Delete GL tex ID when last of GrGLTexture or GrGLRenderTarget that reference it is...
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 10 Mar 2011 14:51:57 +0000 (14:51 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 10 Mar 2011 14:51:57 +0000 (14:51 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@915 2bbb7eff-a529-9590-31e7-b0007b416f81

gpu/include/GrGLTexture.h
gpu/include/GrGpu.h
gpu/include/GrInOrderDrawBuffer.h
gpu/include/GrTexture.h
gpu/src/GrContext.cpp
gpu/src/GrGLTexture.cpp
gpu/src/GrGpuGL.cpp
gpu/src/GrGpuGL.h
gpu/src/GrInOrderDrawBuffer.cpp
src/gpu/SkGpuDevice.cpp

index 14370ab..7b7480c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
 class GrGpuGL;
 class GrGLTexture;
 
+/**
+ * A ref counted tex id that deletes the texture in its destructor.
+ */
+class GrGLTexID : public GrRefCnt {
+public:
+    GrGLTexID(GLuint texID) : fTexID(texID) {}
+
+    virtual ~GrGLTexID() {
+        if (0 != fTexID) {
+            GR_GL(DeleteTextures(1, &fTexID));
+        }
+    }
+
+    void abandon() { fTexID = 0; }
+    GLuint id() const { return fTexID; }
+
+private:
+    GLuint      fTexID;
+};
+
 class GrGLRenderTarget : public GrRenderTarget {
 public:
     virtual ~GrGLRenderTarget();
@@ -49,6 +69,7 @@ protected:
     };
     
     GrGLRenderTarget(const GLRenderTargetIDs& ids,
+                     GrGLTexID* texID,
                      GLuint stencilBits,
                      const GrGLIRect& fViewport,
                      GrGLTexture* texture,
@@ -59,7 +80,7 @@ protected:
 private:
     GrGpuGL*    fGL;
     GLuint      fRTFBOID;
-    GLuint      fTexFBOID;    
+    GLuint      fTexFBOID;
     GLuint      fStencilRenderbufferID;
     GLuint      fMSColorRenderbufferID;
    
@@ -75,7 +96,10 @@ private:
     // only render to to content area (as opposed to the whole allocation) and
     // we want the rendering to be at top left (GL has origin in bottom left) 
     GrGLIRect fViewport;
-    
+
+    // non-NULL if this RT was created by Gr with an associated GrGLTexture.
+    GrGLTexID* fTexIDObj;
+
     friend class GrGpuGL;
     friend class GrGLTexture;
     
@@ -120,9 +144,8 @@ public:
     
     // overloads of GrTexture
     virtual void abandon();
-    virtual bool isRenderTarget() const;
     virtual GrRenderTarget* asRenderTarget();
-    virtual void removeRenderTarget();
+    virtual void releaseRenderTarget();
     virtual void uploadTextureData(uint32_t x,
                                    uint32_t y,
                                    uint32_t width,
@@ -132,7 +155,7 @@ public:
 
     const TexParams& getTexParams() const { return fTexParams; }
     void setTexParams(const TexParams& texParams) { fTexParams = texParams; }
-    GLuint textureID() const { return fTextureID; }
+    GLuint textureID() const { return fTexIDObj->id(); }
 
     GLenum uploadFormat() const { return fUploadFormat; }
     GLenum uploadByteCount() const { return fUploadByteCount; }
@@ -174,7 +197,7 @@ public:
 
 private:
     TexParams           fTexParams;
-    GLuint              fTextureID;
+    GrGLTexID*          fTexIDObj;
     GLenum              fUploadFormat;
     GLenum              fUploadByteCount;
     GLenum              fUploadType;
index 16fbb93..75fb1f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -156,6 +156,11 @@ public:
      * will be embedded in a power of two texture. The extra width and height
      * is filled as though srcData were rendered clamped into the texture.
      *
+     * If kRenderTarget_TextureFlag is specified the GrRenderTarget is 
+     * accessible via GrTexture::asRenderTarget(). The texture will hold a ref
+     * on the render target until its releaseRenderTarget() is called or it is
+     * destroyed.
+     *
      * @param desc        describes the texture to be created.
      * @param srcData     texel data to load texture. Begins with full-size
      *                    palette data for paletted textures. Contains width*
index d59eb96..79ec458 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -134,11 +134,6 @@ private:
     void pushClip();
 
     GrTAllocator<Draw>              fDraws;
-    // HACK: We currently do not hold refs on RTs in the saved draw states.
-    // The reason is that in the GL implementation when a GrTexture is destroyed
-    // that has an associated RT the RT is destroyed regardless of its ref count.
-    // We need a third object that holds the shared GL ids and persists until
-    // both reach ref count 0. (skia issue 122)
     GrTAllocator<SavedDrawState>    fStates;
 
     GrTAllocator<GrClip>            fClips;
index 2d3928c..666aa57 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -161,31 +161,20 @@ public:
     virtual void abandon() = 0;
 
     /**
-     * Queries whether the texture was created as a render target.
-     *
-     * Use asRenderTarget() to use the texture as a render target if this
-     * returns true.
-     *
-     * @return true if the texture was created as a render target.
-     */
-    virtual bool isRenderTarget() const = 0;
-
-    /**
      * Retrieves the render target underlying this texture that can be passed to
      * GrGpu::setRenderTarget().
      *
-     * If isRenderTarget() is false then the returned handle is undefined.
-     *
      * @return    handle to render target or undefined if the texture is not a
      *            render target
      */
     virtual GrRenderTarget* asRenderTarget() = 0;
 
     /**
-     * Removes the "rendertargetness" from a texture. This may or may not
-     * actually do anything with the underlying 3D API.
+     * Removes the reference on the associated GrRenderTarget held by this
+     * texture. Afterwards asRenderTarget() will return NULL. The 
+     * GrRenderTarget survives the release if another ref is held on it.
      */
-    virtual void removeRenderTarget() = 0;
+    virtual void releaseRenderTarget() = 0;
 
     /**
      *  Return the native ID or handle to the texture, depending on the
index c6fa618..cf51cc9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -172,7 +172,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
                                      0, 4);
                 entry = fTextureCache->createAndLock(*key, texture);
             }
-            texture->removeRenderTarget();
+            texture->releaseRenderTarget();
         } else {
             // TODO: Our CPU stretch doesn't filter. But we create separate
             // stretched textures when the sampler state is either filtered or
index ae991e8..1acb871 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 #include "GrGpuGL.h"
 
 GrGLRenderTarget::GrGLRenderTarget(const GLRenderTargetIDs& ids,
+                                   GrGLTexID* texID,
                                    GLuint stencilBits,
                                    const GrGLIRect& viewport,
                                    GrGLTexture* texture,
@@ -34,6 +35,8 @@ GrGLRenderTarget::GrGLRenderTarget(const GLRenderTargetIDs& ids,
     fNeedsResolve           = false;
     fViewport               = viewport;
     fOwnIDs                 = ids.fOwnIDs;
+    fTexIDObj               = texID;
+    GrSafeRef(fTexIDObj);
 }
 
 GrGLRenderTarget::~GrGLRenderTarget() {
@@ -52,6 +55,7 @@ GrGLRenderTarget::~GrGLRenderTarget() {
             GR_GLEXT(fGL->extensions(), DeleteRenderbuffers(1, &fMSColorRenderbufferID));
         }
     }
+    GrSafeUnref(fTexIDObj);
 }
 
 void GrGLRenderTarget::abandon() {
@@ -59,6 +63,9 @@ void GrGLRenderTarget::abandon() {
     fTexFBOID               = 0;
     fStencilRenderbufferID  = 0;
     fMSColorRenderbufferID  = 0;
+    if (NULL != fTexIDObj) {
+        fTexIDObj->abandon();
+    }
 }
 
 
@@ -84,7 +91,7 @@ GrGLTexture::GrGLTexture(const GLTextureDesc& textureDesc,
                     textureDesc.fFormat) {
 
     fTexParams          = initialTexParams;
-    fTextureID          = textureDesc.fTextureID;
+    fTexIDObj           = new GrGLTexID(textureDesc.fTextureID);
     fUploadFormat       = textureDesc.fUploadFormat;
     fUploadByteCount    = textureDesc.fUploadByteCount;
     fUploadType         = textureDesc.fUploadType;
@@ -108,43 +115,32 @@ GrGLTexture::GrGLTexture(const GLTextureDesc& textureDesc,
         vp.fHeight = textureDesc.fContentHeight;
         vp.fBottom = textureDesc.fAllocHeight - textureDesc.fContentHeight;
 
-        fRenderTarget = new GrGLRenderTarget(rtIDs, textureDesc.fStencilBits, 
+        fRenderTarget = new GrGLRenderTarget(rtIDs, fTexIDObj,
+                                             textureDesc.fStencilBits,
                                              vp, this, gl);
     }
 }
 
 GrGLTexture::~GrGLTexture() {
-    // make sure we haven't been abandoned
-    if (fTextureID) {
-        fGpuGL->notifyTextureDelete(this);
-        GR_GL(DeleteTextures(1, &fTextureID));
-    }
-    delete fRenderTarget;
+    fGpuGL->notifyTextureDelete(this);
+    fTexIDObj->unref();
+    GrSafeUnref(fRenderTarget);
 }
 
 void GrGLTexture::abandon() {
-    fTextureID = 0;
+    fTexIDObj->abandon();
     if (NULL != fRenderTarget) {
         fRenderTarget->abandon();
     }
 }
 
-bool GrGLTexture::isRenderTarget() const {
-    return NULL != fRenderTarget;
-}
-
 GrRenderTarget* GrGLTexture::asRenderTarget() {
     return (GrRenderTarget*)fRenderTarget;
 }
 
-void GrGLTexture::removeRenderTarget() {
-    GrAssert(NULL != fRenderTarget);
-    if (NULL != fRenderTarget) {
-        // must do this notify before the delete
-        fGpuGL->notifyTextureRemoveRenderTarget(this);
-        delete fRenderTarget;
-        fRenderTarget = NULL;
-    }
+void GrGLTexture::releaseRenderTarget() {
+    GrSafeUnref(fRenderTarget);
+    fRenderTarget = NULL;
 }
 
 void GrGLTexture::uploadTextureData(uint32_t x,
@@ -162,7 +158,7 @@ void GrGLTexture::uploadTextureData(uint32_t x,
     // If we need to update textures that are created upside down
     // then we have to modify this code to flip the srcData
     GrAssert(kTopDown_Orientation == fOrientation);
-    GR_GL(BindTexture(GL_TEXTURE_2D, fTextureID));
+    GR_GL(BindTexture(GL_TEXTURE_2D, fTexIDObj->id()));
     GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, fUploadByteCount));
     GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, 
                         fUploadFormat, fUploadType, srcData));
@@ -170,7 +166,7 @@ void GrGLTexture::uploadTextureData(uint32_t x,
 }
 
 intptr_t GrGLTexture::getTextureHandle() {
-    return fTextureID;
+    return fTexIDObj->id();
 }
 
 
index b0d5e73..1c3de1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -510,7 +510,7 @@ GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper(
     rtIDs.fRTFBOID  = (GLuint)platformRenderTarget;
     rtIDs.fTexFBOID = (GLuint)platformRenderTarget;
 
-    return new GrGLRenderTarget(rtIDs, stencilBits, viewport, NULL, this);
+    return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this);
 }
 
 GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
@@ -529,7 +529,7 @@ GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() {
 
     rtIDs.fOwnIDs = false;
 
-    return new GrGLRenderTarget(rtIDs, stencilBits, viewport, NULL, this);
+    return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1694,11 +1694,6 @@ void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
 
 void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
     GrAssert(NULL != renderTarget);
-
-    // if the bound FBO is destroyed we can't rely on the implicit bind to 0
-    // a) we want the default RT which may not be FBO 0
-    // b) we set more state than just FBO based on the RT
-    // So trash the HW state to force an RT flush next time
     if (fCurrDrawState.fRenderTarget == renderTarget) {
         fCurrDrawState.fRenderTarget = NULL;
     }
@@ -1719,13 +1714,6 @@ void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
     }
 }
 
-void GrGpuGL::notifyTextureRemoveRenderTarget(GrGLTexture* texture) {
-    GrAssert(NULL != texture->asRenderTarget());
-
-    // if there is a pending resolve, perform it.
-    resolveTextureRenderTarget(texture);
-}
-
 bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config,
                            GLenum* internalFormat,
                            GLenum* format,
index ab504ad..f9a6987 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -151,7 +151,6 @@ private:
     void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer);
     void notifyTextureDelete(GrGLTexture* texture);
     void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
-    void notifyTextureRemoveRenderTarget(GrGLTexture* texture);
 
     void setSpareTextureUnit();
 
index b2fe581..8225425 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -291,12 +291,11 @@ void GrInOrderDrawBuffer::reset() {
     GrAssert(!fReservedGeometry.fLocked);
     uint32_t numStates = fStates.count();
     for (uint32_t i = 0; i < numStates; ++i) {
+        const DrState& dstate = this->accessSavedDrawState(fStates[i]);
         for (int s = 0; s < kNumStages; ++s) {
-            GrTexture* tex = this->accessSavedDrawState(fStates[i]).fTextures[s];
-            if (NULL != tex) {
-                tex->unref();
-            }
+            GrSafeUnref(dstate.fTextures[s]);
         }
+        GrSafeUnref(dstate.fRenderTarget);
     }
     int numDraws = fDraws.count();
     for (int d = 0; d < numDraws; ++d) {
@@ -499,6 +498,7 @@ void GrInOrderDrawBuffer::pushState() {
     for (int s = 0; s < kNumStages; ++s) {
         GrSafeRef(fCurrDrawState.fTextures[s]);
     }
+    GrSafeRef(fCurrDrawState.fRenderTarget);
     this->saveCurrentDrawState(&fStates.push_back());
  }
 
index 86082c5..91a6319 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -142,7 +142,7 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
                        &fTexture, true);
         if (fCache) {
             SkASSERT(NULL != fTexture);
-            SkASSERT(fTexture->isRenderTarget());
+            SkASSERT(NULL != fTexture->asRenderTarget());
         }
 #else
         const GrGpu::TextureDesc desc = {