Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 5ebbe1f3b46845d610f6818e2493c4684a64413d..a2c8d7f3ea753dff24de13c43798bd0e2fc0b71c 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -151,6 +151,9 @@ |
fLastSuccessfulStencilFmtIdx = 0; |
fHWProgramID = 0; |
+ fTempSrcFBOID = 0; |
+ fTempDstFBOID = 0; |
+ fStencilClearFBOID = 0; |
if (this->glCaps().pathRenderingSupport()) { |
fPathRendering.reset(new GrGLPathRendering(this)); |
@@ -165,17 +168,14 @@ |
GL_CALL(UseProgram(0)); |
} |
- if (fTempSrcFBO) { |
- fTempSrcFBO->release(this->glInterface()); |
- fTempSrcFBO.reset(NULL); |
- } |
- if (fTempDstFBO) { |
- fTempDstFBO->release(this->glInterface()); |
- fTempDstFBO.reset(NULL); |
- } |
- if (fStencilClearFBO) { |
- fStencilClearFBO->release(this->glInterface()); |
- fStencilClearFBO.reset(NULL); |
+ if (0 != fTempSrcFBOID) { |
+ GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID)); |
+ } |
+ if (0 != fTempDstFBOID) { |
+ GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID)); |
+ } |
+ if (0 != fStencilClearFBOID) { |
+ GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID)); |
} |
delete fProgramCache; |
@@ -185,19 +185,9 @@ |
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 @@ |
} |
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 @@ |
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 @@ |
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 @@ |
goto FAILED; |
} |
} else { |
- idDesc->fRenderFBO.reset(SkRef(idDesc->fTextureFBO.get())); |
- } |
- |
- if (idDesc->fRenderFBO != idDesc->fTextureFBO) { |
+ idDesc->fRTFBOID = idDesc->fTexFBOID; |
+ } |
+ |
+ // 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 @@ |
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 @@ |
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 @@ |
if (idDesc->fMSColorRenderbufferID) { |
GL_CALL(DeleteRenderbuffers(1, &idDesc->fMSColorRenderbufferID)); |
} |
- if (idDesc->fRenderFBO) { |
- idDesc->fRenderFBO->release(this->glInterface()); |
- } |
- if (idDesc->fTextureFBO) { |
- idDesc->fTextureFBO->release(this->glInterface()); |
+ if (idDesc->fRTFBOID != idDesc->fTexFBOID) { |
+ GL_CALL(DeleteFramebuffers(1, &idDesc->fRTFBOID)); |
+ } |
+ if (idDesc->fTexFBOID) { |
+ GL_CALL(DeleteFramebuffers(1, &idDesc->fTexFBOID)); |
} |
return false; |
} |
@@ -1194,17 +1186,18 @@ |
// 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 @@ |
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::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 @@ |
} 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 @@ |
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 @@ |
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 @@ |
} |
} |
- 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 @@ |
} |
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 @@ |
return; |
} |
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); |
- this->bindFBO(kClear_FBOBinding, glRT->renderFBO()); |
+ this->flushRenderTarget(glRT, &SkIRect::EmptyIRect()); |
this->disableScissor(); |
@@ -1654,7 +1651,7 @@ |
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 @@ |
// 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); |
- } |
- this->bindFBO(kReadPixels_FBOBinding, tgt->textureFBO()); |
+ 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"); |
+ } |
const GrGLIRect& glvp = tgt->getViewport(); |
@@ -1795,8 +1801,7 @@ |
} |
} |
} 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 @@ |
return true; |
} |
-GrGLenum GrGLGpu::bindFBO(FBOBinding binding, const GrGLFBO* fbo) { |
- SkASSERT(fbo); |
- SkASSERT(fbo->isValid()); |
- |
- enum { |
- kDraw = 0, |
- kRead = 1 |
- }; |
- |
- bool useGLFramebuffer = !this->glCaps().usesMSAARenderBuffers() || |
- (this->glCaps().preferBindingToReadAndDrawFramebuffer() && |
- kBlitSrc_FBOBinding != binding && kBlitDst_FBOBinding != binding); |
- |
- if (useGLFramebuffer) { |
- SkASSERT(kBlitSrc_FBOBinding != binding); |
+void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) { |
+ |
+ SkASSERT(target); |
+ |
+ 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; |
- } |
- 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; |
- } |
-} |
- |
-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); |
- } |
+ 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; |
+ } |
+ } |
+ if (NULL == bound || !bound->isEmpty()) { |
+ target->flagAsNeedingResolve(bound); |
+ } |
+ |
+ GrTexture *texture = target->asTexture(); |
+ if (texture) { |
+ texture->texturePriv().dirtyMipMaps(true); |
} |
} |
@@ -1961,8 +1938,8 @@ |
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 @@ |
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 @@ |
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 @@ |
// 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; |
- |
- 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; |
- } |
- |
- GrGLenum target = this->bindFBO(binding, tempFBO); |
- GR_GL_CALL(this->glInterface(), FramebufferTexture2D(target, |
+ GrGLuint* tempFBOID; |
+ tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID; |
+ |
+ if (0 == *tempFBOID) { |
+ GR_GL_CALL(this->glInterface(), GenFramebuffers(1, tempFBOID)); |
+ } |
+ |
+ 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 @@ |
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; |
- } |
-} |
- |
-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, |
+ return tempFBOID; |
+ } |
+} |
+ |
+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 @@ |
} |
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 @@ |
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 @@ |
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,13 +2733,14 @@ |
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; |
} |