Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Unified Diff: src/gpu/GrReducedClip.cpp

Issue 2263343002: Move clip mask generation into GrReducedClip (Closed) Base URL: https://skia.googlesource.com/skia.git@upload2_clipclears
Patch Set: msvc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrReducedClip.h ('k') | src/gpu/GrStencilAttachment.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrReducedClip.cpp
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 237ea221e1a6c84cae087c503011a05134eb12a9..dfc0a2651bd45be8ff51a637f25523f6dd1633f2 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -7,7 +7,17 @@
#include "GrReducedClip.h"
+#include "GrAppliedClip.h"
#include "GrClip.h"
+#include "GrColor.h"
+#include "GrContextPriv.h"
+#include "GrDrawContext.h"
+#include "GrDrawContextPriv.h"
+#include "GrDrawingManager.h"
+#include "GrFixedClip.h"
+#include "GrPathRenderer.h"
+#include "GrStyle.h"
+#include "GrUserStencilSettings.h"
typedef SkClipStack::Element Element;
@@ -421,3 +431,316 @@ inline bool GrReducedClip::intersectIBounds(const SkIRect& irect) {
}
return true;
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Create a 8-bit clip mask in alpha
+
+static bool stencil_element(GrDrawContext* dc,
+ const GrFixedClip& clip,
+ const GrUserStencilSettings* ss,
+ const SkMatrix& viewMatrix,
+ const SkClipStack::Element* element) {
+
+ // TODO: Draw rrects directly here.
+ switch (element->getType()) {
+ case Element::kEmpty_Type:
+ SkDEBUGFAIL("Should never get here with an empty element.");
+ break;
+ case Element::kRect_Type:
+ return dc->drawContextPriv().drawAndStencilRect(clip, ss,
+ element->getOp(),
+ element->isInverseFilled(),
+ element->isAA(),
+ viewMatrix, element->getRect());
+ break;
+ default: {
+ SkPath path;
+ element->asPath(&path);
+ if (path.isInverseFillType()) {
+ path.toggleInverseFillType();
+ }
+
+ return dc->drawContextPriv().drawAndStencilPath(clip, ss,
+ element->getOp(),
+ element->isInverseFilled(),
+ element->isAA(), viewMatrix, path);
+ break;
+ }
+ }
+
+ return false;
+}
+
+static void draw_element(GrDrawContext* dc,
+ const GrClip& clip, // TODO: can this just always be WideOpen?
+ const GrPaint &paint,
+ const SkMatrix& viewMatrix,
+ const SkClipStack::Element* element) {
+
+ // TODO: Draw rrects directly here.
+ switch (element->getType()) {
+ case Element::kEmpty_Type:
+ SkDEBUGFAIL("Should never get here with an empty element.");
+ break;
+ case Element::kRect_Type:
+ dc->drawRect(clip, paint, viewMatrix, element->getRect());
+ break;
+ default: {
+ SkPath path;
+ element->asPath(&path);
+ if (path.isInverseFillType()) {
+ path.toggleInverseFillType();
+ }
+
+ dc->drawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
+ break;
+ }
+ }
+}
+
+bool GrReducedClip::drawAlphaClipMask(GrDrawContext* dc) 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(fIBounds.width(), fIBounds.height()));
+
+ // 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;
+ dc->drawContextPriv().clear(clip, initialCoverage, true);
+
+ // Set the matrix so that rendered clip elements are transformed to mask space from clip space.
+ SkMatrix translate;
+ translate.setTranslate(SkIntToScalar(-fIBounds.left()), SkIntToScalar(-fIBounds.top()));
+
+ // walk through each clip element and perform its set op
+ for (ElementList::Iter iter(fElements); iter.get(); iter.next()) {
+ const Element* element = iter.get();
+ SkRegion::Op op = element->getOp();
+ 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(dc, 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 (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideElement,
+ op, !invert, false,
+ translate,
+ SkRect::Make(fIBounds))) {
+ return false;
+ }
+ } else {
+ // all the remaining ops can just be directly draw into the accumulation buffer
+ GrPaint paint;
+ paint.setAntiAlias(element->isAA());
+ paint.setCoverageSetOpXPFactory(op, false);
+
+ draw_element(dc, clip, paint, translate, element);
+ }
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Create a 1-bit clip mask in the stencil buffer.
+
+class StencilClip final : public GrClip {
+public:
+ StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {}
+ const GrFixedClip& fixedClip() const { return fFixedClip; }
+
+private:
+ bool quickContains(const SkRect&) const final {
+ return false;
+ }
+ void getConservativeBounds(int width, int height, SkIRect* devResult, bool* iior) const final {
+ fFixedClip.getConservativeBounds(width, height, devResult, iior);
+ }
+ bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final {
+ return false;
+ }
+ bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA,
+ bool hasUserStencilSettings, GrAppliedClip* out) const final {
+ if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSettings, out)) {
+ return false;
+ }
+ out->addStencilClip();
+ return true;
+ }
+
+ GrFixedClip fFixedClip;
+
+ typedef GrClip INHERITED;
+};
+
+bool GrReducedClip::drawStencilClipMask(GrContext* context,
+ GrDrawContext* drawContext,
+ const SkIPoint& clipOrigin) const {
+ // We set the current clip to the bounds so that our recursive draws are scissored to them.
+ StencilClip stencilClip(fIBounds.makeOffset(-clipOrigin.x(), -clipOrigin.y()));
+
+ bool initialState = InitialState::kAllIn == this->initialState();
+ drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), initialState);
+
+ // Set the matrix so that rendered clip elements are transformed from clip to stencil space.
+ SkMatrix viewMatrix;
+ viewMatrix.setTranslate(SkIntToScalar(-clipOrigin.x()), SkIntToScalar(-clipOrigin.y()));
+
+ // walk through each clip element and perform its set op
+ // with the existing clip.
+ for (ElementList::Iter iter(fElements); iter.get(); iter.next()) {
+ const Element* element = iter.get();
+ bool useHWAA = element->isAA() && drawContext->isStencilBufferMultisampled();
+
+ bool fillInverted = false;
+
+ // This will be used to determine whether the clip shape can be rendered into the
+ // stencil with arbitrary stencil settings.
+ GrPathRenderer::StencilSupport stencilSupport;
+
+ SkRegion::Op op = element->getOp();
+
+ GrPathRenderer* pr = nullptr;
+ SkPath clipPath;
+ if (Element::kRect_Type == element->getType()) {
+ stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
+ fillInverted = false;
+ } else {
+ element->asPath(&clipPath);
+ fillInverted = clipPath.isInverseFillType();
+ if (fillInverted) {
+ clipPath.toggleInverseFillType();
+ }
+
+ GrShape shape(clipPath, GrStyle::SimpleFill());
+ GrPathRenderer::CanDrawPathArgs canDrawArgs;
+ canDrawArgs.fShaderCaps = context->caps()->shaderCaps();
+ canDrawArgs.fViewMatrix = &viewMatrix;
+ canDrawArgs.fShape = &shape;
+ canDrawArgs.fAntiAlias = false;
+ canDrawArgs.fHasUserStencilSettings = false;
+ canDrawArgs.fIsStencilBufferMSAA = drawContext->isStencilBufferMultisampled();
+
+ GrDrawingManager* dm = context->contextPriv().drawingManager();
+ pr = dm->getPathRenderer(canDrawArgs, false,
+ GrPathRendererChain::kStencilOnly_DrawType,
+ &stencilSupport);
+ if (!pr) {
+ return false;
+ }
+ }
+
+ bool canRenderDirectToStencil =
+ GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport;
+ bool drawDirectToClip; // Given the renderer, the element,
+ // fill rule, and set operation should
+ // we render the element directly to
+ // stencil bit used for clipping.
+ GrUserStencilSettings const* const* stencilPasses =
+ GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, fillInverted,
+ &drawDirectToClip);
+
+ // draw the element to the client stencil bits if necessary
+ if (!drawDirectToClip) {
+ static constexpr GrUserStencilSettings kDrawToStencil(
+ GrUserStencilSettings::StaticInit<
+ 0x0000,
+ GrUserStencilTest::kAlways,
+ 0xffff,
+ GrUserStencilOp::kIncMaybeClamp,
+ GrUserStencilOp::kIncMaybeClamp,
+ 0xffff>()
+ );
+ if (Element::kRect_Type == element->getType()) {
+ drawContext->drawContextPriv().stencilRect(stencilClip.fixedClip(),
+ &kDrawToStencil, useHWAA,
+ viewMatrix, element->getRect());
+ } else {
+ if (!clipPath.isEmpty()) {
+ GrShape shape(clipPath, GrStyle::SimpleFill());
+ if (canRenderDirectToStencil) {
+ GrPaint paint;
+ paint.setXPFactory(GrDisableColorXPFactory::Make());
+ paint.setAntiAlias(element->isAA());
+
+ GrPathRenderer::DrawPathArgs args;
+ args.fResourceProvider = context->resourceProvider();
+ args.fPaint = &paint;
+ args.fUserStencilSettings = &kDrawToStencil;
+ args.fDrawContext = drawContext;
+ args.fClip = &stencilClip.fixedClip();
+ args.fViewMatrix = &viewMatrix;
+ args.fShape = &shape;
+ args.fAntiAlias = false;
+ args.fGammaCorrect = false;
+ pr->drawPath(args);
+ } else {
+ GrPathRenderer::StencilPathArgs args;
+ args.fResourceProvider = context->resourceProvider();
+ args.fDrawContext = drawContext;
+ args.fClip = &stencilClip.fixedClip();
+ args.fViewMatrix = &viewMatrix;
+ args.fIsAA = element->isAA();
+ args.fShape = &shape;
+ pr->stencilPath(args);
+ }
+ }
+ }
+ }
+
+ // now we modify the clip bit by rendering either the clip
+ // element directly or a bounding rect of the entire clip.
+ for (GrUserStencilSettings const* const* pass = stencilPasses; *pass; ++pass) {
+ if (drawDirectToClip) {
+ if (Element::kRect_Type == element->getType()) {
+ drawContext->drawContextPriv().stencilRect(stencilClip, *pass, useHWAA,
+ viewMatrix, element->getRect());
+ } else {
+ GrShape shape(clipPath, GrStyle::SimpleFill());
+ GrPaint paint;
+ paint.setXPFactory(GrDisableColorXPFactory::Make());
+ paint.setAntiAlias(element->isAA());
+ GrPathRenderer::DrawPathArgs args;
+ args.fResourceProvider = context->resourceProvider();
+ args.fPaint = &paint;
+ args.fUserStencilSettings = *pass;
+ args.fDrawContext = drawContext;
+ args.fClip = &stencilClip;
+ args.fViewMatrix = &viewMatrix;
+ args.fShape = &shape;
+ args.fAntiAlias = false;
+ args.fGammaCorrect = false;
+ pr->drawPath(args);
+ }
+ } else {
+ // The view matrix is setup to do clip space -> stencil space translation, so
+ // draw rect in clip space.
+ drawContext->drawContextPriv().stencilRect(stencilClip, *pass,
+ false, viewMatrix,
+ SkRect::Make(fIBounds));
+ }
+ }
+ }
+ return true;
+}
« no previous file with comments | « src/gpu/GrReducedClip.h ('k') | src/gpu/GrStencilAttachment.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698