diff options
author | 2017-04-03 14:49:05 -0700 | |
---|---|---|
committer | 2017-04-04 17:26:38 +0000 | |
commit | 744808823f635c863d7ca6b4eba652115c92ff85 (patch) | |
tree | 050a0e591c7dd355071a78daa6393d2f5f2f054f /src | |
parent | 8b3f9e64ff6d505036f79aeffd98dea4b648cb46 (diff) |
Respect kRectsMustMatchForMSAASrc_BlitFramebufferFlag in dst setup
Crurently, when preparing a texture for blitFramebuffer, we ignore the
kRectsMustMatchForMSAASrc_BlitFramebufferFlag, and may attempt to
copy from one src rect to a different dst rect.
This change updates initDescForDstCopy and setupDstTexture to allocate
larger textures if necessary and accomodate this flags requirements.
Bug: 658277
Change-Id: If4489ac3192dcf6f9996494c63821279721d0a12
Reviewed-on: https://skia-review.googlesource.com/11141
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 34 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 32 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 19 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 7 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.h | 3 |
6 files changed, 80 insertions, 18 deletions
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index e225bc9e5e..f4c4410dc4 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1751,10 +1751,11 @@ void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& cl clip.getConservativeBounds(rt->width(), rt->height(), ©Rect); SkIRect drawIBounds; + SkIRect clippedRect; opBounds.roundOut(&drawIBounds); // Cover up for any precision issues by outsetting the op bounds a pixel in each direction. drawIBounds.outset(1, 1); - if (!copyRect.intersect(drawIBounds)) { + if (!clippedRect.intersect(copyRect, drawIBounds)) { #ifdef SK_DEBUG GrCapsDebugf(this->caps(), "Missed an early reject. " "Bailing on draw from setupDstTexture.\n"); @@ -1765,24 +1766,43 @@ void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& cl // MSAA consideration: When there is support for reading MSAA samples in the shader we could // have per-sample dst values by making the copy multisampled. GrSurfaceDesc desc; - if (!this->caps()->initDescForDstCopy(rt, &desc)) { + bool rectsMustMatch = false; + bool disallowSubrect = false; + if (!this->caps()->initDescForDstCopy(rt, &desc, &rectsMustMatch, &disallowSubrect)) { desc.fOrigin = kDefault_GrSurfaceOrigin; desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fConfig = rt->config(); } - desc.fWidth = copyRect.width(); - desc.fHeight = copyRect.height(); + if (!disallowSubrect) { + copyRect = clippedRect; + } + SkIPoint dstPoint; + SkIPoint dstOffset; static const uint32_t kFlags = 0; - sk_sp<GrTexture> copy(fContext->resourceProvider()->createApproxTexture(desc, kFlags)); + sk_sp<GrTexture> copy; + if (rectsMustMatch) { + SkASSERT(desc.fOrigin == rt->origin()); + desc.fWidth = rt->width(); + desc.fHeight = rt->height(); + dstPoint = {copyRect.fLeft, copyRect.fTop}; + dstOffset = {0, 0}; + copy.reset(fContext->resourceProvider()->createTexture(desc, SkBudgeted::kYes, kFlags)); + } else { + desc.fWidth = copyRect.width(); + desc.fHeight = copyRect.height(); + dstPoint = {0, 0}; + dstOffset = {copyRect.fLeft, copyRect.fTop}; + copy.reset(fContext->resourceProvider()->createApproxTexture(desc, kFlags)); + } if (!copy) { SkDebugf("Failed to create temporary copy of destination texture.\n"); return; } - SkIPoint dstPoint = {0, 0}; + this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint); dstTexture->setTexture(std::move(copy)); - dstTexture->setOffset(copyRect.fLeft, copyRect.fTop); + dstTexture->setOffset(dstOffset); } diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 2ec95347f8..1a41a5b686 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -1018,6 +1018,7 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa // is available. if (ctxInfo.version() >= GR_GL_VER(3, 0)) { fBlitFramebufferFlags = kNoFormatConversionForMSAASrc_BlitFramebufferFlag | + kNoMSAADst_BlitFramebufferFlag | kRectsMustMatchForMSAASrc_BlitFramebufferFlag; } else if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample") || ctxInfo.hasExtension("GL_ANGLE_framebuffer_blit")) { @@ -1026,7 +1027,8 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa fBlitFramebufferFlags = kNoScalingOrMirroring_BlitFramebufferFlag | kResolveMustBeFull_BlitFrambufferFlag | kNoMSAADst_BlitFramebufferFlag | - kNoFormatConversion_BlitFramebufferFlag; + kNoFormatConversion_BlitFramebufferFlag | + kRectsMustMatchForMSAASrc_BlitFramebufferFlag; } } else { if (fUsesMixedSamples) { @@ -2068,7 +2070,14 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions, #endif } -bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const { +bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, + bool* rectsMustMatch, bool* disallowSubrect) const { + // By default, we don't require rects to match. + *rectsMustMatch = false; + + // By default, we allow subrects. + *disallowSubrect = false; + // If the src is a texture, we can implement the blit as a draw assuming the config is // renderable. if (src->asTexture() && this->isConfigRenderable(src->config(), false)) { @@ -2089,7 +2098,20 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc // texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo // creation. It isn't clear that avoiding temporary fbo creation is actually optimal. GrSurfaceOrigin originForBlitFramebuffer = kDefault_GrSurfaceOrigin; - if (this->blitFramebufferSupportFlags() & kNoScalingOrMirroring_BlitFramebufferFlag) { + bool rectsMustMatchForBlitFramebuffer = false; + bool disallowSubrectForBlitFramebuffer = false; + if (src->numColorSamples() && + (this->blitFramebufferSupportFlags() & kResolveMustBeFull_BlitFrambufferFlag)) { + rectsMustMatchForBlitFramebuffer = true; + disallowSubrectForBlitFramebuffer = true; + // Mirroring causes rects to mismatch later, don't allow it. + originForBlitFramebuffer = src->origin(); + } else if (src->numColorSamples() && (this->blitFramebufferSupportFlags() & + kRectsMustMatchForMSAASrc_BlitFramebufferFlag)) { + rectsMustMatchForBlitFramebuffer = true; + // Mirroring causes rects to mismatch later, don't allow it. + originForBlitFramebuffer = src->origin(); + } else if (this->blitFramebufferSupportFlags() & kNoScalingOrMirroring_BlitFramebufferFlag) { originForBlitFramebuffer = src->origin(); } @@ -2100,6 +2122,8 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc if (this->canConfigBeFBOColorAttachment(kBGRA_8888_GrPixelConfig)) { desc->fOrigin = originForBlitFramebuffer; desc->fConfig = kBGRA_8888_GrPixelConfig; + *rectsMustMatch = rectsMustMatchForBlitFramebuffer; + *disallowSubrect = disallowSubrectForBlitFramebuffer; return true; } return false; @@ -2112,6 +2136,8 @@ bool GrGLCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc if (this->canConfigBeFBOColorAttachment(src->config())) { desc->fOrigin = originForBlitFramebuffer; desc->fConfig = src->config(); + *rectsMustMatch = rectsMustMatchForBlitFramebuffer; + *disallowSubrect = disallowSubrectForBlitFramebuffer; return true; } return false; diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index a659435784..b8c4745a50 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -359,7 +359,8 @@ public: return fRGBAToBGRAReadbackConversionsAreSlow; } - bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override; + bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, bool* rectsMustMatch, + bool* disallowSubrect) const override; private: enum ExternalFormatUsage { diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 6cdda0672a..3af3ed25aa 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -3344,8 +3344,13 @@ static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst, } } if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) { - if (srcRT && srcRT->numColorSamples() && dstRT && !dstRT->numColorSamples()) { - return false; + if (srcRT && srcRT->numColorSamples()) { + if (dstRT && !dstRT->numColorSamples()) { + return false; + } + if (SkRect::Make(srcRect) != srcRT->getBoundsRect()) { + return false; + } } } if (GrGLCaps::kNoMSAADst_BlitFramebufferFlag & blitFramebufferFlags) { @@ -3364,9 +3369,13 @@ static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst, } } if (GrGLCaps::kRectsMustMatchForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) { - if (srcRT && srcRT->numColorSamples() && - (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop)) { - return false; + if (srcRT && srcRT->numColorSamples()) { + if (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop) { + return false; + } + if (dst->origin() != src->origin()) { + return false; + } } } return true; diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp index bf343a9ae9..bf7e5ad3ce 100644 --- a/src/gpu/vk/GrVkCaps.cpp +++ b/src/gpu/vk/GrVkCaps.cpp @@ -53,7 +53,12 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* this->init(contextOptions, vkInterface, physDev, featureFlags, extensionFlags); } -bool GrVkCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const { +bool GrVkCaps::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, + bool* rectsMustMatch, bool* disallowSubrect) const { + // Vk doesn't use rectsMustMatch or disallowSubrect. Always return false. + *rectsMustMatch = false; + *disallowSubrect = false; + // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa). // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a // render target as well. diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h index 73ed367896..dce9ce2200 100644 --- a/src/gpu/vk/GrVkCaps.h +++ b/src/gpu/vk/GrVkCaps.h @@ -104,7 +104,8 @@ public: return fPreferedStencilFormat; } - bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const override; + bool initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc, bool* rectsMustMatch, + bool* disallowSubrect) const override; private: enum VkVendor { |