diff options
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 18 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 25 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 118 |
3 files changed, 93 insertions, 68 deletions
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index c2e8f11b3b..23b069f9f8 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -52,7 +52,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fRGBAToBGRAReadbackConversionsAreSlow = false; fDoManualMipmapping = false; - fBlitFramebufferSupport = kNone_BlitFramebufferSupport; + fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag; fShaderCaps.reset(new GrGLSLCaps(contextOptions)); @@ -919,8 +919,6 @@ bool GrGLCaps::readPixelsSupported(GrPixelConfig rtConfig, } void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { - - fMSFBOType = kNone_MSFBOType; if (kGL_GrGLStandard != ctxInfo.standard()) { // We prefer the EXT/IMG extension over ES3 MSAA because we've observed // ES3 driver bugs on at least one device with a tiled GPU (N10). @@ -940,24 +938,28 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa // Above determined the preferred MSAA approach, now decide whether glBlitFramebuffer // is available. if (ctxInfo.version() >= GR_GL_VER(3, 0)) { - fBlitFramebufferSupport = kFull_BlitFramebufferSupport; + fBlitFramebufferFlags = kNoFormatConversionForMSAASrc_BlitFramebufferFlag | + kRectsMustMatchForMSAASrc_BlitFramebufferFlag; } else if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) { // The CHROMIUM extension uses the ANGLE version of glBlitFramebuffer and includes its // limitations. - fBlitFramebufferSupport = kNoScalingNoMirroring_BlitFramebufferSupport; + fBlitFramebufferFlags = kNoScalingOrMirroring_BlitFramebufferFlag | + kResolveMustBeFull_BlitFrambufferFlag | + kNoMSAADst_BlitFramebufferFlag | + kNoFormatConversion_BlitFramebufferFlag; } } else { if (fUsesMixedSamples) { fMSFBOType = kMixedSamples_MSFBOType; - fBlitFramebufferSupport = kFull_BlitFramebufferSupport; + fBlitFramebufferFlags = 0; } else if (ctxInfo.version() >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_ARB_framebuffer_object")) { fMSFBOType = kStandard_MSFBOType; - fBlitFramebufferSupport = kFull_BlitFramebufferSupport; + fBlitFramebufferFlags = 0; } else if (ctxInfo.hasExtension("GL_EXT_framebuffer_multisample") && ctxInfo.hasExtension("GL_EXT_framebuffer_blit")) { fMSFBOType = kEXT_MSFBOType; - fBlitFramebufferSupport = kFull_BlitFramebufferSupport; + fBlitFramebufferFlags = 0; } } } diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index e162b38b9c..794bb75119 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -73,19 +73,14 @@ public: kLast_MSFBOType = kMixedSamples_MSFBOType }; - enum BlitFramebufferSupport { - kNone_BlitFramebufferSupport, - /** - * ANGLE exposes a limited blit framebuffer extension that does not allow for stretching - * or mirroring. - */ - kNoScalingNoMirroring_BlitFramebufferSupport, - /** - * ES3 has restricted support when the src is MSAA: src rect == dst rect, dst format == src - * format. - */ - kRectsAndFormatsMatchForMSAASrc_BlitFramebufferSupport, - kFull_BlitFramebufferSupport + enum BlitFramebufferFlags { + kNoSupport_BlitFramebufferFlag = 1 << 0, + kNoScalingOrMirroring_BlitFramebufferFlag = 1 << 1, + kResolveMustBeFull_BlitFrambufferFlag = 1 << 2, + kNoMSAADst_BlitFramebufferFlag = 1 << 3, + kNoFormatConversion_BlitFramebufferFlag = 1 << 4, + kNoFormatConversionForMSAASrc_BlitFramebufferFlag = 1 << 5, + kRectsMustMatchForMSAASrc_BlitFramebufferFlag = 1 << 6, }; enum InvalidateFBType { @@ -235,7 +230,7 @@ public: /** * What functionality is supported by glBlitFramebuffer. */ - BlitFramebufferSupport blitFramebufferSupport() const { return fBlitFramebufferSupport; } + uint32_t blitFramebufferSupportFlags() const { return fBlitFramebufferFlags; } /** * Is the MSAA FBO extension one where the texture is multisampled when bound to an FBO and @@ -419,7 +414,7 @@ private: bool fRGBAToBGRAReadbackConversionsAreSlow : 1; bool fDoManualMipmapping : 1; - BlitFramebufferSupport fBlitFramebufferSupport; + uint32_t fBlitFramebufferFlags; /** Number type of the components (with out considering number of bits.) */ enum FormatType { diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index eae0aa9963..6b534a01bb 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2921,18 +2921,27 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) { this->disableWindowRectangles(); GL_CALL(ResolveMultisampleFramebuffer()); } else { - GrGLIRect r; - r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop, - dirtyRect.width(), dirtyRect.height(), target->origin()); - - int right = r.fLeft + r.fWidth; - int top = r.fBottom + r.fHeight; + int l, b, r, t; + if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & + this->glCaps().blitFramebufferSupportFlags()) { + l = 0; + b = 0; + r = target->width(); + t = target->height(); + } else { + GrGLIRect rect; + rect.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop, + dirtyRect.width(), dirtyRect.height(), target->origin()); + l = rect.fLeft; + b = rect.fBottom; + r = rect.fLeft + rect.fWidth; + t = rect.fBottom + rect.fHeight; + } // BlitFrameBuffer respects the scissor, so disable it. this->disableScissor(); this->disableWindowRectangles(); - GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top, - r.fLeft, r.fBottom, right, top, + GL_CALL(BlitFramebuffer(l, b, r, t, l, b, r, t, GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); } } @@ -3472,45 +3481,64 @@ void GrGLGpu::setScratchTextureUnit() { fHWBoundTextureUniqueIDs[lastUnitIdx] = SK_InvalidUniqueID; } -// Determines whether glBlitFramebuffer could be used between src and dst. -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)) { - 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; - // 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). - case GrGLCaps::kRectsAndFormatsMatchForMSAASrc_BlitFramebufferSupport: - if ((src->desc().fSampleCnt > 0 || src->config() != dst->config())) { - return false; - } - break; - - case GrGLCaps::kFull_BlitFramebufferSupport: - return true; +// Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface. +static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst, + const GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint, + const GrGLGpu* gpu) { + auto blitFramebufferFlags = gpu->glCaps().blitFramebufferSupportFlags(); + if (!gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) || + !gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0)) { + return false; + } + const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture()); + const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(dst->asTexture()); + const GrRenderTarget* dstRT = dst->asRenderTarget(); + const GrRenderTarget* srcRT = src->asRenderTarget(); + if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) { + return false; + } + if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) { + return false; + } + if (GrGLCaps::kNoSupport_BlitFramebufferFlag & blitFramebufferFlags) { + return false; + } + if (GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag & blitFramebufferFlags) { + // We would mirror to compensate for origin changes. Note that copySurface is + // specified such that the src and dst rects are the same. + if (dst->origin() != src->origin()) { + return false; } - const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture()); - if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) { + } + if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) { + if (srcRT && srcRT->numColorSamples() && dstRT && !dstRT->numColorSamples()) { return false; } - const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(dst->asTexture()); - if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) { + } + if (GrGLCaps::kNoMSAADst_BlitFramebufferFlag & blitFramebufferFlags) { + if (dstRT && dstRT->numColorSamples() > 0) { + return false; + } + } + if (GrGLCaps::kNoFormatConversion_BlitFramebufferFlag & blitFramebufferFlags) { + if (dst->config() != src->config()) { + return false; + } + } else if (GrGLCaps::kNoFormatConversionForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) { + const GrRenderTarget* srcRT = src->asRenderTarget(); + if (srcRT && srcRT->numColorSamples() && dst->config() != src->config()) { return false; } - return true; - } else { - return false; } + if (GrGLCaps::kRectsMustMatchForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) { + if (srcRT && srcRT->numColorSamples() && + (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop)) { + return false; + } + } + return true; } static inline bool can_copy_texsubimage(const GrSurface* dst, @@ -3627,8 +3655,8 @@ bool GrGLGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) // creation. It isn't clear that avoiding temporary fbo creation is actually optimal. GrSurfaceOrigin originForBlitFramebuffer = kDefault_GrSurfaceOrigin; - if (this->glCaps().blitFramebufferSupport() == - GrGLCaps::kNoScalingNoMirroring_BlitFramebufferSupport) { + if (this->glCaps().blitFramebufferSupportFlags() & + GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag) { originForBlitFramebuffer = src->origin(); } @@ -3689,7 +3717,7 @@ bool GrGLGpu::onCopySurface(GrSurface* dst, return true; } - if (can_blit_framebuffer(dst, src, this)) { + if (can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this)) { return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint); } @@ -4279,7 +4307,7 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) { - SkASSERT(can_blit_framebuffer(dst, src, this)); + SkASSERT(can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this)); SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, srcRect.width(), srcRect.height()); if (dst == src) { |