Add class GrGLTextureRenderTarget for GL texture/rendertarget objects
BUG=skia:2889
Review URL: https://codereview.chromium.org/695813003
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 9db1d7f..e4bd92a 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -247,6 +247,7 @@
'<(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',
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
index 9b298dd..4ffe17e 100644
--- a/include/gpu/GrGpuResource.h
+++ b/include/gpu/GrGpuResource.h
@@ -13,10 +13,10 @@
#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
diff --git a/include/gpu/GrGpuResourceRef.h b/include/gpu/GrGpuResourceRef.h
index 0223f18..93298f0 100644
--- a/include/gpu/GrGpuResourceRef.h
+++ b/include/gpu/GrGpuResourceRef.h
@@ -9,6 +9,8 @@
#define GrGpuResourceRef_DEFINED
#include "GrGpuResource.h"
+#include "GrRenderTarget.h"
+#include "GrTexture.h"
#include "SkRefCnt.h"
/**
@@ -96,7 +98,7 @@
/** 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 @@
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.
diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h
index b8e30d9..e0f1199 100644
--- a/include/gpu/GrRenderTarget.h
+++ b/include/gpu/GrRenderTarget.h
@@ -12,36 +12,21 @@
#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 @@
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 @@
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;
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 9a76d3a..9d89149 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -24,15 +24,11 @@
/**
* 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 @@
/**
* @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.
diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h
index 13d5667..87f0d5a 100644
--- a/include/gpu/GrTexture.h
+++ b/include/gpu/GrTexture.h
@@ -10,7 +10,6 @@
#define GrTexture_DEFINED
#include "GrSurface.h"
-#include "GrRenderTarget.h"
#include "SkPoint.h"
#include "SkRefCnt.h"
@@ -18,7 +17,7 @@
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 @@
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 @@
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:
diff --git a/src/effects/SkColorCubeFilter.cpp b/src/effects/SkColorCubeFilter.cpp
index 2242598..d9d6841 100644
--- a/src/effects/SkColorCubeFilter.cpp
+++ b/src/effects/SkColorCubeFilter.cpp
@@ -356,11 +356,12 @@
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));
}
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 5f0001b..c1fee0a 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -255,8 +255,12 @@
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 @@
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) {
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 39c9102..97516e8 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -530,9 +530,7 @@
*
* @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
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index f495b89..c32294b 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -169,9 +169,7 @@
*
* @return The currently set render target.
*/
- GrRenderTarget* getRenderTarget() const {
- return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
- }
+ GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
/// @}
diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp
index 7ed70c9..7aeb4ee 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -31,20 +31,6 @@
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) {
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 0431a27..9754d44 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -180,8 +180,7 @@
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());
}
}
diff --git a/src/gpu/GrResourceCache2.h b/src/gpu/GrResourceCache2.h
index e10b45a..a365a5a 100644
--- a/src/gpu/GrResourceCache2.h
+++ b/src/gpu/GrResourceCache2.h
@@ -42,9 +42,7 @@
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;
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index 2717b31..2139540 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -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 @@
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 @@
//////////////////////////////////////////////////////////////////////////////
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
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index 0e8bd05..8482ecd 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -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);
-
- // we assume this is true, TODO: get rid of viewport as a param.
- SkASSERT(viewport.fWidth == texture->width());
- SkASSERT(viewport.fHeight == texture->height());
-
- this->init(texture->desc(), idDesc, viewport, texID);
+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);
}
-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);
+void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
+ fRTFBOID = idDesc.fRTFBOID;
+ fTexFBOID = idDesc.fTexFBOID;
+ fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
+
+ fViewport.fLeft = 0;
+ fViewport.fBottom = 0;
+ fViewport.fWidth = desc.fWidth;
+ fViewport.fHeight = desc.fHeight;
+
+ // 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;
+ }
+}
+
+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 @@
fRTFBOID = 0;
fTexFBOID = 0;
fMSColorRenderbufferID = 0;
- fTexIDObj.reset(NULL);
INHERITED::onRelease();
}
@@ -75,9 +75,5 @@
fRTFBOID = 0;
fTexFBOID = 0;
fMSColorRenderbufferID = 0;
- if (fTexIDObj.get()) {
- fTexIDObj->abandon();
- fTexIDObj.reset(NULL);
- }
INHERITED::onAbandon();
}
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h
index 116862b..0f04160 100644
--- a/src/gpu/gl/GrGLRenderTarget.h
+++ b/src/gpu/gl/GrGLRenderTarget.h
@@ -14,11 +14,8 @@
#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 @@
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 @@
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 @@
}
}
+ 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;
};
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index 8cf574b..d9db6ea 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -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() {
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index 11d6353..5c64eaf 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -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 @@
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 @@
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 @@
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
index 0000000..55da28f
--- /dev/null
+++ b/src/gpu/gl/GrGLTextureRenderTarget.h
@@ -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
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 9d08f64..6c35e9f 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -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 @@
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 @@
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 @@
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::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget* rt) {
- GrGLRenderTarget* glrt = (GrGLRenderTarget*) rt;
+ GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
GrGLuint fbo = glrt->renderFBOID();
@@ -1575,8 +1570,7 @@
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 @@
// 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);
}
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 1a03c13..e7266f3 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -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"