Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a49934e authored by Nader Jawad's avatar Nader Jawad
Browse files

Added support for BitmapShader anisotropic filtering

Relnote: "Created new BitmapShader constructor that
enables support for anisotropic filtering."

Bug: 267687306
Test: Added tests to BitmapShaderTest
Change-Id: Ie6e5551f3ae6140dc3afb2d65967b5a6bc08523c
parent 288f1363
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -14908,7 +14908,9 @@ package android.graphics {
  public class BitmapShader extends android.graphics.Shader {
  public class BitmapShader extends android.graphics.Shader {
    ctor public BitmapShader(@NonNull android.graphics.Bitmap, @NonNull android.graphics.Shader.TileMode, @NonNull android.graphics.Shader.TileMode);
    ctor public BitmapShader(@NonNull android.graphics.Bitmap, @NonNull android.graphics.Shader.TileMode, @NonNull android.graphics.Shader.TileMode);
    method public int getFilterMode();
    method public int getFilterMode();
    method public int getMaxAnisotropy();
    method public void setFilterMode(int);
    method public void setFilterMode(int);
    method public void setMaxAnisotropy(@IntRange(from=1) int);
    field public static final int FILTER_MODE_DEFAULT = 0; // 0x0
    field public static final int FILTER_MODE_DEFAULT = 0; // 0x0
    field public static final int FILTER_MODE_LINEAR = 2; // 0x2
    field public static final int FILTER_MODE_LINEAR = 2; // 0x2
    field public static final int FILTER_MODE_NEAREST = 1; // 0x1
    field public static final int FILTER_MODE_NEAREST = 1; // 0x1
+46 −3
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.graphics;
package android.graphics;


import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.NonNull;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
@@ -102,6 +103,8 @@ public class BitmapShader extends Shader {


    private boolean mRequestDirectSampling;
    private boolean mRequestDirectSampling;


    private int mMaxAniso = 0;

    /**
    /**
     * Call this to create a new shader that will draw with a bitmap.
     * Call this to create a new shader that will draw with a bitmap.
     *
     *
@@ -135,15 +138,47 @@ public class BitmapShader extends Shader {
    }
    }


    /**
    /**
     * Set the filter mode to be used when sampling from this shader
     * Set the filter mode to be used when sampling from this shader. If this is configured
     * then the anisotropic filtering value specified in any previous call to
     * {@link #setMaxAnisotropy(int)} is ignored.
     */
     */
    public void setFilterMode(@FilterMode int mode) {
    public void setFilterMode(@FilterMode int mode) {
        if (mode != mFilterMode) {
        if (mode != mFilterMode) {
            mFilterMode = mode;
            mFilterMode = mode;
            mMaxAniso = 0;
            discardNativeInstance();
        }
    }

    /**
     * Enables and configures the max anisotropy sampling value. If this value is configured,
     * {@link #setFilterMode(int)} is ignored.
     *
     * Anisotropic filtering can enhance visual quality by removing aliasing effects of images
     * that are at oblique viewing angles. This value is typically consumed as a power of 2 and
     * anisotropic values of the next power of 2 typically provide twice the quality improvement
     * as the previous value. For example, a sampling value of 4 would provide twice the improvement
     * of a sampling value of 2. It is important to note that higher sampling values reach
     * diminishing returns as the improvements between 8 and 16 can be slight.
     *
     * @param maxAnisotropy The Anisotropy value to use for filtering. Must be greater than 0.
     */
    public void setMaxAnisotropy(@IntRange(from = 1) int maxAnisotropy) {
        if (mMaxAniso != maxAnisotropy && maxAnisotropy > 0) {
            mMaxAniso = maxAnisotropy;
            mFilterMode = FILTER_MODE_DEFAULT;
            discardNativeInstance();
            discardNativeInstance();
        }
        }
    }
    }


    /**
     * Returns the current max anisotropic filtering value configured by
     * {@link #setFilterMode(int)}. If {@link #setFilterMode(int)} is invoked this returns zero.
     */
    public int getMaxAnisotropy() {
        return mMaxAniso;
    }

    /** @hide */
    /** @hide */
    /* package */ synchronized long getNativeInstanceWithDirectSampling() {
    /* package */ synchronized long getNativeInstanceWithDirectSampling() {
        mRequestDirectSampling = true;
        mRequestDirectSampling = true;
@@ -162,9 +197,14 @@ public class BitmapShader extends Shader {
        mIsDirectSampled = mRequestDirectSampling;
        mIsDirectSampled = mRequestDirectSampling;
        mRequestDirectSampling = false;
        mRequestDirectSampling = false;


        if (mMaxAniso > 0) {
            return nativeCreateWithMaxAniso(nativeMatrix, mBitmap.getNativeInstance(), mTileX,
                    mTileY, mMaxAniso, mIsDirectSampled);
        } else {
            return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY,
            return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY,
                    enableLinearFilter, mIsDirectSampled);
                    enableLinearFilter, mIsDirectSampled);
        }
        }
    }


    /** @hide */
    /** @hide */
    @Override
    @Override
@@ -175,5 +215,8 @@ public class BitmapShader extends Shader {


    private static native long nativeCreate(long nativeMatrix, long bitmapHandle,
    private static native long nativeCreate(long nativeMatrix, long bitmapHandle,
            int shaderTileModeX, int shaderTileModeY, boolean filter, boolean isDirectSampled);
            int shaderTileModeX, int shaderTileModeY, boolean filter, boolean isDirectSampled);

    private static native long nativeCreateWithMaxAniso(long nativeMatrix, long bitmapHandle,
            int shaderTileModeX, int shaderTileModeY, int maxAniso, boolean isDirectSampled);
}
}
+26 −7
Original line number Original line Diff line number Diff line
@@ -71,11 +71,9 @@ static jlong Shader_getNativeFinalizer(JNIEnv*, jobject) {
    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Shader_safeUnref));
    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Shader_safeUnref));
}
}


///////////////////////////////////////////////////////////////////////////////////////////////
static jlong createBitmapShaderHelper(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,

                                      jint tileModeX, jint tileModeY, bool isDirectSampled,
static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
                                      const SkSamplingOptions& sampling) {
                                      jint tileModeX, jint tileModeY, bool filter,
                                      bool isDirectSampled) {
    const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
    const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
    sk_sp<SkImage> image;
    sk_sp<SkImage> image;
    if (bitmapHandle) {
    if (bitmapHandle) {
@@ -88,8 +86,7 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j
        SkBitmap bitmap;
        SkBitmap bitmap;
        image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
        image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
    }
    }
    SkSamplingOptions sampling(filter ? SkFilterMode::kLinear : SkFilterMode::kNearest,

                               SkMipmapMode::kNone);
    sk_sp<SkShader> shader;
    sk_sp<SkShader> shader;
    if (isDirectSampled) {
    if (isDirectSampled) {
        shader = image->makeRawShader((SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
        shader = image->makeRawShader((SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
@@ -107,6 +104,26 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j


///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////


static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
                                      jint tileModeX, jint tileModeY, bool filter,
                                      bool isDirectSampled) {
    SkSamplingOptions sampling(filter ? SkFilterMode::kLinear : SkFilterMode::kNearest,
                               SkMipmapMode::kNone);
    return createBitmapShaderHelper(env, o, matrixPtr, bitmapHandle, tileModeX, tileModeY,
                                    isDirectSampled, sampling);
}

static jlong BitmapShader_constructorWithMaxAniso(JNIEnv* env, jobject o, jlong matrixPtr,
                                                  jlong bitmapHandle, jint tileModeX,
                                                  jint tileModeY, jint maxAniso,
                                                  bool isDirectSampled) {
    auto sampling = SkSamplingOptions::Aniso(static_cast<int>(maxAniso));
    return createBitmapShaderHelper(env, o, matrixPtr, bitmapHandle, tileModeX, tileModeY,
                                    isDirectSampled, sampling);
}

///////////////////////////////////////////////////////////////////////////////////////////////

static std::vector<SkColor4f> convertColorLongs(JNIEnv* env, jlongArray colorArray) {
static std::vector<SkColor4f> convertColorLongs(JNIEnv* env, jlongArray colorArray) {
    const size_t count = env->GetArrayLength(colorArray);
    const size_t count = env->GetArrayLength(colorArray);
    const jlong* colorValues = env->GetLongArrayElements(colorArray, nullptr);
    const jlong* colorValues = env->GetLongArrayElements(colorArray, nullptr);
@@ -408,6 +425,8 @@ static const JNINativeMethod gShaderMethods[] = {


static const JNINativeMethod gBitmapShaderMethods[] = {
static const JNINativeMethod gBitmapShaderMethods[] = {
        {"nativeCreate", "(JJIIZZ)J", (void*)BitmapShader_constructor},
        {"nativeCreate", "(JJIIZZ)J", (void*)BitmapShader_constructor},
        {"nativeCreateWithMaxAniso", "(JJIIIZ)J", (void*)BitmapShader_constructorWithMaxAniso},

};
};


static const JNINativeMethod gLinearGradientMethods[] = {
static const JNINativeMethod gLinearGradientMethods[] = {