Augmenting SkDeferredCanvas notification interface to signal flushes and memory allocations
Renamed SkDeferredCanvas::DeviceContext to SkDeferredCanvas::NotificationClient

BUG=http://code.google.com/p/chromium/issues/detail?id=136828
TEST=Added coverage for new API to DeferredCanvas unit test. Added DeferredCanvas bench test to track deferred canvas overhead cost.
Review URL: https://codereview.appspot.com/6442108

git-svn-id: http://skia.googlecode.com/svn/trunk@5078 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp
index 69ca75a..d56bba6 100644
--- a/tests/DeferredCanvasTest.cpp
+++ b/tests/DeferredCanvasTest.cpp
@@ -214,12 +214,34 @@
     REPORTER_ASSERT(reporter, mockDevice.fDrawBitmapCallCount == 4);
 }
 
+class NotificationCounter : public SkDeferredCanvas::NotificationClient {
+public:
+    NotificationCounter() {
+        fPrepareForDrawCount = fStorageAllocatedChangedCount = fFlushedDrawCommandsCount = 0;
+    }
+
+    virtual void prepareForDraw() SK_OVERRIDE {
+        fPrepareForDrawCount++;
+    }
+    virtual void storageAllocatedForRecordingChanged(size_t size) SK_OVERRIDE {
+        fStorageAllocatedChangedCount++;
+    }
+    virtual void flushedDrawCommands() SK_OVERRIDE {
+        fFlushedDrawCommandsCount++;        
+    }
+
+    int fPrepareForDrawCount;
+    int fStorageAllocatedChangedCount;
+    int fFlushedDrawCommandsCount;
+};
+
 static void TestDeferredCanvasBitmapCaching(skiatest::Reporter* reporter) {
     SkBitmap store;
     store.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
     store.allocPixels();
     SkDevice device(store);
-    SkDeferredCanvas canvas(&device);
+    NotificationCounter notificationCounter;
+    SkDeferredCanvas canvas(&device, &notificationCounter);
 
     const int imageCount = 2;
     SkBitmap sourceImages[imageCount];
@@ -232,6 +254,7 @@
     size_t bitmapSize = sourceImages[0].getSize();
 
     canvas.drawBitmap(sourceImages[0], 0, 0, NULL);
+    REPORTER_ASSERT(reporter, 1 == notificationCounter.fStorageAllocatedChangedCount);
     // stored bitmap + drawBitmap command
     REPORTER_ASSERT(reporter, canvas.storageAllocatedForRecording() > bitmapSize);
     
@@ -239,7 +262,11 @@
     REPORTER_ASSERT(reporter, 0 == canvas.freeMemoryIfPossible(~0));
 
     // verify that flush leaves image in cache
+    REPORTER_ASSERT(reporter, 0 == notificationCounter.fFlushedDrawCommandsCount);
+    REPORTER_ASSERT(reporter, 0 == notificationCounter.fPrepareForDrawCount);
     canvas.flush();
+    REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
+    REPORTER_ASSERT(reporter, 1 == notificationCounter.fPrepareForDrawCount);
     REPORTER_ASSERT(reporter, canvas.storageAllocatedForRecording() >= bitmapSize);
 
     // verify that after a flush, cached image can be freed
@@ -247,20 +274,27 @@
 
     // Verify that caching works for avoiding multiple copies of the same bitmap
     canvas.drawBitmap(sourceImages[0], 0, 0, NULL);
+    REPORTER_ASSERT(reporter, 2 == notificationCounter.fStorageAllocatedChangedCount);
     canvas.drawBitmap(sourceImages[0], 0, 0, NULL);
+    REPORTER_ASSERT(reporter, 2 == notificationCounter.fStorageAllocatedChangedCount);
+    REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
     REPORTER_ASSERT(reporter, canvas.storageAllocatedForRecording() < 2 * bitmapSize);
 
     // Verify partial eviction based on bytesToFree
     canvas.drawBitmap(sourceImages[1], 0, 0, NULL);
+    REPORTER_ASSERT(reporter, 1 == notificationCounter.fFlushedDrawCommandsCount);
     canvas.flush();
+    REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
     REPORTER_ASSERT(reporter, canvas.storageAllocatedForRecording() > 2 * bitmapSize);
     size_t bytesFreed = canvas.freeMemoryIfPossible(1);
+    REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
     REPORTER_ASSERT(reporter,  bytesFreed >= bitmapSize);
     REPORTER_ASSERT(reporter,  bytesFreed < 2*bitmapSize);
 
     // Verifiy that partial purge works, image zero is in cache but not reffed by 
     // a pending draw, while image 1 is locked-in.
     canvas.freeMemoryIfPossible(~0);
+    REPORTER_ASSERT(reporter, 2 == notificationCounter.fFlushedDrawCommandsCount);
     canvas.drawBitmap(sourceImages[0], 0, 0, NULL);
     canvas.flush();
     canvas.drawBitmap(sourceImages[1], 0, 0, NULL);