DM: Add --skps.
This does render_pictures, plus checks SkRecord optimizations.
Disable an SkRecord optimization that draws several bot SKPs wrong. (To be investigated.)
BUG=skia:2378
R=reed@google.com, mtklein@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/270543004
git-svn-id: http://skia.googlecode.com/svn/trunk@14739 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/dm/DM.cpp b/dm/DM.cpp
index becdc50..f4eefa6 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -5,6 +5,7 @@
#include "SkCommandLineFlags.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
+#include "SkPicture.h"
#include "SkString.h"
#include "Test.h"
#include "gm.h"
@@ -14,6 +15,7 @@
#include "DMGpuGMTask.h"
#include "DMGpuSupport.h"
#include "DMReporter.h"
+#include "DMSKPTask.h"
#include "DMTask.h"
#include "DMTaskRunner.h"
#include "DMTestTask.h"
@@ -43,6 +45,7 @@
DEFINE_string(config, "565 8888 gpu nonrendering",
"Options: 565 8888 gpu nonrendering msaa4 msaa16 nvprmsaa4 nvprmsaa16 gpunull gpudebug angle mesa");
DEFINE_bool(leaks, false, "Print leaked instance-counted objects at exit?");
+DEFINE_string(skps, "", "Directory to read skps from.");
DEFINE_bool(gms, true, "Run GMs?");
DEFINE_bool(benches, true, "Run benches? Does not run GMs-as-benches.");
@@ -143,6 +146,35 @@
}
}
+static void kick_off_skps(DM::Reporter* reporter, DM::TaskRunner* tasks) {
+ if (FLAGS_skps.isEmpty()) {
+ return;
+ }
+
+ SkOSFile::Iter it(FLAGS_skps[0], ".skp");
+ SkString filename;
+ while (it.next(&filename)) {
+ if (SkCommandLineFlags::ShouldSkip(FLAGS_match, filename.c_str())) {
+ continue;
+ }
+
+ const SkString path = SkOSPath::SkPathJoin(FLAGS_skps[0], filename.c_str());
+
+ SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path.c_str()));
+ if (stream.get() == NULL) {
+ SkDebugf("Could not read %s.\n", path.c_str());
+ exit(1);
+ }
+ SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get()));
+ if (pic.get() == NULL) {
+ SkDebugf("Could not read %s as an SkPicture.\n", path.c_str());
+ exit(1);
+ }
+
+ tasks->add(SkNEW_ARGS(DM::SKPTask, (reporter, tasks, pic.detach(), filename)));
+ }
+}
+
static void report_failures(const DM::Reporter& reporter) {
SkTArray<SkString> failures;
reporter.getFailures(&failures);
@@ -215,6 +247,7 @@
kick_off_gms(gms, configs, *expectations, &reporter, &tasks);
kick_off_benches(benches, configs, &reporter, &tasks);
kick_off_tests(tests, &reporter, &tasks);
+ kick_off_skps(&reporter, &tasks);
tasks.wait();
SkDebugf("\n");
diff --git a/dm/DMCpuGMTask.cpp b/dm/DMCpuGMTask.cpp
index 071697b..eb7ed99 100644
--- a/dm/DMCpuGMTask.cpp
+++ b/dm/DMCpuGMTask.cpp
@@ -36,14 +36,14 @@
#define SPAWN(ChildTask, ...) this->spawnChild(SkNEW_ARGS(ChildTask, (*this, __VA_ARGS__)))
SPAWN(ExpectationsTask, fExpectations, bitmap);
- SPAWN(PipeTask, fGMFactory(NULL), bitmap, false, false);
- SPAWN(PipeTask, fGMFactory(NULL), bitmap, true, false);
- SPAWN(PipeTask, fGMFactory(NULL), bitmap, true, true);
+ SPAWN(PipeTask, fGMFactory(NULL), bitmap, PipeTask::kInProcess_Mode);
+ SPAWN(PipeTask, fGMFactory(NULL), bitmap, PipeTask::kCrossProcess_Mode);
+ SPAWN(PipeTask, fGMFactory(NULL), bitmap, PipeTask::kSharedAddress_Mode);
SPAWN(QuiltTask, fGMFactory(NULL), bitmap);
- SPAWN(RecordTask, fGMFactory(NULL), bitmap, true);
- SPAWN(RecordTask, fGMFactory(NULL), bitmap, false);
- SPAWN(ReplayTask, fGMFactory(NULL), bitmap, false);
- SPAWN(ReplayTask, fGMFactory(NULL), bitmap, true);
+ SPAWN(RecordTask, fGMFactory(NULL), bitmap, RecordTask::kOptimize_Mode);
+ SPAWN(RecordTask, fGMFactory(NULL), bitmap, RecordTask::kNoOptimize_Mode);
+ SPAWN(ReplayTask, fGMFactory(NULL), bitmap, ReplayTask::kNormal_Mode);
+ SPAWN(ReplayTask, fGMFactory(NULL), bitmap, ReplayTask::kRTree_Mode);
SPAWN(SerializeTask, fGMFactory(NULL), bitmap);
SPAWN(WriteTask, bitmap);
diff --git a/dm/DMPipeTask.cpp b/dm/DMPipeTask.cpp
index 513594e..13636d6 100644
--- a/dm/DMPipeTask.cpp
+++ b/dm/DMPipeTask.cpp
@@ -10,14 +10,13 @@
namespace DM {
-static uint32_t get_flags(bool crossProcess, bool sharedAddressSpace) {
- SkASSERT(!(!crossProcess && sharedAddressSpace));
+static uint32_t get_flags(PipeTask::Mode mode) {
uint32_t flags = 0;
- if (crossProcess) {
+ if (mode != PipeTask::kInProcess_Mode) {
flags |= SkGPipeWriter::kCrossProcess_Flag;
- if (sharedAddressSpace) {
- flags |= SkGPipeWriter::kSharedAddressSpace_Flag;
- }
+ }
+ if (mode == PipeTask::kSharedAddress_Mode) {
+ flags |= SkGPipeWriter::kSharedAddressSpace_Flag;
}
return flags;
}
@@ -25,7 +24,7 @@
static const char* get_name(const uint32_t flags) {
if (flags & SkGPipeWriter::kCrossProcess_Flag &&
flags & SkGPipeWriter::kSharedAddressSpace_Flag) {
- return "cross_process_shared_address_space_pipe";
+ return "shared_address_space_pipe";
} else if (flags & SkGPipeWriter::kCrossProcess_Flag) {
return "cross_process_pipe";
} else {
@@ -36,10 +35,9 @@
PipeTask::PipeTask(const Task& parent,
skiagm::GM* gm,
SkBitmap reference,
- bool crossProcess,
- bool sharedAddressSpace)
+ Mode mode)
: CpuTask(parent)
- , fFlags(get_flags(crossProcess, sharedAddressSpace))
+ , fFlags(get_flags(mode))
, fName(UnderJoin(parent.name().c_str(), get_name(fFlags)))
, fGM(gm)
, fReference(reference)
diff --git a/dm/DMPipeTask.h b/dm/DMPipeTask.h
index c251d08..bca74e0 100644
--- a/dm/DMPipeTask.h
+++ b/dm/DMPipeTask.h
@@ -14,11 +14,16 @@
class PipeTask : public CpuTask {
public:
+ enum Mode {
+ kInProcess_Mode,
+ kCrossProcess_Mode,
+ kSharedAddress_Mode,
+ };
+
PipeTask(const Task& parent, // PipeTask must be a child task. Pass its parent here.
skiagm::GM*, // GM to run through a pipe. Takes ownership.
SkBitmap reference, // Bitmap to compare pipe results to.
- bool crossProcess, // Should we set up a cross process pipe?
- bool sharedAddressSpace); // If cross process, should it assume shared address space?
+ Mode);
virtual void draw() SK_OVERRIDE;
virtual bool shouldSkip() const SK_OVERRIDE;
diff --git a/dm/DMRecordTask.cpp b/dm/DMRecordTask.cpp
index 531fe57..ce27aaa 100644
--- a/dm/DMRecordTask.cpp
+++ b/dm/DMRecordTask.cpp
@@ -11,21 +11,35 @@
namespace DM {
-RecordTask::RecordTask(const Task& parent, skiagm::GM* gm, SkBitmap reference, bool optimize)
+RecordTask::RecordTask(const Task& parent, skiagm::GM* gm, SkBitmap reference, Mode mode)
: CpuTask(parent)
- , fName(UnderJoin(parent.name().c_str(), optimize ? "skr" : "skr-noopt"))
+ , fOptimize(mode == kOptimize_Mode)
+ , fName(UnderJoin(parent.name().c_str(), fOptimize ? "skr" : "skr-noopt"))
, fGM(gm)
, fReference(reference)
- , fOptimize(optimize)
+ {}
+
+RecordTask::RecordTask(const Task& parent, SkPicture* pic, SkBitmap reference, Mode mode)
+ : CpuTask(parent)
+ , fOptimize(mode == kOptimize_Mode)
+ , fName(UnderJoin(parent.name().c_str(), fOptimize ? "skr" : "skr-noopt"))
+ , fPicture(SkRef(pic))
+ , fReference(reference)
{}
void RecordTask::draw() {
- // Record the GM into an SkRecord.
+ // Record into an SkRecord.
SkRecord record;
SkRecorder recorder(SkRecorder::kWriteOnly_Mode, &record,
fReference.width(), fReference.height());
- recorder.concat(fGM->getInitialTransform());
- fGM->draw(&recorder);
+
+ if (fGM.get()) {
+ recorder.concat(fGM->getInitialTransform());
+ fGM->draw(&recorder);
+ } else {
+ fPicture->draw(&recorder);
+ }
+
if (fOptimize) {
SkRecordOptimize(&record);
@@ -33,7 +47,11 @@
// Draw the SkRecord back into a bitmap.
SkBitmap bitmap;
- SetupBitmap(fReference.colorType(), fGM.get(), &bitmap);
+ if (fGM.get()) {
+ SetupBitmap(fReference.colorType(), fGM.get(), &bitmap);
+ } else {
+ SetupBitmap(fReference.colorType(), *fPicture, &bitmap);
+ }
SkCanvas target(bitmap);
SkRecordDraw(record, &target);
diff --git a/dm/DMRecordTask.h b/dm/DMRecordTask.h
index 94ac412..1420724 100644
--- a/dm/DMRecordTask.h
+++ b/dm/DMRecordTask.h
@@ -3,28 +3,35 @@
#include "DMTask.h"
#include "SkBitmap.h"
+#include "SkPicture.h"
#include "SkString.h"
#include "SkTemplates.h"
#include "gm.h"
-// Records a GM through an SkRecord, draws it, and compares against the reference bitmap.
+// Records a GM or SKP through an SkRecord, draws it, and compares against the reference bitmap.
namespace DM {
class RecordTask : public CpuTask {
public:
- RecordTask(const Task& parent, skiagm::GM*, SkBitmap reference, bool optimize);
+ enum Mode {
+ kNoOptimize_Mode,
+ kOptimize_Mode,
+ };
+ RecordTask(const Task& parent, skiagm::GM*, SkBitmap reference, Mode);
+ RecordTask(const Task& parent, SkPicture*, SkBitmap reference, Mode);
virtual void draw() SK_OVERRIDE;
virtual bool shouldSkip() const SK_OVERRIDE;
virtual SkString name() const SK_OVERRIDE { return fName; }
private:
+ bool fOptimize;
const SkString fName;
+ SkAutoTUnref<SkPicture> fPicture;
SkAutoTDelete<skiagm::GM> fGM;
const SkBitmap fReference;
- bool fOptimize;
};
} // namespace DM
diff --git a/dm/DMReplayTask.cpp b/dm/DMReplayTask.cpp
index e4a9e44..a126f2c 100644
--- a/dm/DMReplayTask.cpp
+++ b/dm/DMReplayTask.cpp
@@ -14,12 +14,12 @@
ReplayTask::ReplayTask(const Task& parent,
skiagm::GM* gm,
SkBitmap reference,
- bool useRTree)
+ Mode mode)
: CpuTask(parent)
- , fName(UnderJoin(parent.name().c_str(), useRTree ? "rtree" : "replay"))
+ , fUseRTree(mode == kRTree_Mode)
+ , fName(UnderJoin(parent.name().c_str(), fUseRTree ? "rtree" : "replay"))
, fGM(gm)
, fReference(reference)
- , fUseRTree(useRTree)
{}
void ReplayTask::draw() {
diff --git a/dm/DMReplayTask.h b/dm/DMReplayTask.h
index 78bef0d..de28172 100644
--- a/dm/DMReplayTask.h
+++ b/dm/DMReplayTask.h
@@ -14,20 +14,24 @@
class ReplayTask : public CpuTask {
public:
+ enum Mode {
+ kNormal_Mode,
+ kRTree_Mode,
+ };
ReplayTask(const Task& parent, // ReplayTask must be a child task. Pass its parent here.
skiagm::GM*, // GM to run through a picture. Takes ownership.
SkBitmap reference, // Bitmap to compare picture replay results to.
- bool useRTree); // Record with an RTree?
+ Mode);
virtual void draw() SK_OVERRIDE;
virtual bool shouldSkip() const SK_OVERRIDE;
virtual SkString name() const SK_OVERRIDE { return fName; }
private:
+ const bool fUseRTree;
const SkString fName;
SkAutoTDelete<skiagm::GM> fGM;
const SkBitmap fReference;
- const bool fUseRTree;
};
} // namespace DM
diff --git a/dm/DMSKPTask.cpp b/dm/DMSKPTask.cpp
new file mode 100644
index 0000000..3eb4c5d
--- /dev/null
+++ b/dm/DMSKPTask.cpp
@@ -0,0 +1,23 @@
+#include "DMRecordTask.h"
+#include "DMSKPTask.h"
+#include "DMUtil.h"
+#include "DMWriteTask.h"
+
+namespace DM {
+
+SKPTask::SKPTask(Reporter* r, TaskRunner* tr, SkPicture* pic, SkString name)
+ : CpuTask(r, tr), fPicture(SkRef(pic)), fName(name) {}
+
+void SKPTask::draw() {
+ SkBitmap bitmap;
+ SetupBitmap(kN32_SkColorType, *fPicture, &bitmap);
+ DrawPicture(fPicture, &bitmap);
+
+ this->spawnChild(SkNEW_ARGS(RecordTask,
+ (*this, fPicture, bitmap, RecordTask::kNoOptimize_Mode)));
+ this->spawnChild(SkNEW_ARGS(RecordTask,
+ (*this, fPicture, bitmap, RecordTask::kOptimize_Mode)));
+ this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap, WriteTask::kVerbatim_Mode)));
+}
+
+} // namespace DM
diff --git a/dm/DMSKPTask.h b/dm/DMSKPTask.h
new file mode 100644
index 0000000..ef465af
--- /dev/null
+++ b/dm/DMSKPTask.h
@@ -0,0 +1,30 @@
+#ifndef DMSKPTask_DEFINED
+#define DMSKPTask_DEFINED
+
+#include "DMReporter.h"
+#include "DMTask.h"
+#include "DMTaskRunner.h"
+#include "SkPicture.h"
+#include "SkString.h"
+#include "SkTemplates.h"
+
+// Draws an SKP to a raster canvas, then compares it with some other modes.
+
+namespace DM {
+
+class SKPTask : public CpuTask {
+public:
+ SKPTask(Reporter*, TaskRunner*, SkPicture*, SkString name);
+
+ virtual void draw() SK_OVERRIDE;
+ virtual bool shouldSkip() const SK_OVERRIDE { return false; }
+ virtual SkString name() const SK_OVERRIDE { return fName; }
+
+private:
+ SkAutoTUnref<SkPicture> fPicture;
+ const SkString fName;
+};
+
+} // namespace DM
+
+#endif // DMSKPTask_DEFINED
diff --git a/dm/DMUtil.cpp b/dm/DMUtil.cpp
index 9a4765a..5c75171 100644
--- a/dm/DMUtil.cpp
+++ b/dm/DMUtil.cpp
@@ -26,14 +26,18 @@
bitmap->eraseColor(0x00000000);
}
-void SetupBitmap(const SkColorType ct, skiagm::GM* gm, SkBitmap* bitmap) {
+void SetupBitmap(SkColorType ct, skiagm::GM* gm, SkBitmap* bitmap) {
setup_bitmap(ct, gm->getISize().width(), gm->getISize().height(), bitmap);
}
-void SetupBitmap(const SkColorType ct, SkBenchmark* bench, SkBitmap* bitmap) {
+void SetupBitmap(SkColorType ct, SkBenchmark* bench, SkBitmap* bitmap) {
setup_bitmap(ct, bench->getSize().x(), bench->getSize().y(), bitmap);
}
+void SetupBitmap(SkColorType ct, const SkPicture& pic, SkBitmap* bitmap) {
+ setup_bitmap(ct, pic.width(), pic.height(), bitmap);
+}
+
void DrawPicture(SkPicture* picture, SkBitmap* bitmap) {
SkASSERT(picture != NULL);
SkASSERT(bitmap != NULL);
diff --git a/dm/DMUtil.h b/dm/DMUtil.h
index 1145f28..c2083ba 100644
--- a/dm/DMUtil.h
+++ b/dm/DMUtil.h
@@ -20,10 +20,11 @@
uint32_t recordFlags = 0,
SkBBHFactory* factory = NULL);
-// Prepare bitmap to have gm or bench draw into it with this config.
+// Prepare bitmap to have gm, bench or picture draw into it with this config.
// TODO(mtklein): make SkBenchmark::getSize()/GM::getISize() const.
-void SetupBitmap(const SkColorType, skiagm::GM* gm, SkBitmap* bitmap);
-void SetupBitmap(const SkColorType, SkBenchmark* bench, SkBitmap* bitmap);
+void SetupBitmap(SkColorType, skiagm::GM* gm, SkBitmap* bitmap);
+void SetupBitmap(SkColorType, SkBenchmark* bench, SkBitmap* bitmap);
+void SetupBitmap(SkColorType, const SkPicture& picture, SkBitmap* bitmap);
// Draw picture to bitmap.
void DrawPicture(SkPicture* picture, SkBitmap* bitmap);
diff --git a/dm/DMWriteTask.cpp b/dm/DMWriteTask.cpp
index f7fa014..cfac415 100644
--- a/dm/DMWriteTask.cpp
+++ b/dm/DMWriteTask.cpp
@@ -26,11 +26,16 @@
return consumed;
}
-WriteTask::WriteTask(const Task& parent, SkBitmap bitmap) : CpuTask(parent), fBitmap(bitmap) {
- const int suffixes = parent.depth() + 1;
- const SkString& name = parent.name();
- const int totalSuffixLength = split_suffixes(suffixes, name.c_str(), &fSuffixes);
- fGmName.set(name.c_str(), name.size()-totalSuffixLength);
+WriteTask::WriteTask(const Task& parent, SkBitmap bitmap, Mode mode)
+ : CpuTask(parent), fBitmap(bitmap) {
+ if (mode == kVerbatim_Mode) {
+ fGmName.set(parent.name());
+ } else {
+ const int suffixes = parent.depth() + 1;
+ const SkString& name = parent.name();
+ const int totalSuffixLength = split_suffixes(suffixes, name.c_str(), &fSuffixes);
+ fGmName.set(name.c_str(), name.size()-totalSuffixLength);
+ }
}
void WriteTask::makeDirOrFail(SkString dir) {
diff --git a/dm/DMWriteTask.h b/dm/DMWriteTask.h
index 839abd7..121dc0d 100644
--- a/dm/DMWriteTask.h
+++ b/dm/DMWriteTask.h
@@ -15,8 +15,13 @@
class WriteTask : public CpuTask {
public:
- WriteTask(const Task& parent, // WriteTask must be a child Task. Pass its parent here.
- SkBitmap bitmap); // Bitmap to write.
+ enum Mode {
+ kParseName_Mode, // Parse the parent's name into directories by underscores.
+ kVerbatim_Mode, // Don't parse the name at all.
+ };
+ WriteTask(const Task& parent, // WriteTask must be a child Task. Pass its parent here.
+ SkBitmap bitmap, // Bitmap to write.
+ Mode = kParseName_Mode);
virtual void draw() SK_OVERRIDE;
virtual bool shouldSkip() const SK_OVERRIDE;