Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index a952c4f7680643ee24dde5c5552352b15abdef76..e08ee85db211c8de3aa650bd4a9e94aecfab4e57 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -121,6 +121,10 @@ GrGLGpu::GrGLGpu(const GrGLContext& ctx, GrContext* context) |
: GrGpu(context) |
, fGLContext(ctx) { |
+ fTempSrcFBO.reset(SkNEW(GrGLFBO)); |
+ fTempDstFBO.reset(SkNEW(GrGLFBO)); |
+ fStencilClearFBO.reset(SkNEW(GrGLFBO)); |
+ |
SkASSERT(ctx.isInitialized()); |
fCaps.reset(SkRef(ctx.caps())); |
@@ -151,9 +155,6 @@ 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)); |
@@ -168,15 +169,9 @@ GrGLGpu::~GrGLGpu() { |
GL_CALL(UseProgram(0)); |
} |
- if (0 != fTempSrcFBOID) { |
- GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID)); |
- } |
- if (0 != fTempDstFBOID) { |
- GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID)); |
- } |
- if (0 != fStencilClearFBOID) { |
- GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID)); |
- } |
+ fTempSrcFBO->deleteIfValid(this); |
+ fTempDstFBO->deleteIfValid(this); |
+ fStencilClearFBO->deleteIfValid(this); |
delete fProgramCache; |
} |
@@ -185,9 +180,9 @@ void GrGLGpu::contextAbandoned() { |
INHERITED::contextAbandoned(); |
fProgramCache->abandon(); |
fHWProgramID = 0; |
- fTempSrcFBOID = 0; |
- fTempDstFBOID = 0; |
- fStencilClearFBOID = 0; |
+ fTempSrcFBO->abandon(this); |
+ fTempDstFBO->abandon(this); |
+ fStencilClearFBO->abandon(this); |
if (this->glCaps().pathRenderingSupport()) { |
this->glPathRendering()->abandonGpuResources(); |
} |
@@ -331,7 +326,9 @@ void GrGLGpu::onResetContext(uint32_t resetBits) { |
} |
if (resetBits & kRenderTarget_GrGLBackendState) { |
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fHWFBOBinding); ++i) { |
+ fHWFBOBinding[i].invalidate(); |
+ } |
} |
if (resetBits & kPathRendering_GrGLBackendState) { |
@@ -432,9 +429,9 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc) { |
GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc) { |
GrGLRenderTarget::IDDesc idDesc; |
- idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); |
+ GrGLuint fboID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); |
+ idDesc.fRenderFBO.reset(SkNEW_ARGS(GrGLFBO, (fboID))); |
idDesc.fMSColorRenderbufferID = 0; |
- idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; |
idDesc.fLifeCycle = GrGpuResource::kWrapped_LifeCycle; |
GrSurfaceDesc desc; |
@@ -814,8 +811,6 @@ 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; |
@@ -827,21 +822,22 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted |
goto FAILED; |
} |
- GL_CALL(GenFramebuffers(1, &idDesc->fTexFBOID)); |
- if (!idDesc->fTexFBOID) { |
+ idDesc->fTextureFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface()))); |
+ if (!idDesc->fTextureFBO->isValid()) { |
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()) { |
- GL_CALL(GenFramebuffers(1, &idDesc->fRTFBOID)); |
+ idDesc->fRenderFBO.reset(SkNEW_ARGS(GrGLFBO, (this->glInterface()))); |
+ if (!idDesc->fRenderFBO->isValid()) { |
+ goto FAILED; |
+ } |
GL_CALL(GenRenderbuffers(1, &idDesc->fMSColorRenderbufferID)); |
- if (!idDesc->fRTFBOID || |
- !idDesc->fMSColorRenderbufferID || |
+ if (!idDesc->fMSColorRenderbufferID || |
!this->configToGLFormats(desc.fConfig, |
// ES2 and ES3 require sized internal formats for rb storage. |
kGLES_GrGLStandard == this->glStandard(), |
@@ -851,12 +847,10 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted |
goto FAILED; |
} |
} else { |
- idDesc->fRTFBOID = idDesc->fTexFBOID; |
+ idDesc->fRenderFBO.reset(SkRef(idDesc->fTextureFBO.get())); |
} |
- // below here we may bind the FBO |
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
- if (idDesc->fRTFBOID != idDesc->fTexFBOID) { |
+ if (idDesc->fRenderFBO != idDesc->fTextureFBO) { |
SkASSERT(desc.fSampleCnt > 0); |
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbufferID)); |
if (!renderbuffer_storage_msaa(fGLContext, |
@@ -865,12 +859,11 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted |
desc.fWidth, desc.fHeight)) { |
goto FAILED; |
} |
- fStats.incRenderTargetBinds(); |
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID)); |
+ this->bindFBO(kDraw_FBOBinding, idDesc->fRenderFBO); |
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
- GR_GL_COLOR_ATTACHMENT0, |
- GR_GL_RENDERBUFFER, |
- idDesc->fMSColorRenderbufferID)); |
+ 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)); |
@@ -880,8 +873,7 @@ bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc, bool budgeted |
fGLContext.caps()->markConfigAsValidColorAttachment(desc.fConfig); |
} |
} |
- fStats.incRenderTargetBinds(); |
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fTexFBOID)); |
+ this->bindFBO(kDraw_FBOBinding, idDesc->fTextureFBO); |
if (this->glCaps().usesImplicitMSAAResolve() && desc.fSampleCnt > 0) { |
GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER, |
@@ -909,12 +901,8 @@ FAILED: |
if (idDesc->fMSColorRenderbufferID) { |
GL_CALL(DeleteRenderbuffers(1, &idDesc->fMSColorRenderbufferID)); |
} |
- if (idDesc->fRTFBOID != idDesc->fTexFBOID) { |
- GL_CALL(DeleteFramebuffers(1, &idDesc->fRTFBOID)); |
- } |
- if (idDesc->fTexFBOID) { |
- GL_CALL(DeleteFramebuffers(1, &idDesc->fTexFBOID)); |
- } |
+ idDesc->fRenderFBO->deleteIfValid(this); |
+ idDesc->fTextureFBO->deleteIfValid(this); |
return false; |
} |
@@ -1186,13 +1174,8 @@ 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 (0 == fStencilClearFBOID) { |
- GL_CALL(GenFramebuffers(1, &fStencilClearFBOID)); |
- } |
- |
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fStencilClearFBOID)); |
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
- fStats.incRenderTargetBinds(); |
+ fStencilClearFBO->generateIfInvalid(this->glInterface()); |
+ this->bindFBO(kDraw_FBOBinding, fStencilClearFBO); |
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
GR_GL_STENCIL_ATTACHMENT, |
GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID)); |
@@ -1230,9 +1213,6 @@ 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, |
@@ -1252,9 +1232,8 @@ bool GrGLGpu::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTar |
GrGLStencilBuffer* glsb = static_cast<GrGLStencilBuffer*>(sb); |
GrGLuint rb = glsb->renderbufferID(); |
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
- fStats.incRenderTargetBinds(); |
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo)); |
+ this->bindFBO(kDraw_FBOBinding, glrt->renderFBO()); |
+ |
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
GR_GL_STENCIL_ATTACHMENT, |
GR_GL_RENDERBUFFER, rb)); |
@@ -1423,7 +1402,7 @@ bool GrGLGpu::flushGLState(const DrawArgs& args, bool isLineDraw) { |
// This must come after textures are flushed because a texture may need |
// to be msaa-resolved (which will modify bound FBO state). |
- this->flushRenderTarget(glRT, NULL); |
+ this->prepareToDrawToRenderTarget(glRT, NULL); |
return true; |
} |
@@ -1520,7 +1499,7 @@ void GrGLGpu::onClear(GrRenderTarget* target, const SkIRect* rect, GrColor color |
} |
} |
- this->flushRenderTarget(glRT, rect); |
+ this->prepareToDrawToRenderTarget(glRT, rect); |
GrScissorState scissorState; |
if (rect) { |
scissorState.set(*rect); |
@@ -1548,17 +1527,13 @@ void GrGLGpu::discard(GrRenderTarget* renderTarget) { |
} |
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(renderTarget); |
- if (renderTarget->getUniqueID() != fHWBoundRenderTargetUniqueID) { |
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
- fStats.incRenderTargetBinds(); |
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRT->renderFBOID())); |
- } |
+ this->bindFBO(kDraw_FBOBinding, glRT->renderFBO()); |
switch (this->glCaps().invalidateFBType()) { |
case GrGLCaps::kNone_InvalidateFBType: |
SkFAIL("Should never get here."); |
break; |
case GrGLCaps::kInvalidate_InvalidateFBType: |
- if (0 == glRT->renderFBOID()) { |
+ if (glRT->renderFBO()->isDefaultFramebuffer()) { |
// 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. |
@@ -1572,7 +1547,7 @@ void GrGLGpu::discard(GrRenderTarget* renderTarget) { |
} |
break; |
case GrGLCaps::kDiscard_InvalidateFBType: { |
- if (0 == glRT->renderFBOID()) { |
+ if (glRT->renderFBO()->isDefaultFramebuffer()) { |
// 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. |
@@ -1596,7 +1571,7 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) { |
return; |
} |
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); |
- this->flushRenderTarget(glRT, &SkIRect::EmptyIRect()); |
+ this->prepareToDrawToRenderTarget(glRT, &SkIRect::EmptyIRect()); |
this->disableScissor(); |
@@ -1632,7 +1607,7 @@ void GrGLGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bo |
value = 0; |
} |
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target); |
- this->flushRenderTarget(glRT, &SkIRect::EmptyIRect()); |
+ this->prepareToDrawToRenderTarget(glRT, &SkIRect::EmptyIRect()); |
GrScissorState scissorState; |
scissorState.set(rect); |
@@ -1702,22 +1677,13 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target, |
// resolve the render target if necessary |
GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target); |
- 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"); |
+ if (tgt->getResolveType() == GrGLRenderTarget::kCantResolve_ResolveType) { |
+ return false; |
+ } |
+ if (tgt->getResolveType() == GrGLRenderTarget::kCanResolve_ResolveType) { |
+ this->onResolveRenderTarget(tgt); |
} |
+ this->bindFBO(kRead_FBOBinding, tgt->textureFBO()); |
const GrGLIRect& glvp = tgt->getViewport(); |
@@ -1803,34 +1769,71 @@ bool GrGLGpu::onReadPixels(GrRenderTarget* target, |
return true; |
} |
-void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) { |
+void GrGLGpu::willDeleteOrAbandonFramebuffer(GrGLFBO* fbo) { |
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fHWFBOBinding); ++i) { |
+ if (fHWFBOBinding[i].fGenID == fbo->genID()) { |
+ fHWFBOBinding[i].invalidate(); |
+ } |
+ } |
+} |
- SkASSERT(target); |
+static GrGLenum glenum_for_binding(GrGLGpu::FBOBinding binding, const GrGLCaps& caps) { |
+ // If the GL doesn't have render buffers then it also doesn't have separate read/write FBOs |
+ if (caps.usesMSAARenderBuffers()) { |
+ return GR_GL_FRAMEBUFFER; |
+ } else { |
+ if (GrGLGpu::kDraw_FBOBinding == binding) { |
+ return GR_GL_DRAW_FRAMEBUFFER; |
+ } else { |
+ SkASSERT(GrGLGpu::kRead_FBOBinding == binding); |
+ return GR_GL_READ_FRAMEBUFFER; |
+ } |
+ } |
+} |
+ |
+GrGLenum GrGLGpu::bindFBO(FBOBinding binding, const GrGLFBO* fbo) { |
+ GrGLenum target = glenum_for_binding(binding, this->glCaps()); |
+ HWFBOBinding* hwFBOState; |
+ if (!this->glCaps().usesMSAARenderBuffers()) { |
+ hwFBOState = &fHWFBOBinding[0]; |
+ } else { |
+ hwFBOState = &fHWFBOBinding[binding]; |
+ } |
- uint32_t rtID = target->getUniqueID(); |
- if (fHWBoundRenderTargetUniqueID != rtID) { |
+ if (hwFBOState->fGenID != fbo->genID()) { |
fStats.incRenderTargetBinds(); |
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, target->renderFBOID())); |
+ GL_CALL(BindFramebuffer(target, fbo->fboID())); |
+ hwFBOState->fGenID = fbo->genID(); |
+ hwFBOState->fIsDefaultFBO = fbo->isDefaultFramebuffer(); |
+ } |
+ return target; |
+} |
+ |
+void GrGLGpu::setViewport(const GrGLIRect& viewport) { |
+ if (viewport != fHWViewport) { |
+ viewport.pushToGLViewport(this->glInterface()); |
+ fHWViewport = viewport; |
+ } |
+} |
+ |
+void GrGLGpu::prepareToDrawToRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) { |
+ SkASSERT(target); |
+ this->bindFBO(kDraw_FBOBinding, target->renderFBO()); |
+ |
#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; |
+ // 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 |
+ this->setViewport(target->getViewport()); |
if (NULL == bound || !bound->isEmpty()) { |
target->flagAsNeedingResolve(bound); |
} |
@@ -1919,7 +1922,7 @@ 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, false); |
- this->flushRenderTarget(rt, NULL); |
+ this->prepareToDrawToRenderTarget(rt, NULL); |
fPathRendering->stencilPath(path, *state.fStencil); |
} |
@@ -1952,14 +1955,9 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) { |
if (rt->needsResolve()) { |
// Some extensions automatically resolves the texture when it is read. |
if (this->glCaps().usesMSAARenderBuffers()) { |
- 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; |
+ SkASSERT(rt->textureFBO() != rt->renderFBO()); |
+ this->bindFBO(kRead_FBOBinding, rt->renderFBO()); |
+ this->bindFBO(kDraw_FBOBinding, rt->textureFBO()); |
const GrGLIRect& vp = rt->getViewport(); |
const SkIRect dirtyRect = rt->getResolveRect(); |
@@ -2522,13 +2520,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->renderFBOID() != dstRT->textureFBOID()) { |
+ if (dstRT && dstRT->renderFBO() != dstRT->textureFBO()) { |
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->renderFBOID() != srcRT->textureFBOID()) { |
+ if (srcRT && srcRT->renderFBO() != srcRT->textureFBO()) { |
return false; |
} |
if (gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) && |
@@ -2545,22 +2543,17 @@ 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. |
-GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport, |
- TempFBOTarget tempFBOTarget) { |
+GrGLGpu::FBOBinding GrGLGpu::bindSurfaceAsFBOForCopy(GrSurface* surface, FBOBinding binding, |
+ GrGLIRect* viewport) { |
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget()); |
if (NULL == rt) { |
SkASSERT(surface->asTexture()); |
GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID(); |
- GrGLuint* tempFBOID; |
- tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID; |
- |
- if (0 == *tempFBOID) { |
- GR_GL_CALL(this->glInterface(), GenFramebuffers(1, tempFBOID)); |
- } |
+ GrGLFBO* tempFBO = kDraw_FBOBinding == binding ? fTempSrcFBO : fTempDstFBO; |
- fStats.incRenderTargetBinds(); |
- GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, *tempFBOID)); |
- GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, |
+ tempFBO->generateIfInvalid(this->glInterface()); |
+ GrGLenum target = this->bindFBO(binding, tempFBO); |
+ GR_GL_CALL(this->glInterface(), FramebufferTexture2D(target, |
GR_GL_COLOR_ATTACHMENT0, |
GR_GL_TEXTURE_2D, |
texID, |
@@ -2569,18 +2562,21 @@ GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLI |
viewport->fBottom = 0; |
viewport->fWidth = surface->width(); |
viewport->fHeight = surface->height(); |
- return *tempFBOID; |
+ return binding; |
} else { |
- GrGLuint tempFBOID = 0; |
- fStats.incRenderTargetBinds(); |
- GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID())); |
+ this->bindFBO(binding, rt->renderFBO()); |
*viewport = rt->getViewport(); |
- return tempFBOID; |
+ return kInvalidFBOBinding; |
} |
} |
-void GrGLGpu::unbindTextureFromFBO(GrGLenum fboTarget) { |
- GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, |
+void GrGLGpu::unbindSurfaceAsFBOForCopy(FBOBinding binding) { |
+ if (kInvalidFBOBinding == binding) { |
+ return; |
+ } |
+ GrGLFBO* tempFBO = kDraw_FBOBinding == binding ? fTempSrcFBO : fTempDstFBO; |
+ GrGLenum target = this->bindFBO(binding, tempFBO); |
+ GR_GL_CALL(this->glInterface(), FramebufferTexture2D(target, |
GR_GL_COLOR_ATTACHMENT0, |
GR_GL_TEXTURE_2D, |
0, |
@@ -2611,7 +2607,7 @@ bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) |
} |
const GrGLRenderTarget* srcRT = static_cast<const GrGLRenderTarget*>(src->asRenderTarget()); |
- if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) { |
+ if (srcRT && srcRT->renderFBO() != srcRT->textureFBO()) { |
// It's illegal to call CopyTexSubImage2D on a MSAA renderbuffer. Set up for FBO blit or |
// fail. |
if (this->caps()->isConfigRenderable(src->config(), false)) { |
@@ -2636,13 +2632,10 @@ bool GrGLGpu::copySurface(GrSurface* dst, |
const SkIPoint& dstPoint) { |
bool copied = false; |
if (can_copy_texsubimage(dst, src, this)) { |
- GrGLuint srcFBO; |
GrGLIRect srcVP; |
- srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget); |
+ FBOBinding srcFBOBinding = this->bindSurfaceAsFBOForCopy(src, kRead_FBOBinding, &srcVP); |
GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture()); |
SkASSERT(dstTex); |
- // We modified the bound FBO |
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
GrGLIRect srcGLRect; |
srcGLRect.setRelativeTo(srcVP, |
srcRect.fLeft, |
@@ -2664,9 +2657,7 @@ bool GrGLGpu::copySurface(GrSurface* dst, |
srcGLRect.fLeft, srcGLRect.fBottom, |
srcGLRect.fWidth, srcGLRect.fHeight)); |
copied = true; |
- if (srcFBO) { |
- this->unbindTextureFromFBO(GR_GL_FRAMEBUFFER); |
- } |
+ this->unbindSurfaceAsFBOForCopy(srcFBOBinding); |
} else if (can_blit_framebuffer(dst, src, this)) { |
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, |
srcRect.width(), srcRect.height()); |
@@ -2676,16 +2667,11 @@ bool GrGLGpu::copySurface(GrSurface* dst, |
} |
if (!selfOverlap) { |
- GrGLuint dstFBO; |
- GrGLuint srcFBO; |
GrGLIRect dstVP; |
GrGLIRect 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; |
+ FBOBinding dstFBOBinding = this->bindSurfaceAsFBOForCopy(dst, kDraw_FBOBinding, &dstVP); |
+ FBOBinding srcFBOBinding = this->bindSurfaceAsFBOForCopy(src, kRead_FBOBinding, &srcVP); |
+ |
GrGLIRect srcGLRect; |
GrGLIRect dstGLRect; |
srcGLRect.setRelativeTo(srcVP, |
@@ -2723,12 +2709,8 @@ bool GrGLGpu::copySurface(GrSurface* dst, |
dstGLRect.fLeft + dstGLRect.fWidth, |
dstGLRect.fBottom + dstGLRect.fHeight, |
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); |
- if (dstFBO) { |
- this->unbindTextureFromFBO(GR_GL_DRAW_FRAMEBUFFER); |
- } |
- if (srcFBO) { |
- this->unbindTextureFromFBO(GR_GL_READ_FRAMEBUFFER); |
- } |
+ this->unbindSurfaceAsFBOForCopy(dstFBOBinding); |
+ this->unbindSurfaceAsFBOForCopy(srcFBOBinding); |
copied = true; |
} |
} |