Add class GrGLTextureRenderTarget for GL texture/rendertarget objects
authorbsalomon <bsalomon@google.com>
Mon, 3 Nov 2014 16:47:23 +0000 (08:47 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 3 Nov 2014 16:47:23 +0000 (08:47 -0800)
BUG=skia:2889

Review URL: https://codereview.chromium.org/695813003

21 files changed:
gyp/gpu.gypi
include/gpu/GrGpuResource.h
include/gpu/GrGpuResourceRef.h
include/gpu/GrRenderTarget.h
include/gpu/GrSurface.h
include/gpu/GrTexture.h
src/effects/SkColorCubeFilter.cpp
src/gpu/GrContext.cpp
src/gpu/GrDrawState.h
src/gpu/GrOptDrawState.h
src/gpu/GrRenderTarget.cpp
src/gpu/GrResourceCache.cpp
src/gpu/GrResourceCache2.h
src/gpu/GrTexture.cpp
src/gpu/gl/GrGLRenderTarget.cpp
src/gpu/gl/GrGLRenderTarget.h
src/gpu/gl/GrGLTexture.cpp
src/gpu/gl/GrGLTexture.h
src/gpu/gl/GrGLTextureRenderTarget.h [new file with mode: 0644]
src/gpu/gl/GrGpuGL.cpp
src/gpu/gl/GrGpuGL.h

index 9db1d7f..e4bd92a 100644 (file)
       '<(skia_src_path)/gpu/gl/GrGLStencilBuffer.h',
       '<(skia_src_path)/gpu/gl/GrGLTexture.cpp',
       '<(skia_src_path)/gpu/gl/GrGLTexture.h',
+      '<(skia_src_path)/gpu/gl/GrGLTextureRenderTarget.h',
       '<(skia_src_path)/gpu/gl/GrGLUtil.cpp',
       '<(skia_src_path)/gpu/gl/GrGLUtil.h',
       '<(skia_src_path)/gpu/gl/GrGLUniformHandle.h',
index 9b298dd..4ffe17e 100644 (file)
 #include "SkInstCnt.h"
 #include "SkTInternalLList.h"
 
-class GrResourceCacheEntry;
-class GrResourceCache2;
-class GrGpu;
 class GrContext;
+class GrGpu;
+class GrResourceCache2;
+class GrResourceCacheEntry;
 
 /**
  * Base class for GrGpuResource. Handles the various types of refs we need. Separated out as a base
index 0223f18..93298f0 100644 (file)
@@ -9,6 +9,8 @@
 #define GrGpuResourceRef_DEFINED
 
 #include "GrGpuResource.h"
+#include "GrRenderTarget.h"
+#include "GrTexture.h"
 #include "SkRefCnt.h"
 
 /**
@@ -96,7 +98,7 @@ public:
 
     /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
         pending on the resource when markPendingIO is called. */
-    GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) {}
+    GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { }
 
     T* get() const { return static_cast<T*>(this->getResource()); }
 
@@ -108,6 +110,49 @@ private:
     typedef GrGpuResourceRef INHERITED;
 };
 
+// Specializations for GrTexture and GrRenderTarget because they use virtual inheritance.
+template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef {
+public:
+    GrTGpuResourceRef() {}
+
+    GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { }
+
+    GrTexture* get() const {
+        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
+        if (surface) {
+            return surface->asTexture();
+        } else {
+            return NULL;
+        }
+    }
+
+    void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); }
+
+private:
+    typedef GrGpuResourceRef INHERITED;
+};
+
+template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef {
+public:
+    GrTGpuResourceRef() {}
+
+    GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { }
+
+    GrRenderTarget* get() const {
+        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
+        if (surface) {
+            return surface->asRenderTarget();
+        } else {
+            return NULL;
+        }
+    }
+
+    void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); }
+
+private:
+    typedef GrGpuResourceRef INHERITED;
+};
+
 /**
  * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a
  * ref.
index b8e30d9..e0f1199 100644 (file)
 #include "SkRect.h"
 
 class GrStencilBuffer;
-class GrTexture;
 
 /**
  * GrRenderTarget represents a 2D buffer of pixels that can be rendered to.
  * A context's render target is set by setRenderTarget(). Render targets are
- * created by a createTexture with the kRenderTarget_TextureFlag flag.
+ * created by a createTexture with the kRenderTarget_SurfaceFlag flag.
  * Additionally, GrContext provides methods for creating GrRenderTargets
  * that wrap externally created render targets.
  */
-class GrRenderTarget : public GrSurface {
+class GrRenderTarget : virtual public GrSurface {
 public:
     SK_DECLARE_INST_COUNT(GrRenderTarget)
 
-    // GrResource overrides
-    virtual size_t gpuMemorySize() const SK_OVERRIDE;
-
     // GrSurface overrides
-    /**
-     * @return the texture associated with the render target, may be NULL.
-     */
-    virtual GrTexture* asTexture() SK_OVERRIDE { return fTexture; }
-    virtual const GrTexture* asTexture() const SK_OVERRIDE { return fTexture; }
-
-    /**
-     * @return this render target.
-     */
     virtual GrRenderTarget* asRenderTarget() SK_OVERRIDE { return this; }
-    virtual const GrRenderTarget* asRenderTarget() const  SK_OVERRIDE {
-        return this;
-    }
+    virtual const GrRenderTarget* asRenderTarget() const  SK_OVERRIDE { return this; }
 
     // GrRenderTarget
     /**
@@ -134,11 +119,9 @@ public:
 protected:
     GrRenderTarget(GrGpu* gpu,
                    bool isWrapped,
-                   GrTexture* texture,
                    const GrSurfaceDesc& desc)
         : INHERITED(gpu, isWrapped, desc)
-        , fStencilBuffer(NULL)
-        , fTexture(texture) {
+        , fStencilBuffer(NULL) {
         fResolveRect.setLargestInverted();
     }
 
@@ -147,15 +130,7 @@ protected:
     virtual void onRelease() SK_OVERRIDE;
 
 private:
-    friend class GrTexture;
-    // called by ~GrTexture to remove the non-ref'ed back ptr.
-    void owningTextureDestroyed() {
-        SkASSERT(fTexture);
-        fTexture = NULL;
-    }
-
     GrStencilBuffer*  fStencilBuffer;
-    GrTexture*        fTexture; // not ref'ed
 
     SkIRect           fResolveRect;
 
index 9a76d3a..9d89149 100644 (file)
@@ -24,15 +24,11 @@ public:
 
     /**
      * Retrieves the width of the surface.
-     *
-     * @return the width in texels
      */
     int width() const { return fDesc.fWidth; }
 
     /**
      * Retrieves the height of the surface.
-     *
-     * @return the height in texels
      */
     int height() const { return fDesc.fHeight; }
 
@@ -63,14 +59,14 @@ public:
     /**
      * @return the texture associated with the surface, may be NULL.
      */
-    virtual GrTexture* asTexture() = 0;
-    virtual const GrTexture* asTexture() const = 0;
+    virtual GrTexture* asTexture() { return NULL; }
+    virtual const GrTexture* asTexture() const { return NULL; }
 
     /**
      * @return the render target underlying this surface, may be NULL.
      */
-    virtual GrRenderTarget* asRenderTarget() = 0;
-    virtual const GrRenderTarget* asRenderTarget() const = 0;
+    virtual GrRenderTarget* asRenderTarget() { return NULL; }
+    virtual const GrRenderTarget* asRenderTarget() const { return NULL; }
 
     /**
      * Reads a rectangle of pixels from the surface.
index 13d5667..87f0d5a 100644 (file)
@@ -10,7 +10,6 @@
 #define GrTexture_DEFINED
 
 #include "GrSurface.h"
-#include "GrRenderTarget.h"
 #include "SkPoint.h"
 #include "SkRefCnt.h"
 
@@ -18,7 +17,7 @@ class GrResourceKey;
 class GrTextureParams;
 class GrTexturePriv;
 
-class GrTexture : public GrSurface {
+class GrTexture : virtual public GrSurface {
 public:
     /**
      *  Approximate number of bytes used by the texture
@@ -27,8 +26,6 @@ public:
 
     virtual GrTexture* asTexture() SK_OVERRIDE { return this; }
     virtual const GrTexture* asTexture() const SK_OVERRIDE { return this; }
-    virtual GrRenderTarget* asRenderTarget() SK_OVERRIDE { return fRenderTarget.get(); }
-    virtual const GrRenderTarget* asRenderTarget() const SK_OVERRIDE { return fRenderTarget.get(); }
 
     /**
      *  Return the native ID or handle to the texture, depending on the
@@ -54,18 +51,8 @@ public:
     inline const GrTexturePriv texturePriv() const;
 
 protected:
-    // A texture refs its rt representation but not vice-versa. It is up to
-    // the subclass constructor to initialize this pointer.
-    SkAutoTUnref<GrRenderTarget> fRenderTarget;
-
     GrTexture(GrGpu* gpu, bool isWrapped, const GrSurfaceDesc& desc);
 
-    virtual ~GrTexture();
-
-    // GrResource overrides
-    virtual void onRelease() SK_OVERRIDE;
-    virtual void onAbandon() SK_OVERRIDE;
-
     void validateDesc() const;
 
 private:
index 2242598..d9d6841 100644 (file)
@@ -356,11 +356,12 @@ GrFragmentProcessor* SkColorCubeFilter::asFragmentProcessor(GrContext* context)
     desc.fHeight = fCache.cubeDimension() * fCache.cubeDimension();
     desc.fConfig = kRGBA_8888_GrPixelConfig;
 
-    SkAutoTUnref<GrTexture> textureCube(
-        static_cast<GrTexture*>(context->findAndRefCachedResource(
-            GrTexturePriv::ComputeKey(context->getGpu(), NULL, desc, cacheID))));
-
-    if (!textureCube) {
+    GrResourceKey rkey = GrTexturePriv::ComputeKey(context->getGpu(), NULL, desc, cacheID);
+    GrSurface* surface = static_cast<GrSurface*>(context->findAndRefCachedResource(rkey));
+    SkAutoTUnref<GrTexture> textureCube;
+    if (surface) {
+        textureCube.reset(surface->asTexture());
+    } else {
         textureCube.reset(context->createTexture(NULL, desc, cacheID, fCubeData->data(), 0));
     }
 
index 5f0001b..c1fee0a 100755 (executable)
@@ -255,8 +255,12 @@ GrTexture* GrContext::findAndRefTexture(const GrSurfaceDesc& desc,
                                         const GrTextureParams* params) {
     GrResourceKey resourceKey = GrTexturePriv::ComputeKey(fGpu, params, desc, cacheID);
     GrGpuResource* resource = fResourceCache->find(resourceKey);
-    SkSafeRef(resource);
-    return static_cast<GrTexture*>(resource);
+    if (resource) {
+        resource->ref();
+        return static_cast<GrSurface*>(resource)->asTexture();
+    } else {
+        return NULL;
+    }
 }
 
 bool GrContext::isTextureInCache(const GrSurfaceDesc& desc,
@@ -471,7 +475,7 @@ GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexM
             GrGpuResource* resource = fResourceCache2->findAndRefScratchResource(key, scratchFlags);
             if (resource) {
                 fResourceCache->makeResourceMRU(resource);
-                return static_cast<GrTexture*>(resource);
+                return static_cast<GrSurface*>(resource)->asTexture();
             }
 
             if (kExact_ScratchTexMatch == match) {
index 39c9102..97516e8 100644 (file)
@@ -530,9 +530,7 @@ public:
      *
      * @return    The currently set render target.
      */
-    GrRenderTarget* getRenderTarget() const {
-        return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
-    }
+    GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
 
     /**
      * Sets the render-target used at the next drawing call
index f495b89..c32294b 100644 (file)
@@ -169,9 +169,7 @@ public:
      *
      * @return    The currently set render target.
      */
-    GrRenderTarget* getRenderTarget() const {
-        return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
-    }
+    GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
 
     /// @}
 
index 7ed70c9..7aeb4ee 100644 (file)
@@ -31,20 +31,6 @@ void GrRenderTarget::discard() {
     context->discardRenderTarget(this);
 }
 
-size_t GrRenderTarget::gpuMemorySize() const {
-    size_t colorBits;
-    if (kUnknown_GrPixelConfig == fDesc.fConfig) {
-        colorBits = 32; // don't know, make a guess
-    } else {
-        colorBits = GrBytesPerPixel(fDesc.fConfig) * 8;
-    }
-    uint64_t size = fDesc.fWidth;
-    size *= fDesc.fHeight;
-    size *= colorBits;
-    size *= SkTMax(1, fDesc.fSampleCnt);
-    return (size_t)(size / 8);
-}
-
 void GrRenderTarget::flagAsNeedingResolve(const SkIRect* rect) {
     if (kCanResolve_ResolveType == getResolveType()) {
         if (rect) {
index 0431a27..9754d44 100644 (file)
@@ -180,8 +180,7 @@ void GrResourceCache::notifyPurgable(const GrGpuResource* resource) {
     if (resource->getCacheEntry()->key().getResourceType() == GrTexturePriv::ResourceType() &&
         resource->getCacheEntry()->key().isScratch() &&
         !fCaps->reuseScratchTextures() &&
-        !(static_cast<const GrTexture*>(resource)->desc().fFlags &
-          kRenderTarget_GrSurfaceFlag)) {
+        !(static_cast<const GrSurface*>(resource)->desc().fFlags & kRenderTarget_GrSurfaceFlag)) {
         this->deleteResource(resource->getCacheEntry());
     }
 }
index e10b45a..a365a5a 100644 (file)
@@ -42,9 +42,7 @@ public:
 
 private:
 #ifdef SK_DEBUG
-    bool isInCache(const GrGpuResource* r) const {
-        return fResources.isInList(r);
-    }
+    bool isInCache(const GrGpuResource* r) const { return fResources.isInList(r); }
 #endif
 
     class AvailableForScratchUse;
index 2717b31..2139540 100644 (file)
@@ -6,21 +6,13 @@
  * found in the LICENSE file.
  */
 
-
 #include "GrContext.h"
 #include "GrDrawTargetCaps.h"
 #include "GrGpu.h"
-#include "GrRenderTarget.h"
 #include "GrResourceCache.h"
 #include "GrTexture.h"
 #include "GrTexturePriv.h"
 
-GrTexture::~GrTexture() {
-    if (fRenderTarget.get()) {
-        fRenderTarget.get()->owningTextureDestroyed();
-    }
-}
-
 void GrTexture::dirtyMipMaps(bool mipMapsDirty) {
     if (mipMapsDirty) {
         if (kValid_MipMapsStatus == fMipMapsStatus) {
@@ -53,18 +45,6 @@ size_t GrTexture::gpuMemorySize() const {
     return textureSize;
 }
 
-void GrTexture::onRelease() {
-
-    INHERITED::onRelease();
-}
-
-void GrTexture::onAbandon() {
-    if (fRenderTarget.get()) {
-        fRenderTarget->abandon();
-    }
-    INHERITED::onAbandon();
-}
-
 void GrTexture::validateDesc() const {
     if (this->asRenderTarget()) {
         // This texture has a render target
@@ -140,7 +120,6 @@ GrSurfaceOrigin resolve_origin(const GrSurfaceDesc& desc) {
 //////////////////////////////////////////////////////////////////////////////
 GrTexture::GrTexture(GrGpu* gpu, bool isWrapped, const GrSurfaceDesc& desc)
     : INHERITED(gpu, isWrapped, desc)
-    , fRenderTarget(NULL)
     , fMipMapsStatus(kNotAllocated_MipMapsStatus) {
     this->setScratchKey(GrTexturePriv::ComputeScratchKey(desc));
     // only make sense if alloc size is pow2
index 0e8bd05..8482ecd 100644 (file)
@@ -9,47 +9,48 @@
 
 #include "GrGpuGL.h"
 
-#define GPUGL static_cast<GrGpuGL*>(getGpu())
-
+#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
 
-void GrGLRenderTarget::init(const GrSurfaceDesc& desc,
-                            const IDDesc& idDesc,
-                            const GrGLIRect& viewport,
-                            GrGLTexID* texID) {
-    fRTFBOID                = idDesc.fRTFBOID;
-    fTexFBOID               = idDesc.fTexFBOID;
-    fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
-    fViewport               = viewport;
-    fTexIDObj.reset(SkSafeRef(texID));
+// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
+GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
+    : GrSurface(gpu, idDesc.fIsWrapped, desc)
+    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    this->init(desc, idDesc);
     this->registerWithCache();
 }
 
-GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu,
-                                   const IDDesc& idDesc,
-                                   const GrGLIRect& viewport,
-                                   GrGLTexID* texID,
-                                   GrGLTexture* texture)
-    : INHERITED(gpu, idDesc.fIsWrapped, texture, texture->desc()) {
-    SkASSERT(texID);
-    SkASSERT(texture);
-    // FBO 0 can't also be a texture, right?
-    SkASSERT(0 != idDesc.fRTFBOID);
-    SkASSERT(0 != idDesc.fTexFBOID);
+GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
+                                   Derived)
+    : GrSurface(gpu, idDesc.fIsWrapped, desc)
+    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    this->init(desc, idDesc);
+}
+
+void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
+    fRTFBOID                = idDesc.fRTFBOID;
+    fTexFBOID               = idDesc.fTexFBOID;
+    fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
 
-    // we assume this is true, TODO: get rid of viewport as a param.
-    SkASSERT(viewport.fWidth == texture->width());
-    SkASSERT(viewport.fHeight == texture->height());
+    fViewport.fLeft   = 0;
+    fViewport.fBottom = 0;
+    fViewport.fWidth  = desc.fWidth;
+    fViewport.fHeight = desc.fHeight;
 
-    this->init(texture->desc(), idDesc, viewport, texID);
+    // We own one color value for each MSAA sample.
+    fColorValuesPerPixel = SkTMax(1, fDesc.fSampleCnt);
+    if (fTexFBOID != fRTFBOID) {
+        // If we own the resolve buffer then that is one more sample per pixel.
+        fColorValuesPerPixel += 1;
+    } 
 }
 
-GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu,
-                                   const GrSurfaceDesc& desc,
-                                   const IDDesc& idDesc,
-                                   const GrGLIRect& viewport)
-    : INHERITED(gpu, idDesc.fIsWrapped, NULL, desc) {
-    this->init(desc, idDesc, viewport, NULL);
+size_t GrGLRenderTarget::gpuMemorySize() const {
+    SkASSERT(kUnknown_GrPixelConfig != fDesc.fConfig);
+    SkASSERT(!GrPixelConfigIsCompressed(fDesc.fConfig));
+    size_t colorBytes = GrBytesPerPixel(fDesc.fConfig);
+    SkASSERT(colorBytes > 0);
+    return fColorValuesPerPixel * fDesc.fWidth * fDesc.fHeight * colorBytes;
 }
 
 void GrGLRenderTarget::onRelease() {
@@ -67,7 +68,6 @@ void GrGLRenderTarget::onRelease() {
     fRTFBOID                = 0;
     fTexFBOID               = 0;
     fMSColorRenderbufferID  = 0;
-    fTexIDObj.reset(NULL);
     INHERITED::onRelease();
 }
 
@@ -75,9 +75,5 @@ void GrGLRenderTarget::onAbandon() {
     fRTFBOID                = 0;
     fTexFBOID               = 0;
     fMSColorRenderbufferID  = 0;
-    if (fTexIDObj.get()) {
-        fTexIDObj->abandon();
-        fTexIDObj.reset(NULL);
-    }
     INHERITED::onAbandon();
 }
index 116862b..0f04160 100644 (file)
 #include "SkScalar.h"
 
 class GrGpuGL;
-class GrGLTexture;
-class GrGLTexID;
 
 class GrGLRenderTarget : public GrRenderTarget {
-
 public:
     // set fTexFBOID to this value to indicate that it is multisampled but
     // Gr doesn't know how to resolve it.
@@ -31,12 +28,7 @@ public:
         bool             fIsWrapped;
     };
 
-    // creates a GrGLRenderTarget associated with a texture
-    GrGLRenderTarget(GrGpuGL*, const IDDesc&, const GrGLIRect& viewport,
-                     GrGLTexID*, GrGLTexture*);
-
-    // creates an independent GrGLRenderTarget
-    GrGLRenderTarget(GrGpuGL*, const GrSurfaceDesc&, const IDDesc&, const GrGLIRect& viewport);
+    GrGLRenderTarget(GrGpuGL*, const GrSurfaceDesc&, const IDDesc&);
 
     virtual ~GrGLRenderTarget() { this->release(); }
 
@@ -52,14 +44,9 @@ public:
     GrGLuint textureFBOID() const { return fTexFBOID; }
 
     // override of GrRenderTarget
-    virtual GrBackendObject getRenderTargetHandle() const {
-        return this->renderFBOID();
-    }
-    virtual GrBackendObject getRenderTargetResolvedHandle() const {
-        return this->textureFBOID();
-    }
+    virtual GrBackendObject getRenderTargetHandle() const { return this->renderFBOID(); }
+    virtual GrBackendObject getRenderTargetResolvedHandle() const { return this->textureFBOID(); }
     virtual ResolveType getResolveType() const {
-
         if (!this->isMultisampled() ||
             fRTFBOID == fTexFBOID) {
             // catches FBO 0 and non MSAA case
@@ -71,26 +58,34 @@ public:
         }
     }
 
+    virtual size_t gpuMemorySize() const SK_OVERRIDE;
+
 protected:
-    // override of GrResource
+    // The public constructor registers this object with the cache. However, only the most derived
+    // class should register with the cache. This constructor does not do the registration and
+    // rather moves that burden onto the derived class.
+    enum Derived { kDerived };
+    GrGLRenderTarget(GrGpuGL*, const GrSurfaceDesc&, const IDDesc&, Derived);
+
+    void init(const GrSurfaceDesc&, const IDDesc&);
+
     virtual void onAbandon() SK_OVERRIDE;
     virtual void onRelease() SK_OVERRIDE;
 
 private:
     GrGLuint      fRTFBOID;
     GrGLuint      fTexFBOID;
-
     GrGLuint      fMSColorRenderbufferID;
 
     // when we switch to this render target we want to set the viewport to
-    // only render to to content area (as opposed to the whole allocation) and
+    // only render 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.
-    SkAutoTUnref<GrGLTexID> fTexIDObj;
-
-    void init(const GrSurfaceDesc&, const IDDesc&, const GrGLIRect& viewport, GrGLTexID*);
+    // gpuMemorySize() needs to know what how many color values are owned per pixel. However,
+    // abandon and release zero out the IDs and the cache needs to know the size even after those
+    // actions.
+    uint8_t fColorValuesPerPixel;
 
     typedef GrRenderTarget INHERITED;
 };
index 8cf574b..d9db6ea 100644 (file)
@@ -8,46 +8,30 @@
 #include "GrGLTexture.h"
 #include "GrGpuGL.h"
 
-#define GPUGL static_cast<GrGpuGL*>(getGpu())
-
+#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
 
-void GrGLTexture::init(GrGpuGL* gpu,
-                       const GrSurfaceDesc& desc,
-                       const IDDesc& idDesc,
-                       const GrGLRenderTarget::IDDesc* rtIDDesc) {
+// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
+GrGLTexture::GrGLTexture(GrGpuGL* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
+    : GrSurface(gpu, idDesc.fIsWrapped, desc)
+    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    this->init(desc, idDesc);
+    this->registerWithCache();
+}
+
+GrGLTexture::GrGLTexture(GrGpuGL* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc, Derived)
+    : GrSurface(gpu, idDesc.fIsWrapped, desc)
+    , INHERITED(gpu, idDesc.fIsWrapped, desc) {
+    this->init(desc, idDesc);
+}
 
+void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
     SkASSERT(0 != idDesc.fTextureID);
-
     fTexParams.invalidate();
     fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
     fTexIDObj.reset(SkNEW_ARGS(GrGLTexID, (GPUGL->glInterface(),
                                            idDesc.fTextureID,
                                            idDesc.fIsWrapped)));
-
-    if (rtIDDesc) {
-        GrGLIRect vp;
-        vp.fLeft   = 0;
-        vp.fWidth  = desc.fWidth;
-        vp.fBottom = 0;
-        vp.fHeight = desc.fHeight;
-
-        fRenderTarget.reset(SkNEW_ARGS(GrGLRenderTarget, (gpu, *rtIDDesc, vp, fTexIDObj, this)));
-    }
-    this->registerWithCache();
-}
-
-GrGLTexture::GrGLTexture(GrGpuGL* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
-    : INHERITED(gpu, idDesc.fIsWrapped, desc) {
-    this->init(gpu, desc, idDesc, NULL);
-}
-
-GrGLTexture::GrGLTexture(GrGpuGL* gpu,
-                         const GrSurfaceDesc& desc,
-                         const IDDesc& idDesc,
-                         const GrGLRenderTarget::IDDesc& rtIDDesc)
-    : INHERITED(gpu, idDesc.fIsWrapped, desc) {
-    this->init(gpu, desc, idDesc, &rtIDDesc);
 }
 
 void GrGLTexture::onRelease() {
index 11d6353..5c64eaf 100644 (file)
@@ -10,7 +10,8 @@
 #define GrGLTexture_DEFINED
 
 #include "GrGpu.h"
-#include "GrGLRenderTarget.h"
+#include "GrTexture.h"
+#include "GrGLUtil.h"
 
 /**
  * A ref counted tex id that deletes the texture in its destructor.
@@ -62,11 +63,7 @@ public:
         bool            fIsWrapped;
     };
 
-    // creates a texture that is also an RT
-    GrGLTexture(GrGpuGL* gpu, const GrSurfaceDesc&, const IDDesc&, const GrGLRenderTarget::IDDesc&);
-
-    // creates a non-RT texture
-    GrGLTexture(GrGpuGL* gpu, const GrSurfaceDesc&, const IDDesc&);
+    GrGLTexture(GrGpuGL*, const GrSurfaceDesc&, const IDDesc&);
 
     virtual ~GrGLTexture() { this->release(); }
 
@@ -89,7 +86,14 @@ public:
     GrGLuint textureID() const { return (fTexIDObj.get()) ? fTexIDObj->id() : 0; }
 
 protected:
-    // overrides of GrTexture
+    // The public constructor registers this object with the cache. However, only the most derived
+    // class should register with the cache. This constructor does not do the registration and
+    // rather moves that burden onto the derived class.
+    enum Derived { kDerived };
+    GrGLTexture(GrGpuGL*, const GrSurfaceDesc&, const IDDesc&, Derived);
+
+    void init(const GrSurfaceDesc&, const IDDesc&);
+
     virtual void onAbandon() SK_OVERRIDE;
     virtual void onRelease() SK_OVERRIDE;
 
@@ -98,8 +102,6 @@ private:
     GrGpu::ResetTimestamp           fTexParamsTimestamp;
     SkAutoTUnref<GrGLTexID>         fTexIDObj;
 
-    void init(GrGpuGL* gpu, const GrSurfaceDesc&, const IDDesc&, const GrGLRenderTarget::IDDesc*);
-
     typedef GrTexture INHERITED;
 };
 
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.h b/src/gpu/gl/GrGLTextureRenderTarget.h
new file mode 100644 (file)
index 0000000..55da28f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrGLTextureRenderTarget_DEFINED
+#define GrGLTextureRenderTarget_DEFINED
+
+#include "GrGLTexture.h"
+#include "GrGLRenderTarget.h"
+
+class GrGpuGL;
+
+#ifdef SK_BUILD_FOR_WIN
+// Windows gives bogus warnings about inheriting asTexture/asRenderTarget via dominance.
+#pragma warning(push)
+#pragma warning(disable: 4250)
+#endif
+
+class GrGLTextureRenderTarget : public GrGLTexture, public GrGLRenderTarget {
+public:
+    // We're virtually derived from GrSurface (via both GrGLTexture and GrGLRenderTarget) so its
+    // constructor must be explicitly called.
+    GrGLTextureRenderTarget(GrGpuGL* gpu,
+                            const GrSurfaceDesc& desc,
+                            const GrGLTexture::IDDesc& texIDDesc,
+                            const GrGLRenderTarget::IDDesc& rtIDDesc)
+        : GrSurface(gpu, texIDDesc.fIsWrapped, desc)
+        , GrGLTexture(gpu, desc, texIDDesc, GrGLTexture::kDerived)
+        , GrGLRenderTarget(gpu, desc, rtIDDesc, GrGLRenderTarget::kDerived) {
+       this->registerWithCache();
+    }
+
+    virtual ~GrGLTextureRenderTarget() { this->release(); }
+
+    // GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory. 
+    virtual size_t gpuMemorySize() const SK_OVERRIDE { return GrGLRenderTarget::gpuMemorySize(); }
+
+protected:
+    virtual void onAbandon() SK_OVERRIDE {
+        GrGLRenderTarget::onAbandon();
+        GrGLTexture::onAbandon();
+    }
+
+    virtual void onRelease() SK_OVERRIDE {
+        GrGLRenderTarget::onRelease();
+        GrGLTexture::onRelease();
+    }
+};
+
+#ifdef SK_BUILD_FOR_WIN
+#pragma warning(pop)
+#endif
+
+#endif
index 9d08f64..6c35e9f 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "GrGpuGL.h"
 #include "GrGLStencilBuffer.h"
+#include "GrGLTextureRenderTarget.h"
 #include "GrOptDrawState.h"
 #include "GrSurfacePriv.h"
 #include "GrTemplates.h"
@@ -403,7 +404,7 @@ GrTexture* GrGpuGL::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
         if (!this->createRenderTargetObjects(surfDesc, idDesc.fTextureID, &rtIDDesc)) {
             return NULL;
         }
-        texture = SkNEW_ARGS(GrGLTexture, (this, surfDesc, idDesc, rtIDDesc));
+        texture = SkNEW_ARGS(GrGLTextureRenderTarget, (this, surfDesc, idDesc, rtIDDesc));
     } else {
         texture = SkNEW_ARGS(GrGLTexture, (this, surfDesc, idDesc));
     }
@@ -428,13 +429,7 @@ GrRenderTarget* GrGpuGL::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
     desc.fSampleCnt = wrapDesc.fSampleCnt;
     desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true);
 
-    GrGLIRect viewport;
-    viewport.fLeft   = 0;
-    viewport.fBottom = 0;
-    viewport.fWidth  = desc.fWidth;
-    viewport.fHeight = desc.fHeight;
-
-    GrRenderTarget* tgt = SkNEW_ARGS(GrGLRenderTarget, (this, desc, idDesc, viewport));
+    GrRenderTarget* tgt = SkNEW_ARGS(GrGLRenderTarget, (this, desc, idDesc));
     if (wrapDesc.fStencilBits) {
         GrGLStencilBuffer::Format format;
         format.fInternalFormat = GrGLStencilBuffer::kUnknownInternalFormat;
@@ -1022,7 +1017,7 @@ GrTexture* GrGpuGL::onCreateTexture(const GrSurfaceDesc& origDesc,
             GL_CALL(DeleteTextures(1, &idDesc.fTextureID));
             return return_null_texture();
         }
-        tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc, rtIDDesc));
+        tex = SkNEW_ARGS(GrGLTextureRenderTarget, (this, desc, idDesc, rtIDDesc));
     } else {
         tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc));
     }
@@ -1193,7 +1188,7 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
 }
 
 bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget* rt) {
-    GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt;
+    GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
 
     GrGLuint fbo = glrt->renderFBOID();
 
@@ -1575,8 +1570,7 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
         case GrGLRenderTarget::kCantResolve_ResolveType:
             return false;
         case GrGLRenderTarget::kAutoResolves_ResolveType:
-            this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target),
-                                    &SkIRect::EmptyIRect());
+            this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect());
             break;
         case GrGLRenderTarget::kCanResolve_ResolveType:
             this->onResolveRenderTarget(tgt);
@@ -1989,7 +1983,7 @@ void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
     // If we created a rt/tex and rendered to it without using a texture and now we're texturing
     // from the rt it will still be the last bound texture, but it needs resolving. So keep this
     // out of the "last != next" check.
-    GrGLRenderTarget* texRT =  static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
+    GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
     if (texRT) {
         this->onResolveRenderTarget(texRT);
     }
index 1a03c13..e7266f3 100644 (file)
@@ -14,6 +14,7 @@
 #include "GrGLIndexBuffer.h"
 #include "GrGLPathRendering.h"
 #include "GrGLProgram.h"
+#include "GrGLRenderTarget.h"
 #include "GrGLStencilBuffer.h"
 #include "GrGLTexture.h"
 #include "GrGLVertexArray.h"