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,