Use bilerp sampling when drawing TextureView with non-translate matrix

Draw TextureView with bilerp sampling, when the matrix is not
integer translate or identity. For example scaling matrix or
translation on X by 0.4f will draw with GL_LINEAR on OpenGL pipeline.
Translation on X by 3.0f will draw TextureView with GL_NEAREST.

Bug: 117890671
Test: Passed CtsViewTestCases and CtsUiRenderingTestCases
Change-Id: I72033410c8b0ab637c2e6b816ac9b04434286fbb
Merged-In: I3acd710ff2cb4ee7b14dd4b7d9227842187130c9
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 093c7cf..ab1d5c2 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -100,15 +100,13 @@
         paint.setAlpha(layer->getAlpha());
         paint.setBlendMode(layer->getMode());
         paint.setColorFilter(layer->getColorSpaceWithFilter());
-        if (layer->getForceFilter()) {
-            paint.setFilterQuality(kLow_SkFilterQuality);
-        }
 
         const bool nonIdentityMatrix = !matrix.isIdentity();
         if (nonIdentityMatrix) {
             canvas->save();
             canvas->concat(matrix);
         }
+        const SkMatrix& totalMatrix = canvas->getTotalMatrix();
         if (dstRect) {
             SkMatrix matrixInv;
             if (!matrix.invert(&matrixInv)) {
@@ -118,9 +116,28 @@
             matrixInv.mapRect(&srcRect);
             SkRect skiaDestRect = *dstRect;
             matrixInv.mapRect(&skiaDestRect);
+            // If (matrix is identity or an integer translation) and (src/dst buffers size match),
+            // then use nearest neighbor, otherwise use bilerp sampling.
+            // Integer translation is defined as when src rect and dst rect align fractionally.
+            // Skia TextureOp has the above logic build-in, but not NonAAFillRectOp. TextureOp works
+            // only for SrcOver blending and without color filter (readback uses Src blending).
+            bool isIntegerTranslate = totalMatrix.isTranslate()
+                    && SkScalarFraction(skiaDestRect.fLeft + totalMatrix[SkMatrix::kMTransX])
+                    == SkScalarFraction(srcRect.fLeft)
+                    && SkScalarFraction(skiaDestRect.fTop + totalMatrix[SkMatrix::kMTransY])
+                    == SkScalarFraction(srcRect.fTop);
+            if (layer->getForceFilter() || !isIntegerTranslate) {
+                paint.setFilterQuality(kLow_SkFilterQuality);
+            }
             canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint,
                                   SkCanvas::kFast_SrcRectConstraint);
         } else {
+            bool isIntegerTranslate = totalMatrix.isTranslate()
+                    && SkScalarIsInt(totalMatrix[SkMatrix::kMTransX])
+                    && SkScalarIsInt(totalMatrix[SkMatrix::kMTransY]);
+            if (layer->getForceFilter() || !isIntegerTranslate) {
+                paint.setFilterQuality(kLow_SkFilterQuality);
+            }
             canvas->drawImage(layerImage.get(), 0, 0, &paint);
         }
         // restore the original matrix