Fix gpu blurring on platforms that "useDrawInsteadOfClear"
Platforms that "useDrawInsteadOfClear" take a different path in
GrRenderTargetContext::internalClear. The different path involves
a lot of comparisons of the drawn rect with the bounds of the RenderTarget. Since the RenderTargets are now deferred (and the instantiated version might be larger than the proxied size) case must be taken in prematurely optimizing away clears and draws.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5148
TBR=bsalomon@google.com
Change-Id: If63b6393fb66328175bc92de211e7242e903f25e
Reviewed-on: https://skia-review.googlesource.com/5148
Reviewed-by: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h
index 20ca59f..6e46cd9 100644
--- a/include/gpu/GrRenderTargetContext.h
+++ b/include/gpu/GrRenderTargetContext.h
@@ -382,6 +382,13 @@
bool isWrapped_ForTesting() const;
+ // These two methods return the worst case size of the backing GPU resource when it is
+ // finally allocated. In the approx-match case the allocated size could be smaller than
+ // what is reported by these entry points (i.e., Ganesh could, optionally, return an
+ // exact match)
+ int worstCaseWidth() const { return fRenderTargetProxy->worstCaseWidth(); }
+ int worstCaseHeight() const { return fRenderTargetProxy->worstCaseHeight(); }
+
protected:
GrRenderTargetContext(GrContext*, GrDrawingManager*, sk_sp<GrRenderTargetProxy>,
sk_sp<SkColorSpace>, const SkSurfaceProps* surfaceProps, GrAuditTrail*,
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 61dc9e1..e60dc28 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -10,6 +10,7 @@
#include "GrGpuResource.h"
#include "GrSurface.h"
+
#include "SkRect.h"
class GrCaps;
@@ -224,6 +225,9 @@
*/
SkRect getBoundsRect() const { return SkRect::MakeIWH(this->width(), this->height()); }
+ int worstCaseWidth() const;
+ int worstCaseHeight() const;
+
/**
* @return the texture proxy associated with the surface proxy, may be NULL.
*/
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 97fa623..8f14bf7 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -141,7 +141,8 @@
SkASSERT(maskFilter);
SkIRect clipBounds;
- clip.getConservativeBounds(renderTargetContext->width(), renderTargetContext->height(),
+ clip.getConservativeBounds(renderTargetContext->worstCaseWidth(),
+ renderTargetContext->worstCaseHeight(),
&clipBounds);
SkTLazy<SkPath> tmpPath;
SkStrokeRec::InitStyle fillOrHairline;
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 0af6c03..548f5b7 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -268,7 +268,8 @@
return true;
}
- SkRect devBounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height());
+ SkRect devBounds = SkRect::MakeIWH(renderTargetContext->worstCaseWidth(),
+ renderTargetContext->worstCaseHeight());
if (!devBounds.intersect(out->clippedDrawBounds())) {
return false;
}
@@ -298,8 +299,8 @@
#ifdef SK_DEBUG
SkASSERT(reducedClip.hasIBounds());
- SkIRect rtIBounds = SkIRect::MakeWH(renderTargetContext->width(),
- renderTargetContext->height());
+ SkIRect rtIBounds = SkIRect::MakeWH(renderTargetContext->worstCaseWidth(),
+ renderTargetContext->worstCaseHeight());
SkIRect clipIBounds = reducedClip.ibounds().makeOffset(-fOrigin.x(), -fOrigin.y());
SkASSERT(rtIBounds.contains(clipIBounds)); // Mask shouldn't be larger than the RT.
#endif
diff --git a/src/gpu/GrFixedClip.cpp b/src/gpu/GrFixedClip.cpp
index 79e2662..9e87588 100644
--- a/src/gpu/GrFixedClip.cpp
+++ b/src/gpu/GrFixedClip.cpp
@@ -48,7 +48,7 @@
bool GrFixedClip::apply(GrContext*, GrRenderTargetContext* rtc,
bool, bool, GrAppliedClip* out) const {
if (fScissorState.enabled()) {
- SkIRect tightScissor = SkIRect::MakeWH(rtc->width(), rtc->height());
+ SkIRect tightScissor = SkIRect::MakeWH(rtc->worstCaseWidth(), rtc->worstCaseHeight());
if (!tightScissor.intersect(fScissorState.rect())) {
return false;
}
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index f08f39a..8cc6dd9 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -254,10 +254,10 @@
// This works around a driver bug with clear by drawing a rect instead.
// The driver will ignore a clear if it is the only thing rendered to a
// target before the target is read.
- SkRect clearRect = SkRect::MakeIWH(this->width(), this->height());
+ SkIRect clearRect = SkIRect::MakeWH(this->worstCaseWidth(), this->worstCaseHeight());
if (isFull) {
this->discard();
- } else if (!clearRect.intersect(SkRect::Make(clip.scissorRect()))) {
+ } else if (!clearRect.intersect(clip.scissorRect())) {
return;
}
@@ -265,7 +265,7 @@
paint.setColor4f(GrColor4f::FromGrColor(color));
paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
- this->drawRect(clip, paint, SkMatrix::I(), clearRect);
+ this->drawRect(clip, paint, SkMatrix::I(), SkRect::Make(clearRect));
} else if (isFull) {
if (this->accessRenderTarget()) {
this->getOpList()->fullClear(this->accessRenderTarget(), color);
@@ -415,7 +415,8 @@
const SkRect& rect,
const GrUserStencilSettings* ss) {
SkRect croppedRect = rect;
- if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
+ if (!crop_filled_rect(this->worstCaseWidth(), this->worstCaseHeight(),
+ clip, viewMatrix, &croppedRect)) {
return true;
}
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 95fc8b9..35e505c 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -12,6 +12,8 @@
#include "GrTextureProvider.h"
#include "GrTextureRenderTargetProxy.h"
+#include "SkMathPriv.h"
+
GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit)
: INHERITED(std::move(surface))
, fDesc(fTarget->desc())
@@ -54,6 +56,30 @@
return fTarget;
}
+int GrSurfaceProxy::worstCaseWidth() const {
+ if (fTarget) {
+ return fTarget->width();
+ }
+
+ if (SkBackingFit::kExact == fFit) {
+ return fDesc.fWidth;
+ }
+
+ return GrNextPow2(fDesc.fWidth);
+}
+
+int GrSurfaceProxy::worstCaseHeight() const {
+ if (fTarget) {
+ return fTarget->height();
+ }
+
+ if (SkBackingFit::kExact == fFit) {
+ return fDesc.fHeight;
+ }
+
+ return GrNextPow2(fDesc.fHeight);
+}
+
void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
if (fLastOpList) {
// The non-MDB world never closes so we can't check this condition
diff --git a/src/gpu/batches/GrAAHairLinePathRenderer.cpp b/src/gpu/batches/GrAAHairLinePathRenderer.cpp
index eb1be15..70c4911 100644
--- a/src/gpu/batches/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/batches/GrAAHairLinePathRenderer.cpp
@@ -961,8 +961,8 @@
SkASSERT(!args.fRenderTargetContext->isUnifiedMultisampled());
SkIRect devClipBounds;
- args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
- args.fRenderTargetContext->height(),
+ args.fClip->getConservativeBounds(args.fRenderTargetContext->worstCaseWidth(),
+ args.fRenderTargetContext->worstCaseHeight(),
&devClipBounds);
SkPath path;
diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp
index 5260368..8e17ea4 100644
--- a/src/gpu/batches/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/batches/GrTessellatingPathRenderer.cpp
@@ -353,8 +353,8 @@
GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
"GrTessellatingPathRenderer::onDrawPath");
SkIRect clipBoundsI;
- args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
- args.fRenderTargetContext->height(),
+ args.fClip->getConservativeBounds(args.fRenderTargetContext->worstCaseWidth(),
+ args.fRenderTargetContext->worstCaseHeight(),
&clipBoundsI);
sk_sp<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fPaint->getColor(),
*args.fShape,