Fix ref leak on GrGpu.

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



git-svn-id: http://skia.googlecode.com/svn/trunk@1015 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrBufferAllocPool.cpp b/gpu/src/GrBufferAllocPool.cpp
index 35f0c5e..0db12fe 100644
--- a/gpu/src/GrBufferAllocPool.cpp
+++ b/gpu/src/GrBufferAllocPool.cpp
@@ -34,11 +34,14 @@
                                      size_t blockSize,
                                      int preallocBufferCnt) :
         fBlocks(GrMax(8, 2*preallocBufferCnt)) {
+
     GrAssert(NULL != gpu);
     fGpu = gpu;
+    fGpu->ref();
+    fGpuIsReffed = true;
+
     fBufferType = bufferType;
     fFrequentResetHint = frequentResetHint;
-    fGpu->ref();
     fBufferPtr = NULL;
     fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
 
@@ -61,11 +64,18 @@
             buffer->unlock();
         }
     }
-    fPreallocBuffers.unrefAll();
     while (!fBlocks.empty()) {
         destroyBlock();
     }
-    fGpu->unref();
+    fPreallocBuffers.unrefAll();
+    releaseGpuRef();
+}
+
+void GrBufferAllocPool::releaseGpuRef() {
+    if (fGpuIsReffed) {
+        fGpu->unref();
+        fGpuIsReffed = false;
+    }
 }
 
 void GrBufferAllocPool::reset() {
diff --git a/gpu/src/GrBufferAllocPool.h b/gpu/src/GrBufferAllocPool.h
index 80f16ab..7d70ebb 100644
--- a/gpu/src/GrBufferAllocPool.h
+++ b/gpu/src/GrBufferAllocPool.h
@@ -39,10 +39,45 @@
  * be allocated at the min size and kept around until the pool is destroyed.
  */
 class GrBufferAllocPool : GrNoncopyable {
-protected:
 
-    // We could make the createBuffer a virtual except that we want to use it
-    // in the cons for pre-allocated buffers.
+public:
+    /**
+     * Ensures all buffers are unlocked and have all data written to them.
+     * Call before drawing using buffers from the pool.
+     */
+    void unlock();
+
+    /**
+     *  Invalidates all the data in the pool, unrefs non-preallocated buffers.
+     */
+    void reset();
+
+    /**
+     * Gets the number of preallocated buffers that are yet to be used.
+     */
+    int preallocatedBuffersRemaining() const;
+
+    /**
+     * gets the number of preallocated buffers
+     */
+    int preallocatedBufferCount() const;
+
+    /**
+     * Frees data from makeSpaces in LIFO order.
+     */
+    void putBack(size_t bytes);
+
+    /**
+     * Gets the GrGpu that this pool is associated with.
+     */
+    GrGpu* getGpu() { return fGpu; }
+
+protected:
+    /**
+     * Used to determine what type of buffers to create. We could make the
+     * createBuffer a virtual except that we want to use it in the cons for
+     * pre-allocated buffers.
+     */
     enum BufferType {
         kVertex_BufferType,
         kIndex_BufferType,
@@ -72,40 +107,6 @@
 
     virtual ~GrBufferAllocPool();
 
-public:
-    /**
-     * Ensures all buffers are unlocked and have all data written to them.
-     * Call before drawing using buffers from the pool.
-     */
-    void unlock();
-
-    /**
-     *  Invalidates all the data in the pool, unrefs non-preallocated buffers.
-     */
-    void reset();
-
-    /**
-     * Gets the number of preallocated buffers that are yet to be used.
-     */
-    int preallocatedBuffersRemaining() const;
-
-    /**
-     * gets the number of preallocated buffers
-     */
-    int preallocatedBufferCount() const;
-
-
-    /**
-     * Frees data from makeSpaces in LIFO order.
-     */
-    void putBack(size_t bytes);
-
-    /**
-     * Gets the GrGpu that this pool is associated with.
-     */
-    GrGpu* getGpu() { return fGpu; }
-
-protected:
     /**
      * Gets the size of the preallocated buffers.
      *
@@ -155,6 +156,10 @@
 
 private:
 
+    // The GrGpu must be able to clear the ref of pools it creates as members
+    friend class GrGpu;
+    void releaseGpuRef();
+
     struct BufferBlock {
         size_t              fBytesFree;
         GrGeometryBuffer*   fBuffer;
@@ -168,6 +173,7 @@
 #endif
 
     GrGpu*                          fGpu;
+    bool                            fGpuIsReffed;
     bool                            fFrequentResetHint;
     GrTDArray<GrGeometryBuffer*>    fPreallocBuffers;
     size_t                          fMinBlockSize;
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 1db9252..378b881 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -432,7 +432,7 @@
                     const GrPath& path = clip.getPath(c);
                     pathIter.reset(path);
                     pr = this->getClipPathRenderer(&pathIter, NonInvertedFill(fill));
-                    canRenderDirectToStencil = 
+                    canRenderDirectToStencil =
                         !pr->requiresStencilPass(this, &pathIter,
                                                  NonInvertedFill(fill));
                 }
@@ -441,14 +441,14 @@
                 int passes;
                 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
 
-                bool canDrawDirectToClip; // Given the renderer, the element, 
+                bool canDrawDirectToClip; // Given the renderer, the element,
                                           // fill rule, and set operation can
                                           // we render the element directly to
                                           // stencil bit used for clipping.
-                canDrawDirectToClip = 
-                    GrStencilSettings::GetClipPasses(op, 
+                canDrawDirectToClip =
+                    GrStencilSettings::GetClipPasses(op,
                                                      canRenderDirectToStencil,
-                                                     clipBit, 
+                                                     clipBit,
                                                      IsFillInverted(fill),
                                                      &passes, stencilSettings);
 
@@ -469,7 +469,7 @@
                     } else {
                         if (canRenderDirectToStencil) {
                             this->setStencil(gDrawToStencil);
-                            pr->drawPath(this, 0, 
+                            pr->drawPath(this, 0,
                                          &pathIter,
                                          NonInvertedFill(fill),
                                          NULL);
@@ -519,12 +519,12 @@
 
 GrPathRenderer* GrGpu::getClipPathRenderer(GrPathIter* path,
                                            GrPathFill fill) {
-    if (NULL != fClientPathRenderer && 
+    if (NULL != fClientPathRenderer &&
         fClientPathRenderer->canDrawPath(this, path, fill)) {
             return fClientPathRenderer;
     } else {
         if (NULL == fDefaultPathRenderer) {
-            fDefaultPathRenderer = 
+            fDefaultPathRenderer =
                 new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
                                           this->supportsStencilWrapOps());
         }
@@ -603,6 +603,7 @@
         fVertexPool = new GrVertexBufferAllocPool(this, true,
                                                   VERTEX_POOL_VB_SIZE,
                                                   VERTEX_POOL_VB_COUNT);
+        fVertexPool->releaseGpuRef();
     } else if (!fVertexPoolInUse) {
         // the client doesn't have valid data in the pool
         fVertexPool->reset();
@@ -612,6 +613,7 @@
 void GrGpu::prepareIndexPool() {
     if (NULL == fIndexPool) {
         fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
+        fIndexPool->releaseGpuRef();
     } else if (!fIndexPoolInUse) {
         // the client doesn't have valid data in the pool
         fIndexPool->reset();