| 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());
|
|
|