diff options
| author | 2021-01-15 20:16:55 +0000 | |
|---|---|---|
| committer | 2021-01-15 20:16:55 +0000 | |
| commit | 106f1b33b43e375e0598dadae52a34a164928f39 (patch) | |
| tree | cf8755748c8327c8488624264b85ed05fb0c7f0c | |
| parent | 601ec92324b89d6c122ba9cec935e8d9cb292132 (diff) | |
| parent | 783e5aeb2e0926419b8bf5ff3550287400552b06 (diff) | |
Merge "Refactor RuntimeShader to support easier assignment of uniforms."
| -rw-r--r-- | graphics/java/android/graphics/RecordingCanvas.java | 2 | ||||
| -rw-r--r-- | graphics/java/android/graphics/RuntimeShader.java | 103 | ||||
| -rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/SkiaCanvas.h | 2 | ||||
| -rw-r--r-- | libs/hwui/canvas/CanvasOps.h | 2 | ||||
| -rw-r--r-- | libs/hwui/hwui/Canvas.h | 4 | ||||
| -rw-r--r-- | libs/hwui/jni/Shader.cpp | 99 | ||||
| -rw-r--r-- | libs/hwui/jni/android_graphics_DisplayListCanvas.cpp | 7 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/AnimatedDrawables.h | 6 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.h | 2 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 9 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java | 28 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java | 178 |
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; + } + } +} |