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>
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index f9e95c7..9144d16 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -667,9 +667,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 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 b8ec966..a40f059 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -624,7 +624,7 @@
     }
 
     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 0ec090e..ef925b6 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -548,10 +548,14 @@
 }
 
 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 d4c0f3f..b2782df 100644
--- a/src/gpu/ops/GrMSAAPathRenderer.cpp
+++ b/src/gpu/ops/GrMSAAPathRenderer.cpp
@@ -677,6 +677,10 @@
 }
 
 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 53de779..7b937e5 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -87,7 +87,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 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 bd5c297..9832359 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;