| Index: src/gpu/GrClipMaskManager.cpp
|
| diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
|
| index b87788b286bc0d22f32cd79c78430d53919e3524..b57f3cc1bcc5fa54e0d5a2ef797f53284640f185 100644
|
| --- a/src/gpu/GrClipMaskManager.cpp
|
| +++ b/src/gpu/GrClipMaskManager.cpp
|
| @@ -46,71 +46,24 @@
|
| 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 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);
|
| - }
|
| -}
|
| -
|
| -// 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);
|
| + 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;
|
| +
|
| + return nullptr == context->getPathRenderer(&pipelineBuilder, viewMatrix, *path, stroke,
|
| + false, type);
|
| }
|
|
|
| GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
|
| @@ -131,22 +84,24 @@
|
| // 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.
|
| - const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
|
| + SkMatrix translate;
|
| + translate.setTranslate(clipToMaskOffset);
|
|
|
| for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
|
| const Element* element = iter.get();
|
| -
|
| - 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;
|
| + // 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;
|
| + }
|
| }
|
| }
|
| return false;
|
| @@ -457,7 +412,7 @@
|
| 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) {
|
| @@ -479,6 +434,32 @@
|
| 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,
|
| @@ -574,7 +555,8 @@
|
|
|
| // Set the matrix so that rendered clip elements are transformed to mask space from clip
|
| // space.
|
| - const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
|
| + SkMatrix translate;
|
| + translate.setTranslate(clipToMaskOffset);
|
|
|
| // The texture may be larger than necessary, this rect represents the part of the texture
|
| // we populate with a rasterization of the clip.
|
| @@ -604,16 +586,13 @@
|
|
|
| pipelineBuilder.setClip(clip);
|
| GrPathRenderer* pr = nullptr;
|
| - bool useTemp = !can_stencil_and_draw_element(this->getContext(), &pipelineBuilder,
|
| - texture, translate, element, &pr);
|
| + bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, texture, &pr, element);
|
| 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;
|
| -
|
| - SkASSERT(!useTemp);
|
|
|
| if (useTemp) {
|
| if (invert) {
|
| @@ -780,7 +759,7 @@
|
| if (fillInverted) {
|
| clipPath.toggleInverseFillType();
|
| }
|
| - pr = this->getContext()->getPathRenderer(pipelineBuilder,
|
| + pr = this->getContext()->getPathRenderer(&pipelineBuilder,
|
| viewMatrix,
|
| clipPath,
|
| stroke,
|
|
|