| Index: src/gpu/GrClipMaskManager.cpp
 | 
| diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
 | 
| index ff00a94f5aaebee244e3269da47199ff454a05c7..caf0cbdff9194c0b18029027200db1ef2b3286ef 100644
 | 
| --- a/src/gpu/GrClipMaskManager.cpp
 | 
| +++ b/src/gpu/GrClipMaskManager.cpp
 | 
| @@ -99,21 +99,14 @@ static bool path_needs_SW_renderer(GrContext* context,
 | 
|  // 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,
 | 
| +static GrPathRenderer* get_path_renderer(GrContext* context,
 | 
|                                           GrPipelineBuilder* pipelineBuilder,
 | 
| -                                         GrTexture* texture,
 | 
|                                           const SkMatrix& viewMatrix,
 | 
| -                                         const SkClipStack::Element* element,
 | 
| -                                         GrPathRenderer** pr) {
 | 
| -    pipelineBuilder->setRenderTarget(texture->asRenderTarget());
 | 
| -
 | 
| +                                         const SkClipStack::Element* element) {
 | 
| +    GrPathRenderer* pr;
 | 
|      static const bool kNeedsStencil = true;
 | 
| -    return !path_needs_SW_renderer(context,
 | 
| -                                   *pipelineBuilder,
 | 
| -                                   viewMatrix,
 | 
| -                                   element,
 | 
| -                                   pr,
 | 
| -                                   kNeedsStencil);
 | 
| +    path_needs_SW_renderer(context, *pipelineBuilder, viewMatrix, element, &pr, kNeedsStencil);
 | 
| +    return pr;
 | 
|  }
 | 
|  
 | 
|  GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
 | 
| @@ -121,8 +114,17 @@ GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
 | 
|      , fClipMode(kIgnoreClip_StencilClipMode) {
 | 
|  }
 | 
|  
 | 
| -GrContext* GrClipMaskManager::getContext() { return fDrawTarget->cmmAccess().context(); }
 | 
| +GrContext* GrClipMaskManager::getContext() {
 | 
| +    return fDrawTarget->cmmAccess().context();
 | 
| +}
 | 
|  
 | 
| +const GrCaps* GrClipMaskManager::caps() const {
 | 
| +    return fDrawTarget->caps();
 | 
| +}
 | 
| +
 | 
| +GrResourceProvider* GrClipMaskManager::resourceProvider() {
 | 
| +    return fDrawTarget->cmmAccess().resourceProvider();
 | 
| +}
 | 
|  /*
 | 
|   * This method traverses the clip stack to see if the GrSoftwarePathRenderer
 | 
|   * will be used on any element. If so, it returns true to indicate that the
 | 
| @@ -482,48 +484,6 @@ bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder,
 | 
|      return true;
 | 
|  }
 | 
|  
 | 
| -void GrClipMaskManager::mergeMask(GrPipelineBuilder* pipelineBuilder,
 | 
| -                                  GrTexture* dstMask,
 | 
| -                                  GrTexture* srcMask,
 | 
| -                                  SkRegion::Op op,
 | 
| -                                  const SkIRect& dstBound,
 | 
| -                                  const SkIRect& srcBound) {
 | 
| -    pipelineBuilder->setRenderTarget(dstMask->asRenderTarget());
 | 
| -
 | 
| -    // We want to invert the coverage here
 | 
| -    set_coverage_drawing_xpf(op, false, pipelineBuilder);
 | 
| -
 | 
| -    SkMatrix sampleM;
 | 
| -    sampleM.setIDiv(srcMask->width(), srcMask->height());
 | 
| -
 | 
| -    pipelineBuilder->addCoverageFragmentProcessor(
 | 
| -        GrTextureDomainEffect::Create(srcMask,
 | 
| -                                      sampleM,
 | 
| -                                      GrTextureDomain::MakeTexelDomain(srcMask, srcBound),
 | 
| -                                      GrTextureDomain::kDecal_Mode,
 | 
| -                                      GrTextureParams::kNone_FilterMode))->unref();
 | 
| -
 | 
| -    // The color passed in here does not matter since the coverageSetOpXP won't read it.
 | 
| -    fDrawTarget->drawNonAARect(*pipelineBuilder,
 | 
| -                               GrColor_WHITE,
 | 
| -                               SkMatrix::I(),
 | 
| -                               SkRect::Make(dstBound));
 | 
| -}
 | 
| -
 | 
| -GrTexture* GrClipMaskManager::createTempMask(int width, int height) {
 | 
| -    GrSurfaceDesc desc;
 | 
| -    desc.fFlags = kRenderTarget_GrSurfaceFlag;
 | 
| -    desc.fWidth = width;
 | 
| -    desc.fHeight = height;
 | 
| -    if (this->getContext()->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
 | 
| -        desc.fConfig = kAlpha_8_GrPixelConfig;
 | 
| -    } else {
 | 
| -        desc.fConfig = kRGBA_8888_GrPixelConfig;
 | 
| -    }
 | 
| -
 | 
| -    return this->getContext()->textureProvider()->createApproxTexture(desc);
 | 
| -}
 | 
| -
 | 
|  ////////////////////////////////////////////////////////////////////////////////
 | 
|  // Create a 8-bit clip mask in alpha
 | 
|  
 | 
| @@ -541,13 +501,13 @@ GrTexture* GrClipMaskManager::createCachedMask(int width, int height, const GrUn
 | 
|      desc.fWidth = width;
 | 
|      desc.fHeight = height;
 | 
|      desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
 | 
| -    if (!renderTarget || fDrawTarget->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
 | 
| +    if (!renderTarget || this->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
 | 
|          desc.fConfig = kAlpha_8_GrPixelConfig;
 | 
|      } else {
 | 
|          desc.fConfig = kRGBA_8888_GrPixelConfig;
 | 
|      }
 | 
|  
 | 
| -    GrTexture* texture = fDrawTarget->cmmAccess().resourceProvider()->createApproxTexture(desc, 0);
 | 
| +    GrTexture* texture = this->resourceProvider()->createApproxTexture(desc, 0);
 | 
|      if (!texture) {
 | 
|          return nullptr;
 | 
|      }
 | 
| @@ -560,17 +520,16 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
 | 
|                                                    const GrReducedClip::ElementList& elements,
 | 
|                                                    const SkVector& clipToMaskOffset,
 | 
|                                                    const SkIRect& clipSpaceIBounds) {
 | 
| -    GrResourceProvider* resourceProvider = fDrawTarget->cmmAccess().resourceProvider();
 | 
| +    GrResourceProvider* resourceProvider = this->resourceProvider();
 | 
|      GrUniqueKey key;
 | 
|      GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
 | 
|      if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
 | 
|          return texture;
 | 
|      }
 | 
|  
 | 
| +    // There's no texture in the cache. Let's try to allocate it then.
 | 
|      SkAutoTUnref<GrTexture> texture(this->createCachedMask(
 | 
|          clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true));
 | 
| -
 | 
| -    // There's no texture in the cache. Let's try to allocate it then.
 | 
|      if (!texture) {
 | 
|          return nullptr;
 | 
|      }
 | 
| @@ -594,8 +553,7 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
 | 
|      // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first
 | 
|      // pass must not set values outside of this bounds or stencil values outside the rect won't be
 | 
|      // cleared.
 | 
| -    GrClip clip(maskSpaceIBounds);
 | 
| -    SkAutoTUnref<GrTexture> temp;
 | 
| +    const GrClip clip(maskSpaceIBounds);
 | 
|  
 | 
|      // walk through each clip element and perform its set op
 | 
|      for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
 | 
| @@ -606,78 +564,36 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
 | 
|              GrPipelineBuilder pipelineBuilder;
 | 
|  
 | 
|              pipelineBuilder.setClip(clip);
 | 
| -            GrPathRenderer* pr = nullptr;
 | 
| -            bool useTemp = !can_stencil_and_draw_element(this->getContext(), &pipelineBuilder,
 | 
| -                                                         texture, translate, element, &pr);
 | 
| -
 | 
| -            // useSWOnlyPath should now filter out all cases where gpu-side mask merging is
 | 
| -            // performed. See skbug.com/4519 for rationale and details.
 | 
| -            SkASSERT(!useTemp);
 | 
| -
 | 
| -            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
 | 
| -            // touch the minimum number of pixels necessary and use decal mode to combine it with
 | 
| -            // the accumulator.
 | 
| -            SkIRect maskSpaceElementIBounds;
 | 
| -
 | 
| -            if (useTemp) {
 | 
| -                if (invert) {
 | 
| -                    maskSpaceElementIBounds = maskSpaceIBounds;
 | 
| -                } else {
 | 
| -                    SkRect elementBounds = element->getBounds();
 | 
| -                    elementBounds.offset(clipToMaskOffset);
 | 
| -                    elementBounds.roundOut(&maskSpaceElementIBounds);
 | 
| -                }
 | 
| -
 | 
| -                if (!temp) {
 | 
| -                    temp.reset(this->createTempMask(maskSpaceIBounds.fRight,
 | 
| -                                                    maskSpaceIBounds.fBottom));
 | 
| -                    if (!temp) {
 | 
| -                        texture->resourcePriv().removeUniqueKey();
 | 
| -                        return nullptr;
 | 
| -                    }
 | 
| -                }
 | 
| -                dst = temp;
 | 
| -                // clear the temp target and set blend to replace
 | 
| -                fDrawTarget->clear(&maskSpaceElementIBounds,
 | 
| -                                   invert ? 0xffffffff : 0x00000000,
 | 
| -                                   true,
 | 
| -                                   dst->asRenderTarget());
 | 
| -                set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &pipelineBuilder);
 | 
| -            } else {
 | 
| -                // draw directly into the result with the stencil set to make the pixels affected
 | 
| -                // by the clip shape be non-zero.
 | 
| -                dst = texture;
 | 
| -                GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
 | 
| -                                             kReplace_StencilOp,
 | 
| -                                             kReplace_StencilOp,
 | 
| -                                             kAlways_StencilFunc,
 | 
| -                                             0xffff,
 | 
| -                                             0xffff,
 | 
| -                                             0xffff);
 | 
| -                pipelineBuilder.setStencil(kStencilInElement);
 | 
| -                set_coverage_drawing_xpf(op, invert, &pipelineBuilder);
 | 
| +            pipelineBuilder.setRenderTarget(texture->asRenderTarget());
 | 
| +
 | 
| +            GrPathRenderer* pr = get_path_renderer(this->getContext(), &pipelineBuilder,
 | 
| +                                                   translate, element);
 | 
| +            if (Element::kRect_Type != element->getType() && !pr) {
 | 
| +                // useSWOnlyPath should now filter out all cases where gpu-side mask merging would
 | 
| +                // be performed (i.e., pr would be NULL for a non-rect path). See skbug.com/4519
 | 
| +                // for rationale and details.
 | 
| +                SkASSERT(0);
 | 
| +                continue;
 | 
|              }
 | 
|  
 | 
| -            if (!this->drawElement(&pipelineBuilder, translate, dst, element, pr)) {
 | 
| +            // draw directly into the result with the stencil set to make the pixels affected
 | 
| +            // by the clip shape be non-zero.
 | 
| +            GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
 | 
| +                                         kReplace_StencilOp,
 | 
| +                                         kReplace_StencilOp,
 | 
| +                                         kAlways_StencilFunc,
 | 
| +                                         0xffff,
 | 
| +                                         0xffff,
 | 
| +                                         0xffff);
 | 
| +            pipelineBuilder.setStencil(kStencilInElement);
 | 
| +            set_coverage_drawing_xpf(op, invert, &pipelineBuilder);
 | 
| +
 | 
| +            if (!this->drawElement(&pipelineBuilder, translate, texture, element, pr)) {
 | 
|                  texture->resourcePriv().removeUniqueKey();
 | 
|                  return nullptr;
 | 
|              }
 | 
|  
 | 
| -            if (useTemp) {
 | 
| -                GrPipelineBuilder backgroundPipelineBuilder;
 | 
| -                backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget());
 | 
| -
 | 
| -                // Now draw into the accumulator using the real operation and the temp buffer as a
 | 
| -                // texture
 | 
| -                this->mergeMask(&backgroundPipelineBuilder,
 | 
| -                                texture,
 | 
| -                                temp,
 | 
| -                                op,
 | 
| -                                maskSpaceIBounds,
 | 
| -                                maskSpaceElementIBounds);
 | 
| -            } else {
 | 
| +            {
 | 
|                  GrPipelineBuilder backgroundPipelineBuilder;
 | 
|                  backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget());
 | 
|  
 | 
| @@ -720,8 +636,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
 | 
|                                                const SkIPoint& clipSpaceToStencilOffset) {
 | 
|      SkASSERT(rt);
 | 
|  
 | 
| -    GrStencilAttachment* stencilAttachment =
 | 
| -        fDrawTarget->cmmAccess().resourceProvider()->attachStencilAttachment(rt);
 | 
| +    GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachStencilAttachment(rt);
 | 
|      if (nullptr == stencilAttachment) {
 | 
|          return false;
 | 
|      }
 | 
| @@ -977,14 +892,13 @@ void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipel
 | 
|  
 | 
|      int stencilBits = 0;
 | 
|      GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
 | 
| -    GrStencilAttachment* stencilAttachment = 
 | 
| -        fDrawTarget->cmmAccess().resourceProvider()->attachStencilAttachment(rt);
 | 
| +    GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachStencilAttachment(rt);
 | 
|      if (stencilAttachment) {
 | 
|          stencilBits = stencilAttachment->bits();
 | 
|      }
 | 
|  
 | 
| -    SkASSERT(fDrawTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp());
 | 
| -    SkASSERT(fDrawTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSided());
 | 
| +    SkASSERT(this->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp());
 | 
| +    SkASSERT(this->caps()->twoSidedStencilSupport() || !settings.isTwoSided());
 | 
|      this->adjustStencilParams(&settings, fClipMode, stencilBits);
 | 
|      ars->set(&pipelineBuilder);
 | 
|      ars->setStencil(settings);
 | 
| @@ -1005,7 +919,7 @@ void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
 | 
|      unsigned int userBits = clipBit - 1;
 | 
|  
 | 
|      GrStencilSettings::Face face = GrStencilSettings::kFront_Face;
 | 
| -    bool twoSided = fDrawTarget->caps()->twoSidedStencilSupport();
 | 
| +    bool twoSided = this->caps()->twoSidedStencilSupport();
 | 
|  
 | 
|      bool finished = false;
 | 
|      while (!finished) {
 | 
| @@ -1077,7 +991,7 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
 | 
|                                                       const SkIRect& clipSpaceIBounds) {
 | 
|      GrUniqueKey key;
 | 
|      GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
 | 
| -    GrResourceProvider* resourceProvider = fDrawTarget->cmmAccess().resourceProvider();
 | 
| +    GrResourceProvider* resourceProvider = this->resourceProvider();
 | 
|      if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
 | 
|          return texture;
 | 
|      }
 | 
| 
 |