aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrReducedClip.cpp
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2018-03-30 15:59:38 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-30 17:03:16 +0000
commitc534808ba21e61507fe3ebf9f23d230a71e5ada7 (patch)
tree3ff1d39feb8fe4c464950178c3bc1ecfaf403b11 /src/gpu/GrReducedClip.cpp
parent7a002c36ce3faed3b3201453770b8f18eecc8f2f (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.cpp128
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,