From f606bd7571e582e0b98e9672f0e702827ea5a9e9 Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Wed, 30 Mar 2022 10:47:23 -0600 Subject: [PATCH] Never reject an MSAA FBO0 GLES2 doesn't support MSAA FBOs, so GrCaps thought it was supposed to reject an MSAA wrapper on FBO0. This actually isn't correct. In GLES2, FBO0 can still be multisampled. --- src/gpu/GrCaps.h | 9 +++++++++ src/gpu/GrGpu.cpp | 2 +- src/gpu/gl/GrGLCaps.cpp | 27 +++++++++++++++++++++++++++ src/gpu/gl/GrGLCaps.h | 3 +++ src/gpu/gl/GrGLGpu.cpp | 13 ++++++++++--- src/image/SkSurface_Gpu.cpp | 2 +- 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h index 53bd1cd8df69..6e86e4b4514c 100644 --- a/src/gpu/GrCaps.h +++ b/src/gpu/GrCaps.h @@ -240,8 +240,17 @@ class GrCaps : public SkRefCnt { virtual bool isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format, int sampleCount = 1) const = 0; + virtual bool isRenderTargetAsColorTypeRenderable(GrColorType ct, + const GrBackendRenderTarget& rt) const { + return this->isFormatAsColorTypeRenderable(ct, rt.getBackendFormat(), rt.sampleCnt()); + } + virtual bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const = 0; + virtual bool isRenderTargetRenderable(const GrBackendRenderTarget& rt) const { + return this->isFormatRenderable(rt.getBackendFormat(), rt.sampleCnt()); + } + // Find a sample count greater than or equal to the requested count which is supported for a // render target of the given format or 0 if no such sample count is supported. If the requested // sample count is 1 then 1 will be returned if non-MSAA rendering is supported, otherwise 0. diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 023d510cb6ba..3f2b059d13a7 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -359,7 +359,7 @@ sk_sp GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget const GrCaps* caps = this->caps(); - if (!caps->isFormatRenderable(backendRT.getBackendFormat(), backendRT.sampleCnt())) { + if (!caps->isRenderTargetRenderable(backendRT)) { return nullptr; } diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index ee78717d52f9..1b3111115c48 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -4481,6 +4481,20 @@ bool GrGLCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendForm return this->isFormatRenderable(f, sampleCount); } +bool GrGLCaps::isRenderTargetAsColorTypeRenderable(GrColorType ct, + const GrBackendRenderTarget& rt) const { + int sampleCntToCheck; + GrGLFramebufferInfo fbi; + if (rt.getGLFramebufferInfo(&fbi) && fbi.fFBOID == 0) { + // FBO0 has different multisampling rules than offscreen render targets. If the user wrapped + // FBO0 and told us it's multisampled, just trust that the msaa is valid. + sampleCntToCheck = 1; + } else { + sampleCntToCheck = rt.sampleCnt(); + } + return this->isFormatAsColorTypeRenderable(ct, rt.getBackendFormat(), sampleCntToCheck); +} + bool GrGLCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const { if (format.textureType() == GrTextureType::kRectangle && !this->rectangleTextureSupport()) { return false; @@ -4491,6 +4505,19 @@ bool GrGLCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount return this->isFormatRenderable(format.asGLFormat(), sampleCount); } +bool GrGLCaps::isRenderTargetRenderable(const GrBackendRenderTarget& rt) const { + int sampleCntToCheck; + GrGLFramebufferInfo fbi; + if (rt.getGLFramebufferInfo(&fbi) && fbi.fFBOID == 0) { + // FBO0 has different multisampling rules than offscreen render targets. If the user wrapped + // FBO0 and told us it's multisampled, just trust that the msaa is valid. + sampleCntToCheck = 1; + } else { + sampleCntToCheck = rt.sampleCnt(); + } + return this->isFormatRenderable(rt.getBackendFormat(), sampleCntToCheck); +} + int GrGLCaps::getRenderTargetSampleCount(int requestedCount, GrGLFormat format) const { const FormatInfo& info = this->getFormatInfo(format); diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 8897cb9ec0f5..864e9827e6ab 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -125,7 +125,10 @@ class GrGLCaps : public GrCaps { bool isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format, int sampleCount = 1) const override; + bool isRenderTargetAsColorTypeRenderable(GrColorType, + const GrBackendRenderTarget&) const override; bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override; + bool isRenderTargetRenderable(const GrBackendRenderTarget&) const override; bool isFormatRenderable(GrGLFormat format, int sampleCount) const { return sampleCount <= this->maxRenderTargetSampleCount(format); } diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 49b98e78c179..00250aae7078 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -784,12 +784,19 @@ sk_sp GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTa return nullptr; } - const auto format = backendRT.getBackendFormat().asGLFormat(); - if (!this->glCaps().isFormatRenderable(format, backendRT.sampleCnt())) { + if (!this->glCaps().isRenderTargetRenderable(backendRT)) { return nullptr; } - int sampleCount = this->glCaps().getRenderTargetSampleCount(backendRT.sampleCnt(), format); + const auto format = backendRT.getBackendFormat().asGLFormat(); + int sampleCount; + if (info.fFBOID == 0) { + // FBO0 has different multisampling rules than offscreen render targets. If the user wrapped + // FBO0 and told us it's multisampled, just trust the provided sample count. + sampleCount = backendRT.sampleCnt(); + } else { + sampleCount = this->glCaps().getRenderTargetSampleCount(backendRT.sampleCnt(), format); + } GrGLRenderTarget::IDs rtIDs; if (sampleCount <= 1) { diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp index 70c4f9f10e15..adaa00bc7d2b 100644 --- a/src/image/SkSurface_Gpu.cpp +++ b/src/image/SkSurface_Gpu.cpp @@ -579,7 +579,7 @@ bool validate_backend_render_target(const GrCaps* caps, const GrBackendRenderTar return false; } - if (!caps->isFormatAsColorTypeRenderable(grCT, rt.getBackendFormat(), rt.sampleCnt())) { + if (!caps->isRenderTargetAsColorTypeRenderable(grCT, rt)) { return false; }