diff options
author | Lucas Dupin <dupin@google.com> | 2021-04-29 20:30:01 -0700 |
---|---|---|
committer | Lucas Dupin <dupin@google.com> | 2021-05-06 15:17:02 -0700 |
commit | 00af5271dabd578397176eda0cd7a66c55fac59a (patch) | |
tree | 0d14a6b9ec55aac9b1670ecc7d2aaddb959e0dcd | |
parent | 7b0989f35dc44b2d4bb01e7396f9547e16544152 (diff) |
Adding force-dark support to RippleDrawable
Add force-dark support to RippleDrawable by modifying the ink color.
Test: manual
Test: atest CanvasOp
Fixes: 186130682
Change-Id: I89eaaf3afa5ec53a74d2d08de8cff6484e55a912
-rw-r--r-- | graphics/java/android/graphics/RecordingCanvas.java | 7 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/RippleAnimationSession.java | 10 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/RippleDrawable.java | 4 | ||||
-rw-r--r-- | libs/hwui/CanvasTransform.cpp | 17 | ||||
-rw-r--r-- | libs/hwui/CanvasTransform.h | 3 | ||||
-rw-r--r-- | libs/hwui/DisplayListOps.in | 1 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.cpp | 31 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.h | 5 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.h | 9 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOpTypes.h | 2 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOps.h | 68 | ||||
-rw-r--r-- | libs/hwui/hwui/Canvas.h | 9 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_DisplayListCanvas.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/AnimatedDrawables.h | 114 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 11 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.h | 9 | ||||
-rw-r--r-- | libs/hwui/tests/unit/CanvasOpTests.cpp | 28 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java | 6 |
19 files changed, 177 insertions, 182 deletions
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java index e9e58c6213bf..a5184f28dbc1 100644 --- a/graphics/java/android/graphics/RecordingCanvas.java +++ b/graphics/java/android/graphics/RecordingCanvas.java @@ -16,6 +16,7 @@ package android.graphics; +import android.annotation.ColorInt; import android.annotation.NonNull; import android.os.SystemProperties; import android.util.Pools.SynchronizedPool; @@ -227,11 +228,11 @@ public final class RecordingCanvas extends BaseRecordingCanvas { public void drawRipple(CanvasProperty<Float> cx, CanvasProperty<Float> cy, CanvasProperty<Float> radius, CanvasProperty<Paint> paint, CanvasProperty<Float> progress, CanvasProperty<Float> turbulencePhase, - RuntimeShader shader) { + @ColorInt int color, RuntimeShader shader) { nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(), radius.getNativeContainer(), paint.getNativeContainer(), progress.getNativeContainer(), turbulencePhase.getNativeContainer(), - shader.getNativeShaderBuilder()); + color, shader.getNativeShaderBuilder()); } /** @@ -292,7 +293,7 @@ public final class RecordingCanvas extends BaseRecordingCanvas { long propCy, long propRadius, long propPaint); @CriticalNative private static native void nDrawRipple(long renderer, long propCx, long propCy, long propRadius, - long propPaint, long propProgress, long turbulencePhase, long runtimeEffect); + long propPaint, long propProgress, long turbulencePhase, int color, long runtimeEffect); @CriticalNative private static native void nDrawRoundRect(long renderer, long propLeft, long propTop, long propRight, long propBottom, long propRx, long propRy, long propPaint); diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java index 60f73b5e0090..ee867ddd5915 100644 --- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java +++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java @@ -19,6 +19,7 @@ package android.graphics.drawable; import android.animation.Animator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; +import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Canvas; @@ -211,6 +212,7 @@ public final class RippleAnimationSession { CanvasProperty.createFloat(mProperties.getNoisePhase()), CanvasProperty.createPaint(mProperties.getPaint()), CanvasProperty.createFloat(mProperties.getProgress()), + mProperties.getColor(), mProperties.getShader()); } return mCanvasProperties; @@ -250,11 +252,12 @@ public final class RippleAnimationSession { private final FloatType mNoisePhase; private final PaintType mPaint; private final RippleShader mShader; + private final @ColorInt int mColor; private FloatType mX; private FloatType mY; AnimationProperties(FloatType x, FloatType y, FloatType maxRadius, FloatType noisePhase, - PaintType paint, FloatType progress, RippleShader shader) { + PaintType paint, FloatType progress, @ColorInt int color, RippleShader shader) { mY = y; mX = x; mMaxRadius = maxRadius; @@ -262,6 +265,7 @@ public final class RippleAnimationSession { mPaint = paint; mShader = shader; mProgress = progress; + mColor = color; } FloatType getProgress() { @@ -296,5 +300,9 @@ public final class RippleAnimationSession { FloatType getNoisePhase() { return mNoisePhase; } + + @ColorInt int getColor() { + return mColor; + } } } diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 895cd3e8531f..d0fb67aff40d 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -902,7 +902,7 @@ public class RippleDrawable extends LayerDrawable { yProp = p.getY(); } can.drawRipple(xProp, yProp, p.getMaxRadius(), p.getPaint(), - p.getProgress(), p.getNoisePhase(), p.getShader()); + p.getProgress(), p.getNoisePhase(), p.getColor(), p.getShader()); } else { RippleAnimationSession.AnimationProperties<Float, Paint> p = s.getProperties(); @@ -975,7 +975,7 @@ public class RippleDrawable extends LayerDrawable { shader.setRadius(radius); shader.setProgress(.0f); properties = new RippleAnimationSession.AnimationProperties<>( - cx, cy, radius, 0f, p, 0f, shader); + cx, cy, radius, 0f, p, 0f, color, shader); if (mMaskShader == null) { shader.setShader(null); } else { diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp index 9d03ce5252a3..d0d24a8738f4 100644 --- a/libs/hwui/CanvasTransform.cpp +++ b/libs/hwui/CanvasTransform.cpp @@ -31,7 +31,7 @@ namespace android::uirenderer { -static SkColor makeLight(SkColor color) { +SkColor makeLight(SkColor color) { Lab lab = sRGBToLab(color); float invertedL = std::min(110 - lab.L, 100.0f); if (invertedL > lab.L) { @@ -42,7 +42,7 @@ static SkColor makeLight(SkColor color) { } } -static SkColor makeDark(SkColor color) { +SkColor makeDark(SkColor color) { Lab lab = sRGBToLab(color); float invertedL = std::min(110 - lab.L, 100.0f); if (invertedL < lab.L) { @@ -53,7 +53,7 @@ static SkColor makeDark(SkColor color) { } } -static SkColor transformColor(ColorTransform transform, SkColor color) { +SkColor transformColor(ColorTransform transform, SkColor color) { switch (transform) { case ColorTransform::Light: return makeLight(color); @@ -64,6 +64,17 @@ static SkColor transformColor(ColorTransform transform, SkColor color) { } } +SkColor transformColorInverse(ColorTransform transform, SkColor color) { + switch (transform) { + case ColorTransform::Dark: + return makeLight(color); + case ColorTransform::Light: + return makeDark(color); + default: + return color; + } +} + static void applyColorTransform(ColorTransform transform, SkPaint& paint) { if (transform == ColorTransform::None) return; diff --git a/libs/hwui/CanvasTransform.h b/libs/hwui/CanvasTransform.h index e723d645e05e..c46a2d369974 100644 --- a/libs/hwui/CanvasTransform.h +++ b/libs/hwui/CanvasTransform.h @@ -42,4 +42,7 @@ bool transformPaint(ColorTransform transform, SkPaint* paint); bool transformPaint(ColorTransform transform, SkPaint* paint, BitmapPalette palette); +SkColor transformColor(ColorTransform transform, SkColor color); +SkColor transformColorInverse(ColorTransform transform, SkColor color); + } // namespace android::uirenderer;
\ No newline at end of file diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in index 1b1be4311498..fb3e21fc1571 100644 --- a/libs/hwui/DisplayListOps.in +++ b/libs/hwui/DisplayListOps.in @@ -49,4 +49,5 @@ X(DrawVertices) X(DrawAtlas) X(DrawShadowRec) X(DrawVectorDrawable) +X(DrawRippleDrawable) X(DrawWebView) diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 170f73120414..442ae0fb2707 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -36,6 +36,7 @@ #include "SkTextBlob.h" #include "SkVertices.h" #include "VectorDrawable.h" +#include "pipeline/skia/AnimatedDrawables.h" #include "pipeline/skia/FunctorDrawable.h" namespace android { @@ -497,6 +498,18 @@ struct DrawVectorDrawable final : Op { SkPaint paint; BitmapPalette palette; }; + +struct DrawRippleDrawable final : Op { + static const auto kType = Type::DrawRippleDrawable; + DrawRippleDrawable(const skiapipeline::RippleDrawableParams& params) : mParams(params) {} + + void draw(SkCanvas* canvas, const SkMatrix&) const { + skiapipeline::AnimatedRippleDrawable::draw(canvas, mParams); + } + + skiapipeline::RippleDrawableParams mParams; +}; + struct DrawWebView final : Op { static const auto kType = Type::DrawWebView; DrawWebView(skiapipeline::FunctorDrawable* drawable) : drawable(sk_ref_sp(drawable)) {} @@ -721,6 +734,10 @@ void DisplayListData::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar mHasText = true; } +void DisplayListData::drawRippleDrawable(const skiapipeline::RippleDrawableParams& params) { + this->push<DrawRippleDrawable>(0, params); +} + void DisplayListData::drawPatch(const SkPoint points[12], const SkColor colors[4], const SkPoint texs[4], SkBlendMode bmode, const SkPaint& paint) { this->push<DrawPatch>(0, points, colors, texs, bmode, paint); @@ -851,6 +868,16 @@ constexpr color_transform_fn colorTransformForOp<DrawTextBlob>() { }; } +template <> +constexpr color_transform_fn colorTransformForOp<DrawRippleDrawable>() { + return [](const void* opRaw, ColorTransform transform) { + const DrawRippleDrawable* op = reinterpret_cast<const DrawRippleDrawable*>(opRaw); + // Ripple drawable needs to contrast against the background, so we need the inverse color. + SkColor color = transformColorInverse(transform, op->mParams.color); + const_cast<DrawRippleDrawable*>(op)->mParams.color = color; + }; +} + #define X(T) colorTransformForOp<T>(), static const color_transform_fn color_transform_fns[] = { #include "DisplayListOps.in" @@ -985,6 +1012,10 @@ void RecordingCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScala fDL->drawTextBlob(blob, x, y, paint); } +void RecordingCanvas::drawRippleDrawable(const skiapipeline::RippleDrawableParams& params) { + fDL->drawRippleDrawable(params); +} + void RecordingCanvas::drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y, const SkSamplingOptions& sampling, const SkPaint* paint, BitmapPalette palette) { diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index a6a7b12ba658..4fae6a13a25a 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -29,6 +29,9 @@ #include "SkPath.h" #include "SkRect.h" +#include "pipeline/skia/AnimatedDrawables.h" + +#include <SkRuntimeEffect.h> #include <vector> namespace android { @@ -125,6 +128,7 @@ private: void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&); void drawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int, SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*); + void drawRippleDrawable(const skiapipeline::RippleDrawableParams& params); void drawShadowRec(const SkPath&, const SkDrawShadowRec&); void drawVectorDrawable(VectorDrawableRoot* tree); void drawWebView(skiapipeline::FunctorDrawable*); @@ -184,6 +188,7 @@ public: void drawImage(const sk_sp<SkImage>&, SkScalar left, SkScalar top, const SkSamplingOptions&, const SkPaint* paint, BitmapPalette pallete); + void drawRippleDrawable(const skiapipeline::RippleDrawableParams& params); void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst, const SkSamplingOptions&, const SkPaint*, SrcRectConstraint, BitmapPalette); diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 3056e977f841..d032e2b00649 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -815,17 +815,8 @@ void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, mCanvas->drawDrawable(drawable.get()); } -void SkiaCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x, - uirenderer::CanvasPropertyPrimitive* y, - uirenderer::CanvasPropertyPrimitive* radius, - uirenderer::CanvasPropertyPaint* paint, - uirenderer::CanvasPropertyPrimitive* progress, - uirenderer::CanvasPropertyPrimitive* turbulencePhase, - const SkRuntimeShaderBuilder& effectBuilder) { - sk_sp<uirenderer::skiapipeline::AnimatedRipple> drawable( - new uirenderer::skiapipeline::AnimatedRipple(x, y, radius, paint, progress, - turbulencePhase, effectBuilder)); - mCanvas->drawDrawable(drawable.get()); +void SkiaCanvas::drawRipple(const uirenderer::skiapipeline::RippleDrawableParams& params) { + uirenderer::skiapipeline::AnimatedRippleDrawable::draw(mCanvas, params); } void SkiaCanvas::drawPicture(const SkPicture& picture) { diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 995f00c6aa8d..438a40cb4c81 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -25,6 +25,7 @@ #include "hwui/Paint.h" #include <SkCanvas.h> +#include "pipeline/skia/AnimatedDrawables.h" #include "src/core/SkArenaAlloc.h" #include <cassert> @@ -148,13 +149,7 @@ public: uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) override; - virtual void drawRipple(uirenderer::CanvasPropertyPrimitive* x, - uirenderer::CanvasPropertyPrimitive* y, - uirenderer::CanvasPropertyPrimitive* radius, - uirenderer::CanvasPropertyPaint* paint, - uirenderer::CanvasPropertyPrimitive* progress, - uirenderer::CanvasPropertyPrimitive* turbulencePhase, - const SkRuntimeShaderBuilder& effectBuilder) override; + virtual void drawRipple(const uirenderer::skiapipeline::RippleDrawableParams& params) override; virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override; virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override; diff --git a/libs/hwui/canvas/CanvasOpTypes.h b/libs/hwui/canvas/CanvasOpTypes.h index b55ef9d5537c..6e18e492e7ca 100644 --- a/libs/hwui/canvas/CanvasOpTypes.h +++ b/libs/hwui/canvas/CanvasOpTypes.h @@ -43,7 +43,7 @@ enum class CanvasOpType : int8_t { DrawRoundRectProperty, DrawDoubleRoundRect, DrawCircleProperty, - DrawRippleProperty, + DrawRippleDrawable, DrawCircle, DrawOval, DrawArc, diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h index 173f3948dd0e..fdc97a4fd8ba 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -145,73 +145,13 @@ struct CanvasOp<CanvasOpType::DrawCircleProperty> { ASSERT_DRAWABLE() }; -template<> -struct CanvasOp<CanvasOpType::DrawRippleProperty> { - sp<uirenderer::CanvasPropertyPrimitive> x; - sp<uirenderer::CanvasPropertyPrimitive> y; - sp<uirenderer::CanvasPropertyPrimitive> radius; - sp<uirenderer::CanvasPropertyPaint> paint; - sp<uirenderer::CanvasPropertyPrimitive> progress; - sp<uirenderer::CanvasPropertyPrimitive> turbulencePhase; - sk_sp<SkRuntimeEffect> effect; - - const float PI = 3.1415926535897932384626; - const float PI_ROTATE_RIGHT = PI * 0.0078125; - const float PI_ROTATE_LEFT = PI * -0.0078125; - const float SCALE = 1.5; - const float CIRCLE_X_1 = 0.01 * cos(SCALE * 0.55); - const float CIRCLE_Y_1 = 0.01 * sin(SCALE * 0.55); - const float CIRCLE_X_2 = -0.0066 * cos(SCALE * 0.45); - const float CIRCLE_Y_2 = -0.0066 * sin(SCALE * 0.45); - const float CIRCLE_X_3 = -0.0066 * cos(SCALE * 0.35); - const float CIRCLE_Y_3 = -0.0066 * sin(SCALE * 0.35); +template <> +struct CanvasOp<CanvasOpType::DrawRippleDrawable> { + skiapipeline::RippleDrawableParams params; void draw(SkCanvas* canvas) const { - SkRuntimeShaderBuilder runtimeEffectBuilder(effect); - - setUniform2f(runtimeEffectBuilder, "in_origin", x->value, y->value); - setUniform(runtimeEffectBuilder, "in_radius", radius); - setUniform(runtimeEffectBuilder, "in_progress", progress); - setUniform(runtimeEffectBuilder, "in_turbulencePhase", turbulencePhase); - - // - // Keep in sync with: - // frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java - // - const float turbulence = turbulencePhase->value; - setUniform2f(runtimeEffectBuilder, "in_tCircle1", SCALE * 0.5 + (turbulence * CIRCLE_X_1), - SCALE * 0.5 + (turbulence * CIRCLE_Y_1)); - setUniform2f(runtimeEffectBuilder, "in_tCircle2", SCALE * 0.2 + (turbulence * CIRCLE_X_2), - SCALE * 0.2 + (turbulence * CIRCLE_Y_2)); - setUniform2f(runtimeEffectBuilder, "in_tCircle3", SCALE + (turbulence * CIRCLE_X_3), - SCALE + (turbulence * CIRCLE_Y_3)); - const float rotation1 = turbulence * PI_ROTATE_RIGHT + 1.7 * PI; - setUniform2f(runtimeEffectBuilder, "in_tRotation1", cos(rotation1), sin(rotation1)); - const float rotation2 = turbulence * PI_ROTATE_LEFT + 2 * PI; - setUniform2f(runtimeEffectBuilder, "in_tRotation2", cos(rotation2), sin(rotation2)); - const float rotation3 = turbulence * PI_ROTATE_RIGHT + 2.75 * PI; - setUniform2f(runtimeEffectBuilder, "in_tRotation3", cos(rotation3), sin(rotation3)); - - SkPaint paintMod = paint->value; - paintMod.setShader(runtimeEffectBuilder.makeShader(nullptr, false)); - canvas->drawCircle(x->value, y->value, radius->value, paintMod); + skiapipeline::AnimatedRippleDrawable::draw(canvas, params); } - - void setUniform(SkRuntimeShaderBuilder& effect, std::string name, - sp<uirenderer::CanvasPropertyPrimitive> property) const { - SkRuntimeShaderBuilder::BuilderUniform uniform = effect.uniform(name.c_str()); - if (uniform.fVar != nullptr) { - uniform = property->value; - } - } - - void setUniform2f(SkRuntimeShaderBuilder effect, std::string name, float a, float b) const { - SkRuntimeShaderBuilder::BuilderUniform uniform = effect.uniform(name.c_str()); - if (uniform.fVar != nullptr) { - uniform = SkV2{a, b}; - } - } - ASSERT_DRAWABLE() }; diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 837b055a8f42..9023613478fc 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -22,6 +22,7 @@ #include <androidfw/ResourceTypes.h> #include "Properties.h" +#include "pipeline/skia/AnimatedDrawables.h" #include "utils/Macros.h" #include <SkBitmap.h> @@ -141,13 +142,7 @@ public: uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) = 0; - virtual void drawRipple(uirenderer::CanvasPropertyPrimitive* x, - uirenderer::CanvasPropertyPrimitive* y, - uirenderer::CanvasPropertyPrimitive* radius, - uirenderer::CanvasPropertyPaint* paint, - uirenderer::CanvasPropertyPrimitive* progress, - uirenderer::CanvasPropertyPrimitive* turbulencePhase, - const SkRuntimeShaderBuilder& effectBuilder) = 0; + virtual void drawRipple(const uirenderer::skiapipeline::RippleDrawableParams& params) = 0; virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0; virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0; diff --git a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp index eb5a88ad7ae8..f060bb32031a 100644 --- a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp +++ b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp @@ -144,7 +144,7 @@ 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 turbulencePhasePtr, - jlong builderPtr) { + jint color, jlong builderPtr) { Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr); CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr); @@ -155,8 +155,12 @@ static void android_view_DisplayListCanvas_drawRippleProps( CanvasPropertyPrimitive* progressProp = reinterpret_cast<CanvasPropertyPrimitive*>(progressPropPtr); SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(builderPtr); - canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, turbulencePhaseProp, - *builder); + + const uirenderer::skiapipeline::RippleDrawableParams params = + uirenderer::skiapipeline::RippleDrawableParams{ + xProp, yProp, radiusProp, progressProp, turbulencePhaseProp, + (SkColor)color, paintProp, *builder}; + canvas->drawRipple(params); } static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) { @@ -186,7 +190,7 @@ static JNINativeMethod gMethods[] = { {"nDrawCircle", "(JJJJJ)V", (void*)android_view_DisplayListCanvas_drawCircleProps}, {"nDrawRoundRect", "(JJJJJJJJ)V", (void*)android_view_DisplayListCanvas_drawRoundRectProps}, {"nDrawWebViewFunctor", "(JI)V", (void*)android_view_DisplayListCanvas_drawWebViewFunctor}, - {"nDrawRipple", "(JJJJJJJJ)V", (void*)android_view_DisplayListCanvas_drawRippleProps}, + {"nDrawRipple", "(JJJJJJJIJ)V", (void*)android_view_DisplayListCanvas_drawRippleProps}, }; int register_android_view_DisplayListCanvas(JNIEnv* env) { diff --git a/libs/hwui/pipeline/skia/AnimatedDrawables.h b/libs/hwui/pipeline/skia/AnimatedDrawables.h index 7d65be1a76e6..10889e7a9229 100644 --- a/libs/hwui/pipeline/skia/AnimatedDrawables.h +++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h @@ -22,6 +22,7 @@ #include <math.h> #include <utils/RefBase.h> #include "CanvasProperty.h" +#include "CanvasTransform.h" namespace android { namespace uirenderer { @@ -56,89 +57,80 @@ private: sp<uirenderer::CanvasPropertyPaint> mPaint; }; -class AnimatedRipple : public SkDrawable { +struct RippleDrawableParams { + sp<uirenderer::CanvasPropertyPrimitive> x; + sp<uirenderer::CanvasPropertyPrimitive> y; + sp<uirenderer::CanvasPropertyPrimitive> radius; + sp<uirenderer::CanvasPropertyPrimitive> progress; + sp<uirenderer::CanvasPropertyPrimitive> turbulencePhase; + SkColor color; + sp<uirenderer::CanvasPropertyPaint> paint; + SkRuntimeShaderBuilder effectBuilder; +}; + +class AnimatedRippleDrawable { public: - AnimatedRipple(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y, - uirenderer::CanvasPropertyPrimitive* radius, - uirenderer::CanvasPropertyPaint* paint, - uirenderer::CanvasPropertyPrimitive* progress, - uirenderer::CanvasPropertyPrimitive* turbulencePhase, - const SkRuntimeShaderBuilder& effectBuilder) - : mX(x) - , mY(y) - , mRadius(radius) - , mPaint(paint) - , mProgress(progress) - , mTurbulencePhase(turbulencePhase) - , mRuntimeEffectBuilder(effectBuilder) {} + static void draw(SkCanvas* canvas, const RippleDrawableParams& params) { + auto& effectBuilder = const_cast<SkRuntimeShaderBuilder&>(params.effectBuilder); -protected: - virtual SkRect onGetBounds() override { - const float x = mX->value; - const float y = mY->value; - const float radius = mRadius->value; - return SkRect::MakeLTRB(x - radius, y - radius, x + radius, y + radius); - } - virtual void onDraw(SkCanvas* canvas) override { - setUniform2f("in_origin", mX->value, mY->value); - setUniform("in_radius", mRadius); - setUniform("in_progress", mProgress); - setUniform("in_turbulencePhase", mTurbulencePhase); + setUniform2f(effectBuilder, "in_origin", params.x->value, params.y->value); + setUniform(effectBuilder, "in_radius", params.radius); + setUniform(effectBuilder, "in_progress", params.progress); + setUniform(effectBuilder, "in_turbulencePhase", params.turbulencePhase); + + SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform("in_color"); + if (uniform.fVar != nullptr) { + uniform = SkV4{SkColorGetR(params.color) / 255.0f, SkColorGetG(params.color) / 255.0f, + SkColorGetB(params.color) / 255.0f, SkColorGetA(params.color) / 255.0f}; + } + + const float CIRCLE_X_1 = 0.01 * cos(SCALE * 0.55); + const float CIRCLE_Y_1 = 0.01 * sin(SCALE * 0.55); + const float CIRCLE_X_2 = -0.0066 * cos(SCALE * 0.45); + const float CIRCLE_Y_2 = -0.0066 * sin(SCALE * 0.45); + const float CIRCLE_X_3 = -0.0066 * cos(SCALE * 0.35); + const float CIRCLE_Y_3 = -0.0066 * sin(SCALE * 0.35); // // Keep in sync with: // frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java // - const float turbulencePhase = mTurbulencePhase->value; - setUniform2f("in_tCircle1", SCALE * 0.5 + (turbulencePhase * CIRCLE_X_1), + const float turbulencePhase = params.turbulencePhase->value; + setUniform2f(effectBuilder, "in_tCircle1", SCALE * 0.5 + (turbulencePhase * CIRCLE_X_1), SCALE * 0.5 + (turbulencePhase * CIRCLE_Y_1)); - setUniform2f("in_tCircle2", SCALE * 0.2 + (turbulencePhase * CIRCLE_X_2), + setUniform2f(effectBuilder, "in_tCircle2", SCALE * 0.2 + (turbulencePhase * CIRCLE_X_2), SCALE * 0.2 + (turbulencePhase * CIRCLE_Y_2)); - setUniform2f("in_tCircle3", SCALE + (turbulencePhase * CIRCLE_X_3), + setUniform2f(effectBuilder, "in_tCircle3", SCALE + (turbulencePhase * CIRCLE_X_3), SCALE + (turbulencePhase * CIRCLE_Y_3)); const float rotation1 = turbulencePhase * PI_ROTATE_RIGHT + 1.7 * PI; - setUniform2f("in_tRotation1", cos(rotation1), sin(rotation1)); + setUniform2f(effectBuilder, "in_tRotation1", cos(rotation1), sin(rotation1)); const float rotation2 = turbulencePhase * PI_ROTATE_LEFT + 2 * PI; - setUniform2f("in_tRotation2", cos(rotation2), sin(rotation2)); + setUniform2f(effectBuilder, "in_tRotation2", cos(rotation2), sin(rotation2)); const float rotation3 = turbulencePhase * PI_ROTATE_RIGHT + 2.75 * PI; - setUniform2f("in_tRotation3", cos(rotation3), sin(rotation3)); + setUniform2f(effectBuilder, "in_tRotation3", cos(rotation3), sin(rotation3)); - SkPaint paint = mPaint->value; - paint.setShader(mRuntimeEffectBuilder.makeShader(nullptr, false)); - canvas->drawCircle(mX->value, mY->value, mRadius->value, paint); + params.paint->value.setShader(effectBuilder.makeShader(nullptr, false)); + canvas->drawCircle(params.x->value, params.y->value, params.radius->value, + params.paint->value); } private: - sp<uirenderer::CanvasPropertyPrimitive> mX; - sp<uirenderer::CanvasPropertyPrimitive> mY; - sp<uirenderer::CanvasPropertyPrimitive> mRadius; - sp<uirenderer::CanvasPropertyPaint> mPaint; - sp<uirenderer::CanvasPropertyPrimitive> mProgress; - sp<uirenderer::CanvasPropertyPrimitive> mTurbulencePhase; - SkRuntimeShaderBuilder mRuntimeEffectBuilder; - - const float PI = 3.1415926535897932384626; - const float PI_ROTATE_RIGHT = PI * 0.0078125; - const float PI_ROTATE_LEFT = PI * -0.0078125; - const float SCALE = 1.5; - const float CIRCLE_X_1 = 0.01 * cos(SCALE * 0.55); - const float CIRCLE_Y_1 = 0.01 * sin(SCALE * 0.55); - const float CIRCLE_X_2 = -0.0066 * cos(SCALE * 0.45); - const float CIRCLE_Y_2 = -0.0066 * sin(SCALE * 0.45); - const float CIRCLE_X_3 = -0.0066 * cos(SCALE * 0.35); - const float CIRCLE_Y_3 = -0.0066 * sin(SCALE * 0.35); - - virtual void setUniform(std::string name, sp<uirenderer::CanvasPropertyPrimitive> property) { - SkRuntimeShaderBuilder::BuilderUniform uniform = - mRuntimeEffectBuilder.uniform(name.c_str()); + static constexpr float PI = 3.1415926535897932384626; + static constexpr float PI_ROTATE_RIGHT = PI * 0.0078125; + static constexpr float PI_ROTATE_LEFT = PI * -0.0078125; + static constexpr float SCALE = 1.5; + + static void setUniform(SkRuntimeShaderBuilder& effectBuilder, std::string name, + sp<uirenderer::CanvasPropertyPrimitive> property) { + SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name.c_str()); if (uniform.fVar != nullptr) { uniform = property->value; } } - virtual void setUniform2f(std::string name, float a, float b) { - SkRuntimeShaderBuilder::BuilderUniform uniform = - mRuntimeEffectBuilder.uniform(name.c_str()); + static void setUniform2f(SkRuntimeShaderBuilder& effectBuilder, std::string name, float a, + float b) { + SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name.c_str()); if (uniform.fVar != nullptr) { uniform = SkV2{a, b}; } diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 9e73f04c32ab..76c4a03d3a91 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -109,15 +109,8 @@ void SkiaRecordingCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, drawDrawable(mDisplayList->allocateDrawable<AnimatedCircle>(x, y, radius, paint)); } -void SkiaRecordingCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x, - uirenderer::CanvasPropertyPrimitive* y, - uirenderer::CanvasPropertyPrimitive* radius, - uirenderer::CanvasPropertyPaint* paint, - uirenderer::CanvasPropertyPrimitive* progress, - uirenderer::CanvasPropertyPrimitive* turbulencePhase, - const SkRuntimeShaderBuilder& effectBuilder) { - drawDrawable(mDisplayList->allocateDrawable<AnimatedRipple>(x, y, radius, paint, progress, - turbulencePhase, effectBuilder)); +void SkiaRecordingCanvas::drawRipple(const skiapipeline::RippleDrawableParams& params) { + mRecorder.drawRippleDrawable(params); } void SkiaRecordingCanvas::enableZ(bool enableZ) { diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h index 4deb3b9c47c8..1445a27e4248 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -20,6 +20,7 @@ #include "ReorderBarrierDrawables.h" #include "SkiaCanvas.h" #include "SkiaDisplayList.h" +#include "pipeline/skia/AnimatedDrawables.h" namespace android { namespace uirenderer { @@ -70,13 +71,7 @@ public: uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) override; - virtual void drawRipple(uirenderer::CanvasPropertyPrimitive* x, - uirenderer::CanvasPropertyPrimitive* y, - uirenderer::CanvasPropertyPrimitive* radius, - uirenderer::CanvasPropertyPaint* paint, - uirenderer::CanvasPropertyPrimitive* progress, - uirenderer::CanvasPropertyPrimitive* turbulencePhase, - const SkRuntimeShaderBuilder& effectBuilder) override; + virtual void drawRipple(const RippleDrawableParams& params) override; virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override; diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp index a718d46c735f..2cf3456694b0 100644 --- a/libs/hwui/tests/unit/CanvasOpTests.cpp +++ b/libs/hwui/tests/unit/CanvasOpTests.cpp @@ -31,6 +31,7 @@ using namespace android; using namespace android::uirenderer; +using namespace android::uirenderer::skiapipeline; using namespace android::uirenderer::test; // We lazy @@ -569,6 +570,33 @@ TEST(CanvasOp, simpleDrawPicture) { EXPECT_EQ(2, canvas.sumTotalDrawCalls()); } +TEST(CanvasOp, simpleDrawRipple) { + CanvasOpBuffer buffer; + EXPECT_EQ(buffer.size(), 0); + + const char* sksl = + "half4 main(float2 coord) {" + " return half4(1.);" + "}"; + auto [effect, error] = SkRuntimeEffect::MakeForShader(SkString(sksl)); + auto params = RippleDrawableParams{ + .x = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(100)), + .y = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(200)), + .radius = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(50)), + .progress = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(0.5)), + .turbulencePhase = sp<CanvasPropertyPrimitive>(new CanvasPropertyPrimitive(1)), + .color = 0xff00ff, + .paint = sp<CanvasPropertyPaint>(new CanvasPropertyPaint(SkPaint{})), + .effectBuilder = SkRuntimeShaderBuilder(effect)}; + buffer.push<Op::DrawRippleDrawable>({.params = params}); + + CallCountingCanvas canvas; + EXPECT_EQ(0, canvas.sumTotalDrawCalls()); + rasterizeCanvasBuffer(buffer, &canvas); + EXPECT_EQ(1, canvas.drawOvalCount); + EXPECT_EQ(1, canvas.sumTotalDrawCalls()); +} + TEST(CanvasOp, immediateRendering) { auto canvas = std::make_shared<CallCountingCanvas>(); diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java index 79410cf35f7a..d925541c76d6 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.CanvasProperty; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.RecordingCanvas; import android.graphics.RuntimeShader; @@ -48,6 +49,7 @@ public class RippleActivity extends Activity { static class RippleView extends View { static final int DURATION = 1000; static final int MAX_RADIUS = 250; + private final int mColor = Color.RED; private boolean mToggle = false; ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>(); @@ -104,7 +106,7 @@ public class RippleActivity extends Activity { Paint p = new Paint(); p.setAntiAlias(true); - p.setColor(0xFFFF0000); + p.setColor(mColor); mPaint = CanvasProperty.createPaint(p); mRuntimeShader = new RuntimeShader(sSkSL, false); @@ -118,7 +120,7 @@ public class RippleActivity extends Activity { if (canvas.isHardwareAccelerated()) { RecordingCanvas recordingCanvas = (RecordingCanvas) canvas; recordingCanvas.drawRipple(mX, mY, mRadius, mPaint, mProgress, mNoisePhase, - mRuntimeShader); + mColor, mRuntimeShader); } } |