Reverting r12427

git-svn-id: http://skia.googlecode.com/svn/trunk@12428 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 8c30fe6..274ec2a 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -6,6 +6,7 @@
 #include "SkCommandLineFlags.h"
 #include "SkForceLinking.h"
 #include "SkGraphics.h"
+#include "SkString.h"
 #include "gm.h"
 
 #include "DMReporter.h"
@@ -39,19 +40,6 @@
 
 __SK_FORCE_IMAGE_DECODER_LINKING;
 
-// Split str on any characters in delimiters into out.  (Think, strtok with a sane API.)
-static void split(const char* str, const char* delimiters, SkTArray<SkString>* out) {
-    const char* end = str + strlen(str);
-    while (str != end) {
-        // Find a token.
-        const size_t len = strcspn(str, delimiters);
-        out->push_back().set(str, len);
-        str += len;
-        // Skip any delimiters.
-        str += strspn(str, delimiters);
-    }
-}
-
 // "FooBar" -> "foobar".  Obviously, ASCII only.
 static SkString lowercase(SkString s) {
     for (size_t i = 0; i < s.size(); i++) {
@@ -134,7 +122,7 @@
     GM::SetResourcePath(FLAGS_resources[0]);
     SkTArray<SkString> configs;
     for (int i = 0; i < FLAGS_config.count(); i++) {
-        split(FLAGS_config[i], ", ", &configs);
+        SkStrSplit(FLAGS_config[i], ", ", &configs);
     }
 
     SkTDArray<GMRegistry::Factory> gms;
diff --git a/dm/DMComparisonTask.cpp b/dm/DMComparisonTask.cpp
deleted file mode 100644
index bb4e656..0000000
--- a/dm/DMComparisonTask.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "DMComparisonTask.h"
-#include "DMUtil.h"
-
-namespace DM {
-
-ComparisonTask::ComparisonTask(const Task& parent,
-                               skiagm::Expectations expectations,
-                               SkBitmap bitmap)
-    : Task(parent)
-    , fName(parent.name())  // Masquerade as parent so failures are attributed to it.
-    , fExpectations(expectations)
-    , fBitmap(bitmap)
-    {}
-
-void ComparisonTask::draw() {
-    if (!MeetsExpectations(fExpectations, fBitmap)) {
-        this->fail();
-    }
-}
-
-}  // namespace DM
diff --git a/dm/DMComparisonTask.h b/dm/DMComparisonTask.h
deleted file mode 100644
index 265a58c..0000000
--- a/dm/DMComparisonTask.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef DMComparisonTask_DEFINED
-#define DMComparisonTask_DEFINED
-
-#include "DMTask.h"
-#include "SkBitmap.h"
-#include "SkString.h"
-#include "gm_expectations.h"
-
-namespace DM {
-
-// We use ComparisonTask to move CPU-bound comparison work of GpuTasks back to
-// the main thread pool, where we probably have more threads available.
-
-class ComparisonTask : public Task {
-public:
-    ComparisonTask(const Task& parent, skiagm::Expectations, SkBitmap);
-
-    virtual void draw() SK_OVERRIDE;
-    virtual bool usesGpu() const SK_OVERRIDE { return false; }
-    virtual bool shouldSkip() const SK_OVERRIDE { return false; }
-    virtual SkString name() const SK_OVERRIDE { return fName; }
-
-private:
-    const SkString fName;
-    const skiagm::Expectations fExpectations;
-    const SkBitmap fBitmap;
-};
-
-}  // namespace DM
-
-#endif  // DMComparisonTask_DEFINED
diff --git a/dm/DMCpuTask.cpp b/dm/DMCpuTask.cpp
index 1d1d401..3f51c8a 100644
--- a/dm/DMCpuTask.cpp
+++ b/dm/DMCpuTask.cpp
@@ -1,7 +1,9 @@
 #include "DMCpuTask.h"
+#include "DMChecksumTask.h"
 #include "DMPipeTask.h"
 #include "DMReplayTask.h"
 #include "DMSerializeTask.h"
+#include "DMTileGridTask.h"
 #include "DMUtil.h"
 #include "DMWriteTask.h"
 
@@ -30,19 +32,19 @@
     fGM->draw(&canvas);
     canvas.flush();
 
-    if (!MeetsExpectations(fExpectations, bitmap)) {
-        this->fail();
-    }
+#define SPAWN(ChildTask, ...) this->spawnChild(SkNEW_ARGS(ChildTask, (*this, __VA_ARGS__)))
+    SPAWN(ChecksumTask, fExpectations, bitmap);
 
-    this->spawnChild(SkNEW_ARGS(PipeTask, (*this, fGMFactory(NULL), bitmap, false, false)));
-    this->spawnChild(SkNEW_ARGS(PipeTask, (*this, fGMFactory(NULL), bitmap, true, false)));
-    this->spawnChild(SkNEW_ARGS(PipeTask, (*this, fGMFactory(NULL), bitmap, true, true)));
+    SPAWN(PipeTask, fGMFactory(NULL), bitmap, false, false);
+    SPAWN(PipeTask, fGMFactory(NULL), bitmap, true, false);
+    SPAWN(PipeTask, fGMFactory(NULL), bitmap, true, true);
+    SPAWN(ReplayTask, fGMFactory(NULL), bitmap, false);
+    SPAWN(ReplayTask, fGMFactory(NULL), bitmap, true);
+    SPAWN(SerializeTask, fGMFactory(NULL), bitmap);
+    SPAWN(TileGridTask, fGMFactory(NULL), bitmap, SkISize::Make(16,16));
 
-    this->spawnChild(SkNEW_ARGS(ReplayTask, (*this, fGMFactory(NULL), bitmap, true)));
-    this->spawnChild(SkNEW_ARGS(ReplayTask, (*this, fGMFactory(NULL), bitmap, false)));
-
-    this->spawnChild(SkNEW_ARGS(SerializeTask, (*this, fGMFactory(NULL), bitmap)));
-    this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap)));
+    SPAWN(WriteTask, bitmap);
+#undef SPAWN
 }
 
 bool CpuTask::shouldSkip() const {
diff --git a/dm/DMGpuTask.cpp b/dm/DMGpuTask.cpp
index 4d99356..d4c4254 100644
--- a/dm/DMGpuTask.cpp
+++ b/dm/DMGpuTask.cpp
@@ -1,6 +1,6 @@
 #include "DMGpuTask.h"
 
-#include "DMComparisonTask.h"
+#include "DMChecksumTask.h"
 #include "DMUtil.h"
 #include "DMWriteTask.h"
 #include "SkCommandLineFlags.h"
@@ -60,9 +60,7 @@
     gr->printCacheStats();
 #endif
 
-    // We offload checksum comparison to the main CPU threadpool.
-    // This cuts run time by about 30%.
-    this->spawnChild(SkNEW_ARGS(ComparisonTask, (*this, fExpectations, bitmap)));
+    this->spawnChild(SkNEW_ARGS(ChecksumTask, (*this, fExpectations, bitmap)));
     this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap)));
 }
 
diff --git a/dm/DMPipeTask.cpp b/dm/DMPipeTask.cpp
index 8a8fe62..de3897a 100644
--- a/dm/DMPipeTask.cpp
+++ b/dm/DMPipeTask.cpp
@@ -6,7 +6,7 @@
 #include "SkCommandLineFlags.h"
 #include "SkGPipe.h"
 
-DEFINE_bool(pipe, false, "If true, check several pipe variants against the reference bitmap.");
+DEFINE_bool(pipe, true, "If true, check several pipe variants against the reference bitmap.");
 
 namespace DM {
 
diff --git a/dm/DMReplayTask.cpp b/dm/DMReplayTask.cpp
index 0ec9e25..af8669b 100644
--- a/dm/DMReplayTask.cpp
+++ b/dm/DMReplayTask.cpp
@@ -5,8 +5,8 @@
 #include "SkCommandLineFlags.h"
 #include "SkPicture.h"
 
-DEFINE_bool(replay, false, "If true, run picture replay tests.");
-DEFINE_bool(rtree,  false, "If true, run picture replay tests with an rtree.");
+DEFINE_bool(replay, true, "If true, run picture replay tests.");
+DEFINE_bool(rtree,  true, "If true, run picture replay tests with an rtree.");
 
 namespace DM {
 
diff --git a/dm/DMReplayTask.h b/dm/DMReplayTask.h
index 1217c07..1245009 100644
--- a/dm/DMReplayTask.h
+++ b/dm/DMReplayTask.h
@@ -15,8 +15,8 @@
 
 public:
     ReplayTask(const Task& parent,  // ReplayTask 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.
+               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?
 
     virtual void draw() SK_OVERRIDE;
diff --git a/dm/DMReporter.cpp b/dm/DMReporter.cpp
index 0e01d71..31310d1 100644
--- a/dm/DMReporter.cpp
+++ b/dm/DMReporter.cpp
@@ -12,7 +12,7 @@
     }
 
     SkString status;
-    status.printf("\r\033[K%d / %d", this->finished(), this->started());
+    status.printf("\r\033[K%d tasks left", this->started() - this->finished());
     const int failed = this->failed();
     if (failed > 0) {
         status.appendf(", %d failed", failed);
diff --git a/dm/DMSerializeTask.cpp b/dm/DMSerializeTask.cpp
index d71dfdc..8bc8c8e 100644
--- a/dm/DMSerializeTask.cpp
+++ b/dm/DMSerializeTask.cpp
@@ -6,7 +6,7 @@
 #include "SkPicture.h"
 #include "SkPixelRef.h"
 
-DEFINE_bool(serialize, false, "If true, run picture serialization tests.");
+DEFINE_bool(serialize, true, "If true, run picture serialization tests.");
 
 namespace DM {
 
diff --git a/dm/DMTask.cpp b/dm/DMTask.cpp
index ba74a5f..a5c75f0 100644
--- a/dm/DMTask.cpp
+++ b/dm/DMTask.cpp
@@ -8,14 +8,15 @@
 namespace DM {
 
 Task::Task(Reporter* reporter, TaskRunner* taskRunner)
-    : fReporter(reporter), fTaskRunner(taskRunner) {
+    : fReporter(reporter), fTaskRunner(taskRunner), fDepth(0) {
     fReporter->start();
 }
 
-Task::Task(const Task& that)
-    : INHERITED(that)
-    , fReporter(that.fReporter)
-    , fTaskRunner(that.fTaskRunner) {
+Task::Task(const Task& parent)
+    : INHERITED(parent)
+    , fReporter(parent.fReporter)
+    , fTaskRunner(parent.fTaskRunner)
+    , fDepth(parent.depth()+1) {
     fReporter->start();
 }
 
diff --git a/dm/DMTask.h b/dm/DMTask.h
index 5388196..0d3ef74 100644
--- a/dm/DMTask.h
+++ b/dm/DMTask.h
@@ -18,7 +18,7 @@
 class Task : public SkRunnable {
 public:
     Task(Reporter* reporter, TaskRunner* taskRunner);
-    Task(const Task& that);
+    Task(const Task& parent);
     virtual ~Task();
 
     void run() SK_OVERRIDE;
@@ -28,6 +28,10 @@
     virtual bool shouldSkip() const = 0;
     virtual SkString name() const = 0;
 
+    // Returns the number of parents above this task.
+    // Top-level tasks return 0, their children 1, and so on.
+    int depth() const { return fDepth; }
+
 protected:
     void spawnChild(Task* task);
     void fail();
@@ -36,6 +40,7 @@
     // Both unowned.
     Reporter* fReporter;
     TaskRunner* fTaskRunner;
+    int fDepth;
 
     typedef SkRunnable INHERITED;
 };
diff --git a/dm/DMUtil.cpp b/dm/DMUtil.cpp
index d521484..6cf6c22 100644
--- a/dm/DMUtil.cpp
+++ b/dm/DMUtil.cpp
@@ -15,18 +15,9 @@
     return s;
 }
 
-bool MeetsExpectations(const skiagm::Expectations& expectations, const SkBitmap bitmap) {
-    if (expectations.ignoreFailure() || expectations.empty()) {
-        return true;
-    }
-    const skiagm::GmResultDigest digest(bitmap);
-    return expectations.match(digest);
-}
-
 void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags) {
-    SkCanvas* canvas = picture->beginRecording(SkScalarCeilToInt(gm->width()),
-                                               SkScalarCeilToInt(gm->height()),
-                                               recordFlags);
+    const SkISize size = gm->getISize();
+    SkCanvas* canvas = picture->beginRecording(size.width(), size.height(), recordFlags);
     canvas->concat(gm->getInitialTransform());
     gm->draw(canvas);
     canvas->flush();
@@ -34,7 +25,8 @@
 }
 
 void SetupBitmap(const SkBitmap::Config config, skiagm::GM* gm, SkBitmap* bitmap) {
-    bitmap->setConfig(config, SkScalarCeilToInt(gm->width()), SkScalarCeilToInt(gm->height()));
+    const SkISize size = gm->getISize();
+    bitmap->setConfig(config, size.width(), size.height());
     bitmap->allocPixels();
     bitmap->eraseColor(0x00000000);
 }
diff --git a/dm/DMUtil.h b/dm/DMUtil.h
index 512ad64..5f22df0 100644
--- a/dm/DMUtil.h
+++ b/dm/DMUtil.h
@@ -15,9 +15,6 @@
 // Png("a") -> "a.png"
 SkString Png(SkString s);
 
-// Roughly, expectations.match(GmResultDigest(bitmap)), but calculates the digest lazily.
-bool MeetsExpectations(const skiagm::Expectations& expectations, const SkBitmap bitmap);
-
 // Draw gm to picture.  Passes recordFlags to SkPicture::beginRecording().
 void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags = 0);
 
diff --git a/dm/DMWriteTask.cpp b/dm/DMWriteTask.cpp
index 011b339..c86381f 100644
--- a/dm/DMWriteTask.cpp
+++ b/dm/DMWriteTask.cpp
@@ -3,41 +3,54 @@
 #include "DMUtil.h"
 #include "SkCommandLineFlags.h"
 #include "SkImageEncoder.h"
-
-#include <string.h>
+#include "SkString.h"
 
 DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs.");
 
 namespace DM {
 
-WriteTask::WriteTask(const Task& parent, SkBitmap bitmap)
-    : Task(parent)
-    , fBitmap(bitmap) {
-    // Split parent's name <gmName>_<config> into gmName and config.
-    const char* parentName = parent.name().c_str();
-    const char* fromLastUnderscore = strrchr(parentName, '_');
-    const ptrdiff_t gmNameLength = fromLastUnderscore - parentName;
+WriteTask::WriteTask(const Task& parent, SkBitmap bitmap) : Task(parent), fBitmap(bitmap) {
+    const int suffixes = parent.depth() + 1;
+    const char* name = parent.name().c_str();
+    SkTArray<SkString> split;
+    SkStrSplit(name, "_", &split);
+    int totalSuffixLength = 0;
+    for (int i = 0; i < suffixes; i++) {
+        // We're splitting off suffixes from the back to front.
+        fSuffixes.push_back(split[split.count()-i-1]);
+        totalSuffixLength += fSuffixes.back().size() + 1;
+    }
+    fGmName.set(name, strlen(name)-totalSuffixLength);
+}
 
-    fConfig.set(fromLastUnderscore+1);
-    fGmName.set(parentName, gmNameLength);
+void WriteTask::makeDirOrFail(SkString dir) {
+    if (!sk_mkdir(dir.c_str())) {
+        this->fail();
+    }
 }
 
 void WriteTask::draw() {
-    const char* root = FLAGS_writePath[0];
-    const SkString dir = SkOSPath::SkPathJoin(root, fConfig.c_str());
-    if (!sk_mkdir(root) ||
-        !sk_mkdir(dir.c_str())  ||
-        !SkImageEncoder::EncodeFile(Png(SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str())).c_str(),
+    SkString dir(FLAGS_writePath[0]);
+    this->makeDirOrFail(dir);
+    for (int i = 0; i < fSuffixes.count(); i++) {
+        dir = SkOSPath::SkPathJoin(dir.c_str(), fSuffixes[i].c_str());
+        this->makeDirOrFail(dir);
+    }
+    if (!SkImageEncoder::EncodeFile(Png(SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str())).c_str(),
                                     fBitmap,
                                     SkImageEncoder::kPNG_Type,
-                                    100/*quality*/))
-    {
+                                    100/*quality*/)) {
         this->fail();
     }
 }
 
 SkString WriteTask::name() const {
-    return SkStringPrintf("writing %s/%s.png", fConfig.c_str(), fGmName.c_str());
+    SkString name("writing ");
+    for (int i = 0; i < fSuffixes.count(); i++) {
+        name.appendf("%s/", fSuffixes[i].c_str());
+    }
+    name.append(fGmName.c_str());
+    return name;
 }
 
 bool WriteTask::shouldSkip() const {
diff --git a/dm/DMWriteTask.h b/dm/DMWriteTask.h
index 7a9b4fa..82a26bc 100644
--- a/dm/DMWriteTask.h
+++ b/dm/DMWriteTask.h
@@ -4,6 +4,7 @@
 #include "DMTask.h"
 #include "SkBitmap.h"
 #include "SkString.h"
+#include "SkTArray.h"
 
 // Writes a bitmap to a file.
 
@@ -12,7 +13,8 @@
 class WriteTask : public Task {
 
 public:
-    WriteTask(const Task& parent, SkBitmap bitmap);
+    WriteTask(const Task& parent,  // WriteTask must be a child Task.  Pass its parent here.
+              SkBitmap bitmap);    // Bitmap to write.
 
     virtual void draw() SK_OVERRIDE;
     virtual bool usesGpu() const SK_OVERRIDE { return false; }
@@ -20,9 +22,11 @@
     virtual SkString name() const SK_OVERRIDE;
 
 private:
-    SkString fConfig;
+    SkTArray<SkString> fSuffixes;
     SkString fGmName;
     const SkBitmap fBitmap;
+
+    void makeDirOrFail(SkString dir);
 };
 
 }  // namespace DM
diff --git a/dm/README b/dm/README
index 6cde686..78b962e 100644
--- a/dm/README
+++ b/dm/README
@@ -7,7 +7,6 @@
   --writePicturePath
 
   --deferred
-  --tiledGrid
 
 
 DM's design is based around Tasks and a TaskRunner.