| 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;
|
| }
|
|
|