aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar csmartdalton <csmartdalton@google.com>2016-08-08 09:55:06 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-08 09:55:06 -0700
commit77f2fae49ec969f0771921f1c1886c12289c7bfe (patch)
tree55a1383dc7e7874e7f0dc66a0d6a13933ff195d1 /src/gpu
parent0652baa23ec2ea9e1bcdf686bf1e1118b186b42c (diff)
Encapsulate GrReducedClip result in class members
Updates GrReducedClip to store its result in class members instead of various pointer arguments. This helps clean up calling code and will make it easier to reduce the clip higher in the stack. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2222873002 Review-Url: https://codereview.chromium.org/2222873002
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrClipStackClip.cpp153
-rw-r--r--src/gpu/GrClipStackClip.h19
-rw-r--r--src/gpu/GrReducedClip.cpp121
-rw-r--r--src/gpu/GrReducedClip.h68
4 files changed, 174 insertions, 187 deletions
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 4bd6d55134..e117144eb9 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -18,6 +18,7 @@
typedef SkClipStack::Element Element;
typedef GrReducedClip::InitialState InitialState;
+typedef GrReducedClip::ElementList ElementList;
static const int kMaxAnalyticElements = 4;
@@ -134,7 +135,7 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
bool hasUserStencilSettings,
const GrDrawContext* drawContext,
const SkVector& clipToMaskOffset,
- const GrReducedClip::ElementList& elements) {
+ const 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.
@@ -143,7 +144,7 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
// space.
const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
- for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(elements); iter.get(); iter.next()) {
const Element* element = iter.get();
SkRegion::Op op = element->getOp();
@@ -159,7 +160,7 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
return false;
}
-static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elements,
+static bool get_analytic_clip_processor(const ElementList& elements,
bool abortIfAA,
const SkVector& clipToRTOffset,
const SkRect& drawBounds,
@@ -168,7 +169,7 @@ static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen
boundsInClipSpace = drawBounds.makeOffset(-clipToRTOffset.fX, -clipToRTOffset.fY);
SkASSERT(elements.count() <= kMaxAnalyticElements);
SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps;
- GrReducedClip::ElementList::Iter iter(elements);
+ ElementList::Iter iter(elements);
while (iter.get()) {
SkRegion::Op op = iter.get()->getOp();
bool invert;
@@ -259,28 +260,19 @@ bool GrClipStackClip::apply(GrContext* context,
const SkScalar clipX = SkIntToScalar(fOrigin.x()),
clipY = SkIntToScalar(fOrigin.y());
- GrReducedClip::ElementList elements;
- int32_t genID = 0;
- SkIRect clipSpaceIBounds;
- bool requiresAA = false;
-
- InitialState initialState = GrReducedClip::ReduceClipStack(*fStack,
- devBounds.makeOffset(clipX, clipY),
- &elements,
- &genID,
- &clipSpaceIBounds,
- &requiresAA);
- if (elements.isEmpty()) {
- if (GrReducedClip::kAllOut_InitialState == initialState || clipSpaceIBounds.isEmpty()) {
+ SkRect clipSpaceDevBounds = devBounds.makeOffset(clipX, clipY);
+ const GrReducedClip reducedClip(*fStack, clipSpaceDevBounds);
+
+ if (reducedClip.elements().isEmpty()) {
+ if (GrReducedClip::InitialState::kAllOut == reducedClip.initialState()) {
return false;
- } else {
- SkIRect scissorSpaceIBounds(clipSpaceIBounds);
+ }
+ if (!GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) {
+ SkIRect scissorSpaceIBounds(reducedClip.iBounds());
scissorSpaceIBounds.offset(-fOrigin);
- if (!GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) {
- out->makeScissored(scissorSpaceIBounds);
- }
- return true;
+ out->makeScissored(scissorSpaceIBounds);
}
+ return true;
}
// An element count of 4 was chosen because of the common pattern in Blink of:
@@ -291,7 +283,7 @@ bool GrClipStackClip::apply(GrContext* context,
// 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) {
+ if (reducedClip.elements().count() <= kMaxAnalyticElements) {
// When there are multiple samples we want to do per-sample clipping, not compute a
// fractional pixel coverage.
bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled();
@@ -302,10 +294,10 @@ bool GrClipStackClip::apply(GrContext* context,
disallowAnalyticAA = useHWAA || hasUserStencilSettings;
}
sk_sp<GrFragmentProcessor> clipFP;
- if (requiresAA &&
- get_analytic_clip_processor(elements, disallowAnalyticAA, {-clipX, -clipY}, devBounds,
- &clipFP)) {
- SkIRect scissorSpaceIBounds(clipSpaceIBounds);
+ if (reducedClip.requiresAA() &&
+ get_analytic_clip_processor(reducedClip.elements(), disallowAnalyticAA,
+ {-clipX, -clipY}, devBounds, &clipFP)) {
+ SkIRect scissorSpaceIBounds(reducedClip.iBounds());
scissorSpaceIBounds.offset(-fOrigin);
if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) {
out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBounds));
@@ -317,32 +309,23 @@ bool GrClipStackClip::apply(GrContext* context,
}
// If the stencil buffer is multisampled we can use it to do everything.
- if (!drawContext->isStencilBufferMultisampled() && requiresAA) {
+ if (!drawContext->isStencilBufferMultisampled() && reducedClip.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)
+ SkIntToScalar(-reducedClip.left()),
+ SkIntToScalar(-reducedClip.top())
};
if (UseSWOnlyPath(context, hasUserStencilSettings, drawContext,
- clipToMaskOffset, elements)) {
+ clipToMaskOffset, reducedClip.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);
+ result = CreateSoftwareClipMask(context->textureProvider(), reducedClip,
+ clipToMaskOffset);
} else {
- result = CreateAlphaClipMask(context,
- genID,
- initialState,
- elements,
- clipToMaskOffset,
- clipSpaceIBounds);
+ result = CreateAlphaClipMask(context, reducedClip, clipToMaskOffset);
// If createAlphaClipMask fails it means UseSWOnlyPath has a bug
SkASSERT(result);
}
@@ -350,7 +333,7 @@ bool GrClipStackClip::apply(GrContext* context,
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;
+ SkIRect rtSpaceMaskBounds = reducedClip.iBounds();
rtSpaceMaskBounds.offset(-fOrigin);
out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds),
SkRect::Make(rtSpaceMaskBounds));
@@ -361,22 +344,16 @@ bool GrClipStackClip::apply(GrContext* context,
// use the stencil clip if we can't represent the clip as a rectangle.
SkIPoint clipSpaceToStencilSpaceOffset = -fOrigin;
- CreateStencilClipMask(context,
- drawContext,
- genID,
- initialState,
- elements,
- clipSpaceIBounds,
- clipSpaceToStencilSpaceOffset);
+ CreateStencilClipMask(context, drawContext, reducedClip, 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);
- if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) {
+ if (GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) {
out->makeStencil(true, devBounds);
} else {
+ SkIRect scissorSpaceIBounds(reducedClip.iBounds());
+ scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
out->makeScissoredStencil(scissorSpaceIBounds);
}
return true;
@@ -457,14 +434,11 @@ static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey
}
sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
- int32_t elementsGenID,
- GrReducedClip::InitialState initialState,
- const GrReducedClip::ElementList& elements,
- const SkVector& clipToMaskOffset,
- const SkIRect& clipSpaceIBounds) {
+ const GrReducedClip& reducedClip,
+ const SkVector& clipToMaskOffset) {
GrResourceProvider* resourceProvider = context->resourceProvider();
GrUniqueKey key;
- GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
+ GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key);
if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
return sk_sp<GrTexture>(texture);
}
@@ -476,8 +450,8 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
}
sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox,
- clipSpaceIBounds.width(),
- clipSpaceIBounds.height(),
+ reducedClip.width(),
+ reducedClip.height(),
config, nullptr));
if (!dc) {
return nullptr;
@@ -485,12 +459,12 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
// The texture may be larger than necessary, this rect represents the part of the texture
// we populate with a rasterization of the clip.
- SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
+ SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.height());
// The scratch texture that we are drawing into can be substantially larger than the mask. Only
// clear the part that we care about.
dc->clear(&maskSpaceIBounds,
- GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
+ GrReducedClip::InitialState::kAllIn == reducedClip.initialState() ? -1 : 0,
true);
// Set the matrix so that rendered clip elements are transformed to mask space from clip
@@ -503,7 +477,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
// cleared.
// walk through each clip element and perform its set op
- for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()) {
const Element* element = iter.get();
SkRegion::Op op = element->getOp();
bool invert = element->isInverseFilled();
@@ -539,7 +513,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideElement,
op, !invert, false,
translate,
- SkRect::Make(clipSpaceIBounds))) {
+ SkRect::Make(reducedClip.iBounds()))) {
return nullptr;
}
} else {
@@ -563,10 +537,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
// (as opposed to canvas) coordinates
bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
GrDrawContext* drawContext,
- int32_t elementsGenID,
- GrReducedClip::InitialState initialState,
- const GrReducedClip::ElementList& elements,
- const SkIRect& clipSpaceIBounds,
+ const GrReducedClip& reducedClip,
const SkIPoint& clipSpaceToStencilOffset) {
SkASSERT(drawContext);
@@ -577,8 +548,10 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
}
// TODO: these need to be swapped over to using a StencilAttachmentProxy
- if (stencilAttachment->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset)) {
- stencilAttachment->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset);
+ if (stencilAttachment->mustRenderClip(reducedClip.genID(), reducedClip.iBounds(),
+ clipSpaceToStencilOffset)) {
+ stencilAttachment->setLastClip(reducedClip.genID(), reducedClip.iBounds(),
+ clipSpaceToStencilOffset);
// Set the matrix so that rendered clip elements are transformed from clip to stencil space.
SkVector translate = {
SkIntToScalar(clipSpaceToStencilOffset.fX),
@@ -588,17 +561,16 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
viewMatrix.setTranslate(translate);
// We set the current clip to the bounds so that our recursive draws are scissored to them.
- SkIRect stencilSpaceIBounds(clipSpaceIBounds);
+ SkIRect stencilSpaceIBounds(reducedClip.iBounds());
stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
GrFixedClip clip(stencilSpaceIBounds);
- drawContext->drawContextPriv().clearStencilClip(
- stencilSpaceIBounds,
- GrReducedClip::kAllIn_InitialState == initialState);
+ bool insideClip = GrReducedClip::InitialState::kAllIn == reducedClip.initialState();
+ drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, insideClip);
// walk through each clip element and perform its set op
// with the existing clip.
- for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
+ for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()) {
const Element* element = iter.get();
bool useHWAA = element->isAA() && drawContext->isStencilBufferMultisampled();
@@ -732,11 +704,11 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
} else {
// The view matrix is setup to do clip space -> stencil space translation, so
// draw rect in clip space.
- SkRect bounds = SkRect::Make(clipSpaceIBounds);
+ SkRect bounds = SkRect::Make(reducedClip.iBounds());
bounds.offset(translate.fX, translate.fY);
clip.enableStencilClip(bounds);
drawContext->drawContextPriv().stencilRect(clip, *pass, false, viewMatrix,
- SkRect::Make(clipSpaceIBounds));
+ SkRect::Make(reducedClip.iBounds()));
}
}
}
@@ -746,20 +718,17 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
////////////////////////////////////////////////////////////////////////////////
sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texProvider,
- int32_t elementsGenID,
- GrReducedClip::InitialState initialState,
- const GrReducedClip::ElementList& elements,
- const SkVector& clipToMaskOffset,
- const SkIRect& clipSpaceIBounds) {
+ const GrReducedClip& reducedClip,
+ const SkVector& clipToMaskOffset) {
GrUniqueKey key;
- GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
+ GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key);
if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) {
return sk_sp<GrTexture>(texture);
}
// The mask texture may be larger than necessary. We round out the clip space bounds and pin
// the top left corner of the resulting rect to the top left of the texture.
- SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
+ SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.height());
GrSWMaskHelper helper(texProvider);
@@ -769,9 +738,9 @@ sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP
translate.setTranslate(clipToMaskOffset);
helper.init(maskSpaceIBounds, &translate);
- helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00);
+ helper.clear(GrReducedClip::InitialState::kAllIn == reducedClip.initialState() ? 0xFF : 0x00);
- for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) {
+ for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()) {
const Element* element = iter.get();
SkRegion::Op op = element->getOp();
@@ -781,7 +750,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP
// but leave the pixels inside the geometry alone. For reverse difference we invert all
// the pixels before clearing the ones outside the geometry.
if (SkRegion::kReverseDifference_Op == op) {
- SkRect temp = SkRect::Make(clipSpaceIBounds);
+ SkRect temp = SkRect::Make(reducedClip.iBounds());
// invert the entire scene
helper.drawRect(temp, SkRegion::kXOR_Op, false, 0xFF);
}
@@ -807,8 +776,8 @@ sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP
// Allocate clip mask texture
GrSurfaceDesc desc;
- desc.fWidth = clipSpaceIBounds.width();
- desc.fHeight = clipSpaceIBounds.height();
+ desc.fWidth = reducedClip.width();
+ desc.fHeight = reducedClip.height();
desc.fConfig = kAlpha_8_GrPixelConfig;
sk_sp<GrTexture> result(texProvider->createApproxTexture(desc));
diff --git a/src/gpu/GrClipStackClip.h b/src/gpu/GrClipStackClip.h
index 38f9e2d671..aaa2f90e3a 100644
--- a/src/gpu/GrClipStackClip.h
+++ b/src/gpu/GrClipStackClip.h
@@ -52,28 +52,19 @@ private:
// Draws the clip into the stencil buffer
static bool CreateStencilClipMask(GrContext*,
GrDrawContext*,
- int32_t elementsGenID,
- GrReducedClip::InitialState initialState,
- const GrReducedClip::ElementList& elements,
- const SkIRect& clipSpaceIBounds,
+ const GrReducedClip&,
const SkIPoint& clipSpaceToStencilOffset);
// Creates an alpha mask of the clip. The mask is a rasterization of elements through the
// rect specified by clipSpaceIBounds.
static sk_sp<GrTexture> CreateAlphaClipMask(GrContext*,
- int32_t elementsGenID,
- GrReducedClip::InitialState initialState,
- const GrReducedClip::ElementList& elements,
- const SkVector& clipToMaskOffset,
- const SkIRect& clipSpaceIBounds);
+ const GrReducedClip&,
+ const SkVector& clipToMaskOffset);
// Similar to createAlphaClipMask but it rasterizes in SW and uploads to the result texture.
static sk_sp<GrTexture> CreateSoftwareClipMask(GrTextureProvider*,
- int32_t elementsGenID,
- GrReducedClip::InitialState initialState,
- const GrReducedClip::ElementList& elements,
- const SkVector& clipToMaskOffset,
- const SkIRect& clipSpaceIBounds);
+ const GrReducedClip&,
+ const SkVector& clipToMaskOffset);
static bool UseSWOnlyPath(GrContext*,
bool hasUserStencilSettings,
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 2940f6a682..f7bac4aa58 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Google Inc.
+ * Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
@@ -23,9 +23,11 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
// b) an operation that is known to make the bounds all inside/outside
// c) a replace operation
- static const GrReducedClip::InitialState kUnknown_InitialState =
- static_cast<GrReducedClip::InitialState>(-1);
- GrReducedClip::InitialState initialState = kUnknown_InitialState;
+ enum class InitialTriState {
+ kUnknown = -1,
+ kAllIn = (int)GrReducedClip::InitialState::kAllIn,
+ kAllOut = (int)GrReducedClip::InitialState::kAllOut
+ } initialState = InitialTriState::kUnknown;
// During our backwards walk, track whether we've seen ops that either grow or shrink the clip.
// TODO: track these per saved clip so that we can consider them on the forward pass.
@@ -39,18 +41,18 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
int numAAElements = 0;
- while (kUnknown_InitialState == initialState) {
+ while (InitialTriState::kUnknown == initialState) {
const Element* element = iter.prev();
if (nullptr == element) {
- initialState = GrReducedClip::kAllIn_InitialState;
+ initialState = InitialTriState::kAllIn;
break;
}
if (SkClipStack::kEmptyGenID == element->getGenID()) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
break;
}
if (SkClipStack::kWideOpenGenID == element->getGenID()) {
- initialState = GrReducedClip::kAllIn_InitialState;
+ initialState = InitialTriState::kAllIn;
break;
}
@@ -65,12 +67,12 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
if (element->contains(relaxedQueryBounds)) {
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
}
} else {
if (element->contains(relaxedQueryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
skippable = true;
@@ -86,7 +88,7 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
// empty.
if (element->isInverseFilled()) {
if (element->contains(relaxedQueryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
skippable = true;
@@ -95,7 +97,7 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
if (element->contains(relaxedQueryBounds)) {
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
}
}
@@ -111,12 +113,12 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
if (element->contains(relaxedQueryBounds)) {
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
- initialState = GrReducedClip::kAllIn_InitialState;
+ initialState = InitialTriState::kAllIn;
skippable = true;
}
} else {
if (element->contains(relaxedQueryBounds)) {
- initialState = GrReducedClip::kAllIn_InitialState;
+ initialState = InitialTriState::kAllIn;
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
skippable = true;
@@ -155,7 +157,7 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
// all outside the current clip.B
if (element->isInverseFilled()) {
if (element->contains(relaxedQueryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
isFlip = true;
@@ -164,7 +166,7 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
if (element->contains(relaxedQueryBounds)) {
isFlip = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
}
}
@@ -180,23 +182,23 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
// setting the correct value for initialState.
if (element->isInverseFilled()) {
if (element->contains(relaxedQueryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
- initialState = GrReducedClip::kAllIn_InitialState;
+ initialState = InitialTriState::kAllIn;
skippable = true;
}
} else {
if (element->contains(relaxedQueryBounds)) {
- initialState = GrReducedClip::kAllIn_InitialState;
+ initialState = InitialTriState::kAllIn;
skippable = true;
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
skippable = true;
}
}
if (!skippable) {
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
embiggens = emsmallens = true;
}
break;
@@ -230,16 +232,16 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
newElement->invertShapeFillType();
newElement->setOp(SkRegion::kDifference_Op);
if (isReplace) {
- SkASSERT(GrReducedClip::kAllOut_InitialState == initialState);
- initialState = GrReducedClip::kAllIn_InitialState;
+ SkASSERT(InitialTriState::kAllOut == initialState);
+ initialState = InitialTriState::kAllIn;
}
}
}
}
}
- if ((GrReducedClip::kAllOut_InitialState == initialState && !embiggens) ||
- (GrReducedClip::kAllIn_InitialState == initialState && !emsmallens)) {
+ if ((InitialTriState::kAllOut == initialState && !embiggens) ||
+ (InitialTriState::kAllIn == initialState && !emsmallens)) {
result->reset();
numAAElements = 0;
} else {
@@ -249,20 +251,20 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
switch (element->getOp()) {
case SkRegion::kDifference_Op:
// subtracting from the empty set yields the empty set.
- skippable = GrReducedClip::kAllOut_InitialState == initialState;
+ skippable = InitialTriState::kAllOut == initialState;
break;
case SkRegion::kIntersect_Op:
// intersecting with the empty set yields the empty set
- if (GrReducedClip::kAllOut_InitialState == initialState) {
+ if (InitialTriState::kAllOut == initialState) {
skippable = true;
} else {
// We can clear to zero and then simply draw the clip element.
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
element->setOp(SkRegion::kReplace_Op);
}
break;
case SkRegion::kUnion_Op:
- if (GrReducedClip::kAllIn_InitialState == initialState) {
+ if (InitialTriState::kAllIn == initialState) {
// unioning the infinite plane with anything is a no-op.
skippable = true;
} else {
@@ -271,23 +273,23 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
}
break;
case SkRegion::kXOR_Op:
- if (GrReducedClip::kAllOut_InitialState == initialState) {
+ if (InitialTriState::kAllOut == initialState) {
// xor could be changed to diff in the kAllIn case, not sure it's a win.
element->setOp(SkRegion::kReplace_Op);
}
break;
case SkRegion::kReverseDifference_Op:
- if (GrReducedClip::kAllIn_InitialState == initialState) {
+ if (InitialTriState::kAllIn == initialState) {
// subtracting the whole plane will yield the empty set.
skippable = true;
- initialState = GrReducedClip::kAllOut_InitialState;
+ initialState = InitialTriState::kAllOut;
} else {
// this picks up flips inserted in the backwards pass.
skippable = element->isInverseFilled() ?
GrClip::IsOutsideClip(element->getBounds(), queryBounds) :
element->contains(relaxedQueryBounds);
if (skippable) {
- initialState = GrReducedClip::kAllIn_InitialState;
+ initialState = InitialTriState::kAllIn;
} else {
element->setOp(SkRegion::kReplace_Op);
}
@@ -315,7 +317,7 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
*requiresAA = numAAElements > 0;
if (0 == result->count()) {
- if (initialState == GrReducedClip::kAllIn_InitialState) {
+ if (initialState == InitialTriState::kAllIn) {
*resultGenID = SkClipStack::kWideOpenGenID;
} else {
*resultGenID = SkClipStack::kEmptyGenID;
@@ -323,7 +325,8 @@ static GrReducedClip::InitialState reduced_stack_walker(const SkClipStack& stack
}
SkASSERT(SkClipStack::kInvalidGenID != *resultGenID);
- return initialState;
+ SkASSERT(InitialTriState::kUnknown != initialState);
+ return static_cast<GrReducedClip::InitialState>(initialState);
}
/*
@@ -333,25 +336,20 @@ for the case where the bounds are kInsideOut_BoundsType. We could restrict earli
based on later intersect operations, and perhaps remove intersect-rects. We could optionally
take a rect in case the caller knows a bound on what is to be drawn through this clip.
*/
-GrReducedClip::InitialState GrReducedClip::ReduceClipStack(const SkClipStack& stack,
- const SkRect& queryBounds,
- ElementList* result,
- int32_t* resultGenID,
- SkIRect* clipIBounds,
- bool* requiresAA) {
+GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds) {
SkASSERT(!queryBounds.isEmpty());
- result->reset();
// The clip established by the element list might be cached based on the last
// generation id. When we make early returns, we do not know what was the generation
// id that lead to the state. Make a conservative guess.
- *resultGenID = stack.getTopmostGenID();
+ fGenID = stack.getTopmostGenID();
// TODO: instead devise a way of telling the caller to disregard some or all of the clip bounds.
- *clipIBounds = GrClip::GetPixelIBounds(queryBounds);
+ fIBounds = GrClip::GetPixelIBounds(queryBounds);
if (stack.isWideOpen()) {
- return kAllIn_InitialState;
+ fInitialState = InitialState::kAllIn;
+ return;
}
SkClipStack::BoundsType stackBoundsType;
@@ -361,7 +359,8 @@ GrReducedClip::InitialState GrReducedClip::ReduceClipStack(const SkClipStack& st
if (stackBounds.isEmpty() || GrClip::IsOutsideClip(stackBounds, queryBounds)) {
bool insideOut = SkClipStack::kInsideOut_BoundsType == stackBoundsType;
- return insideOut ? kAllIn_InitialState : kAllOut_InitialState;
+ fInitialState = insideOut ? InitialState::kAllIn : InitialState::kAllOut;
+ return;
}
if (iior) {
@@ -371,31 +370,39 @@ GrReducedClip::InitialState GrReducedClip::ReduceClipStack(const SkClipStack& st
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
if (!iter.prev()->isAA() || GrClip::IsPixelAligned(stackBounds)) {
// The clip is a non-aa rect. This is the one spot where we can actually implement the
- // clip (using clipIBounds) rather than just telling the caller what it should be.
- stackBounds.round(clipIBounds);
- return kAllIn_InitialState;
+ // clip (using fIBounds) rather than just telling the caller what it should be.
+ stackBounds.round(&fIBounds);
+ fInitialState = fIBounds.isEmpty() ? InitialState::kAllOut : InitialState::kAllIn;
+ return;
}
if (GrClip::IsInsideClip(stackBounds, queryBounds)) {
- return kAllIn_InitialState;
+ fInitialState = InitialState::kAllIn;
+ return;
}
+ SkAssertResult(fIBounds.intersect(GrClip::GetPixelIBounds(stackBounds)));
+ SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsideClip above.
+
// Implement the clip with an AA rect element.
- result->addToHead(stackBounds, SkRegion::kReplace_Op, true/*doAA*/);
- *requiresAA = true;
+ fElements.addToHead(stackBounds, SkRegion::kReplace_Op, true/*doAA*/);
+ fRequiresAA = true;
- SkAssertResult(clipIBounds->intersect(GrClip::GetPixelIBounds(stackBounds)));
- return kAllOut_InitialState;
+ fInitialState = InitialState::kAllOut;
+ return;
}
SkRect tighterQuery = queryBounds;
if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
// Tighten the query by introducing a new clip at the stack's pixel boundaries. (This new
- // clip will be enforced by the scissor through clipIBounds.)
+ // clip will be enforced by the scissor through fIBounds.)
SkAssertResult(tighterQuery.intersect(GrClip::GetPixelBounds(stackBounds)));
- *clipIBounds = GrClip::GetPixelIBounds(tighterQuery);
+ fIBounds = GrClip::GetPixelIBounds(tighterQuery);
}
+ SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsideClip above.
+
// Now that we have determined the bounds to use and filtered out the trivial cases, call the
// helper that actually walks the stack.
- return reduced_stack_walker(stack, tighterQuery, *clipIBounds, result, resultGenID, requiresAA);
+ fInitialState = reduced_stack_walker(stack, tighterQuery, fIBounds, &fElements, &fGenID,
+ &fRequiresAA);
}
diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h
index 780f6f1ff5..07e06694a1 100644
--- a/src/gpu/GrReducedClip.h
+++ b/src/gpu/GrReducedClip.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Google Inc.
+ * Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
@@ -11,37 +11,57 @@
#include "SkClipStack.h"
#include "SkTLList.h"
+/**
+ * This class takes a clip stack and produces a reduced set of elements that are equivalent to
+ * applying that full stack within a specified query rectangle.
+ */
class SK_API GrReducedClip {
public:
+ GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds);
+
+ /**
+ * Uniquely identifies this reduced clip.
+ */
+ int32_t genID() const { return fGenID; }
+
+ /**
+ * Bounding box within which the reduced clip is valid. The caller must not draw any pixels
+ * outside this box.
+ */
+ const SkIRect& iBounds() const { return fIBounds; }
+ int left() const { return this->iBounds().left(); }
+ int top() const { return this->iBounds().top(); }
+ int width() const { return this->iBounds().width(); }
+ int height() const { return this->iBounds().height(); }
+
typedef SkTLList<SkClipStack::Element, 16> ElementList;
- enum InitialState {
- kAllIn_InitialState,
- kAllOut_InitialState,
+ /**
+ * Populated with a minimal list of elements that implement the clip.
+ */
+ const ElementList& elements() const { return fElements; }
+
+ /**
+ * Indicates whether antialiasing is required to process any of the clip elements.
+ */
+ bool requiresAA() const { return fRequiresAA; }
+
+ enum class InitialState : bool {
+ kAllIn,
+ kAllOut
};
/**
- * This function produces a reduced set of SkClipStack::Elements that are equivalent to applying
- * a full clip stack within a specified query rectangle.
- *
- * @param stack the clip stack to reduce.
- * @param queryBounds bounding box of geometry the stack will clip.
- * @param result populated with a minimal list of elements that implement the clip
- * within the provided query bounds.
- * @param resultGenID uniquely identifies the resulting reduced clip.
- * @param clipIBounds bounding box within which the reduced clip is valid. The caller must
- * not draw any pixels outside this box. NOTE: this box may be undefined
- * if no pixels are valid (e.g. empty result, "all out" initial state.)
- * @param requiresAA indicates whether anti-aliasing is required to process any of the
- * elements in the element list result. Undefined if the result is empty.
- * @return the initial clip state within clipIBounds ("all in" or "all out").
+ * The initial state of the clip within iBounds().
*/
- static InitialState ReduceClipStack(const SkClipStack& stack,
- const SkRect& queryBounds,
- ElementList* result,
- int32_t* resultGenID,
- SkIRect* clipIBounds,
- bool* requiresAA);
+ InitialState initialState() const { return fInitialState; }
+
+private:
+ int32_t fGenID;
+ SkIRect fIBounds;
+ ElementList fElements;
+ bool fRequiresAA;
+ InitialState fInitialState;
};
#endif