Added SkDevice onAttachToCanvas & onDetachFromCanvas methods

http://codereview.appspot.com/6348100/



git-svn-id: http://skia.googlecode.com/svn/trunk@4598 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 7d1ecbf..c40275d 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -78,11 +78,11 @@
     const SkMatrix*     fMVMatrix;
     const SkMatrix*     fExtMatrix;
 
-    DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
+    DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
             : fNext(NULL) {
         if (NULL != device) {
             device->ref();
-            device->lockPixels();
+            device->onAttachToCanvas(canvas);
         }
         fDevice = device;
         fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
@@ -90,7 +90,7 @@
 
     ~DeviceCM() {
         if (NULL != fDevice) {
-            fDevice->unlockPixels();
+            fDevice->onDetachFromCanvas();
             fDevice->unref();
         }
         SkDELETE(fPaint);
@@ -256,7 +256,7 @@
             }
             // fCurrLayer may be NULL now
 
-            fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip, *fClipStack);
+            fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip);
             return true;
         }
         return false;
@@ -460,7 +460,7 @@
     fMCRec = (MCRec*)fMCStack.push_back();
     new (fMCRec) MCRec(NULL, 0);
 
-    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL));
+    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
     fMCRec->fTopLayer = fMCRec->fLayer;
     fMCRec->fNext = NULL;
 
@@ -558,14 +558,11 @@
         return device;
     }
 
-    /* Notify the devices that they are going in/out of scope, so they can do
-       things like lock/unlock their pixels, etc.
-    */
     if (device) {
-        device->lockPixels();
+        device->onAttachToCanvas(this);
     }
     if (rootDevice) {
-        rootDevice->unlockPixels();
+        rootDevice->onDetachFromCanvas();
     }
 
     SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
@@ -682,11 +679,10 @@
 }
 
 void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix,
-                                    const SkRegion& clip,
-                                    const SkClipStack& clipStack) {
+                                    const SkRegion& clip) {
     SkASSERT(device);
     if (fLastDeviceToGainFocus != device) {
-        device->gainFocus(this, matrix, clip, clipStack);
+        device->gainFocus(matrix, clip);
         fLastDeviceToGainFocus = device;
     }
 }
@@ -843,7 +839,7 @@
     }
 
     device->setOrigin(ir.fLeft, ir.fTop);
-    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint));
+    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
     device->unref();
 
     layer->fNext = fMCRec->fTopLayer;
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 95664c8..4cd9310 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -20,12 +20,21 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
+SkDevice::SkDevice(const SkBitmap& bitmap) 
+    : fBitmap(bitmap)
+#ifdef SK_DEBUG
+    , fAttachedToCanvas(false) 
+#endif
+{
     fOrigin.setZero();
     fMetaData = NULL;
 }
 
-SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
+SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque) 
+#ifdef SK_DEBUG
+    : fAttachedToCanvas(false) 
+#endif
+{
     fOrigin.setZero();
     fMetaData = NULL;
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 1154313..6443fa2 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -165,12 +165,14 @@
 }
 
 SkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture)
-: SkDevice(make_bitmap(context, texture->asRenderTarget())) {
+: SkDevice(make_bitmap(context, texture->asRenderTarget()))
+, fClipStack(NULL) {
     this->initFromRenderTarget(context, texture->asRenderTarget());
 }
 
 SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget)
-: SkDevice(make_bitmap(context, renderTarget)) {
+: SkDevice(make_bitmap(context, renderTarget))
+, fClipStack(NULL) {
     this->initFromRenderTarget(context, renderTarget);
 }
 
@@ -211,7 +213,8 @@
                          SkBitmap::Config config,
                          int width,
                          int height)
-    : SkDevice(config, width, height, false /*isOpaque*/) {
+    : SkDevice(config, width, height, false /*isOpaque*/)
+    , fClipStack(NULL) {
     fNeedPrepareRenderTarget = false;
     fDrawProcs = NULL;
 
@@ -342,6 +345,19 @@
                                config, bitmap.getPixels(), bitmap.rowBytes());
 }
 
+void SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
+    INHERITED::onAttachToCanvas(canvas);
+
+    // Canvas promises that this ptr is valid until onDetachFromCanvas is called
+    fClipStack = canvas->getClipStack();
+}
+
+void SkGpuDevice::onDetachFromCanvas() {
+    INHERITED::onDetachFromCanvas();
+
+    fClipStack = NULL;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
@@ -366,13 +382,15 @@
 // call this ever each draw call, to ensure that the context reflects our state,
 // and not the state from some other canvas/device
 void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
+    GrAssert(NULL != fClipStack);
+
     if (fNeedPrepareRenderTarget ||
         fContext->getRenderTarget() != fRenderTarget) {
 
         fContext->setRenderTarget(fRenderTarget);
-        SkASSERT(draw.fClipStack);
+        SkASSERT(draw.fClipStack && draw.fClipStack == fClipStack);
         convert_matrixclip(fContext, *draw.fMatrix,
-                           *draw.fClipStack, *draw.fClip, this->getOrigin());
+                           *fClipStack, *draw.fClip, this->getOrigin());
         fNeedPrepareRenderTarget = false;
     }
 }
@@ -384,14 +402,15 @@
     fNeedPrepareRenderTarget = true;
 }
 
-void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
-                            const SkRegion& clip, const SkClipStack& clipStack) {
+void SkGpuDevice::gainFocus(const SkMatrix& matrix, const SkRegion& clip) {
+
+    GrAssert(NULL != fClipStack);
 
     fContext->setRenderTarget(fRenderTarget);
 
-    this->INHERITED::gainFocus(canvas, matrix, clip, clipStack);
+    this->INHERITED::gainFocus(matrix, clip);
 
-    convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin());
+    convert_matrixclip(fContext, matrix, *fClipStack, clip, this->getOrigin());
 
     DO_DEFERRED_CLEAR;
 }
@@ -1964,7 +1983,8 @@
                          GrTexture* texture,
                          TexCache cacheEntry,
                          bool needClear)
-    : SkDevice(make_bitmap(context, texture->asRenderTarget())) {
+    : SkDevice(make_bitmap(context, texture->asRenderTarget()))
+    , fClipStack(NULL) {
     GrAssert(texture && texture->asRenderTarget());
     GrAssert(NULL == cacheEntry.texture() || texture == cacheEntry.texture());
     this->initFromRenderTarget(context, texture->asRenderTarget());
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index d05b640..55aae8d 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -514,7 +514,8 @@
       fPageSize(pageSize),
       fContentSize(contentSize),
       fLastContentEntry(NULL),
-      fLastMarginContentEntry(NULL) {
+      fLastMarginContentEntry(NULL),
+      fClipStack(NULL) {
     // Skia generally uses the top left as the origin but PDF natively has the
     // origin at the bottom left. This matrix corrects for that.  But that only
     // needs to be done once, we don't do it when layering.
@@ -538,7 +539,8 @@
       fExistingClipStack(existingClipStack),
       fExistingClipRegion(existingClipRegion),
       fLastContentEntry(NULL),
-      fLastMarginContentEntry(NULL) {
+      fLastMarginContentEntry(NULL),
+      fClipStack(NULL) {
     fInitialTransform.reset();
     this->init();
 }
@@ -945,6 +947,19 @@
     fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage());
 }
 
+void SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) {
+    INHERITED::onAttachToCanvas(canvas);
+
+    // Canvas promises that this ptr is valid until onDetachFromCanvas is called
+    fClipStack = canvas->getClipStack();
+}
+
+void SkPDFDevice::onDetachFromCanvas() {
+    INHERITED::onDetachFromCanvas();
+
+    fClipStack = NULL;
+}
+
 ContentEntry* SkPDFDevice::getLastContentEntry() {
     if (fDrawingArea == kContent_DrawingArea) {
         return fLastContentEntry;