Adding class SkDeferredCanvas for deferred rendering.

TEST=added a new pass to gm, so all gm tests are run through SkDeferredCanvas
REVIEW=http://codereview.appspot.com/5430058/



git-svn-id: http://skia.googlecode.com/svn/trunk@3059 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 0af2933..878b686 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -11,6 +11,7 @@
 
 #include "SkColorPriv.h"
 #include "SkData.h"
+#include "SkDeferredCanvas.h"
 #include "SkDevice.h"
 #include "SkGpuCanvas.h"
 #include "SkGpuDevice.h"
@@ -268,26 +269,43 @@
 static ErrorBitfield generate_image(GM* gm, const ConfigData& gRec,
                                     GrContext* context,
                                     GrRenderTarget* rt,
-                                    SkBitmap* bitmap) {
+                                    SkBitmap* bitmap,
+                                    bool deferred) {
     SkISize size (gm->getISize());
     setup_bitmap(gRec, size, bitmap);
-    SkCanvas canvas(*bitmap);
 
     if (gRec.fBackend == kRaster_Backend) {
-        invokeGM(gm, &canvas);
+        SkCanvas* canvas;
+        if (deferred) {
+            canvas = new SkDeferredCanvas;
+            canvas->setDevice(new SkDevice(*bitmap))->unref();
+        } else {
+            canvas = new SkCanvas(*bitmap);
+        }
+        SkAutoUnref canvasUnref(canvas);
+        invokeGM(gm, canvas);
+        if (deferred) {
+            canvas->getDevice()->accessBitmap(false); // trigger a flush
+        }
     } else {  // GPU
         if (NULL == context) {
             return ERROR_NO_GPU_CONTEXT;
         }
-        SkGpuCanvas gc(context, rt);
-        gc.setDevice(new SkGpuDevice(context, rt))->unref();
-        invokeGM(gm, &gc);
+        SkCanvas* gc;
+        if (deferred) {
+            gc = new SkDeferredCanvas;
+        } else {
+            gc = new SkGpuCanvas(context, rt);
+        }
+        SkAutoUnref gcUnref(gc);
+        gc->setDevice(new SkGpuDevice(context, rt))->unref();
+        invokeGM(gm, gc);
         // the device is as large as the current rendertarget, so we explicitly
         // only readback the amount we expect (in size)
         // overwrite our previous allocation
         bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
                                                        size.fHeight);
-        gc.readPixels(bitmap, 0, 0);
+        gc->readPixels(bitmap, 0, 0);
     }
     return ERROR_NONE;
 }
@@ -488,7 +506,8 @@
     if (gRec.fBackend == kRaster_Backend ||
         gRec.fBackend == kGPU_Backend) {
         // Early exit if we can't generate the image.
-        ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap);
+        ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap,
+            false);
         if (ERROR_NONE != errors) {
             return errors;
         }
@@ -506,6 +525,28 @@
                                "", *bitmap, &document, NULL);
 }
 
+static ErrorBitfield test_deferred_drawing(GM* gm,
+                         const ConfigData& gRec,
+                         const SkBitmap& comparisonBitmap,
+                         const char diffPath [],
+                         GrContext* context,
+                         GrRenderTarget* rt) {
+    SkDynamicMemoryWStream document;
+
+    if (gRec.fBackend == kRaster_Backend ||
+        gRec.fBackend == kGPU_Backend) {
+        SkBitmap bitmap;
+        // Early exit if we can't generate the image, but this is
+        // expected in some cases, so don't report a test failure.
+        if (!generate_image(gm, gRec, context, rt, &bitmap, true)) {
+            return ERROR_NONE;
+        }
+        return handle_test_results(gm, gRec, NULL, NULL, diffPath,
+                                   "-deferred", bitmap, NULL, &comparisonBitmap);
+    }
+    return ERROR_NONE;
+}
+
 static ErrorBitfield test_picture_playback(GM* gm,
                                            const ConfigData& gRec,
                                            const SkBitmap& comparisonBitmap,
@@ -612,6 +653,7 @@
     bool doReplay = true;
     bool doSerialize = false;
     bool useMesa = false;
+    bool doDeferred = true;
     
     const char* const commandName = argv[0];
     char* const* stop = argv + argc;
@@ -637,6 +679,8 @@
             doReplay = false;
         } else if (strcmp(*argv, "--nopdf") == 0) {
             doPDF = false;
+        } else if (strcmp(*argv, "--nodeferred") == 0) {
+            doDeferred = false;
         } else if (strcmp(*argv, "--serialize") == 0) {
             doSerialize = true;
         } else if (strcmp(*argv, "--match") == 0) {
@@ -758,6 +802,14 @@
                                            rt.get(), &forwardRenderedBitmap);
             }
 
+            if (doDeferred && !testErrors &&
+                (kGPU_Backend == gRec[i].fBackend || 
+                kRaster_Backend == gRec[i].fBackend)) {
+                testErrors |= test_deferred_drawing(gm, gRec[i],
+                                    forwardRenderedBitmap,
+                                    diffPath, gGrContext, rt.get());
+            }
+
             if ((ERROR_NONE == testErrors) && doReplay &&
                 !(gmFlags & GM::kSkipPicture_Flag)) {
                 testErrors |= test_picture_playback(gm, gRec[i],