aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrClip.cpp30
-rw-r--r--src/gpu/GrClipStackClip.cpp90
-rw-r--r--src/gpu/GrClipStackClip.h6
-rw-r--r--src/gpu/GrDrawTarget.cpp60
-rw-r--r--src/gpu/GrReducedClip.cpp13
-rw-r--r--src/gpu/GrReducedClip.h24
6 files changed, 87 insertions, 136 deletions
diff --git a/src/gpu/GrClip.cpp b/src/gpu/GrClip.cpp
index 3eccd801b5..ef9c9cdfa6 100644
--- a/src/gpu/GrClip.cpp
+++ b/src/gpu/GrClip.cpp
@@ -21,10 +21,7 @@ bool GrFixedClip::quickContains(const SkRect& rect) const {
if (fHasStencilClip) {
return false;
}
- if (!fScissorState.enabled()) {
- return true;
- }
- return fScissorState.rect().contains(rect);
+ return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect);
}
void GrFixedClip::getConservativeBounds(int width, int height, SkIRect* devResult,
@@ -40,32 +37,25 @@ void GrFixedClip::getConservativeBounds(int width, int height, SkIRect* devResul
}
}
-bool GrFixedClip::apply(GrContext*,
- GrDrawContext* drawContext,
- const SkRect* devBounds,
- bool isHWAntiAlias,
- bool hasUserStencilSettings,
- GrAppliedClip* out) const {
- SkASSERT(!fDeviceBounds.isLargest());
+bool GrFixedClip::apply(GrContext*, GrDrawContext* drawContext, bool isHWAntiAlias,
+ bool hasUserStencilSettings, GrAppliedClip* out) const {
if (fScissorState.enabled()) {
SkIRect tightScissor;
if (!tightScissor.intersect(fScissorState.rect(),
SkIRect::MakeWH(drawContext->width(), drawContext->height()))) {
return false;
}
- if (devBounds && IsOutsideClip(tightScissor, *devBounds)) {
+ if (IsOutsideClip(tightScissor, out->clippedDrawBounds())) {
return false;
}
- if (!devBounds || !IsInsideClip(fScissorState.rect(), *devBounds)) {
- if (fHasStencilClip) {
- out->makeScissoredStencil(tightScissor, &fDeviceBounds);
- } else {
- out->makeScissored(tightScissor);
- }
- return true;
+ if (!IsInsideClip(fScissorState.rect(), out->clippedDrawBounds())) {
+ out->addScissor(tightScissor);
}
}
- out->makeStencil(fHasStencilClip, fDeviceBounds);
+ if (fHasStencilClip) {
+ out->addStencilClip();
+ }
+
return true;
}
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index e117144eb9..6cb216ee0c 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -242,18 +242,14 @@ static bool get_analytic_clip_processor(const ElementList& elements,
////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
-bool GrClipStackClip::apply(GrContext* context,
- GrDrawContext* drawContext,
- const SkRect* origDevBounds,
- bool useHWAA,
- bool hasUserStencilSettings,
- GrAppliedClip* out) const {
+bool GrClipStackClip::apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA,
+ bool hasUserStencilSettings, GrAppliedClip* out) const {
if (!fStack || fStack->isWideOpen()) {
return true;
}
SkRect devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height());
- if (origDevBounds && !devBounds.intersect(*origDevBounds)) {
+ if (!devBounds.intersect(out->clippedDrawBounds())) {
return false;
}
@@ -263,18 +259,19 @@ bool GrClipStackClip::apply(GrContext* context,
SkRect clipSpaceDevBounds = devBounds.makeOffset(clipX, clipY);
const GrReducedClip reducedClip(*fStack, clipSpaceDevBounds);
+ if (reducedClip.hasIBounds() &&
+ !GrClip::IsInsideClip(reducedClip.ibounds(), clipSpaceDevBounds)) {
+ SkIRect scissorSpaceIBounds(reducedClip.ibounds());
+ scissorSpaceIBounds.offset(-fOrigin);
+ out->addScissor(scissorSpaceIBounds);
+ }
+
if (reducedClip.elements().isEmpty()) {
- if (GrReducedClip::InitialState::kAllOut == reducedClip.initialState()) {
- return false;
- }
- if (!GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) {
- SkIRect scissorSpaceIBounds(reducedClip.iBounds());
- scissorSpaceIBounds.offset(-fOrigin);
- out->makeScissored(scissorSpaceIBounds);
- }
- return true;
+ return InitialState::kAllIn == reducedClip.initialState();
}
+ SkASSERT(reducedClip.hasIBounds());
+
// An element count of 4 was chosen because of the common pattern in Blink of:
// isect RR
// diff RR
@@ -297,13 +294,7 @@ bool GrClipStackClip::apply(GrContext* context,
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));
- } else {
- out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds);
- }
+ out->addCoverageFP(std::move(clipFP));
return true;
}
}
@@ -333,10 +324,9 @@ 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 = reducedClip.iBounds();
+ SkIRect rtSpaceMaskBounds = reducedClip.ibounds();
rtSpaceMaskBounds.offset(-fOrigin);
- out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds),
- SkRect::Make(rtSpaceMaskBounds));
+ out->addCoverageFP(create_fp_for_mask(result.get(), rtSpaceMaskBounds));
return true;
}
// if alpha clip mask creation fails fall through to the non-AA code paths
@@ -345,17 +335,7 @@ 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, 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.
- if (GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) {
- out->makeStencil(true, devBounds);
- } else {
- SkIRect scissorSpaceIBounds(reducedClip.iBounds());
- scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
- out->makeScissoredStencil(scissorSpaceIBounds);
- }
+ out->addStencilClip();
return true;
}
@@ -438,7 +418,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
const SkVector& clipToMaskOffset) {
GrResourceProvider* resourceProvider = context->resourceProvider();
GrUniqueKey key;
- GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key);
+ GetClipMaskKey(reducedClip.genID(), reducedClip.ibounds(), &key);
if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
return sk_sp<GrTexture>(texture);
}
@@ -463,9 +443,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
// 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::InitialState::kAllIn == reducedClip.initialState() ? -1 : 0,
- true);
+ dc->clear(&maskSpaceIBounds, InitialState::kAllIn == reducedClip.initialState() ? -1 : 0, true);
// Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
@@ -513,7 +491,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideElement,
op, !invert, false,
translate,
- SkRect::Make(reducedClip.iBounds()))) {
+ SkRect::Make(reducedClip.ibounds()))) {
return nullptr;
}
} else {
@@ -548,9 +526,9 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
}
// TODO: these need to be swapped over to using a StencilAttachmentProxy
- if (stencilAttachment->mustRenderClip(reducedClip.genID(), reducedClip.iBounds(),
+ if (stencilAttachment->mustRenderClip(reducedClip.genID(), reducedClip.ibounds(),
clipSpaceToStencilOffset)) {
- stencilAttachment->setLastClip(reducedClip.genID(), reducedClip.iBounds(),
+ stencilAttachment->setLastClip(reducedClip.genID(), reducedClip.ibounds(),
clipSpaceToStencilOffset);
// Set the matrix so that rendered clip elements are transformed from clip to stencil space.
SkVector translate = {
@@ -561,11 +539,11 @@ 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(reducedClip.iBounds());
+ SkIRect stencilSpaceIBounds(reducedClip.ibounds());
stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
GrFixedClip clip(stencilSpaceIBounds);
- bool insideClip = GrReducedClip::InitialState::kAllIn == reducedClip.initialState();
+ bool insideClip = InitialState::kAllIn == reducedClip.initialState();
drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, insideClip);
// walk through each clip element and perform its set op
@@ -671,22 +649,19 @@ bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
}
}
+ // Just enable stencil clip. The passes choose whether or not they will actually use it.
+ clip.enableStencilClip();
+
// 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()) {
- clip.enableStencilClip(element->getRect().makeOffset(translate.fX,
- translate.fY));
drawContext->drawContextPriv().stencilRect(clip, *pass, useHWAA, viewMatrix,
element->getRect());
} else {
GrShape shape(clipPath, GrStyle::SimpleFill());
GrPaint paint;
- SkRect bounds = clipPath.getBounds();
- bounds.offset(translate.fX, translate.fY);
- clip.enableStencilClip(bounds);
paint.setXPFactory(GrDisableColorXPFactory::Make());
paint.setAntiAlias(element->isAA());
GrPathRenderer::DrawPathArgs args;
@@ -704,11 +679,8 @@ 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(reducedClip.iBounds());
- bounds.offset(translate.fX, translate.fY);
- clip.enableStencilClip(bounds);
drawContext->drawContextPriv().stencilRect(clip, *pass, false, viewMatrix,
- SkRect::Make(reducedClip.iBounds()));
+ SkRect::Make(reducedClip.ibounds()));
}
}
}
@@ -721,7 +693,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP
const GrReducedClip& reducedClip,
const SkVector& clipToMaskOffset) {
GrUniqueKey key;
- GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key);
+ GetClipMaskKey(reducedClip.genID(), reducedClip.ibounds(), &key);
if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) {
return sk_sp<GrTexture>(texture);
}
@@ -738,7 +710,7 @@ sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP
translate.setTranslate(clipToMaskOffset);
helper.init(maskSpaceIBounds, &translate);
- helper.clear(GrReducedClip::InitialState::kAllIn == reducedClip.initialState() ? 0xFF : 0x00);
+ helper.clear(InitialState::kAllIn == reducedClip.initialState() ? 0xFF : 0x00);
for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()) {
const Element* element = iter.get();
@@ -750,7 +722,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(reducedClip.iBounds());
+ SkRect temp = SkRect::Make(reducedClip.ibounds());
// invert the entire scene
helper.drawRect(temp, SkRegion::kXOR_Op, false, 0xFF);
}
diff --git a/src/gpu/GrClipStackClip.h b/src/gpu/GrClipStackClip.h
index aaa2f90e3a..98675e62ac 100644
--- a/src/gpu/GrClipStackClip.h
+++ b/src/gpu/GrClipStackClip.h
@@ -33,11 +33,7 @@ public:
bool quickContains(const SkRect&) const final;
void getConservativeBounds(int width, int height, SkIRect* devResult,
bool* isIntersectionOfRects) const final;
- bool apply(GrContext*,
- GrDrawContext*,
- const SkRect* devBounds,
- bool useHWAA,
- bool hasUserStencilSettings,
+ bool apply(GrContext*, GrDrawContext*, bool useHWAA, bool hasUserStencilSettings,
GrAppliedClip* out) const final;
private:
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index e143f90291..b4142eb40b 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -321,51 +321,38 @@ static void batch_bounds(SkRect* bounds, const GrBatch* batch) {
}
}
-static inline bool intersect(SkRect* out, const SkRect& a, const SkRect& b) {
- SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom);
- SkASSERT(b.fLeft <= b.fRight && b.fTop <= b.fBottom);
- out->fLeft = SkTMax(a.fLeft, b.fLeft);
- out->fTop = SkTMax(a.fTop, b.fTop);
- out->fRight = SkTMin(a.fRight, b.fRight);
- out->fBottom = SkTMin(a.fBottom, b.fBottom);
- return (out->fLeft <= out->fRight && out->fTop <= out->fBottom);
-}
-
void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
GrDrawContext* drawContext,
const GrClip& clip,
GrDrawBatch* batch) {
// Setup clip
- GrAppliedClip appliedClip;
SkRect bounds;
batch_bounds(&bounds, batch);
- if (!clip.apply(fContext, drawContext, &bounds,
- pipelineBuilder.isHWAntialias(), pipelineBuilder.hasUserStencilSettings(),
- &appliedClip)) {
+ GrAppliedClip appliedClip(bounds);
+ if (!clip.apply(fContext, drawContext, pipelineBuilder.isHWAntialias(),
+ pipelineBuilder.hasUserStencilSettings(), &appliedClip)) {
return;
}
// TODO: this is the only remaining usage of the AutoRestoreFragmentProcessorState - remove it
GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
- if (appliedClip.getClipCoverageFragmentProcessor()) {
+ if (appliedClip.clipCoverageFragmentProcessor()) {
arfps.set(&pipelineBuilder);
- arfps.addCoverageFragmentProcessor(sk_ref_sp(appliedClip.getClipCoverageFragmentProcessor()));
+ arfps.addCoverageFragmentProcessor(sk_ref_sp(appliedClip.clipCoverageFragmentProcessor()));
}
- GrPipeline::CreateArgs args;
- args.fPipelineBuilder = &pipelineBuilder;
- args.fDrawContext = drawContext;
- args.fCaps = this->caps();
- args.fScissor = &appliedClip.scissorState();
- args.fHasStencilClip = appliedClip.hasStencilClip();
if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
if (!fResourceProvider->attachStencilAttachment(drawContext->accessRenderTarget())) {
SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
return;
}
}
+
+ GrPipeline::CreateArgs args;
+ args.fPipelineBuilder = &pipelineBuilder;
+ args.fDrawContext = drawContext;
+ args.fCaps = this->caps();
batch->getPipelineOptimizations(&args.fOpts);
- GrScissorState finalScissor;
if (args.fOpts.fOverrides.fUsePLSDstRead || fClipBatchToBounds) {
GrGLIRect viewport;
viewport.fLeft = 0;
@@ -381,14 +368,9 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
viewport.fWidth);
ibounds.fBottom = SkTPin(SkScalarCeilToInt(batch->bounds().fBottom), viewport.fBottom,
viewport.fHeight);
- if (appliedClip.scissorState().enabled()) {
- const SkIRect& scissorRect = appliedClip.scissorState().rect();
- if (!ibounds.intersect(scissorRect)) {
- return;
- }
+ if (!appliedClip.addScissor(ibounds)) {
+ return;
}
- finalScissor.set(ibounds);
- args.fScissor = &finalScissor;
}
args.fOpts.fColorPOI.completeCalculations(
sk_sp_address_as_pointer_address(pipelineBuilder.fColorFragmentProcessors.begin()),
@@ -396,6 +378,8 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
args.fOpts.fCoveragePOI.completeCalculations(
sk_sp_address_as_pointer_address(pipelineBuilder.fCoverageFragmentProcessors.begin()),
pipelineBuilder.numCoverageFragmentProcessors());
+ args.fScissor = &appliedClip.scissorState();
+ args.fHasStencilClip = appliedClip.hasStencilClip();
if (!this->setupDstReadIfNecessary(pipelineBuilder, drawContext->accessRenderTarget(),
clip, args.fOpts,
&args.fDstTexture, batch->bounds())) {
@@ -410,9 +394,7 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
SkASSERT(fRenderTarget);
batch->pipeline()->addDependenciesTo(fRenderTarget);
#endif
- SkRect clippedBounds;
- SkAssertResult(intersect(&clippedBounds, bounds, appliedClip.deviceBounds()));
- this->recordBatch(batch, clippedBounds);
+ this->recordBatch(batch, appliedClip.clippedDrawBounds());
}
void GrDrawTarget::stencilPath(GrDrawContext* drawContext,
@@ -424,16 +406,20 @@ void GrDrawTarget::stencilPath(GrDrawContext* drawContext,
SkASSERT(path);
SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
+ // FIXME: Use path bounds instead of this WAR once
+ // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
+ SkRect bounds = SkRect::MakeIWH(drawContext->width(), drawContext->height());
+
// Setup clip
- GrAppliedClip appliedClip;
- if (!clip.apply(fContext, drawContext, nullptr, useHWAA, true, &appliedClip)) {
+ GrAppliedClip appliedClip(bounds);
+ if (!clip.apply(fContext, drawContext, useHWAA, true, &appliedClip)) {
return;
}
// TODO: respect fClipBatchToBounds if we ever start computing bounds here.
// Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
// attempt this in a situation that would require coverage AA.
- SkASSERT(!appliedClip.getClipCoverageFragmentProcessor());
+ SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment(
drawContext->accessRenderTarget());
@@ -450,7 +436,7 @@ void GrDrawTarget::stencilPath(GrDrawContext* drawContext,
appliedClip.scissorState(),
drawContext->accessRenderTarget(),
path);
- this->recordBatch(batch, appliedClip.deviceBounds());
+ this->recordBatch(batch, appliedClip.clippedDrawBounds());
batch->unref();
}
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index f7bac4aa58..132936c64e 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -343,9 +343,7 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
// 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.
fGenID = stack.getTopmostGenID();
-
- // TODO: instead devise a way of telling the caller to disregard some or all of the clip bounds.
- fIBounds = GrClip::GetPixelIBounds(queryBounds);
+ fHasIBounds = false;
if (stack.isWideOpen()) {
fInitialState = InitialState::kAllIn;
@@ -372,6 +370,7 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
// The clip is a non-aa rect. This is the one spot where we can actually implement the
// clip (using fIBounds) rather than just telling the caller what it should be.
stackBounds.round(&fIBounds);
+ fHasIBounds = true;
fInitialState = fIBounds.isEmpty() ? InitialState::kAllOut : InitialState::kAllIn;
return;
}
@@ -380,8 +379,11 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
return;
}
- SkAssertResult(fIBounds.intersect(GrClip::GetPixelIBounds(stackBounds)));
+ SkRect tightBounds;
+ SkAssertResult(tightBounds.intersect(stackBounds, queryBounds));
+ fIBounds = GrClip::GetPixelIBounds(tightBounds);
SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsideClip above.
+ fHasIBounds = true;
// Implement the clip with an AA rect element.
fElements.addToHead(stackBounds, SkRegion::kReplace_Op, true/*doAA*/);
@@ -396,10 +398,11 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
// Tighten the query by introducing a new clip at the stack's pixel boundaries. (This new
// clip will be enforced by the scissor through fIBounds.)
SkAssertResult(tighterQuery.intersect(GrClip::GetPixelBounds(stackBounds)));
- fIBounds = GrClip::GetPixelIBounds(tighterQuery);
}
+ fIBounds = GrClip::GetPixelIBounds(tighterQuery);
SkASSERT(!fIBounds.isEmpty()); // Empty should have been blocked by IsOutsideClip above.
+ fHasIBounds = true;
// Now that we have determined the bounds to use and filtered out the trivial cases, call the
// helper that actually walks the stack.
diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h
index 07e06694a1..d7b7ea8881 100644
--- a/src/gpu/GrReducedClip.h
+++ b/src/gpu/GrReducedClip.h
@@ -25,14 +25,20 @@ public:
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.
+ * If hasIBounds() is true, this is the bounding box within which the reduced clip is valid, and
+ * the caller must not modify any pixels outside this box. Undefined if hasIBounds() is false.
*/
- 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(); }
+ const SkIRect& ibounds() const { SkASSERT(fHasIBounds); 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(); }
+
+ /**
+ * Indicates whether ibounds() are defined. They will always be defined if the elements() are
+ * nonempty.
+ */
+ bool hasIBounds() const { return fHasIBounds; }
typedef SkTLList<SkClipStack::Element, 16> ElementList;
@@ -51,14 +57,12 @@ public:
kAllOut
};
- /**
- * The initial state of the clip within iBounds().
- */
InitialState initialState() const { return fInitialState; }
private:
int32_t fGenID;
SkIRect fIBounds;
+ bool fHasIBounds;
ElementList fElements;
bool fRequiresAA;
InitialState fInitialState;