diff options
| author | 2022-01-11 17:58:29 +0000 | |
|---|---|---|
| committer | 2022-01-14 16:23:59 +0000 | |
| commit | 4d3df820d82598fa4dbdf2642cb0ca052650aa92 (patch) | |
| tree | 12e3fe33cdc039c6b4e43eeb182a8fa83d1bdeb0 /graphics/java | |
| parent | 265aab13299f2a630c0daeea4fed3a217f278f0d (diff) | |
Add filtering and directSampling features for BitmapShader
This adds filterMode directly to BitmapShader's public API
which allows users to override the global flag on the paint
or for BitmapShaders used in a RuntimeShader this provides
some explicit control over how the hardware will sample.
Addtionally BitmapShader adds an internal directSampling API
that is exposed only for RuntimeShader via the setInputBuffer
API. Previously, if you want to sample the unaltered contents
of a bitmap you must ensure that the bitmaps contents have the
same format (premul, colorspace, etc) of the destination. This
API enables you to do so without knowledge of the destination
format. This is necessary for use cases where the bitmap content
is data like a normal map or lighting values.
Bug: 189102731
Bug: 201546136
Test: atest CtsGraphicsTestCases:BitmapShaderTest
Test: atest CtsUiRenderingTestCases:RuntimeShaderTests
Change-Id: I8e9eaa8fae1d3ff45ab8c98b3878bb9da24dac47
Diffstat (limited to 'graphics/java')
| -rw-r--r-- | graphics/java/android/graphics/BitmapShader.java | 98 | ||||
| -rw-r--r-- | graphics/java/android/graphics/RuntimeShader.java | 28 |
2 files changed, 119 insertions, 7 deletions
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index e6ff187bd99d..43cb5ee8b5c0 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -16,8 +16,12 @@ package android.graphics; +import android.annotation.IntDef; import android.annotation.NonNull; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Shader used to draw a bitmap as a texture. The bitmap can be repeated or * mirrored by setting the tiling mode. @@ -31,6 +35,47 @@ public class BitmapShader extends Shader { private int mTileX; private int mTileY; + /** @hide */ + @IntDef(prefix = {"FILTER_MODE"}, value = { + FILTER_MODE_DEFAULT, + FILTER_MODE_NEAREST, + FILTER_MODE_LINEAR + }) + @Retention(RetentionPolicy.SOURCE) + public @interface FilterMode {} + + /** + * This FilterMode value will respect the value of the Paint#isFilterBitmap flag while the + * shader is attached to the Paint. + * + * <p>The exception to this rule is when a Shader is attached as input to a RuntimeShader. In + * that case this mode will default to FILTER_MODE_NEAREST.</p> + * + * @see #setFilterMode(int) + */ + public static final int FILTER_MODE_DEFAULT = 0; + /** + * This FilterMode value will cause the shader to sample from the nearest pixel to the requested + * sample point. + * + * <p>This value will override the effect of Paint#isFilterBitmap.</p> + * + * @see #setFilterMode(int) + */ + public static final int FILTER_MODE_NEAREST = 1; + /** + * This FilterMode value will cause the shader to interpolate the output of the shader from a + * 2x2 grid of pixels nearest to the sample point (i.e. bilinear interpolation). + * + * <p>This value will override the effect of Paint#isFilterBitmap.</p> + * + * @see #setFilterMode(int) + */ + public static final int FILTER_MODE_LINEAR = 2; + + @FilterMode + private int mFilterMode; + /* * 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 @@ -49,6 +94,15 @@ public class BitmapShader extends Shader { private boolean mFilterFromPaint; /** + * Stores whether or not the contents of this shader's bitmap will be sampled + * without modification or if the bitmap's properties, like colorspace and + * premultiplied alpha, will be respected when sampling from the bitmap's buffer. + */ + private boolean mIsDirectSampled; + + private boolean mRequestDirectSampling; + + /** * Call this to create a new shader that will draw with a bitmap. * * @param bitmap The bitmap to use inside the shader @@ -66,24 +120,60 @@ public class BitmapShader extends Shader { mBitmap = bitmap; mTileX = tileX; mTileY = tileY; + mFilterMode = FILTER_MODE_DEFAULT; mFilterFromPaint = false; + mIsDirectSampled = false; + mRequestDirectSampling = false; + } + + /** + * Returns the filter mode used when sampling from this shader + */ + @FilterMode + public int getFilterMode() { + return mFilterMode; + } + + /** + * Set the filter mode to be used when sampling from this shader + */ + public void setFilterMode(@FilterMode int mode) { + if (mode != mFilterMode) { + mFilterMode = mode; + discardNativeInstance(); + } + } + + /** @hide */ + /* package */ synchronized long getNativeInstanceWithDirectSampling() { + mRequestDirectSampling = true; + return getNativeInstance(); } /** @hide */ @Override protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) { - mFilterFromPaint = filterFromPaint; + boolean enableLinearFilter = mFilterMode == FILTER_MODE_LINEAR; + if (mFilterMode == FILTER_MODE_DEFAULT) { + mFilterFromPaint = filterFromPaint; + enableLinearFilter = mFilterFromPaint; + } + + mIsDirectSampled = mRequestDirectSampling; + mRequestDirectSampling = false; + return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY, - mFilterFromPaint); + enableLinearFilter, mIsDirectSampled); } /** @hide */ @Override protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) { - return mFilterFromPaint != filterFromPaint; + return mIsDirectSampled != mRequestDirectSampling + || (mFilterMode == FILTER_MODE_DEFAULT && mFilterFromPaint != filterFromPaint); } private static native long nativeCreate(long nativeMatrix, long bitmapHandle, - int shaderTileModeX, int shaderTileModeY, boolean filter); + int shaderTileModeX, int shaderTileModeY, boolean filter, boolean isDirectSampled); } diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java index ef57f4a76007..57046f5de61d 100644 --- a/graphics/java/android/graphics/RuntimeShader.java +++ b/graphics/java/android/graphics/RuntimeShader.java @@ -279,11 +279,11 @@ public class RuntimeShader extends Shader { } /** - * Sets the uniform shader that is declares as input to this shader. If the shader does not + * Assigns the uniform shader to the provided shader parameter. If the shader program does not * have a uniform shader with that name then an IllegalArgumentException is thrown. * - * @param shaderName name matching the uniform declared in the SKSL shader - * @param shader shader passed into the SKSL shader for sampling + * @param shaderName name matching the uniform declared in the AGSL shader program + * @param shader shader passed into the AGSL shader program for sampling */ public void setInputShader(@NonNull String shaderName, @NonNull Shader shader) { if (shaderName == null) { @@ -297,6 +297,28 @@ public class RuntimeShader extends Shader { discardNativeInstance(); } + /** + * Assigns the uniform shader to the provided shader parameter. If the shader program does not + * have a uniform shader with that name then an IllegalArgumentException is thrown. + * + * Unlike setInputShader this method returns samples directly from the bitmap's buffer. This + * means that there will be no transformation of the sampled pixels, such as colorspace + * conversion or alpha premultiplication. + */ + public void setInputBuffer(@NonNull String shaderName, @NonNull BitmapShader shader) { + if (shaderName == null) { + throw new NullPointerException("The shaderName parameter must not be null"); + } + if (shader == null) { + throw new NullPointerException("The shader parameter must not be null"); + } + + nativeUpdateShader(mNativeInstanceRuntimeShaderBuilder, shaderName, + shader.getNativeInstanceWithDirectSampling()); + discardNativeInstance(); + } + + /** @hide */ @Override protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) { |