diff options
author | 2017-05-08 12:02:07 -0700 | |
---|---|---|
committer | 2017-05-09 17:41:25 +0000 | |
commit | 5c77975e4c00e18e644c72b56f369858acd11b15 (patch) | |
tree | 187dff83863784225a9f2aa4d8c5abacefc12ec0 /src | |
parent | fda4600e41ded0b8f0a54222e2dc8a85d53b4121 (diff) |
Add flag to avoid stencil buffers in Skia
Certain systems experience a leak in the GL driver associated with
stencil buffers. Attempts to avoid the leak (while still using stencil
buffers) dind't succeed. This patch adds a GrContextOption
fAvoidStencilBuffers. This disables certain path rendering modes, as
well as stencil based masking/clipping.
Bug: 713854
Change-Id: Ifa6c0f2bd5ee395547bda9165d6c79d197ae8b8b
Reviewed-on: https://skia-review.googlesource.com/15253
Commit-Queue: Eric Karl <ericrk@chromium.org>
Reviewed-by: Eric Karl <ericrk@chromium.org>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrCaps.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrClipStackClip.cpp | 24 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 11 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 8 | ||||
-rw-r--r-- | src/gpu/GrReducedClip.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 5 | ||||
-rw-r--r-- | src/gpu/GrSoftwarePathRenderer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 77 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLRenderTarget.cpp | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTextureRenderTarget.cpp | 5 | ||||
-rw-r--r-- | src/gpu/ops/GrAAConvexPathRenderer.cpp | 6 | ||||
-rw-r--r-- | src/gpu/ops/GrAAHairLinePathRenderer.cpp | 2 | ||||
-rw-r--r-- | src/gpu/ops/GrDefaultPathRenderer.cpp | 8 | ||||
-rw-r--r-- | src/gpu/ops/GrMSAAPathRenderer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/ops/GrSmallPathRenderer.cpp | 2 | ||||
-rw-r--r-- | src/gpu/ops/GrStencilAndCoverPathRenderer.cpp | 2 |
17 files changed, 104 insertions, 68 deletions
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp index 57ab5fdece..4acf90ea13 100644 --- a/src/gpu/GrCaps.cpp +++ b/src/gpu/GrCaps.cpp @@ -77,6 +77,7 @@ GrCaps::GrCaps(const GrContextOptions& options) { fUseDrawInsteadOfPartialRenderTargetWrite = options.fUseDrawInsteadOfPartialRenderTargetWrite; fUseDrawInsteadOfAllRenderTargetWrites = false; fAvoidInstancedDrawsToFPTargets = false; + fAvoidStencilBuffers = false; fPreferVRAMUseOverFlushes = true; } @@ -95,6 +96,7 @@ void GrCaps::applyOptionsOverrides(const GrContextOptions& options) { GrWindowRectangles::kMaxWindows, fMaxWindowRectangles); fMaxWindowRectangles = GrWindowRectangles::kMaxWindows; } + fAvoidStencilBuffers = options.fAvoidStencilBuffers; } static SkString map_flags_to_string(uint32_t flags) { diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index 18df1d6711..e24e63565b 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -115,7 +115,7 @@ bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context, GrShape shape(path, GrStyle::SimpleFill()); GrPathRenderer::CanDrawPathArgs canDrawArgs; - canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); + canDrawArgs.fCaps = context->caps(); canDrawArgs.fViewMatrix = &viewMatrix; canDrawArgs.fShape = &shape; if (!element->isAA()) { @@ -152,6 +152,10 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context, // a clip gets complex enough it can just be done in SW regardless // of whether it would invoke the GrSoftwarePathRenderer. + // If we're avoiding stencils, always use SW: + if (context->caps()->avoidStencilBuffers()) + return true; + // Set the matrix so that rendered clip elements are transformed to mask space from clip // space. SkMatrix translate; @@ -283,6 +287,8 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar SkASSERT(rtIBounds.contains(clipIBounds)); // Mask shouldn't be larger than the RT. #endif + bool avoidStencilBuffers = context->caps()->avoidStencilBuffers(); + // An element count of 4 was chosen because of the common pattern in Blink of: // isect RR // diff RR @@ -294,7 +300,8 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar if (reducedClip.elements().count() <= kMaxAnalyticElements) { // When there are multiple samples we want to do per-sample clipping, not compute a // fractional pixel coverage. - bool disallowAnalyticAA = renderTargetContext->isStencilBufferMultisampled(); + bool disallowAnalyticAA = renderTargetContext->isStencilBufferMultisampled() && + !avoidStencilBuffers; if (disallowAnalyticAA && !renderTargetContext->numColorSamples()) { // With a single color sample, any coverage info is lost from color once it hits the // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe @@ -302,7 +309,7 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar disallowAnalyticAA = useHWAA || hasUserStencilSettings; } sk_sp<GrFragmentProcessor> clipFP; - if (reducedClip.requiresAA() && + if ((reducedClip.requiresAA() || avoidStencilBuffers) && get_analytic_clip_processor(reducedClip.elements(), disallowAnalyticAA, devBounds, &clipFP)) { out->addCoverageFP(std::move(clipFP)); @@ -311,7 +318,8 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar } // If the stencil buffer is multisampled we can use it to do everything. - if (!renderTargetContext->isStencilBufferMultisampled() && reducedClip.requiresAA()) { + if ((!renderTargetContext->isStencilBufferMultisampled() && reducedClip.requiresAA()) || + avoidStencilBuffers) { sk_sp<GrTextureProxy> result; if (UseSWOnlyPath(context, hasUserStencilSettings, renderTargetContext, reducedClip)) { // The clip geometry is complex enough that it will be more efficient to create it @@ -328,7 +336,13 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar reducedClip.ibounds())); return true; } - // if alpha clip mask creation fails fall through to the non-AA code paths + + // If alpha or software clip mask creation fails, fall through to the stencil code paths, + // unless stencils are disallowed. + if (context->caps()->avoidStencilBuffers()) { + SkDebugf("WARNING: Clip mask requires stencil, but stencil unavailable. Clip will be ignored.\n"); + return false; + } } GrRenderTarget* rt = renderTargetContext->accessRenderTarget(); diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index f8ac850bf7..ceb0dee78e 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -197,10 +197,13 @@ sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex, if (!tex) { return nullptr; } - // TODO: defer this and attach dynamically - GrRenderTarget* tgt = tex->asRenderTarget(); - if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) { - return nullptr; + + if (!this->caps()->avoidStencilBuffers()) { + // TODO: defer this and attach dynamically + GrRenderTarget* tgt = tex->asRenderTarget(); + if (tgt && !fContext->resourceProvider()->attachStencilAttachment(tgt)) { + return nullptr; + } } return tex; } diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index 05673d5f86..0845bc0c01 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -74,14 +74,14 @@ public: /** Args to canDrawPath() * - * fShaderCaps The shader caps + * fCaps The context caps * fPipelineBuilder The pipelineBuilder * fViewMatrix The viewMatrix * fShape The shape to draw * fAntiAlias The type of anti aliasing required. */ struct CanDrawPathArgs { - const GrShaderCaps* fShaderCaps; + const GrCaps* fCaps; const SkMatrix* fViewMatrix; const GrShape* fShape; GrAAType fAAType; @@ -91,7 +91,7 @@ public: #ifdef SK_DEBUG void validate() const { - SkASSERT(fShaderCaps); + SkASSERT(fCaps); SkASSERT(fViewMatrix); SkASSERT(fShape); } @@ -153,7 +153,7 @@ public: SkDEBUGCODE(args.validate();) #ifdef SK_DEBUG CanDrawPathArgs canArgs; - canArgs.fShaderCaps = args.fContext->caps()->shaderCaps(); + canArgs.fCaps = args.fContext->caps(); canArgs.fViewMatrix = args.fViewMatrix; canArgs.fShape = args.fShape; canArgs.fAAType = args.fAAType; diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index 4b7e69bc02..28ba47c688 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -730,7 +730,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context, GrShape shape(clipPath, GrStyle::SimpleFill()); GrPathRenderer::CanDrawPathArgs canDrawArgs; - canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); + canDrawArgs.fCaps = context->caps(); canDrawArgs.fViewMatrix = &SkMatrix::I(); canDrawArgs.fShape = &shape; canDrawArgs.fAAType = aaType; diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 7de1f8dddf..fc1ab6850f 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1425,8 +1425,7 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip, GrShape shape(path, GrStyle::SimpleFill()); GrPathRenderer::CanDrawPathArgs canDrawArgs; - canDrawArgs.fShaderCaps = - fRenderTargetContext->drawingManager()->getContext()->caps()->shaderCaps(); + canDrawArgs.fCaps = fRenderTargetContext->drawingManager()->getContext()->caps(); canDrawArgs.fViewMatrix = &viewMatrix; canDrawArgs.fShape = &shape; canDrawArgs.fAAType = aaType; @@ -1487,7 +1486,7 @@ void GrRenderTargetContext::internalDrawPath(const GrClip& clip, aaType = GrAAType::kCoverage; } GrPathRenderer::CanDrawPathArgs canDrawArgs; - canDrawArgs.fShaderCaps = this->drawingManager()->getContext()->caps()->shaderCaps(); + canDrawArgs.fCaps = this->drawingManager()->getContext()->caps(); canDrawArgs.fViewMatrix = &viewMatrix; canDrawArgs.fShape = &shape; canDrawArgs.fHasUserStencilSettings = false; diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp index 0e7cecd97c..a9613b4273 100644 --- a/src/gpu/GrSoftwarePathRenderer.cpp +++ b/src/gpu/GrSoftwarePathRenderer.cpp @@ -136,7 +136,9 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) { bool inverseFilled = false; SkTLazy<GrShape> tmpShape; SkASSERT(!args.fShape->style().applies()); - inverseFilled = args.fShape->inverseFilled(); + // If the path is hairline, ignore inverse fill. + inverseFilled = args.fShape->inverseFilled() && + !IsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr); SkIRect unclippedDevShapeBounds, clippedDevShapeBounds, devClipBounds; // To prevent overloading the cache with entries during animations we limit the cache of masks diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 47f26ff2f5..2c2f7ec113 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -344,23 +344,6 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, * GrCaps fields **************************************************************************/ - // We need dual source blending and the ability to disable multisample in order to support mixed - // samples in every corner case. We only use mixed samples if the stencil-and-cover path - // renderer is available and enabled; no other path renderers support this feature. - if (fMultisampleDisableSupport && - shaderCaps->dualSourceBlendingSupport() && - fShaderCaps->pathRenderingSupport() && - (contextOptions.fGpuPathRenderers & GrContextOptions::GpuPathRenderers::kStencilAndCover)) { - fUsesMixedSamples = ctxInfo.hasExtension("GL_NV_framebuffer_mixed_samples") || - ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_mixed_samples"); - // Workaround NVIDIA bug related to glInvalidateFramebuffer and mixed samples. - if (fUsesMixedSamples && (kNVIDIA_GrGLDriver == ctxInfo.driver() || - kChromium_GrGLDriver == ctxInfo.driver())) { - fDiscardRenderTargetSupport = false; - fInvalidateFBType = kNone_InvalidateFBType; - } - } - // SGX and Mali GPUs that are based on a tiled-deferred architecture that have trouble with // frequently changing VBOs. We've measured a performance increase using non-VBO vertex // data for dynamic content on these GPUs. Perhaps we should read the renderer string and @@ -373,11 +356,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, fPreferClientSideDynamicBuffers = true; } - // fUsesMixedSamples must be set before calling initFSAASupport. - this->initFSAASupport(ctxInfo, gli); + if (!contextOptions.fAvoidStencilBuffers) { + // To reduce surface area, if we avoid stencil buffers, we also disable MSAA. + this->initFSAASupport(contextOptions, ctxInfo, gli); + this->initStencilSupport(ctxInfo); + } this->initBlendEqationSupport(ctxInfo); - this->initStencilFormats(ctxInfo); - if (kGL_GrGLStandard == standard) { fMapBufferFlags = kCanMap_MapFlag; // we require VBO support and the desktop VBO @@ -464,21 +448,6 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, kQualcomm_GrGLVendor != ctxInfo.vendor(); #endif - // initFSAASupport() must have been called before this point - if (GrGLCaps::kES_IMG_MsToTexture_MSFBOType == fMSFBOType) { - GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &fMaxStencilSampleCount); - } else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) { - GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxStencilSampleCount); - } - // We only have a use for raster multisample if there is coverage modulation from mixed samples. - if (fUsesMixedSamples && ctxInfo.hasExtension("GL_EXT_raster_multisample")) { - GR_GL_GetIntegerv(gli, GR_GL_MAX_RASTER_SAMPLES, &fMaxRasterSamples); - // This is to guard against platforms that may not support as many samples for - // glRasterSamples as they do for framebuffers. - fMaxStencilSampleCount = SkTMin(fMaxStencilSampleCount, fMaxRasterSamples); - } - fMaxColorSampleCount = fMaxStencilSampleCount; - if (ctxInfo.hasExtension("GL_EXT_window_rectangles")) { GR_GL_GetIntegerv(gli, GR_GL_MAX_WINDOW_RECTANGLES, &fMaxWindowRectangles); } @@ -982,7 +951,25 @@ bool GrGLCaps::readPixelsSupported(GrPixelConfig surfaceConfig, fConfigTable[surfaceConfig].fSecondReadPixelsFormat.fType == readType; } -void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { +void GrGLCaps::initFSAASupport(const GrContextOptions& contextOptions, const GrGLContextInfo& ctxInfo, + const GrGLInterface* gli) { + // We need dual source blending and the ability to disable multisample in order to support mixed + // samples in every corner case. We only use mixed samples if the stencil-and-cover path + // renderer is available and enabled; no other path renderers support this feature. + if (fMultisampleDisableSupport && + this->shaderCaps()->dualSourceBlendingSupport() && + this->shaderCaps()->pathRenderingSupport() && + (contextOptions.fGpuPathRenderers & GrContextOptions::GpuPathRenderers::kStencilAndCover)) { + fUsesMixedSamples = ctxInfo.hasExtension("GL_NV_framebuffer_mixed_samples") || + ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_mixed_samples"); + // Workaround NVIDIA bug related to glInvalidateFramebuffer and mixed samples. + if (fUsesMixedSamples && (kNVIDIA_GrGLDriver == ctxInfo.driver() || + kChromium_GrGLDriver == ctxInfo.driver())) { + fDiscardRenderTargetSupport = false; + fInvalidateFBType = kNone_InvalidateFBType; + } + } + 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). @@ -1030,6 +1017,20 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa fBlitFramebufferFlags = 0; } } + + if (GrGLCaps::kES_IMG_MsToTexture_MSFBOType == fMSFBOType) { + GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES_IMG, &fMaxStencilSampleCount); + } else if (GrGLCaps::kNone_MSFBOType != fMSFBOType) { + GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxStencilSampleCount); + } + // We only have a use for raster multisample if there is coverage modulation from mixed samples. + if (fUsesMixedSamples && ctxInfo.hasExtension("GL_EXT_raster_multisample")) { + GR_GL_GetIntegerv(gli, GR_GL_MAX_RASTER_SAMPLES, &fMaxRasterSamples); + // This is to guard against platforms that may not support as many samples for + // glRasterSamples as they do for framebuffers. + fMaxStencilSampleCount = SkTMin(fMaxStencilSampleCount, fMaxRasterSamples); + } + fMaxColorSampleCount = fMaxStencilSampleCount; } void GrGLCaps::initBlendEqationSupport(const GrGLContextInfo& ctxInfo) { @@ -1084,7 +1085,7 @@ namespace { const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; } -void GrGLCaps::initStencilFormats(const GrGLContextInfo& ctxInfo) { +void GrGLCaps::initStencilSupport(const GrGLContextInfo& ctxInfo) { // Build up list of legal stencil formats (though perhaps not supported on // the particular gpu/driver) from most preferred to least. diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 7439711c6d..c32e41916f 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -380,9 +380,10 @@ private: void onApplyOptionsOverrides(const GrContextOptions& options) override; - void initFSAASupport(const GrGLContextInfo&, const GrGLInterface*); + void initFSAASupport(const GrContextOptions& contextOptions, const GrGLContextInfo&, + const GrGLInterface*); void initBlendEqationSupport(const GrGLContextInfo&); - void initStencilFormats(const GrGLContextInfo&); + void initStencilSupport(const GrGLContextInfo&); // This must be called after initFSAASupport(). void initConfigTable(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*, GrShaderCaps*); diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp index 45efba2f17..09c2851d56 100644 --- a/src/gpu/gl/GrGLRenderTarget.cpp +++ b/src/gpu/gl/GrGLRenderTarget.cpp @@ -7,6 +7,7 @@ #include "GrGLRenderTarget.h" +#include "GrContext.h" #include "GrGLGpu.h" #include "GrGLUtil.h" #include "GrGpuResourcePriv.h" @@ -170,6 +171,10 @@ GrGLGpu* GrGLRenderTarget::getGLGpu() const { } bool GrGLRenderTarget::canAttemptStencilAttachment() const { + if (this->getGpu()->getContext()->caps()->avoidStencilBuffers()) { + return false; + } + // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently // allow for borrowed FBO ownership, so we can safely assume that if an object is owned, // Skia created it. diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp index 0abeb8ea61..eac29b6d1f 100644 --- a/src/gpu/gl/GrGLTextureRenderTarget.cpp +++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp @@ -7,6 +7,7 @@ #include "GrGLTextureRenderTarget.h" +#include "GrContext.h" #include "SkTraceMemoryDump.h" // GrGLTextureRenderTarget must dump both of its superclasses. @@ -40,8 +41,8 @@ void GrGLTextureRenderTarget::dumpMemoryStatistics( bool GrGLTextureRenderTarget::canAttemptStencilAttachment() const { // The RT FBO of GrGLTextureRenderTarget is never created from a - // wrapped FBO. - return true; + // wrapped FBO, so we only care about the flag. + return !this->getGpu()->getContext()->caps()->avoidStencilBuffers(); } sk_sp<GrGLTextureRenderTarget> GrGLTextureRenderTarget::MakeWrapped( diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp index f9e95c7b59..9144d16511 100644 --- a/src/gpu/ops/GrAAConvexPathRenderer.cpp +++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp @@ -667,9 +667,9 @@ sk_sp<GrGeometryProcessor> QuadEdgeEffect::TestCreate(GrProcessorTestData* d) { /////////////////////////////////////////////////////////////////////////////// bool GrAAConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { - return (args.fShaderCaps->shaderDerivativeSupport() && (GrAAType::kCoverage == args.fAAType) && - args.fShape->style().isSimpleFill() && !args.fShape->inverseFilled() && - args.fShape->knownToBeConvex()); + return (args.fCaps->shaderCaps()->shaderDerivativeSupport() && + (GrAAType::kCoverage == args.fAAType) && args.fShape->style().isSimpleFill() && + !args.fShape->inverseFilled() && args.fShape->knownToBeConvex()); } // extract the result vertices and indices from the GrAAConvexTessellator diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp index b8ec966d48..a40f0597aa 100644 --- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp @@ -624,7 +624,7 @@ bool GrAAHairLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const } if (SkPath::kLine_SegmentMask == args.fShape->segmentMask() || - args.fShaderCaps->shaderDerivativeSupport()) { + args.fCaps->shaderCaps()->shaderDerivativeSupport()) { return true; } diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp index 0ec090e535..ef925b6234 100644 --- a/src/gpu/ops/GrDefaultPathRenderer.cpp +++ b/src/gpu/ops/GrDefaultPathRenderer.cpp @@ -548,10 +548,14 @@ bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTarget } bool GrDefaultPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { + bool isHairline = IsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr); + // If we aren't a single_pass_shape or hairline, we require stencil buffers. + if (!(single_pass_shape(*args.fShape) || isHairline) && args.fCaps->avoidStencilBuffers()) { + return false; + } // This can draw any path with any simple fill style but doesn't do coverage-based antialiasing. return GrAAType::kCoverage != args.fAAType && - (args.fShape->style().isSimpleFill() || - IsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr)); + (args.fShape->style().isSimpleFill() || isHairline); } bool GrDefaultPathRenderer::onDrawPath(const DrawPathArgs& args) { diff --git a/src/gpu/ops/GrMSAAPathRenderer.cpp b/src/gpu/ops/GrMSAAPathRenderer.cpp index d4c0f3f16b..b2782dff96 100644 --- a/src/gpu/ops/GrMSAAPathRenderer.cpp +++ b/src/gpu/ops/GrMSAAPathRenderer.cpp @@ -677,6 +677,10 @@ bool GrMSAAPathRenderer::internalDrawPath(GrRenderTargetContext* renderTargetCon } bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { + // If we aren't a single_pass_shape, we require stencil buffers. + if (!single_pass_shape(*args.fShape) && args.fCaps->avoidStencilBuffers()) { + return false; + } // This path renderer only fills and relies on MSAA for antialiasing. Stroked shapes are // handled by passing on the original shape and letting the caller compute the stroked shape // which will have a fill style. diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp index 53de77905c..7b937e58c6 100644 --- a/src/gpu/ops/GrSmallPathRenderer.cpp +++ b/src/gpu/ops/GrSmallPathRenderer.cpp @@ -87,7 +87,7 @@ GrSmallPathRenderer::~GrSmallPathRenderer() { //////////////////////////////////////////////////////////////////////////////// bool GrSmallPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { - if (!args.fShaderCaps->shaderDerivativeSupport()) { + if (!args.fCaps->shaderCaps()->shaderDerivativeSupport()) { return false; } // If the shape has no key then we won't get any reuse. diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp index bd5c297cd8..983235942b 100644 --- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp +++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp @@ -22,7 +22,7 @@ GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrResourceProvider* resourceProvider, const GrCaps& caps) { - if (caps.shaderCaps()->pathRenderingSupport()) { + if (caps.shaderCaps()->pathRenderingSupport() && !caps.avoidStencilBuffers()) { return new GrStencilAndCoverPathRenderer(resourceProvider); } else { return nullptr; |