diff options
author | Chris Dalton <csmartdalton@google.com> | 2018-03-30 15:59:38 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-03-30 17:03:16 +0000 |
commit | c534808ba21e61507fe3ebf9f23d230a71e5ada7 (patch) | |
tree | 3ff1d39feb8fe4c464950178c3bc1ecfaf403b11 /src/gpu/GrReducedClip.cpp | |
parent | 7a002c36ce3faed3b3201453770b8f18eecc8f2f (diff) |
Revert "Delete GPU alpha clip masks"
This reverts commit a466228a616b1b02ede2d4389fefcfc839a54a25.
Reason for revert: Turned up a vulkan driver bug
Original change's description:
> Delete GPU alpha clip masks
>
> The cost of switching render targets on each draw to make a custom
> clip is enormous. There are virtually no circumstances where this will
> outperform our cached, multi-threaded software mask generator. The
> tried-and-true approach to clipping on-GPU is with analytic FPs. And
> now that we support CCPR clip FPs, there ulitmately should be very few
> clip stacks that even require a mask as long as they don't use
> deprecated SkClipOps.
>
> Bug: skia:
> Change-Id: I79c5558c93c1b99179f1e933d029f69b14ad1ce3
> Reviewed-on: https://skia-review.googlesource.com/116724
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
TBR=robertphillips@google.com,brianosman@google.com,csmartdalton@google.com
# Not skipping CQ checks because original CL landed > 1 day ago.
Bug: skia:
Change-Id: Iba289e00ba2eca7084dc8517491cfb5f6ab6266f
Reviewed-on: https://skia-review.googlesource.com/117420
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'src/gpu/GrReducedClip.cpp')
-rw-r--r-- | src/gpu/GrReducedClip.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index 2f60dad28f..9d27f7696e 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -673,6 +673,134 @@ void GrReducedClip::makeEmpty() { } //////////////////////////////////////////////////////////////////////////////// +// Create a 8-bit clip mask in alpha + +static bool stencil_element(GrRenderTargetContext* rtc, + const GrFixedClip& clip, + const GrUserStencilSettings* ss, + const SkMatrix& viewMatrix, + const SkClipStack::Element* element) { + GrAA aa = GrAA(element->isAA()); + switch (element->getDeviceSpaceType()) { + case SkClipStack::Element::DeviceSpaceType::kEmpty: + SkDEBUGFAIL("Should never get here with an empty element."); + break; + case SkClipStack::Element::DeviceSpaceType::kRect: + return rtc->priv().drawAndStencilRect(clip, ss, (SkRegion::Op)element->getOp(), + element->isInverseFilled(), aa, viewMatrix, + element->getDeviceSpaceRect()); + break; + default: { + SkPath path; + element->asDeviceSpacePath(&path); + if (path.isInverseFillType()) { + path.toggleInverseFillType(); + } + + return rtc->priv().drawAndStencilPath(clip, ss, (SkRegion::Op)element->getOp(), + element->isInverseFilled(), aa, viewMatrix, path); + break; + } + } + + return false; +} + +static void draw_element(GrRenderTargetContext* rtc, + const GrClip& clip, // TODO: can this just always be WideOpen? + GrPaint&& paint, + GrAA aa, + const SkMatrix& viewMatrix, + const SkClipStack::Element* element) { + // TODO: Draw rrects directly here. + switch (element->getDeviceSpaceType()) { + case SkClipStack::Element::DeviceSpaceType::kEmpty: + SkDEBUGFAIL("Should never get here with an empty element."); + break; + case SkClipStack::Element::DeviceSpaceType::kRect: + rtc->drawRect(clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect()); + break; + default: { + SkPath path; + element->asDeviceSpacePath(&path); + if (path.isInverseFillType()) { + path.toggleInverseFillType(); + } + + rtc->drawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill()); + break; + } + } +} + +bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const { + // The texture may be larger than necessary, this rect represents the part of the texture + // we populate with a rasterization of the clip. + GrFixedClip clip(SkIRect::MakeWH(fScissor.width(), fScissor.height())); + + if (!fWindowRects.empty()) { + clip.setWindowRectangles(fWindowRects.makeOffset(-fScissor.left(), -fScissor.top()), + GrWindowRectsState::Mode::kExclusive); + } + + // The scratch texture that we are drawing into can be substantially larger than the mask. Only + // clear the part that we care about. + GrColor initialCoverage = InitialState::kAllIn == this->initialState() ? -1 : 0; + rtc->priv().clear(clip, initialCoverage, GrRenderTargetContext::CanClearFullscreen::kYes); + + // Set the matrix so that rendered clip elements are transformed to mask space from clip space. + SkMatrix translate; + translate.setTranslate(SkIntToScalar(-fScissor.left()), SkIntToScalar(-fScissor.top())); + + // walk through each clip element and perform its set op + for (ElementList::Iter iter(fMaskElements); iter.get(); iter.next()) { + const Element* element = iter.get(); + SkRegion::Op op = (SkRegion::Op)element->getOp(); + GrAA aa = GrAA(element->isAA()); + bool invert = element->isInverseFilled(); + if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { + // draw directly into the result with the stencil set to make the pixels affected + // by the clip shape be non-zero. + static constexpr GrUserStencilSettings kStencilInElement( + GrUserStencilSettings::StaticInit< + 0xffff, + GrUserStencilTest::kAlways, + 0xffff, + GrUserStencilOp::kReplace, + GrUserStencilOp::kReplace, + 0xffff>() + ); + if (!stencil_element(rtc, clip, &kStencilInElement, translate, element)) { + return false; + } + + // Draw to the exterior pixels (those with a zero stencil value). + static constexpr GrUserStencilSettings kDrawOutsideElement( + GrUserStencilSettings::StaticInit< + 0x0000, + GrUserStencilTest::kEqual, + 0xffff, + GrUserStencilOp::kZero, + GrUserStencilOp::kZero, + 0xffff>() + ); + if (!rtc->priv().drawAndStencilRect(clip, &kDrawOutsideElement, op, !invert, GrAA::kNo, + translate, SkRect::Make(fScissor))) { + return false; + } + } else { + // all the remaining ops can just be directly draw into the accumulation buffer + GrPaint paint; + paint.setCoverageSetOpXPFactory(op, false); + + draw_element(rtc, clip, std::move(paint), aa, translate, element); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// // Create a 1-bit clip mask in the stencil buffer. bool GrReducedClip::drawStencilClipMask(GrContext* context, |