Index: src/gpu/GrClipMaskManager.cpp |
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp |
index 2596a06080003e7055de3a68c4e0655c9ead3826..23f2d2b54076146bec09f833ae39f6d9df499517 100644 |
--- a/src/gpu/GrClipMaskManager.cpp |
+++ b/src/gpu/GrClipMaskManager.cpp |
@@ -46,24 +46,64 @@ static const GrFragmentProcessor* create_fp_for_mask(GrTexture* result, const Sk |
kDevice_GrCoordSet); |
} |
+// Does the path in 'element' require SW rendering? If so, return true (and, |
+// optionally, set 'prOut' to NULL. If not, return false (and, optionally, set |
+// 'prOut' to the non-SW path renderer that will do the job). |
static bool path_needs_SW_renderer(GrContext* context, |
const GrPipelineBuilder& pipelineBuilder, |
const SkMatrix& viewMatrix, |
- const SkPath& origPath, |
- const GrStrokeInfo& stroke, |
- bool doAA) { |
- // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer |
- SkTCopyOnFirstWrite<SkPath> path(origPath); |
- if (path->isInverseFillType()) { |
- path.writable()->toggleInverseFillType(); |
- } |
- // last (false) parameter disallows use of the SW path renderer |
- GrPathRendererChain::DrawType type = doAA ? |
- GrPathRendererChain::kColorAntiAlias_DrawType : |
- GrPathRendererChain::kColor_DrawType; |
+ const Element* element, |
+ GrPathRenderer** prOut, |
+ bool tryStencilFirst) { |
+ if (Element::kRect_Type == element->getType()) { |
+ // rects can always be drawn directly w/o using the software path |
+ // TODO: skip rrects once we're drawing them directly. |
+ if (prOut) { |
+ *prOut = nullptr; |
+ } |
+ return false; |
+ } else { |
+ // We shouldn't get here with an empty clip element. |
+ SkASSERT(Element::kEmpty_Type != element->getType()); |
- return nullptr == context->getPathRenderer(&pipelineBuilder, viewMatrix, *path, stroke, |
- false, type); |
+ // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer |
+ SkPath path; |
+ element->asPath(&path); |
+ if (path.isInverseFillType()) { |
+ path.toggleInverseFillType(); |
+ } |
+ GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); |
+ |
+ GrPathRendererChain::DrawType type; |
+ |
+ if (tryStencilFirst) { |
+ type = element->isAA() |
+ ? GrPathRendererChain::kStencilAndColorAntiAlias_DrawType |
+ : GrPathRendererChain::kStencilAndColor_DrawType; |
+ } else { |
+ type = element->isAA() |
+ ? GrPathRendererChain::kColorAntiAlias_DrawType |
+ : GrPathRendererChain::kColor_DrawType; |
+ } |
+ |
+ // the 'false' parameter disallows use of the SW path renderer |
+ GrPathRenderer* pr = context->getPathRenderer(&pipelineBuilder, viewMatrix, path, |
+ stroke, false, type); |
+ if (tryStencilFirst && !pr) { |
+ // If the path can't be stenciled, createAlphaClipMask falls back to color rendering |
+ // it into a temporary buffer. If that fails then SW is truly required. |
+ type = element->isAA() |
+ ? GrPathRendererChain::kColorAntiAlias_DrawType |
+ : GrPathRendererChain::kColor_DrawType; |
+ |
+ pr = context->getPathRenderer(&pipelineBuilder, viewMatrix, path, stroke, false, type); |
+ } |
+ |
+ if (prOut) { |
+ *prOut = pr; |
+ } |
+ return SkToBool(!pr); |
+ } |
} |
GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) |
@@ -84,7 +124,6 @@ bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, |
// TODO: generalize this function so that when |
// a clip gets complex enough it can just be done in SW regardless |
// of whether it would invoke the GrSoftwarePathRenderer. |
- GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); |
// Set the matrix so that rendered clip elements are transformed to mask space from clip |
// space. |
@@ -93,15 +132,16 @@ bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, |
for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { |
const Element* element = iter.get(); |
- // rects can always be drawn directly w/o using the software path |
- // Skip rrects once we're drawing them directly. |
- if (Element::kRect_Type != element->getType()) { |
- SkPath path; |
- element->asPath(&path); |
- if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translate, |
- path, stroke, element->isAA())) { |
- return true; |
- } |
+ |
+ SkRegion::Op op = element->getOp(); |
+ bool invert = element->isInverseFilled(); |
+ bool tryStencilFirst = invert || |
+ SkRegion::kIntersect_Op == op || |
+ SkRegion::kReverseDifference_Op == op; |
+ |
+ if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translate, |
+ element, nullptr, tryStencilFirst)) { |
+ return true; |
} |
} |
return false; |
@@ -325,6 +365,8 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, |
elements, |
clipToMaskOffset, |
clipSpaceIBounds)); |
+ // If createAlphaClipMask fails it means useSWOnlyPath has a bug |
+ SkASSERT(result); |
} |
if (result) { |