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

Unified Diff: src/gpu/GrClipStackClip.cpp

Issue 2138083002: skip call to clip::apply when clip is wide open Base URL: https://chromium.googlesource.com/skia.git@llist
Patch Set: rm gcmm Created 4 years, 5 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/GrClipStackClip.h ('k') | src/gpu/GrDrawTarget.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrClipStackClip.cpp
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipStackClip.cpp
similarity index 91%
rename from src/gpu/GrClipMaskManager.cpp
rename to src/gpu/GrClipStackClip.cpp
index c591bf11826babd6fdfe9861994a1a8bc8da9e7b..84519f1a5eaa21c7d9ce8619ef4250dffdfe5737 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "GrClipMaskManager.h"
+#include "GrClipStackClip.h"
#include "GrCaps.h"
#include "GrDrawingManager.h"
#include "GrDrawContextPriv.h"
@@ -27,6 +27,29 @@
typedef SkClipStack::Element Element;
+bool GrClipStackClip::quickContains(const SkRect& rect) const {
+ if (!fStack) {
+ return true;
+ }
+ return fStack->quickContains(rect.makeOffset(SkIntToScalar(fOrigin.x()),
+ SkIntToScalar(fOrigin.y())));
+}
+
+void GrClipStackClip::getConservativeBounds(int width, int height, SkIRect* devResult,
+ bool* isIntersectionOfRects) const {
+ if (!fStack) {
+ devResult->setXYWH(0, 0, width, height);
+ if (isIntersectionOfRects) {
+ *isIntersectionOfRects = true;
+ }
+ return;
+ }
+ SkRect devBounds;
+ fStack->getConservativeBounds(-fOrigin.x(), -fOrigin.y(), width, height, &devBounds,
+ isIntersectionOfRects);
+ devBounds.roundOut(devResult);
+}
+
static const int kMaxAnalyticElements = 4;
////////////////////////////////////////////////////////////////////////////////
@@ -54,7 +77,7 @@ static sk_sp<GrFragmentProcessor> create_fp_for_mask(GrTexture* result,
// 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).
-bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context,
+bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context,
bool hasUserStencilSettings,
const GrDrawContext* drawContext,
const SkMatrix& viewMatrix,
@@ -114,11 +137,11 @@ bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context,
* will be used on any element. If so, it returns true to indicate that the
* entire clip should be rendered in SW and then uploaded en masse to the gpu.
*/
-bool GrClipMaskManager::UseSWOnlyPath(GrContext* context,
- const GrPipelineBuilder& pipelineBuilder,
- const GrDrawContext* drawContext,
- const SkVector& clipToMaskOffset,
- const GrReducedClip::ElementList& elements) {
+bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
+ const GrPipelineBuilder& pipelineBuilder,
+ const GrDrawContext* drawContext,
+ const SkVector& clipToMaskOffset,
+ const GrReducedClip::ElementList& elements) {
// 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.
@@ -222,157 +245,6 @@ static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen
return true;
}
-////////////////////////////////////////////////////////////////////////////////
-// sort out what kind of clip mask needs to be created: alpha, stencil,
-// scissor, or entirely software
-bool GrClipMaskManager::SetupClipping(GrContext* context,
- const GrPipelineBuilder& pipelineBuilder,
- GrDrawContext* drawContext,
- const GrClipStackClip& clip,
- const SkRect* origDevBounds,
- GrAppliedClip* out) {
- if (!clip.clipStack() || clip.clipStack()->isWideOpen()) {
- return true;
- }
-
- GrReducedClip::ElementList elements;
- int32_t genID = 0;
- GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialState;
- SkIRect clipSpaceIBounds;
- bool requiresAA = false;
-
- SkIRect clipSpaceReduceQueryBounds;
- SkRect devBounds;
- if (origDevBounds) {
- if (!devBounds.intersect(SkRect::MakeIWH(drawContext->width(), drawContext->height()),
- *origDevBounds)) {
- return false;
- }
- devBounds.roundOut(&clipSpaceReduceQueryBounds);
- clipSpaceReduceQueryBounds.offset(clip.origin());
- } else {
- devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height());
- clipSpaceReduceQueryBounds.setXYWH(0, 0, drawContext->width(), drawContext->height());
- clipSpaceReduceQueryBounds.offset(clip.origin());
- }
- GrReducedClip::ReduceClipStack(*clip.clipStack(),
- clipSpaceReduceQueryBounds,
- &elements,
- &genID,
- &initialState,
- &clipSpaceIBounds,
- &requiresAA);
- if (elements.isEmpty()) {
- if (GrReducedClip::kAllOut_InitialState == initialState) {
- return false;
- } else {
- SkIRect scissorSpaceIBounds(clipSpaceIBounds);
- scissorSpaceIBounds.offset(-clip.origin());
- if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
- out->makeScissored(scissorSpaceIBounds);
- }
- return true;
- }
- }
-
- // An element count of 4 was chosen because of the common pattern in Blink of:
- // isect RR
- // diff RR
- // isect convex_poly
- // isect convex_poly
- // when drawing rounded div borders. This could probably be tuned based on a
- // configuration's relative costs of switching RTs to generate a mask vs
- // longer shaders.
- if (elements.count() <= kMaxAnalyticElements) {
- SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX),
- SkIntToScalar(-clip.origin().fY) };
- // When there are multiple samples we want to do per-sample clipping, not compute a
- // fractional pixel coverage.
- bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled();
- if (disallowAnalyticAA && !drawContext->numColorSamples()) {
- // With a single color sample, any coverage info is lost from color once it hits the
- // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe
- // is multisampled.
- disallowAnalyticAA = pipelineBuilder.isHWAntialias() ||
- pipelineBuilder.hasUserStencilSettings();
- }
- sk_sp<GrFragmentProcessor> clipFP;
- if (requiresAA &&
- get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTOffset, devBounds,
- &clipFP)) {
- SkIRect scissorSpaceIBounds(clipSpaceIBounds);
- scissorSpaceIBounds.offset(-clip.origin());
- if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
- out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds);
- return true;
- }
- out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBounds));
- return true;
- }
- }
-
- // If the stencil buffer is multisampled we can use it to do everything.
- if (!drawContext->isStencilBufferMultisampled() && requiresAA) {
- sk_sp<GrTexture> result;
-
- // The top-left of the mask corresponds to the top-left corner of the bounds.
- SkVector clipToMaskOffset = {
- SkIntToScalar(-clipSpaceIBounds.fLeft),
- SkIntToScalar(-clipSpaceIBounds.fTop)
- };
-
- if (UseSWOnlyPath(context, pipelineBuilder, drawContext,
- clipToMaskOffset, elements)) {
- // The clip geometry is complex enough that it will be more efficient to create it
- // entirely in software
- result = CreateSoftwareClipMask(context->textureProvider(),
- genID,
- initialState,
- elements,
- clipToMaskOffset,
- clipSpaceIBounds);
- } else {
- result = CreateAlphaClipMask(context,
- genID,
- initialState,
- elements,
- clipToMaskOffset,
- clipSpaceIBounds);
- // If createAlphaClipMask fails it means UseSWOnlyPath has a bug
- SkASSERT(result);
- }
-
- if (result) {
- // The mask's top left coord should be pinned to the rounded-out top left corner of
- // clipSpace bounds. We determine the mask's position WRT to the render target here.
- SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
- rtSpaceMaskBounds.offset(-clip.origin());
- out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds),
- SkRect::Make(rtSpaceMaskBounds));
- return true;
- }
- // if alpha clip mask creation fails fall through to the non-AA code paths
- }
-
- // use the stencil clip if we can't represent the clip as a rectangle.
- SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin();
- CreateStencilClipMask(context,
- drawContext,
- genID,
- initialState,
- elements,
- clipSpaceIBounds,
- clipSpaceToStencilSpaceOffset);
-
- // This must occur after createStencilClipMask. That function may change the scissor. Also, it
- // only guarantees that the stencil mask is correct within the bounds it was passed, so we must
- // use both stencil and scissor test to the bounds for the final draw.
- SkIRect scissorSpaceIBounds(clipSpaceIBounds);
- scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
- out->makeScissoredStencil(scissorSpaceIBounds);
- return true;
-}
-
static bool stencil_element(GrDrawContext* dc,
const GrFixedClip& clip,
const GrUserStencilSettings* ss,
@@ -447,7 +319,7 @@ static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey
builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
}
-sk_sp<GrTexture> GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
+sk_sp<GrTexture> CreateAlphaClipMask(GrContext* context,
int32_t elementsGenID,
GrReducedClip::InitialState initialState,
const GrReducedClip::ElementList& elements,
@@ -552,13 +424,13 @@ sk_sp<GrTexture> GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
////////////////////////////////////////////////////////////////////////////////
// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
// (as opposed to canvas) coordinates
-bool GrClipMaskManager::CreateStencilClipMask(GrContext* context,
- GrDrawContext* drawContext,
- int32_t elementsGenID,
- GrReducedClip::InitialState initialState,
- const GrReducedClip::ElementList& elements,
- const SkIRect& clipSpaceIBounds,
- const SkIPoint& clipSpaceToStencilOffset) {
+bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
+ GrDrawContext* drawContext,
+ int32_t elementsGenID,
+ GrReducedClip::InitialState initialState,
+ const GrReducedClip::ElementList& elements,
+ const SkIRect& clipSpaceIBounds,
+ const SkIPoint& clipSpaceToStencilOffset) {
SkASSERT(drawContext);
GrStencilAttachment* stencilAttachment = context->resourceProvider()->attachStencilAttachment(
@@ -735,7 +607,7 @@ bool GrClipMaskManager::CreateStencilClipMask(GrContext* context,
}
////////////////////////////////////////////////////////////////////////////////
-sk_sp<GrTexture> GrClipMaskManager::CreateSoftwareClipMask(
+sk_sp<GrTexture> CreateSoftwareClipMask(
GrTextureProvider* texProvider,
int32_t elementsGenID,
GrReducedClip::InitialState initialState,
@@ -812,3 +684,148 @@ sk_sp<GrTexture> GrClipMaskManager::CreateSoftwareClipMask(
return result;
}
+
+bool GrClipStackClip::apply(GrContext* context,
+ const GrPipelineBuilder& pipelineBuilder, GrDrawContext* drawContext,
+ const SkRect* origDevBounds, GrAppliedClip* out) const {
+ ////////////////////////////////////////////////////////////////////////////////
+ // sort out what kind of clip mask needs to be created: alpha, stencil,
+ // scissor, or entirely software
+
+ GrReducedClip::ElementList elements;
+ int32_t genID = 0;
+ GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialState;
+ SkIRect clipSpaceIBounds;
+ bool requiresAA = false;
+
+ SkIRect clipSpaceReduceQueryBounds;
+ SkRect devBounds;
+ if (origDevBounds) {
+ if (!devBounds.intersect(SkRect::MakeIWH(drawContext->width(), drawContext->height()),
+ *origDevBounds)) {
+ return false;
+ }
+ devBounds.roundOut(&clipSpaceReduceQueryBounds);
+ clipSpaceReduceQueryBounds.offset(this->origin());
+ } else {
+ devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height());
+ clipSpaceReduceQueryBounds.setXYWH(0, 0, drawContext->width(), drawContext->height());
+ clipSpaceReduceQueryBounds.offset(this->origin());
+ }
+ GrReducedClip::ReduceClipStack(*this->clipStack(),
+ clipSpaceReduceQueryBounds,
+ &elements,
+ &genID,
+ &initialState,
+ &clipSpaceIBounds,
+ &requiresAA);
+ if (elements.isEmpty()) {
+ if (GrReducedClip::kAllOut_InitialState == initialState) {
+ return false;
+ } else {
+ SkIRect scissorSpaceIBounds(clipSpaceIBounds);
+ scissorSpaceIBounds.offset(-this->origin());
+ if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
+ out->makeScissored(scissorSpaceIBounds);
+ }
+ return true;
+ }
+ }
+
+ // An element count of 4 was chosen because of the common pattern in Blink of:
+ // isect RR
+ // diff RR
+ // isect convex_poly
+ // isect convex_poly
+ // when drawing rounded div borders. This could probably be tuned based on a
+ // configuration's relative costs of switching RTs to generate a mask vs
+ // longer shaders.
+ if (elements.count() <= kMaxAnalyticElements) {
+ SkVector clipToRTOffset = { SkIntToScalar(-this->origin().fX),
+ SkIntToScalar(-this->origin().fY) };
+ // When there are multiple samples we want to do per-sample clipping, not compute a
+ // fractional pixel coverage.
+ bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled();
+ if (disallowAnalyticAA && !drawContext->numColorSamples()) {
+ // With a single color sample, any coverage info is lost from color once it hits the
+ // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe
+ // is multisampled.
+ disallowAnalyticAA = pipelineBuilder.isHWAntialias() ||
+ pipelineBuilder.hasUserStencilSettings();
+ }
+ sk_sp<GrFragmentProcessor> clipFP;
+ if (requiresAA &&
+ get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTOffset, devBounds,
+ &clipFP)) {
+ SkIRect scissorSpaceIBounds(clipSpaceIBounds);
+ scissorSpaceIBounds.offset(-this->origin());
+ if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
+ out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds);
+ return true;
+ }
+ out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBounds));
+ return true;
+ }
+ }
+
+ // If the stencil buffer is multisampled we can use it to do everything.
+ if (!drawContext->isStencilBufferMultisampled() && requiresAA) {
+ sk_sp<GrTexture> result;
+
+ // The top-left of the mask corresponds to the top-left corner of the bounds.
+ SkVector clipToMaskOffset = {
+ SkIntToScalar(-clipSpaceIBounds.fLeft),
+ SkIntToScalar(-clipSpaceIBounds.fTop)
+ };
+
+ if (UseSWOnlyPath(context, pipelineBuilder, drawContext,
+ clipToMaskOffset, elements)) {
+ // The clip geometry is complex enough that it will be more efficient to create it
+ // entirely in software
+ result = CreateSoftwareClipMask(context->textureProvider(),
+ genID,
+ initialState,
+ elements,
+ clipToMaskOffset,
+ clipSpaceIBounds);
+ } else {
+ result = CreateAlphaClipMask(context,
+ genID,
+ initialState,
+ elements,
+ clipToMaskOffset,
+ clipSpaceIBounds);
+ // If createAlphaClipMask fails it means UseSWOnlyPath has a bug
+ SkASSERT(result);
+ }
+
+ if (result) {
+ // The mask's top left coord should be pinned to the rounded-out top left corner of
+ // clipSpace bounds. We determine the mask's position WRT to the render target here.
+ SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
+ rtSpaceMaskBounds.offset(-this->origin());
+ out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds),
+ SkRect::Make(rtSpaceMaskBounds));
+ return true;
+ }
+ // if alpha clip mask creation fails fall through to the non-AA code paths
+ }
+
+ // use the stencil clip if we can't represent the clip as a rectangle.
+ SkIPoint clipSpaceToStencilSpaceOffset = -this->origin();
+ CreateStencilClipMask(context,
+ drawContext,
+ genID,
+ initialState,
+ elements,
+ clipSpaceIBounds,
+ clipSpaceToStencilSpaceOffset);
+
+ // This must occur after createStencilClipMask. That function may change the scissor. Also, it
+ // only guarantees that the stencil mask is correct within the bounds it was passed, so we must
+ // use both stencil and scissor test to the bounds for the final draw.
+ SkIRect scissorSpaceIBounds(clipSpaceIBounds);
+ scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
+ out->makeScissoredStencil(scissorSpaceIBounds);
+ return true;
+}
« no previous file with comments | « src/gpu/GrClipStackClip.h ('k') | src/gpu/GrDrawTarget.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698