diff options
author | 2020-12-17 11:06:03 -0500 | |
---|---|---|
committer | 2021-01-08 12:47:31 +0000 | |
commit | df301aaa540ebe6c21b98a7cb5cce6d39101d0c7 (patch) | |
tree | 85cf5afc5b7a6797f0248432125a8f20f6a5369a | |
parent | fa2a82b01dd316d3aa60a4e10dd8de0e09b087fc (diff) |
Initial framework needed to draw circle with RuntimeShader.
This also adds the ability for RenderThread to animate a few
predefined shader uniforms.
Bug: 177051137
Test: demo in ag/13296877
Change-Id: I6e58e671ad1242a07ecb1cf4cdb48031f85c2088
-rw-r--r-- | graphics/java/android/graphics/RecordingCanvas.java | 23 | ||||
-rw-r--r-- | graphics/java/android/graphics/RuntimeShader.java | 4 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.h | 6 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOpTypes.h | 1 | ||||
-rw-r--r-- | libs/hwui/canvas/CanvasOps.h | 37 | ||||
-rw-r--r-- | libs/hwui/hwui/Canvas.h | 7 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_DisplayListCanvas.cpp | 18 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/AnimatedDrawables.h | 54 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.h | 6 |
11 files changed, 177 insertions, 1 deletions
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java index 9f46ceb61332..49888fd5f977 100644 --- a/graphics/java/android/graphics/RecordingCanvas.java +++ b/graphics/java/android/graphics/RecordingCanvas.java @@ -204,6 +204,26 @@ public final class RecordingCanvas extends BaseRecordingCanvas { } /** + * Draws a ripple + * + * @param cx + * @param cy + * @param radius + * @param paint + * @param progress + * @param shader + * + * @hide + */ + public void drawRipple(CanvasProperty<Float> cx, CanvasProperty<Float> cy, + CanvasProperty<Float> radius, CanvasProperty<Paint> paint, + CanvasProperty<Float> progress, RuntimeShader shader) { + nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(), + radius.getNativeContainer(), paint.getNativeContainer(), + progress.getNativeContainer(), shader.getNativeShaderFactory()); + } + + /** * Draws a round rect * * @param left @@ -260,6 +280,9 @@ public final class RecordingCanvas extends BaseRecordingCanvas { private static native void nDrawCircle(long renderer, long propCx, 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 runtimeEffect); + @CriticalNative private static native void nDrawRoundRect(long renderer, long propLeft, long propTop, long propRight, long propBottom, long propRx, long propRy, long propPaint); @CriticalNative diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java index fb0983a83f9d..7f2e503ac8fd 100644 --- a/graphics/java/android/graphics/RuntimeShader.java +++ b/graphics/java/android/graphics/RuntimeShader.java @@ -115,6 +115,10 @@ public class RuntimeShader extends Shader { nativeShaders, colorSpace().getNativeInstance(), mIsOpaque); } + public long getNativeShaderFactory() { + return mNativeInstanceRuntimeShaderFactory; + } + private static native long nativeCreate(long shaderFactory, long matrix, byte[] inputs, long[] shaderInputs, long colorSpaceHandle, boolean isOpaque); diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index acb74f415f41..815ffdeade45 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -814,6 +814,18 @@ 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, + sk_sp<SkRuntimeEffect> runtimeEffect) { + sk_sp<uirenderer::skiapipeline::AnimatedRipple> drawable( + new uirenderer::skiapipeline::AnimatedRipple(x, y, radius, paint, progress, + runtimeEffect)); + mCanvas->drawDrawable(drawable.get()); +} + void SkiaCanvas::drawPicture(const SkPicture& picture) { // TODO: Change to mCanvas->drawPicture()? SkCanvas::drawPicture seems to be // where the logic is for playback vs. ref picture. Using picture.playback here diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 591ae5c44227..1372bc48511a 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -147,6 +147,12 @@ 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, + sk_sp<SkRuntimeEffect> runtimeEffect) 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 f0aa7774a6cc..cde50bd66a15 100644 --- a/libs/hwui/canvas/CanvasOpTypes.h +++ b/libs/hwui/canvas/CanvasOpTypes.h @@ -42,6 +42,7 @@ enum class CanvasOpType : int8_t { DrawRoundRectProperty, DrawDoubleRoundRect, DrawCircleProperty, + DrawRippleProperty, DrawCircle, DrawOval, DrawArc, diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h index 62c26c7b6f6a..ea9fea974d06 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -23,6 +23,7 @@ #include <SkVertices.h> #include <SkImage.h> #include <SkPicture.h> +#include <SkRuntimeEffect.h> #include <hwui/Bitmap.h> #include <log/log.h> #include "CanvasProperty.h" @@ -142,6 +143,42 @@ 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; + sk_sp<SkRuntimeEffect> effect; + + void draw(SkCanvas* canvas) const { + SkRuntimeShaderBuilder runtimeEffectBuilder(effect); + + SkRuntimeShaderBuilder::BuilderUniform center = runtimeEffectBuilder.uniform("in_origin"); + if (center.fVar != nullptr) { + center = SkV2{x->value, y->value}; + } + + SkRuntimeShaderBuilder::BuilderUniform radiusU = + runtimeEffectBuilder.uniform("in_maxRadius"); + if (radiusU.fVar != nullptr) { + radiusU = radius->value; + } + + SkRuntimeShaderBuilder::BuilderUniform progressU = + runtimeEffectBuilder.uniform("in_progress"); + if (progressU.fVar != nullptr) { + progressU = progress->value; + } + + SkPaint paintMod = paint->value; + paintMod.setShader(runtimeEffectBuilder.makeShader(nullptr, false)); + canvas->drawCircle(x->value, y->value, radius->value, paintMod); + } + ASSERT_DRAWABLE() +}; + template <> struct CanvasOp<CanvasOpType::DrawColor> { SkColor4f color; diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 11fa3223a9c8..d0c996bee449 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -31,6 +31,7 @@ class SkAnimatedImage; class SkCanvasState; +class SkRuntimeEffect; class SkVertices; namespace minikin { @@ -133,6 +134,12 @@ 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, + sk_sp<SkRuntimeEffect> runtimeEffect) = 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 7c1422de0984..f4877f4a4fc4 100644 --- a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp +++ b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp @@ -20,8 +20,8 @@ #include <utils/Looper.h> #endif -#include <SkBitmap.h> #include <SkRegion.h> +#include <SkRuntimeEffect.h> #include <Rect.h> #include <RenderNode.h> @@ -139,6 +139,21 @@ static void android_view_DisplayListCanvas_drawCircleProps(CRITICAL_JNI_PARAMS_C canvas->drawCircle(xProp, yProp, radiusProp, paintProp); } +static void android_view_DisplayListCanvas_drawRippleProps(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, + jlong xPropPtr, jlong yPropPtr, + jlong radiusPropPtr, jlong paintPropPtr, + jlong progressPropPtr, jlong effectPtr) { + Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); + CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr); + CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr); + CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr); + 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)); +} + static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) { Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr); canvas->drawWebViewFunctor(functor); @@ -163,6 +178,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", "(JJJJJJJ)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 bf19655825b3..3142d927d4c4 100644 --- a/libs/hwui/pipeline/skia/AnimatedDrawables.h +++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h @@ -18,6 +18,7 @@ #include <SkCanvas.h> #include <SkDrawable.h> +#include <SkRuntimeEffect.h> #include <utils/RefBase.h> #include "CanvasProperty.h" @@ -54,6 +55,59 @@ private: sp<uirenderer::CanvasPropertyPaint> mPaint; }; +class AnimatedRipple : public SkDrawable { +public: + AnimatedRipple(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y, + uirenderer::CanvasPropertyPrimitive* radius, + uirenderer::CanvasPropertyPaint* paint, + uirenderer::CanvasPropertyPrimitive* progress, + sk_sp<SkRuntimeEffect> runtimeEffect) + : mX(x) + , mY(y) + , mRadius(radius) + , mPaint(paint) + , mProgress(progress) + , mRuntimeEffectBuilder(std::move(runtimeEffect)) {} + +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 { + SkRuntimeShaderBuilder::BuilderUniform center = mRuntimeEffectBuilder.uniform("in_origin"); + if (center.fVar != nullptr) { + center = SkV2{mX->value, mY->value}; + } + + SkRuntimeShaderBuilder::BuilderUniform radiusU = + mRuntimeEffectBuilder.uniform("in_maxRadius"); + if (radiusU.fVar != nullptr) { + radiusU = mRadius->value; + } + + SkRuntimeShaderBuilder::BuilderUniform progressU = + mRuntimeEffectBuilder.uniform("in_progress"); + if (progressU.fVar != nullptr) { + progressU = mProgress->value; + } + + SkPaint paint = mPaint->value; + paint.setShader(mRuntimeEffectBuilder.makeShader(nullptr, false)); + canvas->drawCircle(mX->value, mY->value, mRadius->value, paint); + } + +private: + sp<uirenderer::CanvasPropertyPrimitive> mX; + sp<uirenderer::CanvasPropertyPrimitive> mY; + sp<uirenderer::CanvasPropertyPrimitive> mRadius; + sp<uirenderer::CanvasPropertyPaint> mPaint; + sp<uirenderer::CanvasPropertyPrimitive> mProgress; + SkRuntimeShaderBuilder mRuntimeEffectBuilder; +}; + class AnimatedCircle : public SkDrawable { public: AnimatedCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y, diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index e292cbdd101f..f6a60bb289ac 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -85,6 +85,16 @@ 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, + sk_sp<SkRuntimeEffect> runtimeEffect) { + drawDrawable(mDisplayList->allocateDrawable<AnimatedRipple>(x, y, radius, paint, progress, + runtimeEffect)); +} + void SkiaRecordingCanvas::enableZ(bool enableZ) { if (mCurrentBarrier && enableZ) { // Already in a re-order section, nothing to do diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h index 83e934974afd..622df43b0528 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -66,6 +66,12 @@ 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, + sk_sp<SkRuntimeEffect> runtimeEffect) override; virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override; |