Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index e29a7f81f317aa189e7263dc23416263cb264e8e..b9a5ee98373e56a08091e69b9ff528a3b086c683 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -2438,7 +2438,7 @@ void GrGLGpu::performFlushWorkaround() { |
} |
} |
-void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) { |
+void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bounds) { |
SkASSERT(target); |
uint32_t rtID = target->getUniqueID(); |
@@ -2459,11 +2459,7 @@ void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) |
} |
#endif |
fHWBoundRenderTargetUniqueID = rtID; |
- const GrGLIRect& vp = target->getViewport(); |
- if (fHWViewport != vp) { |
- vp.pushToGLViewport(this->glInterface()); |
- fHWViewport = vp; |
- } |
+ this->flushViewport(target->getViewport()); |
if (this->glCaps().srgbWriteControl()) { |
bool enableSRGBWrite = GrPixelConfigIsSRGB(target->config()); |
if (enableSRGBWrite && kYes_TriState != fHWSRGBFramebuffer) { |
@@ -2475,11 +2471,24 @@ void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) |
} |
} |
} |
+ this->didWriteToSurface(target, bounds); |
+} |
+ |
+void GrGLGpu::flushViewport(const GrGLIRect& viewport) { |
+ if (fHWViewport != viewport) { |
+ viewport.pushToGLViewport(this->glInterface()); |
+ fHWViewport = viewport; |
+ } |
+} |
+void GrGLGpu::didWriteToSurface(GrSurface* surface, const SkIRect* bounds) const { |
+ SkASSERT(surface); |
// Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds. |
- if (nullptr == bound || !bound->isEmpty()) { |
- target->flagAsNeedingResolve(bound); |
- if (GrTexture *texture = target->asTexture()) { |
+ if (nullptr == bounds || !bounds->isEmpty()) { |
+ if (GrRenderTarget* target = surface->asRenderTarget()) { |
+ target->flagAsNeedingResolve(bounds); |
+ } |
+ if (GrTexture* texture = surface->asTexture()) { |
texture->texturePriv().dirtyMipMaps(true); |
} |
} |
@@ -2759,6 +2768,8 @@ void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) { |
} |
void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled) { |
+ // rt is only optional if useHWAA is false. |
+ SkASSERT(rt || !useHWAA); |
SkASSERT(!useHWAA || rt->isStencilBufferMultisampled()); |
if (this->glCaps().multisampleDisableSupport()) { |
@@ -3068,8 +3079,19 @@ static inline bool can_blit_framebuffer(const GrSurface* dst, |
const GrSurface* src, |
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()) { |
+ gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0)) { |
+ switch (gpu->glCaps().blitFramebufferSupport()) { |
+ case GrGLCaps::kNone_BlitFramebufferSupport: |
+ return false; |
+ case GrGLCaps::kNoScalingNoMirroring_BlitFramebufferSupport: |
+ // Our copy surface doesn't support scaling so just check for mirroring. |
+ if (dst->origin() != src->origin()) { |
+ return false; |
+ } |
+ break; |
+ case GrGLCaps::kFull_BlitFramebufferSupport: |
+ break; |
+ } |
// ES3 doesn't allow framebuffer blits when the src has MSAA and the configs don't match |
// or the rects are not the same (not just the same size but have the same edges). |
if (GrGLCaps::kES_3_0_MSFBOType == gpu->glCaps().msFBOType() && |
@@ -3140,7 +3162,7 @@ static inline bool can_copy_texsubimage(const GrSurface* dst, |
void GrGLGpu::bindSurfaceFBOForCopy(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport, |
TempFBOTarget tempFBOTarget) { |
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget()); |
- if (nullptr == rt) { |
+ if (!rt) { |
SkASSERT(surface->asTexture()); |
GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID(); |
GrGLenum target = static_cast<GrGLTexture*>(surface->asTexture())->target(); |
@@ -3250,7 +3272,9 @@ bool GrGLGpu::onCopySurface(GrSurface* dst, |
this->glCaps().glslCaps()->configOutputSwizzle(dst->config())) { |
return false; |
} |
- if (src->asTexture() && dst->asRenderTarget()) { |
+ // Don't prefer copying as a draw if the dst doesn't already have a FBO object. |
+ bool preferCopy = SkToBool(dst->asRenderTarget()); |
+ if (preferCopy && src->asTexture()) { |
this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); |
return true; |
} |
@@ -3264,6 +3288,11 @@ bool GrGLGpu::onCopySurface(GrSurface* dst, |
return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint); |
} |
+ if (!preferCopy && src->asTexture()) { |
+ this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); |
+ return true; |
+ } |
+ |
return false; |
} |
@@ -3560,9 +3589,12 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst, |
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode); |
this->bindTexture(0, params, srcTex); |
- GrGLRenderTarget* dstRT = static_cast<GrGLRenderTarget*>(dst->asRenderTarget()); |
+ GrGLIRect dstVP; |
+ this->bindSurfaceFBOForCopy(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget); |
+ this->flushViewport(dstVP); |
+ fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
+ |
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h); |
- this->flushRenderTarget(dstRT, &dstRect); |
int progIdx = TextureTargetToCopyProgramIdx(srcTex->target()); |
@@ -3618,13 +3650,16 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst, |
this->flushBlend(blendInfo, GrSwizzle::RGBA()); |
this->flushColorWrite(true); |
this->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace); |
- this->flushHWAAState(dstRT, false, false); |
+ this->flushHWAAState(nullptr, false, false); |
this->disableScissor(); |
GrStencilSettings stencil; |
stencil.setDisabled(); |
this->flushStencil(stencil); |
GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4)); |
+ this->unbindTextureFBOForCopy(GR_GL_FRAMEBUFFER, dst); |
+ this->didWriteToSurface(dst, &dstRect); |
+ |
} |
void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, |
@@ -3634,7 +3669,7 @@ void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, |
SkASSERT(can_copy_texsubimage(dst, src, this)); |
GrGLIRect srcVP; |
this->bindSurfaceFBOForCopy(src, GR_GL_FRAMEBUFFER, &srcVP, kSrc_TempFBOTarget); |
- GrGLTexture* dstTex = static_cast<GrGLTexture*>(dst->asTexture()); |
+ GrGLTexture* dstTex = static_cast<GrGLTexture *>(dst->asTexture()); |
SkASSERT(dstTex); |
// We modified the bound FBO |
fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; |
@@ -3655,10 +3690,13 @@ void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst, |
dstY = dstPoint.fY; |
} |
GL_CALL(CopyTexSubImage2D(dstTex->target(), 0, |
- dstPoint.fX, dstY, |
- srcGLRect.fLeft, srcGLRect.fBottom, |
- srcGLRect.fWidth, srcGLRect.fHeight)); |
+ dstPoint.fX, dstY, |
+ srcGLRect.fLeft, srcGLRect.fBottom, |
+ srcGLRect.fWidth, srcGLRect.fHeight)); |
this->unbindTextureFBOForCopy(GR_GL_FRAMEBUFFER, src); |
+ SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, |
+ srcRect.width(), srcRect.height()); |
+ this->didWriteToSurface(dst, &dstRect); |
} |
bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, |
@@ -3719,6 +3757,7 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, |
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); |
this->unbindTextureFBOForCopy(GR_GL_DRAW_FRAMEBUFFER, dst); |
this->unbindTextureFBOForCopy(GR_GL_READ_FRAMEBUFFER, src); |
+ this->didWriteToSurface(dst, &dstRect); |
return true; |
} |