diff options
author | egdaniel <egdaniel@google.com> | 2015-02-03 11:10:51 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-03 11:10:51 -0800 |
commit | 0f5f967f6777612353c762e6d0095f733adfb326 (patch) | |
tree | f2ae7268e8595088975901e1d702bfa97d6cb9f2 /src | |
parent | 46c77f76be8cbcddccc1ae0058d589cbbdb468f7 (diff) |
Save and temp dst and src FBO on GrGLGpu and use the temp FBOs for copySurface if needed.
BUG=skia:
Review URL: https://codereview.chromium.org/893703003
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 73 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 13 |
2 files changed, 57 insertions, 29 deletions
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index e32b2e6b8f..dd55abb0a6 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -150,6 +150,8 @@ GrGLGpu::GrGLGpu(const GrGLContext& ctx, GrContext* context) fLastSuccessfulStencilFmtIdx = 0; fHWProgramID = 0; + fTempSrcFBOID = 0; + fTempDstFBOID = 0; if (this->glCaps().pathRenderingSupport()) { fPathRendering.reset(new GrGLPathRendering(this)); @@ -164,6 +166,13 @@ GrGLGpu::~GrGLGpu() { GL_CALL(UseProgram(0)); } + if (0 != fTempSrcFBOID) { + GL_CALL(DeleteFramebuffers(1, &fTempSrcFBOID)); + } + if (0 != fTempDstFBOID) { + GL_CALL(DeleteFramebuffers(1, &fTempDstFBOID)); + } + delete fProgramCache; } @@ -171,6 +180,8 @@ void GrGLGpu::contextAbandoned() { INHERITED::contextAbandoned(); fProgramCache->abandon(); fHWProgramID = 0; + fTempSrcFBOID = 0; + fTempDstFBOID = 0; if (this->glCaps().pathRenderingSupport()) { this->glPathRendering()->abandonGpuResources(); } @@ -2452,8 +2463,7 @@ namespace { // Determines whether glBlitFramebuffer could be used between src and dst. inline bool can_blit_framebuffer(const GrSurface* dst, const GrSurface* src, - const GrGLGpu* gpu, - bool* wouldNeedTempFBO = NULL) { + const GrGLGpu* gpu) { if (gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) && gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) && gpu->glCaps().usesMSAARenderBuffers()) { @@ -2463,9 +2473,6 @@ inline bool can_blit_framebuffer(const GrSurface* dst, (src->desc().fSampleCnt > 0 || src->config() != dst->config())) { return false; } - if (wouldNeedTempFBO) { - *wouldNeedTempFBO = NULL == dst->asRenderTarget() || NULL == src->asRenderTarget(); - } return true; } else { return false; @@ -2474,8 +2481,7 @@ inline bool can_blit_framebuffer(const GrSurface* dst, inline bool can_copy_texsubimage(const GrSurface* dst, const GrSurface* src, - const GrGLGpu* gpu, - bool* wouldNeedTempFBO = NULL) { + const GrGLGpu* gpu) { // Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage // and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps // many drivers would allow it to work, but ANGLE does not. @@ -2499,9 +2505,6 @@ inline bool can_copy_texsubimage(const GrSurface* dst, dst->asTexture() && dst->origin() == src->origin() && !GrPixelConfigIsCompressed(src->config())) { - if (wouldNeedTempFBO) { - *wouldNeedTempFBO = NULL == src->asRenderTarget(); - } return true; } else { return false; @@ -2512,15 +2515,21 @@ 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) { +GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport, + TempFBOTarget tempFBOTarget) { GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget()); - GrGLuint tempFBOID; if (NULL == rt) { SkASSERT(surface->asTexture()); GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID(); - GR_GL_CALL(this->glInterface(), GenFramebuffers(1, &tempFBOID)); + 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(), BindFramebuffer(fboTarget, *tempFBOID)); GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, GR_GL_COLOR_ATTACHMENT0, GR_GL_TEXTURE_2D, @@ -2530,13 +2539,22 @@ GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLI viewport->fBottom = 0; viewport->fWidth = surface->width(); viewport->fHeight = surface->height(); + return *tempFBOID; } else { - tempFBOID = 0; + GrGLuint tempFBOID = 0; fStats.incRenderTargetBinds(); GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBOID())); *viewport = rt->getViewport(); + return tempFBOID; } - return tempFBOID; +} + +void GrGLGpu::unbindTextureFromFBO(GrGLenum fboTarget) { + GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, + GR_GL_COLOR_ATTACHMENT0, + GR_GL_TEXTURE_2D, + 0, + 0)); } bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) { @@ -2590,7 +2608,7 @@ bool GrGLGpu::copySurface(GrSurface* dst, if (can_copy_texsubimage(dst, src, this)) { GrGLuint srcFBO; GrGLIRect srcVP; - srcFBO = this->bindSurfaceAsFBO(src, GR_GL_FRAMEBUFFER, &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 @@ -2617,7 +2635,7 @@ bool GrGLGpu::copySurface(GrSurface* dst, srcGLRect.fWidth, srcGLRect.fHeight)); copied = true; if (srcFBO) { - GL_CALL(DeleteFramebuffers(1, &srcFBO)); + this->unbindTextureFromFBO(GR_GL_FRAMEBUFFER); } } else if (can_blit_framebuffer(dst, src, this)) { SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, @@ -2632,8 +2650,10 @@ bool GrGLGpu::copySurface(GrSurface* dst, GrGLuint srcFBO; GrGLIRect dstVP; GrGLIRect srcVP; - dstFBO = this->bindSurfaceAsFBO(dst, GR_GL_DRAW_FRAMEBUFFER, &dstVP); - srcFBO = this->bindSurfaceAsFBO(src, GR_GL_READ_FRAMEBUFFER, &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; @@ -2674,10 +2694,10 @@ bool GrGLGpu::copySurface(GrSurface* dst, dstGLRect.fBottom + dstGLRect.fHeight, GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); if (dstFBO) { - GL_CALL(DeleteFramebuffers(1, &dstFBO)); + this->unbindTextureFromFBO(GR_GL_DRAW_FRAMEBUFFER); } if (srcFBO) { - GL_CALL(DeleteFramebuffers(1, &srcFBO)); + this->unbindTextureFromFBO(GR_GL_READ_FRAMEBUFFER); } copied = true; } @@ -2689,14 +2709,11 @@ bool GrGLGpu::canCopySurface(const GrSurface* dst, const GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) { - // This mirrors the logic in onCopySurface. We prefer our base makes the copy if we need to - // create a temp fbo. TODO verify the assumption that temp fbos are expensive; it may not be - // true at all. - bool wouldNeedTempFBO = false; - if (can_copy_texsubimage(dst, src, this, &wouldNeedTempFBO) && !wouldNeedTempFBO) { + // This mirrors the logic in onCopySurface. + if (can_copy_texsubimage(dst, src, this)) { return true; } - if (can_blit_framebuffer(dst, src, this, &wouldNeedTempFBO) && !wouldNeedTempFBO) { + if (can_blit_framebuffer(dst, src, this)) { if (dst == src) { SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, srcRect.width(), srcRect.height()); diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index c5103ebb11..7eda014344 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -283,7 +283,15 @@ private: bool createRenderTargetObjects(const GrSurfaceDesc&, bool budgeted, GrGLuint texID, GrGLRenderTarget::IDDesc*); - GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport); + enum TempFBOTarget { + kSrc_TempFBOTarget, + kDst_TempFBOTarget + }; + + GrGLuint bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport, + TempFBOTarget tempFBOTarget); + + void unbindTextureFromFBO(GrGLenum fboTarget); GrGLContext fGLContext; @@ -303,6 +311,9 @@ private: kUnknown_TriState }; + GrGLuint fTempSrcFBOID; + GrGLuint fTempDstFBOID; + // last scissor / viewport scissor state seen by the GL. struct { TriState fEnabled; |