RESTRICT AUTOMERGE pixel-snap on HWUI side

Bug: 254771190
Test: android.uirendering.cts.testclasses.ExactCanvasTests#testDrawLine
Change-Id: Idfb5027fe3230f2c2b0cad224f2c7640e147ce4a
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 602554a..f56d19b 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -793,6 +793,10 @@
     return size;
 }
 
+const SkM44& CanvasContext::getPixelSnapMatrix() const {
+    return mRenderPipeline->getPixelSnapMatrix();
+}
+
 void CanvasContext::prepareAndDraw(RenderNode* node) {
     ATRACE_CALL();
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 951ee21..d85e579 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -195,6 +195,9 @@
 
     SkISize getNextFrameSize() const;
 
+    // Returns the matrix to use to nudge non-AA'd points/lines towards the fragment center
+    const SkM44& getPixelSnapMatrix() const;
+
     // Called when SurfaceStats are available.
     static void onSurfaceStatsAvailable(void* context, int32_t surfaceControlId,
                                         ASurfaceControlStats* stats);
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index ef58bc5..54adec2 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -88,6 +88,8 @@
     virtual void setPictureCapturedCallback(
             const std::function<void(sk_sp<SkPicture>&&)>& callback) = 0;
 
+    virtual const SkM44& getPixelSnapMatrix() const = 0;
+
     virtual ~IRenderPipeline() {}
 };
 
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 7dd3561..666f329 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -63,6 +63,18 @@
     return SkMatrix::I();
 }
 
+static SkM44 GetPixelSnapMatrix(SkISize windowSize, int transform) {
+    // Small (~1/16th) nudge to ensure that pixel-aligned non-AA'd draws fill the
+    // desired fragment
+    static const SkScalar kOffset = 0.063f;
+    SkMatrix preRotation = GetPreTransformMatrix(windowSize, transform);
+    SkMatrix invert;
+    LOG_ALWAYS_FATAL_IF(!preRotation.invert(&invert));
+    return SkM44::Translate(kOffset, kOffset)
+            .postConcat(SkM44(preRotation))
+            .preConcat(SkM44(invert));
+}
+
 static bool ConnectAndSetWindowDefaults(ANativeWindow* window) {
     ATRACE_CALL();
 
@@ -178,6 +190,8 @@
 
     outWindowInfo->preTransform =
             GetPreTransformMatrix(outWindowInfo->size, outWindowInfo->transform);
+    outWindowInfo->pixelSnapMatrix =
+            GetPixelSnapMatrix(outWindowInfo->size, outWindowInfo->transform);
 
     err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
     if (err != 0 || query_value < 0) {
@@ -406,6 +420,7 @@
         }
 
         mWindowInfo.preTransform = GetPreTransformMatrix(mWindowInfo.size, mWindowInfo.transform);
+        mWindowInfo.pixelSnapMatrix = GetPixelSnapMatrix(mWindowInfo.size, mWindowInfo.transform);
     }
 
     uint32_t idx;
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index beb71b72..b8ccf78 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -45,6 +45,8 @@
     }
     const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }
 
+    const SkM44& getPixelSnapMatrix() const { return mWindowInfo.pixelSnapMatrix; }
+
 private:
     /*
      * All structs/methods in this private section are specifically for use by the VulkanManager
@@ -101,6 +103,7 @@
         SkISize actualSize;
         // transform to be applied to the SkSurface to map the coordinates to the provided transform
         SkMatrix preTransform;
+        SkM44 pixelSnapMatrix;
     };
 
     VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, GrDirectContext* grContext);