Adding setSurface public API method to SkDeferredCanvas

The purpose of this change is to provide an API that Blink 2D canvas layers can use
to install a new render target when recovering from a lost graphics context.

Review URL: https://codereview.chromium.org/15896005

git-svn-id: http://skia.googlecode.com/svn/trunk@9276 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp
index 3def190..762c916 100644
--- a/tests/DeferredCanvasTest.cpp
+++ b/tests/DeferredCanvasTest.cpp
@@ -548,6 +548,51 @@
     REPORTER_ASSERT(reporter, pixels4 == pixels5);
 }
 
+static void TestDeferredCanvasSetSurface(skiatest::Reporter* reporter, GrContextFactory* factory) {
+    SkImage::Info imageSpec = {
+        10,  // width
+        10,  // height
+        SkImage::kPMColor_ColorType,
+        SkImage::kPremul_AlphaType
+    };
+    SkSurface* surface;
+    SkSurface* alternateSurface;
+    bool useGpu = NULL != factory;
+#if SK_SUPPORT_GPU
+    if (useGpu) {
+        GrContext* context = factory->get(GrContextFactory::kNative_GLContextType);
+        surface = SkSurface::NewRenderTarget(context, imageSpec);
+        alternateSurface = SkSurface::NewRenderTarget(context, imageSpec);
+    } else {
+        surface = SkSurface::NewRaster(imageSpec);
+        alternateSurface = SkSurface::NewRaster(imageSpec);
+    }
+#else
+    SkASSERT(!useGpu);
+    surface = SkSurface::NewRaster(imageSpec);
+    alternateSurface = SkSurface::NewRaster(imageSpec);
+#endif
+    SkASSERT(NULL != surface);
+    SkASSERT(NULL != alternateSurface);
+    SkAutoTUnref<SkSurface> aur1(surface);
+    SkAutoTUnref<SkSurface> aur2(alternateSurface);
+    PixelPtr pixels1 = getSurfacePixelPtr(surface, useGpu);
+    PixelPtr pixels2 = getSurfacePixelPtr(alternateSurface, useGpu);
+    SkDeferredCanvas canvas(surface);
+    SkAutoTUnref<SkImage> image1(canvas.newImageSnapshot());
+    canvas.setSurface(alternateSurface);
+    SkAutoTUnref<SkImage> image2(canvas.newImageSnapshot());
+    REPORTER_ASSERT(reporter, image1->uniqueID() != image2->uniqueID());
+    // Verify that none of the above operations triggered a surface copy on write.
+    REPORTER_ASSERT(reporter, getSurfacePixelPtr(surface, useGpu) == pixels1);
+    REPORTER_ASSERT(reporter, getSurfacePixelPtr(alternateSurface, useGpu) == pixels2);
+    // Verify that a flushed draw command will trigger a copy on write on alternateSurface.
+    canvas.clear(SK_ColorWHITE);
+    canvas.flush();
+    REPORTER_ASSERT(reporter, getSurfacePixelPtr(surface, useGpu) == pixels1);
+    REPORTER_ASSERT(reporter, getSurfacePixelPtr(alternateSurface, useGpu) != pixels2);
+}
+
 static void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporter) {
     SkBitmap store;
     store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
@@ -581,8 +626,10 @@
     TestDeferredCanvasBitmapSizeThreshold(reporter);
     TestDeferredCanvasCreateCompatibleDevice(reporter);
     TestDeferredCanvasSurface(reporter, NULL);
+    TestDeferredCanvasSetSurface(reporter, NULL);
     if (NULL != factory) {
         TestDeferredCanvasSurface(reporter, factory);
+        TestDeferredCanvasSetSurface(reporter, factory);
     }
 }