Revert of Improve tracking of bound FBOs in GrGLGpu. (patchset #17 id:320001 of https...
authoregdaniel <egdaniel@google.com>
Wed, 18 Mar 2015 20:01:52 +0000 (13:01 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 18 Mar 2015 20:01:52 +0000 (13:01 -0700)
Reason for revert:
Perf regression on win8 hd7700 gpu skps

Original issue's description:
> Improve tracking of bound FBOs in GrGLGpu.
>
> Committed: https://skia.googlesource.com/skia/+/d2ad8eb5801e2c8c0fa544a6a776bb46eedde2a0
>
> Committed: https://skia.googlesource.com/skia/+/b2af2d8b83ca4774c3b3bb1e49bc72605faa9589
>
> Committed: https://skia.googlesource.com/skia/+/0b70b86a7e9fda52ee7ebc1b9897eeaa09b9abef
>
> Committed: https://skia.googlesource.com/skia/+/6ba6fa15261be591f33cf0e5df7134e4fc6432ac
>
> Committed: https://skia.googlesource.com/skia/+/dc963b9264908f53650c40a97cff414101dd3e88
>
> Committed: https://skia.googlesource.com/skia/+/160f24ce0e8d6dd7ca80b78871e063d4f4609cfb

TBR=bsalomon@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

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

src/gpu/gl/GrGLCaps.cpp
src/gpu/gl/GrGLCaps.h
src/gpu/gl/GrGLGpu.cpp
src/gpu/gl/GrGLGpu.h
src/gpu/gl/GrGLNoOpInterface.cpp
src/gpu/gl/GrGLRenderTarget.cpp
src/gpu/gl/GrGLRenderTarget.h
src/gpu/gl/debug/GrGLCreateDebugInterface.cpp

index e70e6f04fba39336841b2a38f4e7e3757da1d1eb..9911d53f43c373d54cb88561d4269ea5e5361884 100644 (file)
@@ -52,8 +52,6 @@ void GrGLCaps::reset() {
     fDropsTileOnZeroDivide = false;
     fFBFetchSupport = false;
     fFBFetchNeedsCustomOutput = false;
-    fPreferBindingToReadAndDrawFramebuffer = false;
-
     fFBFetchColorName = NULL;
     fFBFetchExtensionString = NULL;
 
@@ -101,7 +99,6 @@ GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
     fFBFetchNeedsCustomOutput = caps.fFBFetchNeedsCustomOutput;
     fFBFetchColorName = caps.fFBFetchColorName;
     fFBFetchExtensionString = caps.fFBFetchExtensionString;
-    fPreferBindingToReadAndDrawFramebuffer = caps.fPreferBindingToReadAndDrawFramebuffer;
 
     return *this;
 }
@@ -282,12 +279,6 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
     this->initFSAASupport(ctxInfo, gli);
     this->initStencilFormats(ctxInfo);
 
-    // Workaround for Mac/Chromium issue.
-#ifdef SK_BUILD_FOR_MAC
-    // This relies on the fact that initFSAASupport() was already called.
-    fPreferBindingToReadAndDrawFramebuffer = ctxInfo.isChromium() && this->usesMSAARenderBuffers();
-#endif
-
     /**************************************************************************
      * GrDrawTargetCaps fields
      **************************************************************************/
index 932e66fdfc160a573645916e2596cbc66d4e34b9..1b77ed0e3204099847b26decf6c6a5ddb8753904 100644 (file)
@@ -267,10 +267,6 @@ public:
     bool fullClearIsFree() const { return fFullClearIsFree; }
 
     bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
-    
-    bool preferBindingToReadAndDrawFramebuffer() const {
-        return fPreferBindingToReadAndDrawFramebuffer;
-    }
 
     /**
      * Returns a string containing the caps info.
@@ -393,7 +389,6 @@ private:
     bool fDropsTileOnZeroDivide : 1;
     bool fFBFetchSupport : 1;
     bool fFBFetchNeedsCustomOutput : 1;
-    bool fPreferBindingToReadAndDrawFramebuffer : 1;
 
     const char* fFBFetchColorName;
     const char* fFBFetchExtensionString;
index 5ebbe1f3b46845d610f6818e2493c4684a64413d..a2c8d7f3ea753dff24de13c43798bd0e2fc0b71c 100644 (file)
@@ -151,6 +151,9 @@ GrGLGpu::GrGLGpu(const GrGLContext& ctx, GrContext* context)
 
     fLastSuccessfulStencilFmtIdx = 0;
     fHWProgramID = 0;
+    fTempSrcFBOID = 0;
+    fTempDstFBOID = 0;
+    fStencilClearFBOID = 0;
 
     if (this->glCaps().pathRenderingSupport()) {
         fPathRendering.reset(new GrGLPathRendering(this));
@@ -165,17 +168,14 @@ GrGLGpu::~GrGLGpu() {
         GL_CALL(UseProgram(0));
     }
 
-    if (fTempSrcFBO) {
-        fTempSrcFBO->release(this->glInterface());
-        fTempSrcFBO.reset(NULL);
+    if (0 != fTempSrcFBOID) {
+        GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID));
     }
-    if (fTempDstFBO) {
-        fTempDstFBO->release(this->glInterface());
-        fTempDstFBO.reset(NULL);
+    if (0 != fTempDstFBOID) {
+        GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID));
     }
-    if (fStencilClearFBO) {
-        fStencilClearFBO->release(this->glInterface());
-        fStencilClearFBO.reset(NULL);
+    if (0 != fStencilClearFBOID) {
+        GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
     }
 
     delete fProgramCache;
@@ -185,19 +185,9 @@ void GrGLGpu::contextAbandoned() {
     INHERITED::contextAbandoned();
     fProgramCache->abandon();
     fHWProgramID = 0;
-    if (fTempSrcFBO) {
-        fTempSrcFBO->abandon();
-        fTempSrcFBO.reset(NULL);
-    }
-    if (fTempDstFBO) {
-        fTempDstFBO->abandon();
-        fTempDstFBO.reset(NULL);
-    }
-    if (fStencilClearFBO) {
-        fStencilClearFBO->abandon();
-        fStencilClearFBO.reset(NULL);
-    }
-
+    fTempSrcFBOID = 0;
+    fTempDstFBOID = 0;
+    fStencilClearFBOID = 0;
     if (this->glCaps().pathRenderingSupport()) {
         this->glPathRendering()->abandonGpuResources();
     }
@@ -341,9 +331,7 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
     }
 
     if (resetBits & kRenderTarget_GrGLBackendState) {
-        for (size_t i = 0; i < SK_ARRAY_COUNT(fHWFBOBinding); ++i) {
-            fHWFBOBinding[i].invalidate();
-        }
+        fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
     }
 
     if (resetBits & kPathRendering_GrGLBackendState) {
@@ -444,9 +432,9 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
 
 GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc) {
     GrGLRenderTarget::IDDesc idDesc;
-    GrGLuint fboID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
-    idDesc.fRenderFBO.reset(SkNEW_ARGS(GrGLFBO, (fboID)));
+    idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
     idDesc.fMSColorRenderbufferID = 0;
+    idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
     idDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle;
 
     GrSurfaceDesc desc;
@@ -826,34 +814,34 @@ static bool renderbuffer_storage_msaa(GrGLContext& ctx,
 bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted, GrGLuint texID,
                                         GrGLRenderTarget::IDDesc* idDesc) {
     idDesc->fMSColorRenderbufferID = 0;
+    idDesc->fRTFBOID = 0;
+    idDesc->fTexFBOID = 0;
     idDesc->fLifeCycle = budgeted ? GrGpuResource::kCached_LifeCycle :
                                     GrGpuResource::kUncached_LifeCycle;
 
     GrGLenum status;
 
     GrGLenum msColorFormat = 0; // suppress warning
-    GrGLenum fboTarget = 0; // suppress warning
 
     if (desc.fSampleCnt > 0 && GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType()) {
         goto FAILED;
     }
 
-    idDesc->fTextureFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
-    if (!idDesc->fTextureFBO->isValid()) {
+    GL_CALL(GenFramebuffers(1, &idDesc->fTexFBOID));
+    if (!idDesc->fTexFBOID) {
         goto FAILED;
     }
 
+
     // If we are using multisampling we will create two FBOS. We render to one and then resolve to
     // the texture bound to the other. The exception is the IMG multisample extension. With this
     // extension the texture is multisampled when rendered to and then auto-resolves it when it is
     // rendered from.
     if (desc.fSampleCnt > 0 && this->glCaps().usesMSAARenderBuffers()) {
-        idDesc->fRenderFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
-        if (!idDesc->fRenderFBO->isValid()) {
-            goto FAILED;
-        }
+        GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID));
         GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
-        if (!idDesc->fMSColorRenderbufferID ||
+        if (!idDesc->fRTFBOID ||
+            !idDesc->fMSColorRenderbufferID ||
             !this->configToGLFormats(desc.fConfig,
                                      // ES2 and ES3 require sized internal formats for rb storage.
                                      kGLES_GrGLStandard == this->glStandard(),
@@ -863,10 +851,12 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted
             goto FAILED;
         }
     } else {
-        idDesc->fRenderFBO.reset(SkRef(idDesc->fTextureFBO.get()));
+        idDesc->fRTFBOID = idDesc->fTexFBOID;
     }
 
-    if (idDesc->fRenderFBO != idDesc->fTextureFBO) {
+    // below here we may bind the FBO
+    fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+    if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
         SkASSERT(desc.fSampleCnt > 0);
         GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbufferID));
         if (!renderbuffer_storage_msaa(fGLContext,
@@ -875,11 +865,12 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted
                                        desc.fWidth, desc.fHeight)) {
             goto FAILED;
         }
-        fboTarget = this->bindFBO(kChangeAttachments_FBOBinding, idDesc->fRenderFBO);
-        GL_CALL(FramebufferRenderbuffer(fboTarget,
-                                        GR_GL_COLOR_ATTACHMENT0,
-                                        GR_GL_RENDERBUFFER,
-                                        idDesc->fMSColorRenderbufferID));
+        fStats.incRenderTargetBinds();
+        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID));
+        GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+                                      GR_GL_COLOR_ATTACHMENT0,
+                                      GR_GL_RENDERBUFFER,
+                                      idDesc->fMSColorRenderbufferID));
         if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
             !this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
@@ -889,22 +880,23 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted
             fGLContext.caps()->markConfigAsValidColorAttachment(desc.fConfig);
         }
     }
-    fboTarget = this->bindFBO(kChangeAttachments_FBOBinding, idDesc->fTextureFBO);
+    fStats.incRenderTargetBinds();
+    GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fTexFBOID));
 
     if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 0) {
-        GL_CALL(FramebufferTexture2DMultisample(fboTarget,
+        GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER,
                                                 GR_GL_COLOR_ATTACHMENT0,
                                                 GR_GL_TEXTURE_2D,
                                                 texID, 0, desc.fSampleCnt));
     } else {
-        GL_CALL(FramebufferTexture2D(fboTarget,
+        GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
                                      GR_GL_COLOR_ATTACHMENT0,
                                      GR_GL_TEXTURE_2D,
                                      texID, 0));
     }
     if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) ||
         !this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) {
-        GL_CALL_RET(status, CheckFramebufferStatus(fboTarget));
+        GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
         if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
             goto FAILED;
         }
@@ -917,11 +909,11 @@ FAILED:
     if (idDesc->fMSColorRenderbufferID) {
         GL_CALL(DeleteRenderbuffers(1, &idDesc->fMSColorRenderbufferID));
     }
-    if (idDesc->fRenderFBO) {
-        idDesc->fRenderFBO->release(this->glInterface());
+    if (idDesc->fRTFBOID != idDesc->fTexFBOID) {
+        GL_CALL(DeleteFramebuffers(1, &idDesc->fRTFBOID));
     }
-    if (idDesc->fTextureFBO) {
-        idDesc->fTextureFBO->release(this->glInterface());
+    if (idDesc->fTexFBOID) {
+        GL_CALL(DeleteFramebuffers(1, &idDesc->fTexFBOID));
     }
     return false;
 }
@@ -1194,17 +1186,18 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
                 // Clear the stencil buffer. We use a special purpose FBO for this so that the
                 // entire stencil buffer is cleared, even if it is attached to an FBO with a
                 // smaller color target.
-                if (!fStencilClearFBO) {
-                    fStencilClearFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
+                if (0 == fStencilClearFBOID) {
+                    GL_CALL(GenFramebuffers(1, &fStencilClearFBOID));
                 }
-                SkASSERT(fStencilClearFBO->isValid());
-                GrGLenum fboTarget = this->bindFBO(kClear_FBOBinding, fStencilClearFBO);
 
-                GL_CALL(FramebufferRenderbuffer(fboTarget,
+                GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fStencilClearFBOID));
+                fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+                fStats.incRenderTargetBinds();
+                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                                 GR_GL_STENCIL_ATTACHMENT,
                                                 GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
                 if (sFmt.fPacked) {
-                    GL_CALL(FramebufferRenderbuffer(fboTarget,
+                    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                                     GR_GL_DEPTH_ATTACHMENT,
                                                     GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
                 }
@@ -1215,29 +1208,28 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
                 GrGLuint tempRB;
                 GL_CALL(GenRenderbuffers(1, &tempRB));
                 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, tempRB));
-
                 if (samples > 0) {
                     renderbuffer_storage_msaa(fGLContext, samples, GR_GL_RGBA8, width, height);
                 } else {
                     GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, GR_GL_RGBA8, width, height));
                 }
-                GL_CALL(FramebufferRenderbuffer(fboTarget,
+                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                                 GR_GL_COLOR_ATTACHMENT0,
                                                 GR_GL_RENDERBUFFER, tempRB));
 
                 GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
 
-                GL_CALL(FramebufferRenderbuffer(fboTarget,
+                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                                 GR_GL_COLOR_ATTACHMENT0,
                                                 GR_GL_RENDERBUFFER, 0));
                 GL_CALL(DeleteRenderbuffers(1, &tempRB));
 
                 // Unbind the SB from the FBO so that we don't keep it alive.
-                GL_CALL(FramebufferRenderbuffer(fboTarget,
+                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                                 GR_GL_STENCIL_ATTACHMENT,
                                                 GR_GL_RENDERBUFFER, 0));
                 if (sFmt.fPacked) {
-                    GL_CALL(FramebufferRenderbuffer(fboTarget,
+                    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                                     GR_GL_DEPTH_ATTACHMENT,
                                                     GR_GL_RENDERBUFFER, 0));
                 }
@@ -1257,6 +1249,9 @@ bool GrGLGpu::createStencilBufferForRenderTarget(GrRenderTarget* rt, int width,
 
 bool GrGLGpu::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTarget* rt) {
     GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(rt);
+
+    GrGLuint fbo = glrt->renderFBOID();
+
     if (NULL == sb) {
         if (rt->renderTargetPriv().getStencilBuffer()) {
             GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
@@ -1275,17 +1270,19 @@ bool GrGLGpu::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTar
     } else {
         GrGLStencilBuffer* glsb = static_cast<GrGLStencilBuffer*>(sb);
         GrGLuint rb = glsb->renderbufferID();
-        GrGLenum fboTarget = this->bindFBO(kChangeAttachments_FBOBinding, glrt->renderFBO());
 
-        GL_CALL(FramebufferRenderbuffer(fboTarget,
+        fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+        fStats.incRenderTargetBinds();
+        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
+        GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                         GR_GL_STENCIL_ATTACHMENT,
                                         GR_GL_RENDERBUFFER, rb));
         if (glsb->format().fPacked) {
-            GL_CALL(FramebufferRenderbuffer(fboTarget,
+            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                             GR_GL_DEPTH_ATTACHMENT,
                                             GR_GL_RENDERBUFFER, rb));
         } else {
-            GL_CALL(FramebufferRenderbuffer(fboTarget,
+            GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                             GR_GL_DEPTH_ATTACHMENT,
                                             GR_GL_RENDERBUFFER, 0));
         }
@@ -1294,13 +1291,13 @@ bool GrGLGpu::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTar
         if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(), glsb->format())) {
             GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
             if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
-                GL_CALL(FramebufferRenderbuffer(fboTarget,
-                                                GR_GL_STENCIL_ATTACHMENT,
-                                                GR_GL_RENDERBUFFER, 0));
+                GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+                                              GR_GL_STENCIL_ATTACHMENT,
+                                              GR_GL_RENDERBUFFER, 0));
                 if (glsb->format().fPacked) {
-                    GL_CALL(FramebufferRenderbuffer(fboTarget,
-                                                    GR_GL_DEPTH_ATTACHMENT,
-                                                    GR_GL_RENDERBUFFER, 0));
+                    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+                                                  GR_GL_DEPTH_ATTACHMENT,
+                                                  GR_GL_RENDERBUFFER, 0));
                 }
                 return false;
             } else {
@@ -1432,23 +1429,20 @@ bool GrGLGpu::flushGLState(const DrawArgs& args) {
         fHWProgramID = programID;
     }
 
+    if (blendInfo.fWriteColor) {
+        this->flushBlend(blendInfo);
+    }
 
     fCurrentProgram->setData(*args.fPrimitiveProcessor, pipeline, *args.fBatchTracker);
 
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
-
     this->flushStencil(pipeline.getStencil());
     this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin());
     this->flushHWAAState(glRT, pipeline.isHWAntialiasState());
 
     // This must come after textures are flushed because a texture may need
-    // to be msaa-resolved (which will modify bound FBO and scissor state).
-    this->bindFBO(kDraw_FBOBinding, glRT->renderFBO());
-    this->setViewport(glRT->getViewport());
-    if (blendInfo.fWriteColor) {
-        this->flushBlend(blendInfo);
-        this->markSurfaceContentsDirty(glRT, NULL);
-    }
+    // to be msaa-resolved (which will modify bound FBO state).
+    this->flushRenderTarget(glRT, NULL);
 
     return true;
 }
@@ -1545,8 +1539,7 @@ void GrGLGpu::onClear(GrRenderTarget* target, const SkIRect* rect, GrColor color
         }
     }
 
-    this->bindFBO(kClear_FBOBinding, glRT->renderFBO());
-    this->markSurfaceContentsDirty(glRT, rect);
+    this->flushRenderTarget(glRT, rect);
     GrScissorState scissorState;
     if (rect) {
         scissorState.set(*rect);
@@ -1574,36 +1567,40 @@ void GrGLGpu::discard(GrRenderTarget* renderTarget) {
     }
 
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(renderTarget);
-    GrGLenum fboTarget = this->bindFBO(kDiscard_FBOBinding, glRT->renderFBO());
+    if (renderTarget->getUniqueID() != fHWBoundRenderTargetUniqueID) {
+        fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+        fStats.incRenderTargetBinds();
+        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRT->renderFBOID()));
+    }
     switch (this->glCaps().invalidateFBType()) {
         case GrGLCaps::kNone_InvalidateFBType:
             SkFAIL("Should never get here.");
             break;
         case GrGLCaps::kInvalidate_InvalidateFBType:
-            if (glRT->renderFBO()->isDefaultFramebuffer()) {
+            if (0 == glRT->renderFBOID()) {
                 //  When rendering to the default framebuffer the legal values for attachments
                 //  are GL_COLOR, GL_DEPTH, GL_STENCIL, ... rather than the various FBO attachment
                 //  types.
                 static const GrGLenum attachments[] = { GR_GL_COLOR };
-                GL_CALL(InvalidateFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
+                GL_CALL(InvalidateFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
                         attachments));
             } else {
                 static const GrGLenum attachments[] = { GR_GL_COLOR_ATTACHMENT0 };
-                GL_CALL(InvalidateFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
+                GL_CALL(InvalidateFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
                         attachments));
             }
             break;
         case GrGLCaps::kDiscard_InvalidateFBType: {
-            if (glRT->renderFBO()->isDefaultFramebuffer()) {
+            if (0 == glRT->renderFBOID()) {
                 //  When rendering to the default framebuffer the legal values for attachments
                 //  are GL_COLOR, GL_DEPTH, GL_STENCIL, ... rather than the various FBO attachment
                 //  types. See glDiscardFramebuffer() spec.
                 static const GrGLenum attachments[] = { GR_GL_COLOR };
-                GL_CALL(DiscardFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
+                GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
                         attachments));
             } else {
                 static const GrGLenum attachments[] = { GR_GL_COLOR_ATTACHMENT0 };
-                GL_CALL(DiscardFramebuffer(fboTarget, SK_ARRAY_COUNT(attachments),
+                GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
                         attachments));
             }
             break;
@@ -1618,7 +1615,7 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) {
         return;
     }
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
-    this->bindFBO(kClear_FBOBinding, glRT->renderFBO());
+    this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
 
     this->disableScissor();
 
@@ -1654,7 +1651,7 @@ void GrGLGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bo
         value = 0;
     }
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
-    this->bindFBO(kClear_FBOBinding, glRT->renderFBO());
+    this->flushRenderTarget(glRT, &SkIRect::EmptyIRect());
 
     GrScissorState scissorState;
     scissorState.set(rect);
@@ -1724,13 +1721,22 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target,
 
     // resolve the render target if necessary
     GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
-    if (tgt->getResolveType() == GrGLRenderTarget::kCantResolve_ResolveType) {
-        return false;
-    }
-    if (tgt->getResolveType() == GrGLRenderTarget::kCanResolve_ResolveType) {
-        this->onResolveRenderTarget(tgt);
+    switch (tgt->getResolveType()) {
+        case GrGLRenderTarget::kCantResolve_ResolveType:
+            return false;
+        case GrGLRenderTarget::kAutoResolves_ResolveType:
+            this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect());
+            break;
+        case GrGLRenderTarget::kCanResolve_ResolveType:
+            this->onResolveRenderTarget(tgt);
+            // we don't track the state of the READ FBO ID.
+            fStats.incRenderTargetBinds();
+            GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
+                                    tgt->textureFBOID()));
+            break;
+        default:
+            SkFAIL("Unknown resolve type");
     }
-    this->bindFBO(kReadPixels_FBOBinding, tgt->textureFBO());
 
     const GrGLIRect& glvp = tgt->getViewport();
 
@@ -1795,8 +1801,7 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target,
             }
         }
     } else {
-        SkASSERT(readDst != buffer);
-        SkASSERT(rowBytes != tightRowBytes);
+        SkASSERT(readDst != buffer);        SkASSERT(rowBytes != tightRowBytes);
         // copy from readDst to buffer while flipping y
         // const int halfY = height >> 1;
         const char* src = reinterpret_cast<const char*>(readDst);
@@ -1817,69 +1822,41 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target,
     return true;
 }
 
-GrGLenum GrGLGpu::bindFBO(FBOBinding binding, const GrGLFBO* fbo) {
-    SkASSERT(fbo);
-    SkASSERT(fbo->isValid());
-    
-    enum {
-        kDraw = 0,
-        kRead = 1
-    };
+void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) {
 
-    bool useGLFramebuffer = !this->glCaps().usesMSAARenderBuffers() ||
-        (this->glCaps().preferBindingToReadAndDrawFramebuffer() &&
-         kBlitSrc_FBOBinding != binding && kBlitDst_FBOBinding != binding);
+    SkASSERT(target);
 
-    if (useGLFramebuffer) {
-        SkASSERT(kBlitSrc_FBOBinding != binding);
+    uint32_t rtID = target->getUniqueID();
+    if (fHWBoundRenderTargetUniqueID != rtID) {
         fStats.incRenderTargetBinds();
-        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo->fboID()));
-        fHWFBOBinding[kDraw].fFBO.reset(SkRef(fbo));
-        fHWFBOBinding[kRead].fFBO.reset(SkRef(fbo));
-        return GR_GL_FRAMEBUFFER;
-    }
-    GrGLenum target = 0;
-    HWFBOBinding* hwFBOBinding = NULL;
-    switch (binding) {
-        case kDraw_FBOBinding:
-        case kClear_FBOBinding:
-        case kDiscard_FBOBinding:
-        case kChangeAttachments_FBOBinding:
-        case kBlitDst_FBOBinding:
-            target = GR_GL_DRAW_FRAMEBUFFER;
-            hwFBOBinding = &fHWFBOBinding[kDraw];
-            break;
-
-        case kReadPixels_FBOBinding:
-        case kBlitSrc_FBOBinding:
-        case kCopyTexSrc_FBOBinding:
-            target = GR_GL_READ_FRAMEBUFFER;
-            hwFBOBinding = &fHWFBOBinding[kRead];
-            break;
+        GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, target->renderFBOID()));
+#ifdef SK_DEBUG
+        // don't do this check in Chromium -- this is causing
+        // lots of repeated command buffer flushes when the compositor is
+        // rendering with Ganesh, which is really slow; even too slow for
+        // Debug mode.
+        if (!this->glContext().isChromium()) {
+            GrGLenum status;
+            GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
+            if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
+                SkDebugf("GrGLGpu::flushRenderTarget glCheckFramebufferStatus %x\n", status);
+            }
+        }
+#endif
+        fHWBoundRenderTargetUniqueID = rtID;
+        const GrGLIRect& vp = target->getViewport();
+        if (fHWViewport != vp) {
+            vp.pushToGLViewport(this->glInterface());
+            fHWViewport = vp;
+        }
     }
-    fStats.incRenderTargetBinds();
-    GL_CALL(BindFramebuffer(target, fbo->fboID()));
-    hwFBOBinding->fFBO.reset(SkRef(fbo));
-    return target;
-}
-
-void GrGLGpu::setViewport(const GrGLIRect& viewport) {
-    if (viewport != fHWViewport) {
-        viewport.pushToGLViewport(this->glInterface());
-        fHWViewport = viewport;
+    if (NULL == bound || !bound->isEmpty()) {
+        target->flagAsNeedingResolve(bound);
     }
-}
 
-void GrGLGpu::markSurfaceContentsDirty(GrSurface* surface, const SkIRect* bounds) {
-    if (NULL == bounds || !bounds->isEmpty()) {
-        GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
-        if (rt) {
-            rt->flagAsNeedingResolve(bounds);
-        }
-        GrGLTexture* texture = static_cast<GrGLTexture*>(surface->asTexture());
-        if (texture) {
-            texture->texturePriv().dirtyMipMaps(true);
-        }
+    GrTexture *texture = target->asTexture();
+    if (texture) {
+        texture->texturePriv().dirtyMipMaps(true);
     }
 }
 
@@ -1961,8 +1938,8 @@ void GrGLGpu::onStencilPath(const GrPath* path, const StencilPathState& state) {
     this->glPathRendering()->setProjectionMatrix(*state.fViewMatrix, size, rt->origin());
     this->flushScissor(*state.fScissor, rt->getViewport(), rt->origin());
     this->flushHWAAState(rt, state.fUseHWAA);
-    this->bindFBO(kDraw_FBOBinding, rt->renderFBO());
-    this->setViewport(rt->getViewport());
+    this->flushRenderTarget(rt, NULL);
+
     fPathRendering->stencilPath(path, *state.fStencil);
 }
 
@@ -1994,9 +1971,14 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
     if (rt->needsResolve()) {
         // Some extensions automatically resolves the texture when it is read.
         if (this->glCaps().usesMSAARenderBuffers()) {
-            SkASSERT(rt->textureFBO() != rt->renderFBO());
-            this->bindFBO(kBlitSrc_FBOBinding, rt->renderFBO());
-            this->bindFBO(kBlitDst_FBOBinding, rt->textureFBO());
+            SkASSERT(rt->textureFBOID() != rt->renderFBOID());
+            fStats.incRenderTargetBinds();
+            fStats.incRenderTargetBinds();
+            GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID()));
+            GL_CALL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID()));
+            // make sure we go through flushRenderTarget() since we've modified
+            // the bound DRAW FBO ID.
+            fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
             const GrGLIRect& vp = rt->getViewport();
             const SkIRect dirtyRect = rt->getResolveRect();
 
@@ -2550,13 +2532,13 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
     const GrGLRenderTarget* dstRT = static_cast<const GrGLRenderTarget*>(dst->asRenderTarget());
     // If dst is multisampled (and uses an extension where there is a separate MSAA renderbuffer)
     // then we don't want to copy to the texture but to the MSAA buffer.
-    if (dstRT && dstRT->renderFBO() != dstRT->textureFBO()) {
+    if (dstRT && dstRT->renderFBOID() != dstRT->textureFBOID()) {
         return false;
     }
     const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget());
     // If the src is multisampled (and uses an extension where there is a separate MSAA
     // renderbuffer) then it is an invalid operation to call CopyTexSubImage
-    if (srcRT && srcRT->renderFBO() != srcRT->textureFBO()) {
+    if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) {
         return false;
     }
     if (gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) &&
@@ -2573,31 +2555,22 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
 
 // If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is
 // relative to is output.
-GrGLGpu::FBOBinding GrGLGpu::bindSurfaceAsFBOForCopy(GrSurface* surface, FBOBinding binding,
-                                                     GrGLIRect* viewport) {
+GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
+                                   TempFBOTarget tempFBOTarget) {
     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
     if (NULL == rt) {
         SkASSERT(surface->asTexture());
         GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID();
-        GrGLFBO* tempFBO;
+        GrGLuint* tempFBOID;
+        tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID;
 
-        if (kBlitSrc_FBOBinding == binding || kCopyTexSrc_FBOBinding == binding) {
-            if (!fTempSrcFBO) {
-                fTempSrcFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
-                SkASSERT(fTempSrcFBO->isValid());
-            }
-            tempFBO = fTempSrcFBO;
-        } else {
-            SkASSERT(kBlitDst_FBOBinding == binding);
-            if (!fTempDstFBO) {
-                fTempDstFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface())));
-                SkASSERT(fTempDstFBO->isValid());
-            }
-            tempFBO = fTempDstFBO;
+        if (0 == *tempFBOID) {
+            GR_GL_CALL(this->glInterface(), GenFramebuffers(1, tempFBOID));
         }
 
-        GrGLenum target = this->bindFBO(binding, tempFBO);
-        GR_GL_CALL(this->glInterface(), FramebufferTexture2D(target,
+        fStats.incRenderTargetBinds();
+        GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, *tempFBOID));
+        GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
                                                              GR_GL_COLOR_ATTACHMENT0,
                                                              GR_GL_TEXTURE_2D,
                                                              texID,
@@ -2606,21 +2579,18 @@ GrGLGpu::FBOBinding GrGLGpu::bindSurfaceAsFBOForCopy(GrSurface* surface, FBOBind
         viewport->fBottom = 0;
         viewport->fWidth = surface->width();
         viewport->fHeight = surface->height();
-        return binding;
+        return *tempFBOID;
     } else {
-        this->bindFBO(binding, rt->renderFBO());
+        GrGLuint tempFBOID = 0;
+        fStats.incRenderTargetBinds();
+        GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID()));
         *viewport = rt->getViewport();
-        return kInvalidFBOBinding;
+        return tempFBOID;
     }
 }
 
-void GrGLGpu::unbindSurfaceAsFBOForCopy(FBOBinding binding) {
-    if (kInvalidFBOBinding == binding) {
-        return;
-    }
-    GrGLFBO* tempFBO = kBlitDst_FBOBinding == binding ? fTempSrcFBO : fTempDstFBO;
-    GrGLenum target = this->bindFBO(binding, tempFBO);
-    GR_GL_CALL(this->glInterface(), FramebufferTexture2D(target,
+void GrGLGpu::unbindTextureFromFBO(GrGLenum fboTarget) {
+    GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget,
                                                          GR_GL_COLOR_ATTACHMENT0,
                                                          GR_GL_TEXTURE_2D,
                                                          0,
@@ -2651,7 +2621,7 @@ bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc)
     }
 
     const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget());
-    if (srcRT && srcRT->renderFBO() != srcRT->textureFBO()) {
+    if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) {
         // It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO blit or
         // fail.
         if (this->caps()->isConfigRenderable(src->config(), false)) {
@@ -2675,14 +2645,14 @@ bool GrGLGpu::copySurface(GrSurface* dst,
                           const SkIRect& srcRect,
                           const SkIPoint& dstPoint) {
     bool copied = false;
-    SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
-                                        srcRect.width(), srcRect.height());
     if (can_copy_texsubimage(dst, src, this)) {
+        GrGLuint srcFBO;
         GrGLIRect srcVP;
-        FBOBinding srcFBOBinding = this->bindSurfaceAsFBOForCopy(src, kCopyTexSrc_FBOBinding,
-                                                                 &srcVP);
+        srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget);
         GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture());
         SkASSERT(dstTex);
+        // We modified the bound FBO
+        fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
         GrGLIRect srcGLRect;
         srcGLRect.setRelativeTo(srcVP,
                                 srcRect.fLeft,
@@ -2704,21 +2674,28 @@ bool GrGLGpu::copySurface(GrSurface* dst,
                                   srcGLRect.fLeft, srcGLRect.fBottom,
                                   srcGLRect.fWidth, srcGLRect.fHeight));
         copied = true;
-        this->unbindSurfaceAsFBOForCopy(srcFBOBinding);
+        if (srcFBO) {
+            this->unbindTextureFromFBO(GR_GL_FRAMEBUFFER);
+        }
     } else if (can_blit_framebuffer(dst, src, this)) {
+        SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
+                                            srcRect.width(), srcRect.height());
         bool selfOverlap = false;
         if (dst == src) {
             selfOverlap = SkIRect::IntersectsNoEmptyCheck(dstRect, srcRect);
         }
 
         if (!selfOverlap) {
+            GrGLuint dstFBO;
+            GrGLuint srcFBO;
             GrGLIRect dstVP;
             GrGLIRect srcVP;
-            FBOBinding dstFBOBinding = this->bindSurfaceAsFBOForCopy(dst, kBlitDst_FBOBinding,
-                                                                     &dstVP);
-            FBOBinding srcFBOBinding = this->bindSurfaceAsFBOForCopy(src, kBlitSrc_FBOBinding,
-                                                                     &srcVP);
-
+            dstFBO = this->bindSurfaceAsFBO(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP,
+                                            kDst_TempFBOTarget);
+            srcFBO = this->bindSurfaceAsFBO(src, GR_GL_READ_FRAMEBUFFER, &srcVP,
+                                            kSrc_TempFBOTarget);
+            // We modified the bound FBO
+            fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
             GrGLIRect srcGLRect;
             GrGLIRect dstGLRect;
             srcGLRect.setRelativeTo(srcVP,
@@ -2756,14 +2733,15 @@ bool GrGLGpu::copySurface(GrSurface* dst,
                                     dstGLRect.fLeft + dstGLRect.fWidth,
                                     dstGLRect.fBottom + dstGLRect.fHeight,
                                     GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
-            this->unbindSurfaceAsFBOForCopy(dstFBOBinding);
-            this->unbindSurfaceAsFBOForCopy(srcFBOBinding);
+            if (dstFBO) {
+                this->unbindTextureFromFBO(GR_GL_DRAW_FRAMEBUFFER);
+            }
+            if (srcFBO) {
+                this->unbindTextureFromFBO(GR_GL_READ_FRAMEBUFFER);
+            }
             copied = true;
         }
     }
-    if (copied) {
-        this->markSurfaceContentsDirty(dst, &dstRect);
-    }
     return copied;
 }
 
index 6bd8e4db6668bfe9cd8e3a34060b200dcf0439e4..c9e280c3cbc8b7478c8d9c25e24b326086df42b8 100644 (file)
@@ -244,29 +244,11 @@ private:
     // ensures that such operations don't negatively interact with tracking bound textures.
     void setScratchTextureUnit();
 
-    // Enumerates the reasons for binding an FBO.
-    enum FBOBinding {
-        kDraw_FBOBinding,
-        kClear_FBOBinding,
-        kDiscard_FBOBinding,
-        kChangeAttachments_FBOBinding,
-        kReadPixels_FBOBinding,
-        kCopyTexSrc_FBOBinding,
-        kBlitSrc_FBOBinding,
-        kBlitDst_FBOBinding,
-    };
-
-    // binds the FBO and returns the GL enum of the framebuffer target it was bound to.
-    GrGLenum bindFBO(FBOBinding, const GrGLFBO*);
-
-    // Tracks dirty area for resolve, and tracks whether mip maps need rebuilding. bounds is the
-    // region that may be modified. NULL means whole surface. Can be an empty rect.
-    void markSurfaceContentsDirty(GrSurface*, const SkIRect* bounds);
-
-    void setViewport(const GrGLIRect& viewport);
+    // bounds is region that may be modified and therefore has to be resolved.
+    // NULL means whole target. Can be an empty rect.
+    void flushRenderTarget(GrGLRenderTarget*, const SkIRect* bounds);
 
     void flushStencil(const GrStencilSettings&);
-
     void flushHWAAState(GrRenderTarget* rt, bool useHWAA);
 
     bool configToGLFormats(GrPixelConfig config,
@@ -297,14 +279,15 @@ private:
     bool createRenderTargetObjects(const GrSurfaceDesc&, bool budgeted, GrGLuint texID, 
                                    GrGLRenderTarget::IDDesc*);
 
-    static const FBOBinding kInvalidFBOBinding = static_cast<FBOBinding>(-1);
+    enum TempFBOTarget {
+        kSrc_TempFBOTarget,
+        kDst_TempFBOTarget
+    };
 
-    // Binds a surface as an FBO. A temporary FBO ID may be used if the surface is not already
-    // a render target. Afterwards unbindSurfaceAsFBOForCopy must be called with the value returned.
-    FBOBinding bindSurfaceAsFBOForCopy(GrSurface*, FBOBinding, GrGLIRect* viewport);
+    GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
+                              TempFBOTarget tempFBOTarget);
 
-    // Must be matched with bindSurfaceAsFBOForCopy.
-    void unbindSurfaceAsFBOForCopy(FBOBinding);
+    void unbindTextureFromFBO(GrGLenum fboTarget);
 
     GrGLContext fGLContext;
 
@@ -324,9 +307,10 @@ private:
         kUnknown_TriState
     };
 
-    SkAutoTUnref<GrGLFBO> fTempSrcFBO;
-    SkAutoTUnref<GrGLFBO> fTempDstFBO;
-    SkAutoTUnref<GrGLFBO> fStencilClearFBO;
+    GrGLuint                    fTempSrcFBOID;
+    GrGLuint                    fTempDstFBOID;
+
+    GrGLuint                    fStencilClearFBOID;
 
     // last scissor / viewport scissor state seen by the GL.
     struct {
@@ -472,14 +456,9 @@ private:
     GrPipelineBuilder::DrawFace fHWDrawFace;
     TriState                    fHWWriteToColor;
     TriState                    fHWDitherEnabled;
+    uint32_t                    fHWBoundRenderTargetUniqueID;
     SkTArray<uint32_t, true>    fHWBoundTextureUniqueIDs;
 
-    // Track fbo binding state for GL_DRAW_FRAMEBUFFER and GL_READ_FRAMEBUFFER
-    struct HWFBOBinding {
-        SkAutoTUnref<const GrGLFBO> fFBO;
-        void invalidate() { fFBO.reset(NULL); }
-    } fHWFBOBinding[2];
-
     ///@}
 
     // we record what stencil format worked last time to hopefully exit early
index 38ad65e5c156fb8ad75f4a4c4d6f50b4faed9e11..6b8880ed81c9c19ad1bf646438b4a88fa41e2ba1 100644 (file)
@@ -440,8 +440,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLBindFragDataLocationIndexed(GrGLuint program,
 
 GrGLenum GR_GL_FUNCTION_TYPE noOpGLCheckFramebufferStatus(GrGLenum target) {
 
-    GrAlwaysAssert(GR_GL_FRAMEBUFFER == target || GR_GL_READ_FRAMEBUFFER == target ||
-                   GR_GL_DRAW_FRAMEBUFFER == target);
+    GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
 
     return GR_GL_FRAMEBUFFER_COMPLETE;
 }
index 8b9bb98b6b5ac8d89c020a4198c79da1901fe1ed..3eb2ae09fea489802fe38faa77523be8c6c17fc9 100644 (file)
@@ -9,20 +9,8 @@
 
 #include "GrGLGpu.h"
 
-void GrGLFBO::release(const GrGLInterface* gl) {
-    SkASSERT(gl);
-    if (this->isValid()) {
-        GR_GL_CALL(gl, DeleteFramebuffers(1, &fID));
-        fIsValid = false;
-    }
-}
-
-void GrGLFBO::abandon() { fIsValid = false; }
-
-//////////////////////////////////////////////////////////////////////////////
-
-#define GLGPU static_cast<GrGLGpu*>(this->getGpu())
-#define GL_CALL(X) GR_GL_CALL(GLGPU->glInterface(), X)
+#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
+#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
 
 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
@@ -40,10 +28,8 @@ GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, cons
 }
 
 void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
-    fRenderFBO.reset(SkRef(idDesc.fRenderFBO.get()));
-    fTextureFBO.reset(SkSafeRef(idDesc.fTextureFBO.get()));
-    SkASSERT(fRenderFBO->isValid());
-    SkASSERT(!fTextureFBO || fTextureFBO->isValid());
+    fRTFBOID                = idDesc.fRTFBOID;
+    fTexFBOID               = idDesc.fTexFBOID;
     fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
     fIsWrapped              = kWrapped_LifeCycle == idDesc.fLifeCycle;
 
@@ -54,7 +40,7 @@ void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
 
     // We own one color value for each MSAA sample.
     fColorValuesPerPixel = SkTMax(1, fDesc.fSampleCnt);
-    if (fTextureFBO && fTextureFBO != fRenderFBO) {
+    if (fTexFBOID != fRTFBOID) {
         // If we own the resolve buffer then that is one more sample per pixel.
         fColorValuesPerPixel += 1;
     } 
@@ -70,42 +56,27 @@ size_t GrGLRenderTarget::onGpuMemorySize() const {
 
 void GrGLRenderTarget::onRelease() {
     if (!fIsWrapped) {
-        const GrGLInterface* gl = GLGPU->glInterface();
-        if (fRenderFBO) {
-            fRenderFBO->release(gl);
-            fRenderFBO.reset(NULL);
+        if (fTexFBOID) {
+            GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
         }
-        if (fTextureFBO) {
-            fTextureFBO->release(gl);
-            fTextureFBO.reset(NULL);
+        if (fRTFBOID && fRTFBOID != fTexFBOID) {
+            GL_CALL(DeleteFramebuffers(1, &fRTFBOID));
         }
         if (fMSColorRenderbufferID) {
             GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
-            fMSColorRenderbufferID = 0;
         }
-    } else {
-        if (fRenderFBO) {
-            fRenderFBO->abandon();
-            fRenderFBO.reset(NULL);
-        }
-        if (fTextureFBO) {
-            fTextureFBO->abandon();
-            fTextureFBO.reset(NULL);
-        }
-        fMSColorRenderbufferID  = 0;
     }
+    fRTFBOID                = 0;
+    fTexFBOID               = 0;
+    fMSColorRenderbufferID  = 0;
+    fIsWrapped              = false;
     INHERITED::onRelease();
 }
 
 void GrGLRenderTarget::onAbandon() {
-    if (fRenderFBO) {
-        fRenderFBO->abandon();
-        fRenderFBO.reset(NULL);
-    }
-    if (fTextureFBO) {
-        fTextureFBO->abandon();
-        fTextureFBO.reset(NULL);
-    }
+    fRTFBOID                = 0;
+    fTexFBOID               = 0;
     fMSColorRenderbufferID  = 0;
+    fIsWrapped              = false;
     INHERITED::onAbandon();
 }
index 485ae4a7919d1d967b8600ac8c8093da80fe4af1..7e7349257f054ac44e8a32cd5626c1cf94e1041c 100644 (file)
 
 class GrGLGpu;
 
-/** 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:
-    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:
+    // set fTexFBOID to this value to indicate that it is multisampled but
+    // Gr doesn't know how to resolve it.
+    enum { kUnresolvableFBOID = 0 };
+
     struct IDDesc {
-        SkAutoTUnref<GrGLFBO>       fRenderFBO;
-        SkAutoTUnref<GrGLFBO>       fTextureFBO;
+        GrGLuint                    fRTFBOID;
+        GrGLuint                    fTexFBOID;
         GrGLuint                    fMSColorRenderbufferID;
         GrGpuResource::LifeCycle    fLifeCycle;
     };
@@ -77,33 +33,21 @@ public:
     void setViewport(const GrGLIRect& rect) { fViewport = rect; }
     const GrGLIRect& getViewport() const { return fViewport; }
 
-    // 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;
-    }
+    // 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; }
 
     // override of GrRenderTarget
     ResolveType getResolveType() const SK_OVERRIDE {
-        if (!this->isMultisampled() || this->renderFBO() == this->textureFBO()) {
+        if (!this->isMultisampled() ||
+            fRTFBOID == fTexFBOID) {
             // catches FBO 0 and non MSAA case
             return kAutoResolves_ResolveType;
-        } else if (!this->textureFBO()) {
+        } else if (kUnresolvableFBOID == fTexFBOID) {
             return kCantResolve_ResolveType;
         } else {
             return kCanResolve_ResolveType;
@@ -129,23 +73,23 @@ protected:
     size_t onGpuMemorySize() const SK_OVERRIDE;
 
 private:
-    SkAutoTUnref<GrGLFBO>   fRenderFBO;
-    SkAutoTUnref<GrGLFBO>   fTextureFBO;
-    GrGLuint                fMSColorRenderbufferID;
+    GrGLuint      fRTFBOID;
+    GrGLuint      fTexFBOID;
+    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;
 };
index b4643cc6d72f1acc165774cbe4f9e9e6bd579b16..77a1422af173212a3bf7178295e2906929b5e875 100644 (file)
@@ -382,8 +382,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLReadPixels(GrGLint x,
                                                              GrGLenum renderbuffertarget,
                                                              GrGLuint renderBufferID) {
 
-    GrAlwaysAssert(GR_GL_FRAMEBUFFER == target || GR_GL_READ_FRAMEBUFFER == target ||
-                   GR_GL_DRAW_FRAMEBUFFER == target);
+     GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
      GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
                     GR_GL_DEPTH_ATTACHMENT == attachment ||
                     GR_GL_STENCIL_ATTACHMENT == attachment);
@@ -423,8 +422,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLReadPixels(GrGLint x,
                                                           GrGLuint textureID,
                                                           GrGLint level) {
 
-    GrAlwaysAssert(GR_GL_FRAMEBUFFER == target || GR_GL_READ_FRAMEBUFFER == target ||
-                   GR_GL_DRAW_FRAMEBUFFER == target);
+     GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
      GrAlwaysAssert(GR_GL_COLOR_ATTACHMENT0 == attachment ||
                     GR_GL_DEPTH_ATTACHMENT == attachment ||
                     GR_GL_STENCIL_ATTACHMENT == attachment);