Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 6d14e7e6c583920215ecda7f6f6100487221d7c4..df41883ace784a8a84eecda9cad80bb0abcb1b79 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -118,7 +118,9 @@ static bool gPrintStartupSpew; |
GrGLGpu::GrGLGpu(const GrGLContext& ctx, GrContext* context) |
: GrGpu(context) |
- , fGLContext(ctx) { |
+ , fGLContext(ctx) |
+ , fTempSrcFBO(this) |
+ , fTempDstFBO(this) { |
SkASSERT(ctx.isInitialized()); |
fCaps.reset(SkRef(ctx.caps())); |
@@ -171,6 +173,8 @@ void GrGLGpu::contextAbandoned() { |
INHERITED::contextAbandoned(); |
fProgramCache->abandon(); |
fHWProgramID = 0; |
+ fTempSrcFBO.reset(); |
+ fTempDstFBO.reset(); |
if (this->glCaps().pathRenderingSupport()) { |
this->glPathRendering()->abandonGpuResources(); |
} |
@@ -2452,8 +2456,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 +2466,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 +2474,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 +2498,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 +2508,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)); |
+ TempFBO* tempFBO = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBO : &fTempDstFBO; |
+ |
+ if (0 == tempFBO->fID) { |
+ GR_GL_CALL(this->glInterface(), GenFramebuffers(1, &tempFBO->fID)); |
+ } |
+ |
fGPUStats.incRenderTargetBinds(); |
- GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, tempFBOID)); |
+ GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, tempFBO->fID)); |
GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, |
GR_GL_COLOR_ATTACHMENT0, |
GR_GL_TEXTURE_2D, |
@@ -2539,6 +2541,14 @@ GrGLuint GrGLGpu::bindSurfaceAsFBO(GrSurface* surface, GrGLenum fboTarget, GrGLI |
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) { |
// In here we look for opportunities to use CopyTexSubImage, or fbo blit. If neither are |
// possible and we return false to fallback to creating a render target dst for render-to- |
@@ -2590,7 +2600,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 +2627,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 +2642,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 +2686,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 +2701,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()); |