Use GrResourceProvider::MakeApprox for mask filter proxy sizes

This allows us to demand exact matches in size and eliminate our
dependence on absClear.

In the future we can take this a step further and offset the mask to
leave a transparent border on all sides, thereby creating a "decal"
effect.

Bug: skia:
Change-Id: I8cd02ba1365ace0ccaae250a7195f51d0c77ce8d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/242720
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index c8fdc0b..c22d0f0 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -174,14 +174,24 @@
                                              const SkMatrix& origViewMatrix,
                                              const GrShape& shape,
                                              int sampleCnt) {
+    // Use GrResourceProvider::MakeApprox to implement our own approximate size matching, but demand
+    // a "SkBackingFit::kExact" size match on the actual render target. We do this because the
+    // filter will reach outside the src bounds, so we need to pre-clear these values to ensure a
+    // "decal" sampling effect (i.e., ensure reads outside the src bounds return alpha=0).
+    //
+    // FIXME: Reads outside the left and top edges will actually clamp to the edge pixel. And in the
+    // event that MakeApprox does not change the size, reads outside the right and/or bottom will do
+    // the same. We should offset our filter within the render target and expand the size as needed
+    // to guarantee at least 1px of padding on all sides.
     auto rtContext = context->priv().makeDeferredRenderTargetContextWithFallback(
-            SkBackingFit::kApprox, maskRect.width(), maskRect.height(), GrColorType::kAlpha_8,
-            nullptr, sampleCnt, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
+            SkBackingFit::kExact, GrResourceProvider::MakeApprox(maskRect.width()),
+            GrResourceProvider::MakeApprox(maskRect.height()), GrColorType::kAlpha_8, nullptr,
+            sampleCnt, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
     if (!rtContext) {
         return nullptr;
     }
 
-    rtContext->priv().absClear(nullptr);
+    rtContext->clear(SK_PMColor4fTRANSPARENT);
 
     GrPaint maskPaint;
     maskPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 83c20f7..1bc8165 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -81,6 +81,10 @@
      */
     void clear(const SkIRect* rect, const SkPMColor4f& color, CanClearFullscreen);
 
+    void clear(const SkPMColor4f& color) {
+        return this->clear(nullptr, color, CanClearFullscreen::kYes);
+    }
+
     /**
      *  Draw everywhere (respecting the clip) with the paint.
      */
diff --git a/src/gpu/effects/GrRRectBlurEffect.fp b/src/gpu/effects/GrRRectBlurEffect.fp
index 74ad750..9974955 100644
--- a/src/gpu/effects/GrRRectBlurEffect.fp
+++ b/src/gpu/effects/GrRRectBlurEffect.fp
@@ -53,11 +53,12 @@
         sk_sp<GrTextureProxy> mask(proxyProvider->findOrCreateProxyByUniqueKey(
                 key, GrColorType::kAlpha_8, kBottomLeft_GrSurfaceOrigin));
         if (!mask) {
-            // TODO: this could be approx but the texture coords will need to be updated
-            auto rtc =
-                    context->priv().makeDeferredRenderTargetContextWithFallback(
-                                                SkBackingFit::kExact, size.fWidth,
-                                                size.fHeight, GrColorType::kAlpha_8, nullptr);
+            // TODO: this could be SkBackingFit::kApprox, but:
+            //   1) The texture coords would need to be updated.
+            //   2) We would have to use GrTextureDomain::kClamp_Mode for the GaussianBlur.
+            auto rtc = context->priv().makeDeferredRenderTargetContextWithFallback(
+                    SkBackingFit::kExact, size.fWidth, size.fHeight, GrColorType::kAlpha_8,
+                    nullptr);
             if (!rtc) {
                 return nullptr;
             }
diff --git a/src/gpu/effects/generated/GrRRectBlurEffect.h b/src/gpu/effects/generated/GrRRectBlurEffect.h
index 8b48489..e2f3dd5 100644
--- a/src/gpu/effects/generated/GrRRectBlurEffect.h
+++ b/src/gpu/effects/generated/GrRRectBlurEffect.h
@@ -54,7 +54,9 @@
         sk_sp<GrTextureProxy> mask(proxyProvider->findOrCreateProxyByUniqueKey(
                 key, GrColorType::kAlpha_8, kBottomLeft_GrSurfaceOrigin));
         if (!mask) {
-            // TODO: this could be approx but the texture coords will need to be updated
+            // TODO: this could be SkBackingFit::kApprox, but:
+            //   1) The texture coords would need to be updated.
+            //   2) We would have to use GrTextureDomain::kClamp_Mode for the GaussianBlur.
             auto rtc = context->priv().makeDeferredRenderTargetContextWithFallback(
                     SkBackingFit::kExact, size.fWidth, size.fHeight, GrColorType::kAlpha_8,
                     nullptr);