Use SkSamplingOptions when creating image-shader

Test: make

Change-Id: Ie979cdb10263a08ea3d8c817234b94c9b61abb76
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 1cb5912..e6ff187 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -31,6 +31,23 @@
     private int mTileX;
     private int mTileY;
 
+    /*
+     *  This is cache of the last value from the Paint of bitmap-filtering.
+     *  In the future, BitmapShaders will carry their own (expanded) data for this
+     *  (e.g. including mipmap options, or bicubic weights)
+     *
+     *  When that happens, this bool will become those extended values, and we will
+     *  need to track whether this Shader was created with those new constructors,
+     *  or from the current "legacy" constructor, which (for compatibility) will
+     *  still need to know the Paint's setting.
+     *
+     *  When the filter Paint setting is finally gone, we will be able to remove
+     *  the filterFromPaint parameter currently being passed to createNativeInstance()
+     *  and shouldDiscardNativeInstance(), as shaders will always know their filter
+     *  settings.
+     */
+    private boolean mFilterFromPaint;
+
     /**
      * Call this to create a new shader that will draw with a bitmap.
      *
@@ -49,14 +66,24 @@
         mBitmap = bitmap;
         mTileX = tileX;
         mTileY = tileY;
+        mFilterFromPaint = false;
     }
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
-        return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY);
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+        mFilterFromPaint = filterFromPaint;
+        return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY,
+                            mFilterFromPaint);
+    }
+
+    /** @hide */
+    @Override
+    protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+        return mFilterFromPaint != filterFromPaint;
     }
 
     private static native long nativeCreate(long nativeMatrix, long bitmapHandle,
-            int shaderTileModeX, int shaderTileModeY);
+            int shaderTileModeX, int shaderTileModeY, boolean filter);
 }
+
diff --git a/graphics/java/android/graphics/BlurShader.java b/graphics/java/android/graphics/BlurShader.java
index 3bc8119..2e4bd7d 100644
--- a/graphics/java/android/graphics/BlurShader.java
+++ b/graphics/java/android/graphics/BlurShader.java
@@ -69,16 +69,18 @@
 
     /** @hide **/
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
-        mNativeInputShader = mInputShader != null ? mInputShader.getNativeInstance() : 0;
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+        mNativeInputShader = mInputShader != null
+                ? mInputShader.getNativeInstance(filterFromPaint) : 0;
         return nativeCreate(nativeMatrix, mRadiusX, mRadiusY, mNativeInputShader,
                 mEdgeTreatment.nativeInt);
     }
 
     /** @hide **/
     @Override
-    protected boolean shouldDiscardNativeInstance() {
-        long currentNativeInstance = mInputShader != null ? mInputShader.getNativeInstance() : 0;
+    protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+        long currentNativeInstance = mInputShader != null
+                ? mInputShader.getNativeInstance(filterFromPaint) : 0;
         return mNativeInputShader != currentNativeInstance;
     }
 
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index b840f3f..977aeaa 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -86,18 +86,18 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
-        mNativeInstanceShaderA = mShaderA.getNativeInstance();
-        mNativeInstanceShaderB = mShaderB.getNativeInstance();
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+        mNativeInstanceShaderA = mShaderA.getNativeInstance(filterFromPaint);
+        mNativeInstanceShaderB = mShaderB.getNativeInstance(filterFromPaint);
         return nativeCreate(nativeMatrix,
                 mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
     }
 
     /** @hide */
     @Override
-    protected boolean shouldDiscardNativeInstance() {
-        return mShaderA.getNativeInstance() != mNativeInstanceShaderA
-                || mShaderB.getNativeInstance() != mNativeInstanceShaderB;
+    protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+        return mShaderA.getNativeInstance(filterFromPaint) != mNativeInstanceShaderA
+                || mShaderB.getNativeInstance(filterFromPaint) != mNativeInstanceShaderB;
     }
 
     private static native long nativeCreate(long nativeMatrix,
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 4eedbf5..56d912b 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -154,7 +154,7 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return nativeCreate(nativeMatrix, mX0, mY0, mX1, mY1,
                 mColorLongs, mPositions, mTileMode.nativeInt,
                 colorSpace().getNativeInstance());
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 4b6e4d1..f1f9a5f 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -698,7 +698,8 @@
      */
     @UnsupportedAppUsage
     public synchronized long getNativeInstance() {
-        long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
+        boolean filter = isFilterBitmap();
+        long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance(filter);
         if (newNativeShader != mNativeShader) {
             mNativeShader = newNativeShader;
             nSetShader(mNativePaint, mNativeShader);
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index dd1be15..199365e 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -207,7 +207,7 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return nativeCreate(nativeMatrix, mFocalX, mFocalY, mFocalRadius, mX, mY, mRadius,
                 mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance());
     }
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 63089e2..fb0983a 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -105,10 +105,10 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         long[] nativeShaders = mInputShaders.length > 0 ? new long[mInputShaders.length] : null;
         for (int i = 0; i < mInputShaders.length; i++) {
-            nativeShaders[i] = mInputShaders[i].getNativeInstance();
+            nativeShaders[i] = mInputShaders[i].getNativeInstance(filterFromPaint);
         }
 
         return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 7651d01..4d6bead 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -148,7 +148,7 @@
     /**
      *  @hide Only to be used by subclasses in the graphics package.
      */
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return 0;
     }
 
@@ -173,7 +173,7 @@
      * constructed native instance is still valid.
      *  @hide Only to be used by subclasses in the graphics package.
      */
-    protected boolean shouldDiscardNativeInstance() {
+    protected boolean shouldDiscardNativeInstance(boolean filterBitmap) {
         return false;
     }
 
@@ -182,14 +182,14 @@
      * @hide so it can be called by android.graphics.drawable but must not be called from outside
      * the module.
      */
-    public synchronized final long getNativeInstance() {
-        if (shouldDiscardNativeInstance()) {
+    public final synchronized long getNativeInstance(boolean filterFromPaint) {
+        if (shouldDiscardNativeInstance(filterFromPaint)) {
             discardNativeInstanceLocked();
         }
 
         if (mNativeInstance == 0) {
             mNativeInstance = createNativeInstance(mLocalMatrix == null
-                    ? 0 : mLocalMatrix.ni());
+                    ? 0 : mLocalMatrix.ni(), filterFromPaint);
             if (mNativeInstance != 0) {
                 mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
                         this, mNativeInstance);
@@ -199,6 +199,15 @@
     }
 
     /**
+     * @hide so it can be called by android.graphics.drawable but must not be called from outside
+     * the module.
+     */
+    public final long getNativeInstance() {
+        // If the caller has no paint flag for filtering bitmaps, we just pass false
+        return getNativeInstance(false);
+    }
+
+    /**
      * @hide Only to be called by subclasses in the android.graphics package.
      */
     protected static @ColorLong long[] convertColors(@NonNull @ColorInt int[] colors) {
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 2280780..3a29395 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -133,7 +133,7 @@
 
     /** @hide */
     @Override
-    protected long createNativeInstance(long nativeMatrix) {
+    protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
         return nativeCreate(nativeMatrix, mCx, mCy, mColorLongs, mPositions,
                 colorSpace().getNativeInstance());
     }
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 9a4ed81..acb74f4 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -669,7 +669,10 @@
     if (paint) {
         pnt = *paint;
     }
-    pnt.setShader(bitmap.makeImage()->makeShader());
+    SkSamplingOptions sampling(pnt.isFilterBitmap() ? SkFilterMode::kLinear
+                                                    : SkFilterMode::kNearest,
+                               SkMipmapMode::kNone);
+    pnt.setShader(bitmap.makeImage()->makeShader(sampling));
     auto v = builder.detach();
     apply_looper(&pnt, [&](const SkPaint& p) {
         mCanvas->drawVertices(v, SkBlendMode::kModulate, p);
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index e75e9e7..05bae5c 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -137,6 +137,9 @@
     bool isDevKern() const { return mDevKern; }
     void setDevKern(bool d) { mDevKern = d; }
 
+    // Deprecated -- bitmapshaders will be taking this flag explicitly
+    bool isFilterBitmap() const { return this->getFilterQuality() != kNone_SkFilterQuality; }
+
     // The Java flags (Paint.java) no longer fit into the native apis directly.
     // These methods handle converting to and from them and the native representations
     // in android::Paint.
@@ -149,7 +152,7 @@
     // The only respected flags are : [ antialias, dither, filterBitmap ]
     static uint32_t GetSkPaintJavaFlags(const SkPaint&);
     static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags);
- 
+
 private:
     SkFont mFont;
     sk_sp<SkDrawLooper> mLooper;
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 45795ff..aaec60b 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -61,7 +61,7 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
-        jint tileModeX, jint tileModeY) {
+        jint tileModeX, jint tileModeY, bool filter) {
     const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
     sk_sp<SkImage> image;
     if (bitmapHandle) {
@@ -74,8 +74,10 @@
         SkBitmap bitmap;
         image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
     }
+    SkSamplingOptions sampling(filter ? SkFilterMode::kLinear : SkFilterMode::kNearest,
+                               SkMipmapMode::kNone);
     sk_sp<SkShader> shader = image->makeShader(
-            (SkTileMode)tileModeX, (SkTileMode)tileModeY);
+            (SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
     ThrowIAE_IfNull(env, shader.get());
 
     if (matrix) {
@@ -291,7 +293,7 @@
 };
 
 static const JNINativeMethod gBitmapShaderMethods[] = {
-    { "nativeCreate",      "(JJII)J",  (void*)BitmapShader_constructor },
+    { "nativeCreate",      "(JJIIZ)J",  (void*)BitmapShader_constructor },
 };
 
 static const JNINativeMethod gLinearGradientMethods[] = {
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index c4067af..03aeb55 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -44,15 +44,16 @@
                     skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
                 });
 
+        SkSamplingOptions sampling;
         Paint paint;
         sk_sp<SkImage> image = hwuiBitmap->makeImage();
         sk_sp<SkShader> repeatShader =
-                image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
+                image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, sampling);
         paint.setShader(std::move(repeatShader));
         canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
 
         sk_sp<SkShader> mirrorShader =
-                image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror);
+                image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror, sampling);
         paint.setShader(std::move(mirrorShader));
         canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
     }
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 5886ea3..564354f 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -74,6 +74,6 @@
 
     sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
         sk_sp<SkImage> image = bitmap.makeImage();
-        return image->makeShader();
+        return image->makeShader(SkSamplingOptions());
     }
 };