summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2021-01-15 20:16:55 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-01-15 20:16:55 +0000
commit106f1b33b43e375e0598dadae52a34a164928f39 (patch)
treecf8755748c8327c8488624264b85ed05fb0c7f0c
parent601ec92324b89d6c122ba9cec935e8d9cb292132 (diff)
parent783e5aeb2e0926419b8bf5ff3550287400552b06 (diff)
Merge "Refactor RuntimeShader to support easier assignment of uniforms."
-rw-r--r--graphics/java/android/graphics/RecordingCanvas.java2
-rw-r--r--graphics/java/android/graphics/RuntimeShader.java103
-rw-r--r--libs/hwui/SkiaCanvas.cpp4
-rw-r--r--libs/hwui/SkiaCanvas.h2
-rw-r--r--libs/hwui/canvas/CanvasOps.h2
-rw-r--r--libs/hwui/hwui/Canvas.h4
-rw-r--r--libs/hwui/jni/Shader.cpp99
-rw-r--r--libs/hwui/jni/android_graphics_DisplayListCanvas.cpp7
-rw-r--r--libs/hwui/pipeline/skia/AnimatedDrawables.h6
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp4
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.h2
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java28
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java178
14 files changed, 329 insertions, 121 deletions
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index 2d626b9a622f..8dd7f317c842 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -220,7 +220,7 @@ public final class RecordingCanvas extends BaseRecordingCanvas {
CanvasProperty<Float> progress, RuntimeShader shader) {
nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
radius.getNativeContainer(), paint.getNativeContainer(),
- progress.getNativeContainer(), shader.getNativeShaderFactory());
+ progress.getNativeContainer(), shader.getNativeShaderBuilder());
}
/**
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 7f2e503ac8fd..1ace32277f0a 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -17,7 +17,6 @@
package android.graphics;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import libcore.util.NativeAllocationRegistry;
@@ -33,14 +32,12 @@ public class RuntimeShader extends Shader {
RuntimeShader.class.getClassLoader(), nativeGetFinalizer());
}
- private byte[] mUniforms;
- private Shader[] mInputShaders;
private boolean mIsOpaque;
/**
- * Current native shader factory instance.
+ * Current native shader builder instance.
*/
- private long mNativeInstanceRuntimeShaderFactory;
+ private long mNativeInstanceRuntimeShaderBuilder;
/**
* Creates a new RuntimeShader.
@@ -50,80 +47,86 @@ public class RuntimeShader extends Shader {
* on number of uniforms declared by sksl.
* @param isOpaque True if all pixels have alpha 1.0f.
*/
- public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque) {
- this(sksl, uniforms, null, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
+ public RuntimeShader(@NonNull String sksl, boolean isOpaque) {
+ super(ColorSpace.get(ColorSpace.Named.SRGB));
+ mIsOpaque = isOpaque;
+ mNativeInstanceRuntimeShaderBuilder = nativeCreateBuilder(sksl);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeInstanceRuntimeShaderBuilder);
}
/**
- * Creates a new RuntimeShader.
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than float then an
+ * IllegalArgumentException is thrown.
*
- * @param sksl The text of SKSL program to run on the GPU.
- * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
- * on number of uniforms declared by sksl.
- * @param shaderInputs Array of shaders passed to the SKSL shader. Array size depends
- * on the number of input shaders declared in the sksl
- * @param isOpaque True if all pixels have alpha 1.0f.
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param value
*/
- public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
- @Nullable Shader[] shaderInputs, boolean isOpaque) {
- this(sksl, uniforms, shaderInputs, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
+ public void setUniform(@NonNull String uniformName, float value) {
+ setUniform(uniformName, new float[] {value});
}
- private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
- @Nullable Shader[] shaderInputs, boolean isOpaque,
- ColorSpace colorSpace) {
- super(colorSpace);
- mUniforms = uniforms;
- mInputShaders = shaderInputs;
- mIsOpaque = isOpaque;
- mNativeInstanceRuntimeShaderFactory = nativeCreateShaderFactory(sksl);
- NoImagePreloadHolder.sRegistry.registerNativeAllocation(this,
- mNativeInstanceRuntimeShaderFactory);
+ /**
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than float2/vec2 then an
+ * IllegalArgumentException is thrown.
+ *
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param value1
+ * @param value2
+ */
+ public void setUniform(@NonNull String uniformName, float value1, float value2) {
+ setUniform(uniformName, new float[] {value1, value2});
}
/**
- * Sets new value for shader parameters.
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than a vecN/floatN where N is
+ * the size of the values array then an IllegalArgumentException is thrown.
*
- * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
- * on number of uniforms declared by mSksl.
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param values
*/
- public void updateUniforms(@Nullable byte[] uniforms) {
- mUniforms = uniforms;
+ public void setUniform(@NonNull String uniformName, float[] values) {
+ nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, values);
discardNativeInstance();
}
/**
- * Sets new values for the shaders that serve as inputs to this shader.
+ * Sets the uniform shader that is declares as input to this shader. If the shader does not
+ * have a uniform shader with that name then an IllegalArgumentException is thrown.
*
- * @param shaderInputs Array of Shaders passed into the SKSL shader. Array size depends
- * on number of input shaders declared by sksl.
+ * @param shaderName name matching the uniform declared in the SKSL shader
+ * @param shader shader passed into the SKSL shader for sampling
*/
- public void updateInputShaders(@Nullable Shader[] shaderInputs) {
- mInputShaders = shaderInputs;
+ public void setInputShader(@NonNull String shaderName, @NonNull Shader shader) {
+ nativeUpdateShader(
+ mNativeInstanceRuntimeShaderBuilder, shaderName, shader.getNativeInstance());
discardNativeInstance();
}
/** @hide */
@Override
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(filterFromPaint);
- }
-
- return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
- nativeShaders, colorSpace().getNativeInstance(), mIsOpaque);
+ return nativeCreateShader(mNativeInstanceRuntimeShaderBuilder, nativeMatrix, mIsOpaque);
}
- public long getNativeShaderFactory() {
- return mNativeInstanceRuntimeShaderFactory;
+ public long getNativeShaderBuilder() {
+ return mNativeInstanceRuntimeShaderBuilder;
}
- private static native long nativeCreate(long shaderFactory, long matrix, byte[] inputs,
- long[] shaderInputs, long colorSpaceHandle, boolean isOpaque);
-
- private static native long nativeCreateShaderFactory(String sksl);
+ public boolean isOpaque() {
+ return mIsOpaque;
+ }
private static native long nativeGetFinalizer();
+ private static native long nativeCreateBuilder(String sksl);
+ private static native long nativeCreateShader(
+ long shaderBuilder, long matrix, boolean isOpaque);
+ private static native void nativeUpdateUniforms(
+ long shaderBuilder, String uniformName, float[] uniforms);
+ private static native void nativeUpdateShader(
+ long shaderBuilder, String shaderName, long shader);
}
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 815ffdeade45..1ebc48900349 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -819,10 +819,10 @@ void SkiaCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x,
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) {
+ const SkRuntimeShaderBuilder& effectBuilder) {
sk_sp<uirenderer::skiapipeline::AnimatedRipple> drawable(
new uirenderer::skiapipeline::AnimatedRipple(x, y, radius, paint, progress,
- runtimeEffect));
+ effectBuilder));
mCanvas->drawDrawable(drawable.get());
}
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index e6fc9da0a9d3..82b7de4a616b 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -152,7 +152,7 @@ public:
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) override;
+ const SkRuntimeShaderBuilder& effectBuilder) override;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index ea9fea974d06..fa0c45b5221c 100644
--- a/libs/hwui/canvas/CanvasOps.h
+++ b/libs/hwui/canvas/CanvasOps.h
@@ -161,7 +161,7 @@ struct CanvasOp<CanvasOpType::DrawRippleProperty> {
}
SkRuntimeShaderBuilder::BuilderUniform radiusU =
- runtimeEffectBuilder.uniform("in_maxRadius");
+ runtimeEffectBuilder.uniform("in_radius");
if (radiusU.fVar != nullptr) {
radiusU = radius->value;
}
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 9304b7af9cd9..184b11e735bb 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -31,7 +31,7 @@
class SkAnimatedImage;
class SkCanvasState;
-class SkRuntimeEffect;
+class SkRuntimeShaderBuilder;
class SkVertices;
namespace minikin {
@@ -139,7 +139,7 @@ public:
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) = 0;
+ const SkRuntimeShaderBuilder& effectBuilder) = 0;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0;
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index aaec60baaa4a..ad3fd552204e 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -1,3 +1,6 @@
+#undef LOG_TAG
+#define LOG_TAG "ShaderJNI"
+
#include "GraphicsJNI.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
@@ -232,53 +235,72 @@ static jlong ComposeShader_create(JNIEnv* env, jobject o, jlong matrixPtr,
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr,
- jbyteArray inputs, jlongArray inputShaders, jlong colorSpaceHandle, jboolean isOpaque) {
- SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory);
- AutoJavaByteArray arInputs(env, inputs);
-
- std::vector<sk_sp<SkShader>> shaderVector;
- if (inputShaders) {
- jsize shaderCount = env->GetArrayLength(inputShaders);
- shaderVector.resize(shaderCount);
- jlong* arrayPtr = env->GetLongArrayElements(inputShaders, NULL);
- for (int i = 0; i < shaderCount; i++) {
- shaderVector[i] = sk_ref_sp(reinterpret_cast<SkShader*>(arrayPtr[i]));
- }
- env->ReleaseLongArrayElements(inputShaders, arrayPtr, 0);
- }
-
- sk_sp<SkData> fData;
- fData = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length());
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- sk_sp<SkShader> shader = effect->makeShader(fData, shaderVector.data(), shaderVector.size(),
- matrix, isOpaque == JNI_TRUE);
- ThrowIAE_IfNull(env, shader);
-
- return reinterpret_cast<jlong>(shader.release());
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong RuntimeShader_createShaderFactory(JNIEnv* env, jobject, jstring sksl) {
+static jlong RuntimeShader_createShaderBuilder(JNIEnv* env, jobject, jstring sksl) {
ScopedUtfChars strSksl(env, sksl);
auto result = SkRuntimeEffect::Make(SkString(strSksl.c_str()));
sk_sp<SkRuntimeEffect> effect = std::get<0>(result);
- if (!effect) {
+ if (effect.get() == nullptr) {
const auto& err = std::get<1>(result);
doThrowIAE(env, err.c_str());
+ return 0;
}
- return reinterpret_cast<jlong>(effect.release());
+ return reinterpret_cast<jlong>(new SkRuntimeShaderBuilder(std::move(effect)));
}
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-static void Effect_safeUnref(SkRuntimeEffect* effect) {
- SkSafeUnref(effect);
+static void SkRuntimeShaderBuilder_delete(SkRuntimeShaderBuilder* builder) {
+ delete builder;
}
static jlong RuntimeShader_getNativeFinalizer(JNIEnv*, jobject) {
- return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Effect_safeUnref));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SkRuntimeShaderBuilder_delete));
+}
+
+static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderBuilder, jlong matrixPtr,
+ jboolean isOpaque) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+ sk_sp<SkShader> shader = builder->makeShader(matrix, isOpaque == JNI_TRUE);
+ ThrowIAE_IfNull(env, shader);
+ return reinterpret_cast<jlong>(shader.release());
+}
+
+static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", fmt, args);
+ va_end(args);
+}
+
+static void RuntimeShader_updateUniforms(JNIEnv* env, jobject, jlong shaderBuilder,
+ jstring jUniformName, jfloatArray jvalues) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ ScopedUtfChars name(env, jUniformName);
+ AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess);
+
+ SkRuntimeShaderBuilder::BuilderUniform uniform = builder->uniform(name.c_str());
+ if (uniform.fVar == nullptr) {
+ ThrowIAEFmt(env, "unable to find uniform named %s", name.c_str());
+ } else if (!uniform.set<float>(autoValues.ptr(), autoValues.length())) {
+ ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]",
+ uniform.fVar->sizeInBytes(), sizeof(float) * autoValues.length());
+ }
+}
+
+static void RuntimeShader_updateShader(JNIEnv* env, jobject, jlong shaderBuilder,
+ jstring jUniformName, jlong shaderHandle) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ ScopedUtfChars name(env, jUniformName);
+ SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
+
+ SkRuntimeShaderBuilder::BuilderChild child = builder->child(name.c_str());
+ if (child.fIndex == -1) {
+ ThrowIAEFmt(env, "unable to find shader named %s", name.c_str());
+ return;
+ }
+
+ builder->child(name.c_str()) = sk_ref_sp(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -313,10 +335,11 @@ static const JNINativeMethod gComposeShaderMethods[] = {
};
static const JNINativeMethod gRuntimeShaderMethods[] = {
- { "nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer },
- { "nativeCreate", "(JJ[B[JJZ)J", (void*)RuntimeShader_create },
- { "nativeCreateShaderFactory", "(Ljava/lang/String;)J",
- (void*)RuntimeShader_createShaderFactory },
+ {"nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer},
+ {"nativeCreateShader", "(JJZ)J", (void*)RuntimeShader_create},
+ {"nativeCreateBuilder", "(Ljava/lang/String;)J", (void*)RuntimeShader_createShaderBuilder},
+ {"nativeUpdateUniforms", "(JLjava/lang/String;[F)V", (void*)RuntimeShader_updateUniforms},
+ {"nativeUpdateShader", "(JLjava/lang/String;J)V", (void*)RuntimeShader_updateShader},
};
int register_android_graphics_Shader(JNIEnv* env)
diff --git a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
index a74e56183bfd..926e23349a05 100644
--- a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
+++ b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
@@ -144,7 +144,8 @@ static void android_view_DisplayListCanvas_drawCircleProps(CRITICAL_JNI_PARAMS_C
static void android_view_DisplayListCanvas_drawRippleProps(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr,
jlong xPropPtr, jlong yPropPtr,
jlong radiusPropPtr, jlong paintPropPtr,
- jlong progressPropPtr, jlong effectPtr) {
+ jlong progressPropPtr,
+ jlong builderPtr) {
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
@@ -152,8 +153,8 @@ static void android_view_DisplayListCanvas_drawRippleProps(CRITICAL_JNI_PARAMS_C
CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
CanvasPropertyPrimitive* progressProp =
reinterpret_cast<CanvasPropertyPrimitive*>(progressPropPtr);
- SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(effectPtr);
- canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, sk_ref_sp(effect));
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(builderPtr);
+ canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, *builder);
}
static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) {
diff --git a/libs/hwui/pipeline/skia/AnimatedDrawables.h b/libs/hwui/pipeline/skia/AnimatedDrawables.h
index 3142d927d4c4..78591450f10a 100644
--- a/libs/hwui/pipeline/skia/AnimatedDrawables.h
+++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h
@@ -61,13 +61,13 @@ public:
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect)
+ const SkRuntimeShaderBuilder& effectBuilder)
: mX(x)
, mY(y)
, mRadius(radius)
, mPaint(paint)
, mProgress(progress)
- , mRuntimeEffectBuilder(std::move(runtimeEffect)) {}
+ , mRuntimeEffectBuilder(effectBuilder) {}
protected:
virtual SkRect onGetBounds() override {
@@ -83,7 +83,7 @@ protected:
}
SkRuntimeShaderBuilder::BuilderUniform radiusU =
- mRuntimeEffectBuilder.uniform("in_maxRadius");
+ mRuntimeEffectBuilder.uniform("in_radius");
if (radiusU.fVar != nullptr) {
radiusU = mRadius->value;
}
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 5f35155c2b5a..9e91dff9e28e 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -90,9 +90,9 @@ void SkiaRecordingCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x,
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) {
+ const SkRuntimeShaderBuilder& effectBuilder) {
drawDrawable(mDisplayList->allocateDrawable<AnimatedRipple>(x, y, radius, paint, progress,
- runtimeEffect));
+ effectBuilder));
}
void SkiaRecordingCanvas::enableZ(bool enableZ) {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index ee308f0832a2..32c179191ec6 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -71,7 +71,7 @@ public:
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) override;
+ const SkRuntimeShaderBuilder& effectBuilder) override;
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 9a2def935f5d..1a940c75cfa4 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -1016,6 +1016,15 @@
</intent-filter>
</activity>
+ <activity android:name="RippleActivity"
+ android:label="Animation/Ripple Animation"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.android.test.hwui.TEST"/>
+ </intent-filter>
+ </activity>
+
<activity android:name="MultiProducerActivity"
android:label="Threads/Multiple Producers"
android:exported="true">
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index b53b78a8d5b2..8be3b7e35d42 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -35,9 +35,6 @@ import android.graphics.Shader;
import android.os.Bundle;
import android.view.View;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
@SuppressWarnings({"UnusedDeclaration"})
public class ColorFiltersMutateActivity extends Activity {
@Override
@@ -54,11 +51,13 @@ public class ColorFiltersMutateActivity extends Activity {
private final Paint mLightingPaint;
private final Paint mBlendPaint;
private final Paint mShaderPaint;
+ private final RuntimeShader mRuntimeShader;
private float mSaturation = 0.0f;
private int mLightAdd = 0;
private int mLightMul = 0;
private int mPorterDuffColor = 0;
+ private float mShaderParam1 = 0.0f;
static final String sSkSL =
"in shader bitmapShader;\n"
@@ -67,8 +66,6 @@ public class ColorFiltersMutateActivity extends Activity {
+ " return half4(sample(bitmapShader, xy).rgb, param1);\n"
+ "}\n";
- private byte[] mUniforms = new byte[4];
-
BitmapsView(Context c) {
super(c);
@@ -86,11 +83,13 @@ public class ColorFiltersMutateActivity extends Activity {
mBlendPaint = new Paint();
mBlendPaint.setColorFilter(new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_OVER));
+ mRuntimeShader = new RuntimeShader(sSkSL, false);
+ mRuntimeShader.setUniform("param1", mShaderParam1);
+ mRuntimeShader.setInputShader("bitmapShader", new BitmapShader(mBitmap1,
+ Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP));
mShaderPaint = new Paint();
- Shader[] inputShaders = { new BitmapShader(mBitmap1, Shader.TileMode.CLAMP,
- Shader.TileMode.CLAMP) };
- mShaderPaint.setShader(new RuntimeShader(sSkSL, mUniforms, inputShaders, true));
- setShaderParam1(0.0f);
+ mShaderPaint.setShader(mRuntimeShader);
ObjectAnimator sat = ObjectAnimator.ofFloat(this, "saturation", 1.0f);
sat.setDuration(1000);
@@ -177,20 +176,15 @@ public class ColorFiltersMutateActivity extends Activity {
}
public void setShaderParam1(float value) {
- RuntimeShader shader = (RuntimeShader) mShaderPaint.getShader();
- ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
- buffer.order(ByteOrder.LITTLE_ENDIAN);
- buffer.putFloat(value);
- shader.updateUniforms(mUniforms);
+ mShaderParam1 = value;
+ mRuntimeShader.setUniform("param1", mShaderParam1);
invalidate();
}
// If either valueFrom or valueTo is null, then a getter function will also be derived
// and called by the animator class.
public float getShaderParam1() {
- ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
- buffer.order(ByteOrder.LITTLE_ENDIAN);
- return buffer.getFloat();
+ return mShaderParam1;
}
@Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
new file mode 100644
index 000000000000..f6d9a7301949
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RuntimeShader;
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.RenderNodeAnimator;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+
+import java.util.ArrayList;
+
+public class RippleActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.addView(new RippleView(this),
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+ setContentView(layout);
+ }
+
+ static class RippleView extends View {
+ static final int DURATION = 1000;
+ static final int MAX_RADIUS = 250;
+
+ private boolean mToggle = false;
+ ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>();
+
+ CanvasProperty<Float> mX;
+ CanvasProperty<Float> mY;
+ CanvasProperty<Float> mRadius;
+ CanvasProperty<Float> mProgress;
+ CanvasProperty<Paint> mPaint;
+ RuntimeShader mRuntimeShader;
+
+ static final String sSkSL = ""
+ + "uniform float2 in_origin;"
+ + "uniform float in_progress;\n"
+ + "uniform float in_maxRadius;\n"
+ + "uniform shader in_paintColor;\n"
+ + "float dist2(float2 p0, float2 pf) { return sqrt((pf.x - p0.x) * (pf.x - p0.x) + "
+ + "(pf.y - p0.y) * (pf.y - p0.y)); }\n"
+ + "float mod2(float a, float b) { return a - (b * floor(a / b)); }\n"
+ + "float rand(float2 src) { return fract(sin(dot(src.xy, float2(12.9898, 78.233)))"
+ + " * 43758.5453123); }\n"
+ + "float4 main(float2 p)\n"
+ + "{\n"
+ + " float fraction = in_progress;\n"
+ + " float2 fragCoord = p;//sk_FragCoord.xy;\n"
+ + " float maxDist = in_maxRadius;\n"
+ + " float fragDist = dist2(in_origin, fragCoord.xy);\n"
+ + " float circleRadius = maxDist * fraction;\n"
+ + " float colorVal = (fragDist - circleRadius) / maxDist;\n"
+ + " float d = fragDist < circleRadius \n"
+ + " ? 1. - abs(colorVal * 2. * smoothstep(0., 1., fraction)) \n"
+ + " : 1. - abs(colorVal * 3.);\n"
+ + " d = smoothstep(0., 1., d);\n"
+ + " float divider = 2.;\n"
+ + " float x = floor(fragCoord.x / divider);\n"
+ + " float y = floor(fragCoord.y / divider);\n"
+ + " float density = .95;\n"
+ + " d = rand(float2(x, y)) > density ? d : d * .2;\n"
+ + " d = d * rand(float2(fraction, x * y));\n"
+ + " float alpha = 1. - pow(fraction, 3.);\n"
+ + " return float4(sample(in_paintColor).rgb, d * alpha);\n"
+ + "}";
+
+ RippleView(Context c) {
+ super(c);
+ setClickable(true);
+
+ mX = CanvasProperty.createFloat(200.0f);
+ mY = CanvasProperty.createFloat(200.0f);
+ mRadius = CanvasProperty.createFloat(150.0f);
+ mProgress = CanvasProperty.createFloat(0.0f);
+
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+ p.setColor(0xFFFF0000);
+ mPaint = CanvasProperty.createPaint(p);
+
+ mRuntimeShader = new RuntimeShader(sSkSL, false);
+ mRuntimeShader.setUniform("in_maxRadius", MAX_RADIUS);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (canvas.isHardwareAccelerated()) {
+ RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ recordingCanvas.drawRipple(mX, mY, mRadius, mPaint, mProgress, mRuntimeShader);
+ }
+ }
+
+ @Override
+ public boolean performClick() {
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).cancel();
+ }
+ mRunningAnimations.clear();
+
+ mToggle = !mToggle;
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mX, mToggle ? 400.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mY, mToggle ? 600.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mRadius, mToggle ? MAX_RADIUS : 150.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mProgress, mToggle ? 1.0f : 0.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA, 64.0f));
+
+ // Will be "chained" to run after the above
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA, 255.0f));
+
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ RenderNodeAnimator anim = mRunningAnimations.get(i);
+ anim.setDuration(DURATION);
+ anim.setTarget(this);
+ if (i == (mRunningAnimations.size() - 1)) {
+ // "chain" test
+ anim.setStartValue(64.0f);
+ anim.setStartDelay(anim.getDuration());
+ }
+ anim.start();
+ }
+
+ if (mToggle) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "pretendBusy");
+ try {
+ Thread.sleep(DURATION);
+ } catch (InterruptedException e) {
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ });
+ }
+ return true;
+ }
+ }
+}