GrTextureEffect handles insets for float rects as well as integer rects.

Fix insets for clamp/nearest case.

Change-Id: I1fa2f6d172fdac59836ae73c7a5fec0d0cde020c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268397
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/effects/GrTextureEffect.cpp b/src/gpu/effects/GrTextureEffect.cpp
index 7b4a292..298cf47 100644
--- a/src/gpu/effects/GrTextureEffect.cpp
+++ b/src/gpu/effects/GrTextureEffect.cpp
@@ -78,7 +78,6 @@
 GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
                                     GrSamplerState sampler,
                                     const SkRect& subset,
-                                    bool adjustForFilter,
                                     const SkRect* domain,
                                     const GrCaps& caps) {
     using Mode = GrSamplerState::WrapMode;
@@ -91,9 +90,8 @@
         Filter fFilter;
     };
 
-    auto resolve = [adjustForFilter, filter = sampler.filter(), &caps](int size, Mode mode,
-                                                                       Span subset, Span domain) {
-        float inset;
+    auto resolve = [filter = sampler.filter(), &caps](int size, Mode mode, Span subset,
+                                                      Span domain) {
         Result1D r;
         r.fFilter = filter;
         bool canDoHW = (mode != Mode::kClampToBorder || caps.clampToBorderSupport()) &&
@@ -104,10 +102,27 @@
             return r;
         }
 
-        inset = (adjustForFilter && filter != Filter::kNearest) ? 0.5 : 0;
-        auto insetSubset = subset.makeInset(inset);
-
-        if (canDoHW && insetSubset.contains(domain)) {
+        bool domainIsSafe = false;
+        Span insetSubset;
+        if (filter == Filter::kNearest) {
+            Span isubset{sk_float_floor(subset.fA), sk_float_ceil(subset.fB)};
+            if (domain.fA > isubset.fA && domain.fB < isubset.fB) {
+                domainIsSafe = true;
+            }
+            if (mode == Mode::kClamp) {
+                // This inset prevents sampling neighboring texels that could occur when
+                // texture coords fall exactly at texel boundaries (depending on precision
+                // and GPU-specific snapping at the boundary).
+                insetSubset = isubset.makeInset(0.5f);
+            } else {
+                // TODO: Handle other modes properly in this case.
+                insetSubset = subset;
+            }
+        } else {
+            insetSubset = subset.makeInset(0.5f);
+            domainIsSafe = insetSubset.contains(domain);
+        }
+        if (canDoHW && domainIsSafe) {
             r.fShaderMode = ShaderMode::kNone;
             r.fHWMode = mode;
             return r;
@@ -173,8 +188,7 @@
                                                                       GrSamplerState sampler,
                                                                       const SkIRect& subset,
                                                                       const GrCaps& caps) {
-    Sampling sampling(*view.proxy(), sampler, SkRect::Make(subset), true, nullptr, caps);
-
+    Sampling sampling(*view.proxy(), sampler, SkRect::Make(subset), nullptr, caps);
     return std::unique_ptr<GrFragmentProcessor>(
             new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
 }
@@ -186,7 +200,7 @@
                                                                       const SkIRect& subset,
                                                                       const SkRect& domain,
                                                                       const GrCaps& caps) {
-    Sampling sampling(*view.proxy(), sampler, SkRect::Make(subset), true, &domain, caps);
+    Sampling sampling(*view.proxy(), sampler, SkRect::Make(subset), &domain, caps);
     return std::unique_ptr<GrFragmentProcessor>(
             new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
 }
@@ -197,7 +211,7 @@
                                                                  GrSamplerState sampler,
                                                                  const SkRect& subset,
                                                                  const GrCaps& caps) {
-    Sampling sampling(*view.proxy(), sampler, subset, false, nullptr, caps);
+    Sampling sampling(*view.proxy(), sampler, subset, nullptr, caps);
     return std::unique_ptr<GrFragmentProcessor>(
             new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
 }
@@ -209,7 +223,7 @@
                                                                  const SkRect& subset,
                                                                  const SkRect& domain,
                                                                  const GrCaps& caps) {
-    Sampling sampling(*view.proxy(), sampler, subset, false, &domain, caps);
+    Sampling sampling(*view.proxy(), sampler, subset, &domain, caps);
     return std::unique_ptr<GrFragmentProcessor>(
             new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
 }