Index: src/image/SkSurface_Raster.cpp |
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp |
index 9c38640933926fdef9becf5221626faeba8e79ee..9b55c697a5e425fe1931706e5f0d72d2c9d90208 100644 |
--- a/src/image/SkSurface_Raster.cpp |
+++ b/src/image/SkSurface_Raster.cpp |
@@ -6,12 +6,14 @@ |
*/ |
#include "SkSurface_Base.h" |
-#include "SkImagePriv.h" |
+#include "SkBitmapDevice.h" |
#include "SkCanvas.h" |
-#include "SkDevice.h" |
+#include "SkDeviceProperties.h" |
+#include "SkImagePriv.h" |
#include "SkMallocPixelRef.h" |
static const size_t kIgnoreRowBytesValue = (size_t)~0; |
+class SkRasterDevice; |
class SkSurface_Raster : public SkSurface_Base { |
public: |
@@ -21,7 +23,7 @@ public: |
void (*releaseProc)(void* pixels, void* context), void* context, |
const SkSurfaceProps*); |
SkSurface_Raster(SkPixelRef*, const SkSurfaceProps*); |
- |
+ ~SkSurface_Raster(); |
SkCanvas* onNewCanvas() SK_OVERRIDE; |
SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE; |
SkImage* onNewImageSnapshot(Budgeted) SK_OVERRIDE; |
@@ -30,12 +32,102 @@ public: |
void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE; |
private: |
- SkBitmap fBitmap; |
- bool fWeOwnThePixels; |
+ SkRasterDevice* fDevice; |
typedef SkSurface_Base INHERITED; |
}; |
+/** A bitmap device that is used by SkSurface_Raster. */ |
+class SkRasterDevice : public SkBitmapDevice { |
+public: |
+ SkRasterDevice(const SkBitmap& bitmap); |
+ enum Direct { kDirect }; |
+ SkRasterDevice(const SkBitmap& bitmap, Direct); |
+ SkRasterDevice(const SkBitmap& bitmap, const SkDeviceProperties& props); |
+ void setSurface(SkSurface_Raster* surface) { fSurface = surface; } |
+ |
+ void discard() SK_OVERRIDE; |
+ SkImage* newImageSnapshot(const SkSurfaceProps* props); |
+ |
+ bool backendUsesPixelRef(const SkPixelRef* other) { |
+ return this->getBackendBitmap().pixelRef() == other; |
+ } |
+ |
+ void discardOnWrite(); |
+ void copyOnWrite(); |
+private: |
+ SkBaseDevice* onCreateCompatibleDevice(const CreateInfo& cinfo) SK_OVERRIDE; |
+ const SkBitmap& onAccessBitmap() SK_OVERRIDE; |
+ SkBitmap& getBackendBitmap() { |
+ return fBitmap; // Note: accessing private SkBitmapDevice::fBitmap |
+ } |
+ |
+ bool fWeOwnThePixels; |
+ SkSurface_Raster* fSurface; |
+ |
+ typedef SkBitmapDevice INHERITED; |
+}; |
+ |
+SkRasterDevice::SkRasterDevice(const SkBitmap& bitmap) |
+ : INHERITED(bitmap) |
+ , fWeOwnThePixels(true) |
+ , fSurface(NULL) { |
+} |
+ |
+SkRasterDevice::SkRasterDevice(const SkBitmap& bitmap, Direct) |
+ : INHERITED(bitmap) |
+ , fWeOwnThePixels(false) |
+ , fSurface(NULL) { |
+ |
+} |
+SkRasterDevice::SkRasterDevice(const SkBitmap& bitmap, const SkDeviceProperties& props) |
+ : INHERITED(bitmap, props) |
+ , fWeOwnThePixels(true) |
+ , fSurface(NULL) { |
+} |
+ |
+SkBaseDevice* SkRasterDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { |
+ SkDeviceProperties leaky(cinfo.fPixelGeometry); |
+ SkBitmap bitmap; |
+ if (!CreateBackendBitmap(cinfo.fInfo, &bitmap)) { |
+ return NULL; |
+ } |
+ return SkNEW_ARGS(SkRasterDevice, (bitmap, leaky)); |
+} |
+ |
+const SkBitmap& SkRasterDevice::onAccessBitmap() { |
+ if (fSurface) { |
+ fSurface->aboutToDraw(SkSurface::kRetain_ContentChangeMode); |
+ } |
+ return this->INHERITED::onAccessBitmap(); |
+} |
+ |
+SkImage* SkRasterDevice::newImageSnapshot(const SkSurfaceProps* props) { |
+ return SkNewImageFromBitmap(this->getBackendBitmap(), fWeOwnThePixels, props); |
+} |
+ |
+void SkRasterDevice::discard() { |
+ if (fSurface) { |
+ fSurface->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); |
+ } |
+} |
+ |
+void SkRasterDevice::discardOnWrite() { |
+ SkASSERT(fWeOwnThePixels); |
+ SkBitmap bitmap(this->getBackendBitmap()); |
+ bitmap.setPixelRef(NULL); |
+ bitmap.allocPixels(); |
+ this->replaceBitmapBackend(bitmap); |
+} |
+ |
+void SkRasterDevice::copyOnWrite() { |
+ SkASSERT(fWeOwnThePixels); |
+ SkBitmap bitmap; |
+ SkBitmap prev(this->getBackendBitmap()); |
+ prev.deepCopyTo(&bitmap); |
+ this->replaceBitmapBackend(bitmap); |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) { |
@@ -85,10 +177,11 @@ bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) { |
SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb, |
void (*releaseProc)(void* pixels, void* context), void* context, |
const SkSurfaceProps* props) |
- : INHERITED(info, props) |
-{ |
- fBitmap.installPixels(info, pixels, rb, NULL, releaseProc, context); |
- fWeOwnThePixels = false; // We are "Direct" |
+ : INHERITED(info, props) { |
+ SkBitmap bitmap; |
+ bitmap.installPixels(info, pixels, rb, NULL, releaseProc, context); |
+ fDevice = SkNEW_ARGS(SkRasterDevice, (bitmap, SkRasterDevice::kDirect)); |
+ fDevice->setSurface(this); |
} |
SkSurface_Raster::SkSurface_Raster(SkPixelRef* pr, const SkSurfaceProps* props) |
@@ -96,17 +189,23 @@ SkSurface_Raster::SkSurface_Raster(SkPixelRef* pr, const SkSurfaceProps* props) |
{ |
const SkImageInfo& info = pr->info(); |
- fBitmap.setInfo(info, info.minRowBytes()); |
- fBitmap.setPixelRef(pr); |
- fWeOwnThePixels = true; |
- |
+ SkBitmap bitmap; |
+ bitmap.setInfo(info, info.minRowBytes()); |
+ bitmap.setPixelRef(pr); |
if (!info.isOpaque()) { |
- fBitmap.eraseColor(SK_ColorTRANSPARENT); |
+ bitmap.eraseColor(SK_ColorTRANSPARENT); |
} |
+ fDevice = SkNEW_ARGS(SkRasterDevice, (bitmap)); |
+ fDevice->setSurface(this); |
+} |
+ |
+SkSurface_Raster::~SkSurface_Raster() { |
+ fDevice->setSurface(NULL); |
+ SkSafeUnref(fDevice); |
} |
SkCanvas* SkSurface_Raster::onNewCanvas() { |
- return SkNEW_ARGS(SkCanvas, (fBitmap, this->props())); |
+ return SkNEW_ARGS(SkCanvas, (fDevice, &this->props(), SkCanvas::kDefault_InitFlags)); |
} |
SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) { |
@@ -115,30 +214,23 @@ SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) { |
void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, |
const SkPaint* paint) { |
- canvas->drawBitmap(fBitmap, x, y, paint); |
+ canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint); |
} |
SkImage* SkSurface_Raster::onNewImageSnapshot(Budgeted) { |
- return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels, &this->props()); |
+ return fDevice->newImageSnapshot(&this->props()); |
} |
void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) { |
- // are we sharing pixelrefs with the image? |
- SkASSERT(this->getCachedImage(kNo_Budgeted)); |
- if (SkBitmapImageGetPixelRef(this->getCachedImage(kNo_Budgeted)) == fBitmap.pixelRef()) { |
- SkASSERT(fWeOwnThePixels); |
+ // Is the device sharing pixelrefs with the image? |
+ SkImage* image = this->getCachedImage(kNo_Budgeted); |
+ SkASSERT(image); |
+ if (fDevice->backendUsesPixelRef(SkBitmapImageGetPixelRef(image))) { |
if (kDiscard_ContentChangeMode == mode) { |
- fBitmap.setPixelRef(NULL); |
- fBitmap.allocPixels(); |
+ fDevice->discardOnWrite(); |
} else { |
- SkBitmap prev(fBitmap); |
- prev.deepCopyTo(&fBitmap); |
+ fDevice->copyOnWrite(); |
} |
- // 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. |
- SkASSERT(this->getCachedCanvas()); |
- this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap); |
} |
} |