Fix crash in GrStencilBuffer when it tries to unlock itself but has lost its GrGpu ptr.

Review URL: http://codereview.appspot.com/4810088/



git-svn-id: http://skia.googlecode.com/svn/trunk@2084 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrStencilBuffer.cpp b/gpu/src/GrStencilBuffer.cpp
index d004612..4b08e23 100644
--- a/gpu/src/GrStencilBuffer.cpp
+++ b/gpu/src/GrStencilBuffer.cpp
@@ -13,8 +13,8 @@
 
 void GrStencilBuffer::wasDetachedFromRenderTarget(const GrRenderTarget* rt) {
     GrAssert(fRTAttachmentCnt > 0);
-    if (0 == --fRTAttachmentCnt && NULL != fCacheEntry) {
-        this->getGpu()->getContext()->unlockStencilBuffer(fCacheEntry);
+    if (0 == --fRTAttachmentCnt) {
+        this->unlockInCache();
         // At this point we could be deleted!
     }
 }
@@ -24,3 +24,32 @@
     fCacheEntry = 
         this->getGpu()->getContext()->addAndLockStencilBuffer(this);
 }
+
+void GrStencilBuffer::onRelease() {
+    // When the GrGpu rips through its list of resources and releases
+    // them it may release an SB before it releases its attached RTs.
+    // In that case when GrStencilBuffer sees its last detach it no
+    // long has a gpu ptr (gets nulled in GrResource::release()) and can't
+    // access the cache to unlock itself. So if we're being released and still
+    // have attachments go ahead and unlock now.
+    if (fRTAttachmentCnt) {
+        this->unlockInCache();
+        // we shouldn't be deleted here because some RT still has a ref on us.
+    }
+    fCacheEntry = NULL;
+}
+
+void GrStencilBuffer::onAbandon() {
+    // we can use the same behavior as release.
+    this->onRelease();
+}
+
+void GrStencilBuffer::unlockInCache() {
+    if (NULL != fCacheEntry) {
+        GrGpu* gpu = this->getGpu();
+        if (NULL != gpu) {
+            GrAssert(NULL != gpu->getContext());
+            gpu->getContext()->unlockStencilBuffer(fCacheEntry);
+        }
+    }
+}