summaryrefslogtreecommitdiff
path: root/graphics/java
diff options
context:
space:
mode:
author Derek Sollenberger <djsollen@google.com> 2022-01-11 17:58:29 +0000
committer Derek Sollenberger <djsollen@google.com> 2022-01-14 16:23:59 +0000
commit4d3df820d82598fa4dbdf2642cb0ca052650aa92 (patch)
tree12e3fe33cdc039c6b4e43eeb182a8fa83d1bdeb0 /graphics/java
parent265aab13299f2a630c0daeea4fed3a217f278f0d (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.java98
-rw-r--r--graphics/java/android/graphics/RuntimeShader.java28
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) {