Merge "Initial framework needed to draw circle with RuntimeShader."

This commit is contained in:
TreeHugger Robot
2021-01-08 15:42:48 +00:00
committed by Android (Google) Code Review
11 changed files with 177 additions and 1 deletions

View File

@@ -203,6 +203,26 @@ public final class RecordingCanvas extends BaseRecordingCanvas {
radius.getNativeContainer(), paint.getNativeContainer());
}
/**
* 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
*
@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -42,6 +42,7 @@ enum class CanvasOpType : int8_t {
DrawRoundRectProperty,
DrawDoubleRoundRect,
DrawCircleProperty,
DrawRippleProperty,
DrawCircle,
DrawOval,
DrawArc,

View File

@@ -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;

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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

View File

@@ -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;