Fixing deferred canvases so that they do not return deferred devices on createCompatibleDevice

TEST= DeferredCanvas unit test.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@9224 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index c181818..f2aae06 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -475,12 +475,11 @@
     // Save layer usage not supported, and not required by SkDeferredCanvas.
     SkASSERT(usage != kSaveLayer_Usage);
     // Create a compatible non-deferred device.
-    SkAutoTUnref<SkDevice> compatibleDevice
-        (immediateDevice()->createCompatibleDevice(config, width, height,
-            isOpaque));
-    DeferredDevice* device = SkNEW_ARGS(DeferredDevice, (compatibleDevice));
-    device->setNotificationClient(fNotificationClient);
-    return device;
+    // We do not create a deferred device because we know the new device
+    // will not be used with a deferred canvas (there is no API for that).
+    // And connecting a DeferredDevice to non-deferred canvas can result
+    // in unpredictable behavior.
+    return immediateDevice()->createCompatibleDevice(config, width, height, isOpaque);
 }
 
 bool DeferredDevice::onReadPixels(
diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp
index 3e73393..3def190 100644
--- a/tests/DeferredCanvasTest.cpp
+++ b/tests/DeferredCanvasTest.cpp
@@ -548,6 +548,28 @@
     REPORTER_ASSERT(reporter, pixels4 == pixels5);
 }
 
+static void TestDeferredCanvasCreateCompatibleDevice(skiatest::Reporter* reporter) {
+    SkBitmap store;
+    store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
+    store.allocPixels();
+    SkDevice device(store);
+    NotificationCounter notificationCounter;
+    SkDeferredCanvas canvas(&device);
+    canvas.setNotificationClient(&notificationCounter);
+    SkAutoTUnref<SkDevice> secondaryDevice(canvas.createCompatibleDevice(
+        SkBitmap::kARGB_8888_Config, 10, 10, device.isOpaque()));
+    SkCanvas secondaryCanvas(secondaryDevice.get());
+    SkRect rect = SkRect::MakeWH(5, 5);
+    SkPaint paint;
+    // After spawning a compatible canvas:
+    // 1) Verify that secondary canvas is usable and does not report to the notification client.
+    secondaryCanvas.drawRect(rect, paint);
+    REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 0);
+    // 2) Verify that original canvas is usable and still reports to the notification client.
+    canvas.drawRect(rect, paint);
+    REPORTER_ASSERT(reporter, notificationCounter.fStorageAllocatedChangedCount == 1);
+}
+
 static void TestDeferredCanvas(skiatest::Reporter* reporter, GrContextFactory* factory) {
     TestDeferredCanvasBitmapAccess(reporter);
     TestDeferredCanvasFlush(reporter);
@@ -557,6 +579,7 @@
     TestDeferredCanvasSkip(reporter);
     TestDeferredCanvasBitmapShaderNoLeak(reporter);
     TestDeferredCanvasBitmapSizeThreshold(reporter);
+    TestDeferredCanvasCreateCompatibleDevice(reporter);
     TestDeferredCanvasSurface(reporter, NULL);
     if (NULL != factory) {
         TestDeferredCanvasSurface(reporter, factory);