add deferred config to DM

BUG=skia:

Review URL: https://codereview.chromium.org/1113273006
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 006e208..70057dd 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -368,6 +368,7 @@
 #define VIA(t, via, ...) if (0 == strcmp(t, tag)) { return new via(__VA_ARGS__); }
     VIA("pipe",      ViaPipe,          wrapped);
     VIA("serialize", ViaSerialization, wrapped);
+    VIA("deferred",  ViaDeferred,      wrapped);
     VIA("2ndpic",    ViaSecondPicture, wrapped);
     VIA("tiles",     ViaTiles, 256, 256,               NULL, wrapped);
     VIA("tiles_rt",  ViaTiles, 256, 256, new SkRTreeFactory, wrapped);
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 9811f9e..b33ba14 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -10,6 +10,7 @@
 #include "SkCommonFlags.h"
 #include "SkCodec.h"
 #include "SkData.h"
+#include "SkDeferredCanvas.h"
 #include "SkDocument.h"
 #include "SkError.h"
 #include "SkImageGenerator.h"
@@ -590,6 +591,41 @@
 }
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+    
+ViaDeferred::ViaDeferred(Sink* sink) : fSink(sink) {}
+
+Error ViaDeferred::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
+    // We turn ourselves into another Src that draws our argument into a deferred canvas,
+    // via a surface created by the original canvas. We then draw a snapped image from that
+    // surface back into the original canvas.
+    struct ProxySrc : public Src {
+        const Src& fSrc;
+        ProxySrc(const Src& src) : fSrc(src) {}
+
+        Error draw(SkCanvas* canvas) const override {
+            SkAutoTUnref<SkSurface> surface(canvas->newSurface(canvas->imageInfo()));
+            if (!surface.get()) {
+                return "can't make surface for deferred canvas";
+            }
+            SkAutoTDelete<SkDeferredCanvas> defcan(SkDeferredCanvas::Create(surface));
+            Error err = fSrc.draw(defcan);
+            if (!err.isEmpty()) {
+                return err;
+            }
+            SkAutoTUnref<SkImage> image(defcan->newImageSnapshot());
+            if (!image) {
+                return "failed to create deferred image snapshot";
+            }
+            canvas->drawImage(image, 0, 0, NULL);
+            return "";
+        }
+        SkISize size() const override { return fSrc.size(); }
+        Name name() const override { sk_throw(); return ""; }  // No one should be calling this.
+    } proxy(src);
+    return fSink->draw(proxy, bitmap, stream, log);
+}
+    
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
 ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
 
diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h
index 0807cb6..ea5572a 100644
--- a/dm/DMSrcSink.h
+++ b/dm/DMSrcSink.h
@@ -249,6 +249,17 @@
     SkAutoTDelete<Sink>  fSink;
 };
 
+class ViaDeferred : public Sink {
+public:
+    explicit ViaDeferred(Sink*);
+
+    Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
+    int enclave() const override { return fSink->enclave(); }
+    const char* fileExtension() const override { return fSink->fileExtension(); }
+private:
+    SkAutoTDelete<Sink>  fSink;
+};
+
 class ViaSerialization : public Sink {
 public:
     explicit ViaSerialization(Sink*);