Index: src/gpu/gl/GrGLRenderTarget.h |
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h |
index 7e7349257f054ac44e8a32cd5626c1cf94e1041c..485ae4a7919d1d967b8600ac8c8093da80fe4af1 100644 |
--- a/src/gpu/gl/GrGLRenderTarget.h |
+++ b/src/gpu/gl/GrGLRenderTarget.h |
@@ -15,15 +15,59 @@ |
class GrGLGpu; |
-class GrGLRenderTarget : public GrRenderTarget { |
+/** Represents a GL FBO object. It has a gen ID which is valid whenever the FBO ID owned by the |
+ object is valid. The gen IDs are not recycled after FBOs are freed, unlike FBO IDs, and so |
+ can be used to uniquely identity FBO ID instantiations. If this object owns an FBO ID, the ID |
+ must be deleted or abandoned before this object is freed. FBO IDs should never be owned by |
+ more than one instance. */ |
+class GrGLFBO : public SkNVRefCnt<GrGLFBO> { |
public: |
- // set fTexFBOID to this value to indicate that it is multisampled but |
- // Gr doesn't know how to resolve it. |
- enum { kUnresolvableFBOID = 0 }; |
+ SK_DECLARE_INST_COUNT(GrGLFBO); |
+ |
+ /** Initializes to an FBO. The FBO should already be valid in the relevant GL context. */ |
+ GrGLFBO(GrGLint id) : fID(id), fIsValid(true) {} |
+ |
+ /** Initializes to an FBO ID generated using the interface. */ |
+ GrGLFBO(const GrGLInterface* gl) { |
+ GR_GL_CALL(gl, GenFramebuffers(1, &fID)); |
+ fIsValid = SkToBool(fID); |
+ } |
+ |
+ ~GrGLFBO() { SkASSERT(!this->isValid()); } |
+ |
+ /** Has this object been released or abandoned? */ |
+ bool isValid() const { return fIsValid; } |
+ |
+ GrGLint fboID() const { SkASSERT(this->isValid()); return fID; } |
+ |
+ bool isDefaultFramebuffer() const { return fIsValid && 0 == fID; } |
+ |
+ /** Give up ownership of the FBO ID owned by this object without deleting it. */ |
+ void abandon(); |
+ |
+ /** Delete and give up ownership of the the FBO ID if it is valid. */ |
+ void release(const GrGLInterface*); |
+ |
+private: |
+ static uint32_t NextGenID() { |
+ static int32_t gGenID = SK_InvalidGenID + 1; |
+ return static_cast<uint32_t>(sk_atomic_inc(&gGenID)); |
+ } |
+ |
+ GrGLuint fID; |
+ bool fIsValid; |
+ |
+ typedef SkRefCnt INHERITED; |
+}; |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+/** GL-specific subclass of GrRenderTarget. */ |
+class GrGLRenderTarget : public GrRenderTarget { |
+public: |
struct IDDesc { |
- GrGLuint fRTFBOID; |
- GrGLuint fTexFBOID; |
+ SkAutoTUnref<GrGLFBO> fRenderFBO; |
+ SkAutoTUnref<GrGLFBO> fTextureFBO; |
GrGLuint fMSColorRenderbufferID; |
GrGpuResource::LifeCycle fLifeCycle; |
}; |
@@ -33,21 +77,33 @@ public: |
void setViewport(const GrGLIRect& rect) { fViewport = rect; } |
const GrGLIRect& getViewport() const { return fViewport; } |
- // The following two functions return the same ID when a |
- // texture/render target is multisampled, and different IDs when |
- // it is. |
- // FBO ID used to render into |
- GrGLuint renderFBOID() const { return fRTFBOID; } |
- // FBO ID that has texture ID attached. |
- GrGLuint textureFBOID() const { return fTexFBOID; } |
+ // For multisampled renderbuffer render targets, these will return different GrGLFBO objects. If |
+ // the render target is not texturable, textureFBO() returns NULL. If the render target auto |
+ // resolves to a texture, the same object is returned. |
+ |
+ // FBO that should be rendered into. Always non-NULL unless this resource is destroyed |
+ // (this->wasDestroyed()). |
+ const GrGLFBO* renderFBO() const { |
+ SkASSERT(fRenderFBO && fRenderFBO->isValid()); |
+ return fRenderFBO; |
+ } |
+ |
+ // FBO that has the target's texture ID attached. The return value may be: |
+ // * NULL when this render target is not a texture, |
+ // * the same as renderFBO() when this surface is not multisampled or auto-resolves, |
+ // * or different than renderFBO() when it requires explicit resolving via |
+ // glBlitFramebuffer. |
+ const GrGLFBO* textureFBO() const { |
+ SkASSERT(!fTextureFBO || fTextureFBO->isValid()); |
+ return fTextureFBO; |
+ } |
// override of GrRenderTarget |
ResolveType getResolveType() const SK_OVERRIDE { |
- if (!this->isMultisampled() || |
- fRTFBOID == fTexFBOID) { |
+ if (!this->isMultisampled() || this->renderFBO() == this->textureFBO()) { |
// catches FBO 0 and non MSAA case |
return kAutoResolves_ResolveType; |
- } else if (kUnresolvableFBOID == fTexFBOID) { |
+ } else if (!this->textureFBO()) { |
return kCantResolve_ResolveType; |
} else { |
return kCanResolve_ResolveType; |
@@ -73,23 +129,23 @@ protected: |
size_t onGpuMemorySize() const SK_OVERRIDE; |
private: |
- GrGLuint fRTFBOID; |
- GrGLuint fTexFBOID; |
- GrGLuint fMSColorRenderbufferID; |
+ SkAutoTUnref<GrGLFBO> fRenderFBO; |
+ SkAutoTUnref<GrGLFBO> fTextureFBO; |
+ GrGLuint fMSColorRenderbufferID; |
// We track this separately from GrGpuResource because this may be both a texture and a render |
// target, and the texture may be wrapped while the render target is not. |
- bool fIsWrapped; |
+ bool fIsWrapped; |
// when we switch to this render target we want to set the viewport to |
// 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; |
+ GrGLIRect fViewport; |
// onGpuMemorySize() 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; |
+ uint8_t fColorValuesPerPixel; |
typedef GrRenderTarget INHERITED; |
}; |