| Index: src/gpu/GrClipMaskManager.cpp | 
| diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp | 
| index b57f3cc1bcc5fa54e0d5a2ef797f53284640f185..b87788b286bc0d22f32cd79c78430d53919e3524 100644 | 
| --- a/src/gpu/GrClipMaskManager.cpp | 
| +++ b/src/gpu/GrClipMaskManager.cpp | 
| @@ -46,24 +46,71 @@ 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(); | 
| +                                   const Element* element, | 
| +                                   GrPathRenderer** prOut, | 
| +                                   bool needsStencil) { | 
| +    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. | 
| +        return false; | 
| +    } else { | 
| +        // We shouldn't get here with an empty clip element. | 
| +        SkASSERT(Element::kEmpty_Type != element->getType()); | 
| + | 
| +        // 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 (needsStencil) { | 
| +            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 (prOut) { | 
| +            *prOut = pr; | 
| +        } | 
| +        return SkToBool(!pr); | 
| } | 
| -    // last (false) parameter disallows use of the SW path renderer | 
| -    GrPathRendererChain::DrawType type = doAA ? | 
| -                                         GrPathRendererChain::kColorAntiAlias_DrawType : | 
| -                                         GrPathRendererChain::kColor_DrawType; | 
| +} | 
|  | 
| -    return nullptr == context->getPathRenderer(&pipelineBuilder, viewMatrix, *path, stroke, | 
| -                                               false, type); | 
| +// Determines whether it is possible to draw the element to both the stencil buffer and the | 
| +// alpha mask simultaneously. If so and the element is a path a compatible path renderer is | 
| +// also returned. | 
| +static bool can_stencil_and_draw_element(GrContext* context, | 
| +                                         GrPipelineBuilder* pipelineBuilder, | 
| +                                         GrTexture* texture, | 
| +                                         const SkMatrix& viewMatrix, | 
| +                                         const SkClipStack::Element* element, | 
| +                                         GrPathRenderer** pr) { | 
| +    pipelineBuilder->setRenderTarget(texture->asRenderTarget()); | 
| + | 
| +    static const bool kNeedsStencil = true; | 
| +    return !path_needs_SW_renderer(context, | 
| +                                   *pipelineBuilder, | 
| +                                   viewMatrix, | 
| +                                   element, | 
| +                                   pr, | 
| +                                   kNeedsStencil); | 
| } | 
|  | 
| GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) | 
| @@ -84,24 +131,22 @@ 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. | 
| -    SkMatrix translate; | 
| -    translate.setTranslate(clipToMaskOffset); | 
| +    const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY); | 
|  | 
| 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 needsStencil = invert || | 
| +                            SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op; | 
| + | 
| +        if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translate, | 
| +                                   element, nullptr, needsStencil)) { | 
| +            return true; | 
| } | 
| } | 
| return false; | 
| @@ -412,7 +457,7 @@ bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, | 
| GrPathRendererChain::DrawType type; | 
| type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : | 
| GrPathRendererChain::kColor_DrawType; | 
| -                pr = this->getContext()->getPathRenderer(pipelineBuilder, viewMatrix, | 
| +                pr = this->getContext()->getPathRenderer(*pipelineBuilder, viewMatrix, | 
| path, stroke, false, type); | 
| } | 
| if (nullptr == pr) { | 
| @@ -434,32 +479,6 @@ bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, | 
| return true; | 
| } | 
|  | 
| -bool GrClipMaskManager::canStencilAndDrawElement(GrPipelineBuilder* pipelineBuilder, | 
| -                                                 GrTexture* target, | 
| -                                                 GrPathRenderer** pr, | 
| -                                                 const SkClipStack::Element* element) { | 
| -    pipelineBuilder->setRenderTarget(target->asRenderTarget()); | 
| - | 
| -    if (Element::kRect_Type == element->getType()) { | 
| -        return true; | 
| -    } else { | 
| -        // We shouldn't get here with an empty clip element. | 
| -        SkASSERT(Element::kEmpty_Type != element->getType()); | 
| -        SkPath path; | 
| -        element->asPath(&path); | 
| -        if (path.isInverseFillType()) { | 
| -            path.toggleInverseFillType(); | 
| -        } | 
| -        GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); | 
| -        GrPathRendererChain::DrawType type = element->isAA() ? | 
| -            GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : | 
| -            GrPathRendererChain::kStencilAndColor_DrawType; | 
| -        *pr = this->getContext()->getPathRenderer(pipelineBuilder, SkMatrix::I(), path, | 
| -                                                  stroke, false, type); | 
| -        return SkToBool(*pr); | 
| -    } | 
| -} | 
| - | 
| void GrClipMaskManager::mergeMask(GrPipelineBuilder* pipelineBuilder, | 
| GrTexture* dstMask, | 
| GrTexture* srcMask, | 
| @@ -555,8 +574,7 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, | 
|  | 
| // Set the matrix so that rendered clip elements are transformed to mask space from clip | 
| // space. | 
| -    SkMatrix translate; | 
| -    translate.setTranslate(clipToMaskOffset); | 
| +    const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY); | 
|  | 
| // The texture may be larger than necessary, this rect represents the part of the texture | 
| // we populate with a rasterization of the clip. | 
| @@ -586,7 +604,8 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, | 
|  | 
| pipelineBuilder.setClip(clip); | 
| GrPathRenderer* pr = nullptr; | 
| -            bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, texture, &pr, element); | 
| +            bool useTemp = !can_stencil_and_draw_element(this->getContext(), &pipelineBuilder, | 
| +                                                         texture, translate, element, &pr); | 
| GrTexture* dst; | 
| // This is the bounds of the clip element in the space of the alpha-mask. The temporary | 
| // mask buffer can be substantially larger than the actually clip stack element. We | 
| @@ -594,6 +613,8 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, | 
| // the accumulator. | 
| SkIRect maskSpaceElementIBounds; | 
|  | 
| +            SkASSERT(!useTemp); | 
| + | 
| if (useTemp) { | 
| if (invert) { | 
| maskSpaceElementIBounds = maskSpaceIBounds; | 
| @@ -759,7 +780,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, | 
| if (fillInverted) { | 
| clipPath.toggleInverseFillType(); | 
| } | 
| -                pr = this->getContext()->getPathRenderer(&pipelineBuilder, | 
| +                pr = this->getContext()->getPathRenderer(pipelineBuilder, | 
| viewMatrix, | 
| clipPath, | 
| stroke, | 
|  |