GrClips know their device dimensions
If GrClips know their dimensions then getConservativeBounds() does not
need any arguments and isRRect() can remove its rtBounds argument.
I also updated GrFixedClip to report the render target bounds as a
degenerate rrect in its isRRect implementation if it was wide open. Its
apply() function was also simplified to take advantage of the prior
GrScissorState work where the rectangle was always valid to access and
contained within the render target bounds.
Change-Id: I627b97976cb176b1c80627462027034b06ad2cb2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/290957
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 7068b77..084e8ef 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -244,8 +244,7 @@
SkIRect* unclippedDevShapeBounds,
SkIRect* devClipBounds) {
// compute bounds as intersection of rt size, clip, and path
- *devClipBounds = clip ? clip->getConservativeBounds(renderTargetContext->width(),
- renderTargetContext->height())
+ *devClipBounds = clip ? clip->getConservativeBounds()
: SkIRect::MakeWH(renderTargetContext->width(),
renderTargetContext->height());
diff --git a/src/gpu/GrClip.h b/src/gpu/GrClip.h
index cec96d0..ee6935d 100644
--- a/src/gpu/GrClip.h
+++ b/src/gpu/GrClip.h
@@ -21,6 +21,8 @@
*/
class GrClip {
public:
+ virtual ~GrClip() {}
+
virtual bool quickContains(const SkRect&) const = 0;
virtual bool quickContains(const SkRRect& rrect) const {
return this->quickContains(rrect.getBounds());
@@ -30,9 +32,7 @@
* The returned bounds represent the limits of pixels that can be drawn; anything outside of the
* bounds will be entirely clipped out.
*/
- virtual SkIRect getConservativeBounds(int width, int height) const {
- return SkIRect::MakeWH(width, height);
- }
+ virtual SkIRect getConservativeBounds() const = 0;
/**
* This computes a GrAppliedClip from the clip which in turn can be used to build a GrPipeline.
@@ -45,22 +45,18 @@
virtual bool apply(GrRecordingContext*, GrRenderTargetContext*, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip*, SkRect* bounds) const = 0;
- virtual ~GrClip() {}
-
/**
* This method quickly and conservatively determines whether the entire clip is equivalent to
- * intersection with a rrect. This will only return true if the rrect does not fully contain
- * the render target bounds. Moreover, the returned rrect need not be contained by the render
+ * intersection with a rrect. Moreover, the returned rrect need not be contained by the render
* target bounds. We assume all draws will be implicitly clipped by the render target bounds.
*
- * @param rtBounds The bounds of the render target that the clip will be applied to.
* @param rrect If return is true rrect will contain the rrect equivalent to the clip within
* rtBounds.
* @param aa If return is true aa will indicate whether the rrect clip is antialiased.
* @return true if the clip is equivalent to a single rrect, false otherwise.
*
*/
- virtual bool isRRect(const SkRect& rtBounds, SkRRect* rrect, GrAA* aa) const = 0;
+ virtual bool isRRect(SkRRect* rrect, GrAA* aa) const = 0;
/**
* This is the maximum distance that a draw may extend beyond a clip's boundary and still count
@@ -151,12 +147,12 @@
* return 'bounds' has been intersected with a conservative bounds of the clip. A return value
* of false indicates that the draw can be skipped as it is fully clipped out.
*/
- virtual bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const = 0;
+ virtual bool apply(GrAppliedHardClip* out, SkRect* bounds) const = 0;
private:
bool apply(GrRecordingContext*, GrRenderTargetContext* rtc, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const final {
- return this->apply(rtc->width(), rtc->height(), &out->hardClip(), bounds);
+ return this->apply(&out->hardClip(), bounds);
}
};
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 391f86e..dd12281 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -48,26 +48,27 @@
return fStack->quickContains(rrect);
}
-bool GrClipStackClip::isRRect(const SkRect& origRTBounds, SkRRect* rr, GrAA* aa) const {
+bool GrClipStackClip::isRRect(SkRRect* rr, GrAA* aa) const {
if (!fStack) {
return false;
}
- const SkRect* rtBounds = &origRTBounds;
+
+ SkRect rtBounds = SkRect::MakeIWH(fDeviceSize.fWidth, fDeviceSize.fHeight);
bool isAA;
- if (fStack->isRRect(*rtBounds, rr, &isAA)) {
+ if (fStack->isRRect(rtBounds, rr, &isAA)) {
*aa = GrAA(isAA);
return true;
}
return false;
}
-SkIRect GrClipStackClip::getConservativeBounds(int width, int height) const {
+SkIRect GrClipStackClip::getConservativeBounds() const {
if (fStack) {
SkRect devBounds;
- fStack->getConservativeBounds(0, 0, width, height, &devBounds);
+ fStack->getConservativeBounds(0, 0, fDeviceSize.fWidth, fDeviceSize.fHeight, &devBounds);
return devBounds.roundOut();
} else {
- return this->GrClip::getConservativeBounds(width, height);
+ return SkIRect::MakeSize(fDeviceSize);
}
}
@@ -199,7 +200,9 @@
bool GrClipStackClip::apply(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext,
bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out,
SkRect* bounds) const {
- SkRect devBounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height());
+ SkASSERT(renderTargetContext->width() == fDeviceSize.fWidth &&
+ renderTargetContext->height() == fDeviceSize.fHeight);
+ SkRect devBounds = SkRect::MakeIWH(fDeviceSize.fWidth, fDeviceSize.fHeight);
if (!devBounds.intersect(*bounds)) {
return false;
}
diff --git a/src/gpu/GrClipStackClip.h b/src/gpu/GrClipStackClip.h
index 7bef90b..ffbd001 100644
--- a/src/gpu/GrClipStackClip.h
+++ b/src/gpu/GrClipStackClip.h
@@ -20,23 +20,20 @@
*/
class GrClipStackClip final : public GrClip {
public:
- GrClipStackClip(const SkClipStack* stack = nullptr,
- const SkMatrixProvider* matrixProvider = nullptr) {
- this->reset(stack, matrixProvider);
- }
-
- void reset(const SkClipStack* stack, const SkMatrixProvider* matrixProvider) {
- fStack = stack;
- fMatrixProvider = matrixProvider;
- }
+ GrClipStackClip(const SkISize& dimensions,
+ const SkClipStack* stack = nullptr,
+ const SkMatrixProvider* matrixProvider = nullptr)
+ : fDeviceSize(dimensions)
+ , fStack(stack)
+ , fMatrixProvider(matrixProvider) {}
bool quickContains(const SkRect&) const final;
bool quickContains(const SkRRect&) const final;
- SkIRect getConservativeBounds(int width, int height) const final;
+ SkIRect getConservativeBounds() const final;
bool apply(GrRecordingContext*, GrRenderTargetContext*, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const final;
- bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override;
+ bool isRRect(SkRRect* rr, GrAA* aa) const override;
sk_sp<GrTextureProxy> testingOnly_createClipMask(GrContext*) const;
static const char kMaskTestTag[];
@@ -67,6 +64,9 @@
const GrRenderTargetContext*,
const GrReducedClip&);
+ // SkClipStack does not track device bounds explicitly, but it will refine these device bounds
+ // as clip elements are added to the stack.
+ SkISize fDeviceSize;
const SkClipStack* fStack;
const SkMatrixProvider* fMatrixProvider; // for applying clip shaders
};
diff --git a/src/gpu/GrFixedClip.cpp b/src/gpu/GrFixedClip.cpp
index 2f826fb..2f75bc9 100644
--- a/src/gpu/GrFixedClip.cpp
+++ b/src/gpu/GrFixedClip.cpp
@@ -14,47 +14,33 @@
if (fWindowRectsState.enabled()) {
return false;
}
+
return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect);
}
-SkIRect GrFixedClip::getConservativeBounds(int w, int h) const {
- SkIRect devResult = this->GrClip::getConservativeBounds(w, h);
- if (fScissorState.enabled()) {
- if (!devResult.intersect(fScissorState.rect())) {
- devResult.setEmpty();
- }
- }
- return devResult;
+SkIRect GrFixedClip::getConservativeBounds() const {
+ return fScissorState.rect();
}
-bool GrFixedClip::isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const {
+bool GrFixedClip::isRRect(SkRRect* rr, GrAA* aa) const {
if (fWindowRectsState.enabled()) {
return false;
}
- if (fScissorState.enabled()) {
- SkRect rect = SkRect::Make(fScissorState.rect());
- if (!rect.intersects(rtBounds)) {
- return false;
- }
- rr->setRect(rect);
- *aa = GrAA::kNo;
- return true;
- }
- return false;
+ // Whether or not the scissor test is enabled, the remaining clip is a rectangle described
+ // by scissorState.rect() (either the scissor or the rt bounds).
+ rr->setRect(SkRect::Make(fScissorState.rect()));
+ *aa = GrAA::kNo;
+ return true;
};
-bool GrFixedClip::apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const {
- if (fScissorState.enabled()) {
- SkIRect tightScissor = SkIRect::MakeWH(rtWidth, rtHeight);
- if (!tightScissor.intersect(fScissorState.rect())) {
- return false;
- }
- if (IsOutsideClip(tightScissor, *bounds)) {
- return false;
- }
- if (!IsInsideClip(fScissorState.rect(), *bounds)) {
- out->addScissor(tightScissor, bounds);
- }
+bool GrFixedClip::apply(GrAppliedHardClip* out, SkRect* bounds) const {
+ if (IsOutsideClip(fScissorState.rect(), *bounds)) {
+ return false;
+ }
+ if (!IsInsideClip(fScissorState.rect(), *bounds)) {
+ SkIRect tightScissor = bounds->roundOut();
+ SkAssertResult(tightScissor.intersect(fScissorState.rect()));
+ out->addScissor(tightScissor, bounds);
}
if (fWindowRectsState.enabled()) {
diff --git a/src/gpu/GrFixedClip.h b/src/gpu/GrFixedClip.h
index 422b11d..5abc310 100644
--- a/src/gpu/GrFixedClip.h
+++ b/src/gpu/GrFixedClip.h
@@ -47,9 +47,9 @@
}
bool quickContains(const SkRect&) const override;
- SkIRect getConservativeBounds(int w, int h) const override;
- bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const override;
- bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const override;
+ SkIRect getConservativeBounds() const override;
+ bool isRRect(SkRRect* rr, GrAA*) const override;
+ bool apply(GrAppliedHardClip*, SkRect*) const override;
private:
GrScissorState fScissorState;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 49f91b7..d9727ad 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -701,8 +701,7 @@
}
static SkIRect get_clip_bounds(const GrRenderTargetContext* rtc, const GrClip* clip) {
- return clip ? clip->getConservativeBounds(rtc->width(), rtc->height())
- : SkIRect::MakeWH(rtc->width(), rtc->height());
+ return clip ? clip->getConservativeBounds() : SkIRect::MakeWH(rtc->width(), rtc->height());
}
GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimization(
@@ -761,7 +760,7 @@
GrAA clipAA = stencilSettings ? *aa : GrAA::kNo;
bool axisAlignedClip = true;
if (clip && !clip->quickContains(rtRect)) {
- if (!clip->isRRect(rtRect, &clipRRect, &clipAA)) {
+ if (!clip->isRRect(&clipRRect, &clipAA)) {
axisAlignedClip = false;
}
}
@@ -1079,8 +1078,7 @@
GrAppliedHardClip appliedClip(fRenderTargetContext->dimensions(),
fRenderTargetContext->asSurfaceProxy()->backingStoreDimensions());
- if (clip && !clip->apply(fRenderTargetContext->width(), fRenderTargetContext->height(),
- &appliedClip, &bounds)) {
+ if (clip && !clip->apply(&appliedClip, &bounds)) {
return;
}
// else see FIXME above; we'd normally want to check path bounds with render target bounds,
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 9212325..95ab059 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -75,8 +75,7 @@
SkIRect* clippedDevShapeBounds,
SkIRect* devClipBounds) {
// compute bounds as intersection of rt size, clip, and path
- *devClipBounds = clip ? clip->getConservativeBounds(renderTargetContext->width(),
- renderTargetContext->height())
+ *devClipBounds = clip ? clip->getConservativeBounds()
: SkIRect::MakeWH(renderTargetContext->width(),
renderTargetContext->height());
diff --git a/src/gpu/GrStencilClip.h b/src/gpu/GrStencilClip.h
index 5c9f4a5..4ab8a82 100644
--- a/src/gpu/GrStencilClip.h
+++ b/src/gpu/GrStencilClip.h
@@ -35,14 +35,14 @@
bool quickContains(const SkRect& rect) const override {
return !this->hasStencilClip() && fFixedClip.quickContains(rect);
}
- SkIRect getConservativeBounds(int width, int height) const override {
- return fFixedClip.getConservativeBounds(width, height);
+ SkIRect getConservativeBounds() const override {
+ return fFixedClip.getConservativeBounds();
}
- bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override {
- return !this->hasStencilClip() && fFixedClip.isRRect(rtBounds, rr, aa);
+ bool isRRect(SkRRect* rr, GrAA* aa) const override {
+ return !this->hasStencilClip() && fFixedClip.isRRect(rr, aa);
}
- bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const override {
- if (!fFixedClip.apply(rtWidth, rtHeight, out, bounds)) {
+ bool apply(GrAppliedHardClip* out, SkRect* bounds) const override {
+ if (!fFixedClip.apply(out, bounds)) {
return false;
}
if (this->hasStencilClip()) {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index dd13b97..577eb08 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -125,7 +125,7 @@
renderTargetContext->surfaceProps())
, fContext(SkRef(context))
, fRenderTargetContext(std::move(renderTargetContext))
- , fClip(&this->cs(), &this->asMatrixProvider()) {
+ , fClip(fRenderTargetContext->dimensions(), &this->cs(), &this->asMatrixProvider()) {
if (flags & kNeedClear_Flag) {
this->clearAll();
}
@@ -725,7 +725,8 @@
dstRectClip.clipDevRect(
SkIRect::MakeXYWH(left, top, subset.width(), subset.height()),
SkClipOp::kIntersect);
- GrClipStackClip clip(&dstRectClip);
+ GrClipStackClip clip(fRenderTargetContext->dimensions(), &dstRectClip,
+ &this->asMatrixProvider());
SkMatrix local = SkMatrix::Concat(SkMatrix::MakeRectToRect(
dstRect, srcRect, SkMatrix::kFill_ScaleToFit), ctm);
fRenderTargetContext->fillRectWithLocalMatrix(&clip, std::move(grPaint),
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index c19971f..cc323e1 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -130,7 +130,7 @@
const SkMatrix& srcToDstRect,
const SkISize& imageDimensions,
const SkRect* srcRectPtr) {
- SkIRect clippedSrcIRect = clip ? clip->getConservativeBounds(width, height)
+ SkIRect clippedSrcIRect = clip ? clip->getConservativeBounds()
: SkIRect::MakeWH(width, height);
SkMatrix inv = SkMatrix::Concat(viewMatrix, srcToDstRect);
if (!inv.invert(&inv)) {
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 69d2d1e..5e5b8dc 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -447,7 +447,7 @@
// and we have an axis-aligned rectangular non-AA clip
if (!this->drawAsDistanceFields() &&
!this->needsTransform() &&
- (!clip || (clip->isRRect(rtBounds, &clipRRect, &aa) &&
+ (!clip || (clip->isRRect(&clipRRect, &aa) &&
clipRRect.isRect() && GrAA::kNo == aa))) {
// We only need to do clipping work if the subrun isn't contained by the clip
SkRect subRunBounds = this->deviceRect(deviceMatrix.localToDevice(), drawOrigin);