aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Eric Karl <ericrk@chromium.org>2017-05-08 12:02:07 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-09 17:41:25 +0000
commit5c77975e4c00e18e644c72b56f369858acd11b15 (patch)
tree187dff83863784225a9f2aa4d8c5abacefc12ec0 /src
parentfda4600e41ded0b8f0a54222e2dc8a85d53b4121 (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.cpp2
-rw-r--r--src/gpu/GrClipStackClip.cpp24
-rw-r--r--src/gpu/GrGpu.cpp11
-rw-r--r--src/gpu/GrPathRenderer.h8
-rw-r--r--src/gpu/GrReducedClip.cpp2
-rw-r--r--src/gpu/GrRenderTargetContext.cpp5
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp4
-rw-r--r--src/gpu/gl/GrGLCaps.cpp77
-rw-r--r--src/gpu/gl/GrGLCaps.h5
-rw-r--r--src/gpu/gl/GrGLRenderTarget.cpp5
-rw-r--r--src/gpu/gl/GrGLTextureRenderTarget.cpp5
-rw-r--r--src/gpu/ops/GrAAConvexPathRenderer.cpp6
-rw-r--r--src/gpu/ops/GrAAHairLinePathRenderer.cpp2
-rw-r--r--src/gpu/ops/GrDefaultPathRenderer.cpp8
-rw-r--r--src/gpu/ops/GrMSAAPathRenderer.cpp4
-rw-r--r--src/gpu/ops/GrSmallPathRenderer.cpp2
-rw-r--r--src/gpu/ops/GrStencilAndCoverPathRenderer.cpp2
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;