Use SkBitmapProcStateAutoMapper for filter samplers also

Observation: filter procs are also biased by s.fFilterOne{X,Y} / 2.  They all do
something along these lines:

  s.fInvProc(s.fInvMatrix,
    SkIntToScalar(x) + SK_ScalarHalf,
    SkIntToScalar(y) + SK_ScalarHalf, &srcPt);

  SkFixed fx = SkScalarToFixed(srcPt.fX) - (s.fFilterOneX >> 1);
  SkFixed fy = SkScalarToFixed(srcPt.fY) - (s.fFilterOneX >> 1);

It's trivial to extend SkBitmapProcStateAutoMapper to handle this internally, and
convert everyone off explicit mapping.

R=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1661613002
CQ_EXTRA_TRYBOTS=client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Review URL: https://codereview.chromium.org/1661613002
diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h
index 0ae8cf2..fca7dc0 100644
--- a/src/core/SkBitmapProcState.h
+++ b/src/core/SkBitmapProcState.h
@@ -189,7 +189,6 @@
                                    uint32_t xy[], int count, int x, int y);
 
 // Helper class for mapping the middle of pixel (x, y) into SkFractionalInt bitmap space.
-// TODO: filtered version which applies a fFilterOne{X,Y}/2 bias instead of epsilon?
 class SkBitmapProcStateAutoMapper {
 public:
     SkBitmapProcStateAutoMapper(const SkBitmapProcState& s, int x, int y,
@@ -199,12 +198,19 @@
                    SkIntToScalar(x) + SK_ScalarHalf,
                    SkIntToScalar(y) + SK_ScalarHalf, &pt);
 
-        // SkFixed epsilon bias to ensure inverse-mapped bitmap coordinates are rounded
-        // consistently WRT geometry.  Note that we only need the bias for positive scales:
-        // for negative scales, the rounding is intrinsically correct.
-        // We scale it to persist SkFractionalInt -> SkFixed conversions.
-        const SkFixed biasX = (s.fInvMatrix.getScaleX() > 0);
-        const SkFixed biasY = (s.fInvMatrix.getScaleY() > 0);
+        SkFixed biasX, biasY;
+        if (s.fFilterLevel == kNone_SkFilterQuality) {
+            // SkFixed epsilon bias to ensure inverse-mapped bitmap coordinates are rounded
+            // consistently WRT geometry.  Note that we only need the bias for positive scales:
+            // for negative scales, the rounding is intrinsically correct.
+            // We scale it to persist SkFractionalInt -> SkFixed conversions.
+            biasX = (s.fInvMatrix.getScaleX() > 0);
+            biasY = (s.fInvMatrix.getScaleY() > 0);
+        } else {
+            biasX = s.fFilterOneX >> 1;
+            biasY = s.fFilterOneY >> 1;
+        }
+
         fX = SkScalarToFractionalInt(pt.x()) - SkFixedToFractionalInt(biasX);
         fY = SkScalarToFractionalInt(pt.y()) - SkFixedToFractionalInt(biasY);
 
diff --git a/src/core/SkBitmapProcState_matrix.h b/src/core/SkBitmapProcState_matrix.h
index bdab846..273a35b 100644
--- a/src/core/SkBitmapProcState_matrix.h
+++ b/src/core/SkBitmapProcState_matrix.h
@@ -61,15 +61,13 @@
     SkFractionalInt fx;
 
     {
-        SkPoint pt;
-        s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
-                                  SkIntToScalar(y) + SK_ScalarHalf, &pt);
-        const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
+        const SkBitmapProcStateAutoMapper mapper(s, x, y);
+        const SkFixed fy = SkFractionalIntToFixed(mapper.y());
         const unsigned maxY = s.fPixmap.height() - 1;
         // compute our two Y values up front
         *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
         // now initialize fx
-        fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1);
+        fx = mapper.x();
     }
 
 #ifdef CHECK_FOR_DECAL
@@ -95,15 +93,12 @@
                              SkMatrix::kAffine_Mask)) == 0);
 
     PREAMBLE(s);
-    SkPoint srcPt;
-    s.fInvProc(s.fInvMatrix,
-               SkIntToScalar(x) + SK_ScalarHalf,
-               SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+    const SkBitmapProcStateAutoMapper mapper(s, x, y);
 
     SkFixed oneX = s.fFilterOneX;
     SkFixed oneY = s.fFilterOneY;
-    SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
-    SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
+    SkFixed fx = SkFractionalIntToFixed(mapper.x());
+    SkFixed fy = SkFractionalIntToFixed(mapper.y());
     SkFixed dx = s.fInvSx;
     SkFixed dy = s.fInvKy;
     unsigned maxX = s.fPixmap.width() - 1;
diff --git a/src/core/SkBitmapProcState_shaderproc.h b/src/core/SkBitmapProcState_shaderproc.h
index d41ff06..1ff2e6b 100644
--- a/src/core/SkBitmapProcState_shaderproc.h
+++ b/src/core/SkBitmapProcState_shaderproc.h
@@ -31,10 +31,8 @@
     unsigned subY;
 
     {
-        SkPoint pt;
-        s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
-                   SkIntToScalar(y) + SK_ScalarHalf, &pt);
-        SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
+        const SkBitmapProcStateAutoMapper mapper(s, x, y);
+        SkFixed fy = SkFractionalIntToFixed(mapper.y());
         const unsigned maxY = s.fPixmap.height() - 1;
         // compute our two Y values up front
         subY = TILEY_LOW_BITS(fy, maxY);
@@ -46,7 +44,7 @@
         row0 = (const SRCTYPE*)(srcAddr + y0 * rb);
         row1 = (const SRCTYPE*)(srcAddr + y1 * rb);
         // now initialize fx
-        fx = SkScalarToFixed(pt.fX) - (oneX >> 1);
+        fx = SkFractionalIntToFixed(mapper.x());
     }
 
 #ifdef PREAMBLE
diff --git a/src/opts/SkBitmapProcState_matrix_neon.h b/src/opts/SkBitmapProcState_matrix_neon.h
index 4546f70..df151b2 100644
--- a/src/opts/SkBitmapProcState_matrix_neon.h
+++ b/src/opts/SkBitmapProcState_matrix_neon.h
@@ -298,15 +298,13 @@
     SkFractionalInt fx;
 
     {
-        SkPoint pt;
-        s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
-                                 SkIntToScalar(y) + SK_ScalarHalf, &pt);
-        const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
+        const SkBitmapProcStateAutoMapper mapper(s, x, y);
+        const SkFixed fy = SkFractionalIntToFixed(mapper.y());
         const unsigned maxY = s.fPixmap.height() - 1;
         // compute our two Y values up front
         *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
         // now initialize fx
-        fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1);
+        fx = mapper.x();
     }
 
 #ifdef CHECK_FOR_DECAL
@@ -357,15 +355,12 @@
                              SkMatrix::kAffine_Mask)) == 0);
 
     PREAMBLE(s);
-    SkPoint srcPt;
-    s.fInvProc(s.fInvMatrix,
-               SkIntToScalar(x) + SK_ScalarHalf,
-               SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+    const SkBitmapProcStateAutoMapper mapper(s, x, y);
 
     SkFixed oneX = s.fFilterOneX;
     SkFixed oneY = s.fFilterOneY;
-    SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
-    SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
+    SkFixed fx = SkFractionalIntToFixed(mapper.x());
+    SkFixed fy = SkFractionalIntToFixed(mapper.y());
     SkFixed dx = s.fInvSx;
     SkFixed dy = s.fInvKy;
     unsigned maxX = s.fPixmap.width() - 1;
diff --git a/src/opts/SkBitmapProcState_opts_SSE2.cpp b/src/opts/SkBitmapProcState_opts_SSE2.cpp
index b5da8e2..cb9a2db 100644
--- a/src/opts/SkBitmapProcState_opts_SSE2.cpp
+++ b/src/opts/SkBitmapProcState_opts_SSE2.cpp
@@ -252,17 +252,14 @@
     const unsigned maxX = s.fPixmap.width() - 1;
     const SkFixed one = s.fFilterOneX;
     const SkFixed dx = s.fInvSx;
-    SkFixed fx;
 
-    SkPoint pt;
-    s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
-                             SkIntToScalar(y) + SK_ScalarHalf, &pt);
-    const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
+    const SkBitmapProcStateAutoMapper mapper(s, x, y);
+    const SkFixed fy = SkFractionalIntToFixed(mapper.y());
     const unsigned maxY = s.fPixmap.height() - 1;
     // compute our two Y values up front
     *xy++ = ClampX_ClampY_pack_filter(fy, maxY, s.fFilterOneY);
     // now initialize fx
-    fx = SkScalarToFixed(pt.fX) - (one >> 1);
+    SkFixed fx = SkFractionalIntToFixed(mapper.x());
 
     // test if we don't need to apply the tile proc
     if (dx > 0 && (unsigned)(fx >> 16) <= maxX &&
@@ -485,15 +482,12 @@
  */
 void ClampX_ClampY_filter_affine_SSE2(const SkBitmapProcState& s,
                                       uint32_t xy[], int count, int x, int y) {
-    SkPoint srcPt;
-    s.fInvProc(s.fInvMatrix,
-               SkIntToScalar(x) + SK_ScalarHalf,
-               SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+    const SkBitmapProcStateAutoMapper mapper(s, x, y);
 
     SkFixed oneX = s.fFilterOneX;
     SkFixed oneY = s.fFilterOneY;
-    SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
-    SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
+    SkFixed fx = SkFractionalIntToFixed(mapper.x());
+    SkFixed fy = SkFractionalIntToFixed(mapper.y());
     SkFixed dx = s.fInvSx;
     SkFixed dy = s.fInvKy;
     unsigned maxX = s.fPixmap.width() - 1;