Add caching of the snapshot image form a surface
Notify the surface when the canvas draws into it, so it can invalidate the
cached image, and (if needed) perform a copy-on-write on the surface if it
was being shared with the image.
Review URL: https://codereview.appspot.com/6441115

git-svn-id: http://skia.googlecode.com/svn/trunk@5306 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index c4ac959..8afab6b 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -8,6 +8,7 @@
 #include "SkSurface_Base.h"
 #include "SkImagePriv.h"
 #include "SkCanvas.h"
+#include "SkDevice.h"
 #include "SkMallocPixelRef.h"
 
 static const size_t kIgnoreRowBytesValue = (size_t)~0;
@@ -24,6 +25,7 @@
     virtual SkImage* onNewImageShapshot() SK_OVERRIDE;
     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
                         const SkPaint*) SK_OVERRIDE;
+    virtual void onCopyOnWrite(SkImage*, SkCanvas*) SK_OVERRIDE;
 
 private:
     SkBitmap    fBitmap;
@@ -89,7 +91,7 @@
     fBitmap.setConfig(config, info.fWidth, info.fHeight, rb);
     fBitmap.setPixels(pixels);
     fBitmap.setIsOpaque(isOpaque);
-    fWeOwnThePixels = false;
+    fWeOwnThePixels = false;    // We are "Direct"
 }
 
 SkSurface_Raster::SkSurface_Raster(const SkImage::Info& info, SkColorSpace* cs,
@@ -117,18 +119,28 @@
     return SkSurface::NewRaster(info, cs);
 }
 
-SkImage* SkSurface_Raster::onNewImageShapshot() {
-    // if we don't own the pixels, we need to make a deep-copy
-    // if we do, we need to perform a copy-on-write the next time
-    // we draw to this bitmap from our canvas...
-    return SkNewImageFromBitmap(fBitmap);
-}
-
 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
                               const SkPaint* paint) {
     canvas->drawBitmap(fBitmap, x, y, paint);
 }
 
+SkImage* SkSurface_Raster::onNewImageShapshot() {
+    return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
+}
+
+void SkSurface_Raster::onCopyOnWrite(SkImage* image, SkCanvas* canvas) {
+    // are we sharing pixelrefs with the image?
+    if (SkBitmapImageGetPixelRef(image) == fBitmap.pixelRef()) {
+        SkASSERT(fWeOwnThePixels);
+        SkBitmap prev(fBitmap);
+        prev.deepCopyTo(&fBitmap, prev.config());
+        // Now fBitmap is a deep copy of itself (and therefore different from
+        // what is being used by the image. Next we update the canvas to use
+        // this as its backend, so we can't modify the image's pixels anymore.
+        canvas->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 SkSurface* SkSurface::NewRasterDirect(const SkImage::Info& info,