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
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index 9f46ceb..49888fd 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -204,6 +204,26 @@
}
/**
+ * 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 @@
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 fb0983a..7f2e503 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -115,6 +115,10 @@
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 acb74f4..815ffde 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -814,6 +814,18 @@
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 591ae5c..1372bc4 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -147,6 +147,12 @@
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 f0aa777..cde50bd 100644
--- a/libs/hwui/canvas/CanvasOpTypes.h
+++ b/libs/hwui/canvas/CanvasOpTypes.h
@@ -42,6 +42,7 @@
DrawRoundRectProperty,
DrawDoubleRoundRect,
DrawCircleProperty,
+ DrawRippleProperty,
DrawCircle,
DrawOval,
DrawArc,
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index 62c26c7..ea9fea97 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 @@
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 11fa322..d0c996b 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 @@
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 7c1422d..f4877f4 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 @@
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 @@
{ "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 bf19655..3142d92 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 @@
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 e292cbd..f6a60bb 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -85,6 +85,16 @@
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 83e9349..622df43 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -66,6 +66,12 @@
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;