Merge "Move sparkle animation to RenderThread" into sc-dev
This commit is contained in:
@@ -226,10 +226,12 @@ public final class RecordingCanvas extends BaseRecordingCanvas {
|
|||||||
*/
|
*/
|
||||||
public void drawRipple(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
|
public void drawRipple(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
|
||||||
CanvasProperty<Float> radius, CanvasProperty<Paint> paint,
|
CanvasProperty<Float> radius, CanvasProperty<Paint> paint,
|
||||||
CanvasProperty<Float> progress, RuntimeShader shader) {
|
CanvasProperty<Float> progress, CanvasProperty<Float> turbulencePhase,
|
||||||
|
RuntimeShader shader) {
|
||||||
nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
|
nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
|
||||||
radius.getNativeContainer(), paint.getNativeContainer(),
|
radius.getNativeContainer(), paint.getNativeContainer(),
|
||||||
progress.getNativeContainer(), shader.getNativeShaderBuilder());
|
progress.getNativeContainer(), turbulencePhase.getNativeContainer(),
|
||||||
|
shader.getNativeShaderBuilder());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -290,7 +292,7 @@ public final class RecordingCanvas extends BaseRecordingCanvas {
|
|||||||
long propCy, long propRadius, long propPaint);
|
long propCy, long propRadius, long propPaint);
|
||||||
@CriticalNative
|
@CriticalNative
|
||||||
private static native void nDrawRipple(long renderer, long propCx, long propCy, long propRadius,
|
private static native void nDrawRipple(long renderer, long propCx, long propCy, long propRadius,
|
||||||
long propPaint, long propProgress, long runtimeEffect);
|
long propPaint, long propProgress, long turbulencePhase, long runtimeEffect);
|
||||||
@CriticalNative
|
@CriticalNative
|
||||||
private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
|
private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
|
||||||
long propRight, long propBottom, long propRx, long propRy, long propPaint);
|
long propRight, long propBottom, long propRx, long propRy, long propPaint);
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ public final class RippleAnimationSession {
|
|||||||
private static final String TAG = "RippleAnimationSession";
|
private static final String TAG = "RippleAnimationSession";
|
||||||
private static final int ENTER_ANIM_DURATION = 450;
|
private static final int ENTER_ANIM_DURATION = 450;
|
||||||
private static final int EXIT_ANIM_DURATION = 300;
|
private static final int EXIT_ANIM_DURATION = 300;
|
||||||
|
private static final long NOISE_ANIMATION_DURATION = 7000;
|
||||||
|
private static final long MAX_NOISE_PHASE = NOISE_ANIMATION_DURATION / 120;
|
||||||
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
|
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
|
||||||
private static final Interpolator FAST_OUT_SLOW_IN =
|
private static final Interpolator FAST_OUT_SLOW_IN =
|
||||||
new PathInterpolator(0.4f, 0f, 0.2f, 1f);
|
new PathInterpolator(0.4f, 0f, 0.2f, 1f);
|
||||||
@@ -49,7 +51,7 @@ public final class RippleAnimationSession {
|
|||||||
private Runnable mOnUpdate;
|
private Runnable mOnUpdate;
|
||||||
private long mStartTime;
|
private long mStartTime;
|
||||||
private boolean mForceSoftware;
|
private boolean mForceSoftware;
|
||||||
private boolean mAnimateSparkle;
|
private Animator mLoopAnimation;
|
||||||
|
|
||||||
RippleAnimationSession(@NonNull AnimationProperties<Float, Paint> properties,
|
RippleAnimationSession(@NonNull AnimationProperties<Float, Paint> properties,
|
||||||
boolean forceSoftware) {
|
boolean forceSoftware) {
|
||||||
@@ -88,16 +90,6 @@ public final class RippleAnimationSession {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldAnimateSparkle() {
|
|
||||||
return mAnimateSparkle && ValueAnimator.getDurationScale() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getSparklePhase() {
|
|
||||||
final long now = AnimationUtils.currentAnimationTimeMillis();
|
|
||||||
final long elapsed = now - mStartTime;
|
|
||||||
return (float) elapsed / 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isHwAccelerated(Canvas canvas) {
|
private boolean isHwAccelerated(Canvas canvas) {
|
||||||
return canvas.isHardwareAccelerated() && !mForceSoftware;
|
return canvas.isHardwareAccelerated() && !mForceSoftware;
|
||||||
}
|
}
|
||||||
@@ -114,7 +106,7 @@ public final class RippleAnimationSession {
|
|||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
super.onAnimationEnd(animation);
|
super.onAnimationEnd(animation);
|
||||||
mAnimateSparkle = false;
|
if (mLoopAnimation != null) mLoopAnimation.cancel();
|
||||||
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
|
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
|
||||||
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
|
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
|
||||||
}
|
}
|
||||||
@@ -148,7 +140,7 @@ public final class RippleAnimationSession {
|
|||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
super.onAnimationEnd(animation);
|
super.onAnimationEnd(animation);
|
||||||
mAnimateSparkle = false;
|
if (mLoopAnimation != null) mLoopAnimation.cancel();
|
||||||
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
|
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
|
||||||
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
|
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
|
||||||
}
|
}
|
||||||
@@ -167,24 +159,42 @@ public final class RippleAnimationSession {
|
|||||||
RenderNodeAnimator expand =
|
RenderNodeAnimator expand =
|
||||||
new RenderNodeAnimator(props.getProgress(), .5f);
|
new RenderNodeAnimator(props.getProgress(), .5f);
|
||||||
expand.setTarget(canvas);
|
expand.setTarget(canvas);
|
||||||
startAnimation(expand);
|
RenderNodeAnimator loop = new RenderNodeAnimator(props.getNoisePhase(), MAX_NOISE_PHASE);
|
||||||
|
loop.setTarget(canvas);
|
||||||
|
startAnimation(expand, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startAnimation(Animator expand) {
|
private void startAnimation(Animator expand, Animator loop) {
|
||||||
expand.setDuration(ENTER_ANIM_DURATION);
|
expand.setDuration(ENTER_ANIM_DURATION);
|
||||||
expand.addListener(new AnimatorListener(this));
|
expand.addListener(new AnimatorListener(this));
|
||||||
expand.setInterpolator(FAST_OUT_SLOW_IN);
|
expand.setInterpolator(FAST_OUT_SLOW_IN);
|
||||||
expand.start();
|
expand.start();
|
||||||
mAnimateSparkle = true;
|
loop.setDuration(NOISE_ANIMATION_DURATION);
|
||||||
|
loop.addListener(new AnimatorListener(this) {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
super.onAnimationEnd(animation);
|
||||||
|
mLoopAnimation = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
loop.setInterpolator(LINEAR_INTERPOLATOR);
|
||||||
|
loop.start();
|
||||||
|
if (mLoopAnimation != null) mLoopAnimation.cancel();
|
||||||
|
mLoopAnimation = loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enterSoftware() {
|
private void enterSoftware() {
|
||||||
ValueAnimator expand = ValueAnimator.ofFloat(0f, 0.5f);
|
ValueAnimator expand = ValueAnimator.ofFloat(0f, 0.5f);
|
||||||
expand.addUpdateListener(updatedAnimation -> {
|
expand.addUpdateListener(updatedAnimation -> {
|
||||||
notifyUpdate();
|
notifyUpdate();
|
||||||
mProperties.getShader().setProgress((Float) expand.getAnimatedValue());
|
mProperties.getShader().setProgress((float) expand.getAnimatedValue());
|
||||||
});
|
});
|
||||||
startAnimation(expand);
|
ValueAnimator loop = ValueAnimator.ofFloat(0f, MAX_NOISE_PHASE);
|
||||||
|
loop.addUpdateListener(updatedAnimation -> {
|
||||||
|
notifyUpdate();
|
||||||
|
mProperties.getShader().setNoisePhase((float) loop.getAnimatedValue());
|
||||||
|
});
|
||||||
|
startAnimation(expand, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull AnimationProperties<Float, Paint> getProperties() {
|
@NonNull AnimationProperties<Float, Paint> getProperties() {
|
||||||
@@ -198,6 +208,7 @@ public final class RippleAnimationSession {
|
|||||||
CanvasProperty.createFloat(mProperties.getX()),
|
CanvasProperty.createFloat(mProperties.getX()),
|
||||||
CanvasProperty.createFloat(mProperties.getY()),
|
CanvasProperty.createFloat(mProperties.getY()),
|
||||||
CanvasProperty.createFloat(mProperties.getMaxRadius()),
|
CanvasProperty.createFloat(mProperties.getMaxRadius()),
|
||||||
|
CanvasProperty.createFloat(mProperties.getNoisePhase()),
|
||||||
CanvasProperty.createPaint(mProperties.getPaint()),
|
CanvasProperty.createPaint(mProperties.getPaint()),
|
||||||
CanvasProperty.createFloat(mProperties.getProgress()),
|
CanvasProperty.createFloat(mProperties.getProgress()),
|
||||||
mProperties.getShader());
|
mProperties.getShader());
|
||||||
@@ -236,16 +247,18 @@ public final class RippleAnimationSession {
|
|||||||
static class AnimationProperties<FloatType, PaintType> {
|
static class AnimationProperties<FloatType, PaintType> {
|
||||||
private final FloatType mProgress;
|
private final FloatType mProgress;
|
||||||
private final FloatType mMaxRadius;
|
private final FloatType mMaxRadius;
|
||||||
|
private final FloatType mNoisePhase;
|
||||||
private final PaintType mPaint;
|
private final PaintType mPaint;
|
||||||
private final RippleShader mShader;
|
private final RippleShader mShader;
|
||||||
private FloatType mX;
|
private FloatType mX;
|
||||||
private FloatType mY;
|
private FloatType mY;
|
||||||
|
|
||||||
AnimationProperties(FloatType x, FloatType y, FloatType maxRadius,
|
AnimationProperties(FloatType x, FloatType y, FloatType maxRadius, FloatType noisePhase,
|
||||||
PaintType paint, FloatType progress, RippleShader shader) {
|
PaintType paint, FloatType progress, RippleShader shader) {
|
||||||
mY = y;
|
mY = y;
|
||||||
mX = x;
|
mX = x;
|
||||||
mMaxRadius = maxRadius;
|
mMaxRadius = maxRadius;
|
||||||
|
mNoisePhase = noisePhase;
|
||||||
mPaint = paint;
|
mPaint = paint;
|
||||||
mShader = shader;
|
mShader = shader;
|
||||||
mProgress = progress;
|
mProgress = progress;
|
||||||
@@ -279,5 +292,9 @@ public final class RippleAnimationSession {
|
|||||||
RippleShader getShader() {
|
RippleShader getShader() {
|
||||||
return mShader;
|
return mShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FloatType getNoisePhase() {
|
||||||
|
return mNoisePhase;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -858,15 +858,6 @@ public class RippleDrawable extends LayerDrawable {
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < mRunningAnimations.size(); i++) {
|
for (int i = 0; i < mRunningAnimations.size(); i++) {
|
||||||
RippleAnimationSession s = mRunningAnimations.get(i);
|
RippleAnimationSession s = mRunningAnimations.get(i);
|
||||||
if (s.shouldAnimateSparkle()) {
|
|
||||||
final float phase = s.getSparklePhase();
|
|
||||||
if (useCanvasProps) {
|
|
||||||
s.getCanvasProperties().getShader().setNoisePhase(phase);
|
|
||||||
} else {
|
|
||||||
s.getProperties().getShader().setNoisePhase(phase);
|
|
||||||
}
|
|
||||||
invalidateSelf();
|
|
||||||
}
|
|
||||||
if (useCanvasProps) {
|
if (useCanvasProps) {
|
||||||
RippleAnimationSession.AnimationProperties<CanvasProperty<Float>,
|
RippleAnimationSession.AnimationProperties<CanvasProperty<Float>,
|
||||||
CanvasProperty<Paint>>
|
CanvasProperty<Paint>>
|
||||||
@@ -883,7 +874,7 @@ public class RippleDrawable extends LayerDrawable {
|
|||||||
yProp = p.getY();
|
yProp = p.getY();
|
||||||
}
|
}
|
||||||
can.drawRipple(xProp, yProp, p.getMaxRadius(), p.getPaint(),
|
can.drawRipple(xProp, yProp, p.getMaxRadius(), p.getPaint(),
|
||||||
p.getProgress(), p.getShader());
|
p.getProgress(), p.getNoisePhase(), p.getShader());
|
||||||
} else {
|
} else {
|
||||||
RippleAnimationSession.AnimationProperties<Float, Paint> p =
|
RippleAnimationSession.AnimationProperties<Float, Paint> p =
|
||||||
s.getProperties();
|
s.getProperties();
|
||||||
@@ -953,7 +944,7 @@ public class RippleDrawable extends LayerDrawable {
|
|||||||
shader.setRadius(radius);
|
shader.setRadius(radius);
|
||||||
shader.setProgress(.0f);
|
shader.setProgress(.0f);
|
||||||
properties = new RippleAnimationSession.AnimationProperties<>(
|
properties = new RippleAnimationSession.AnimationProperties<>(
|
||||||
cx, cy, radius, p, 0f, shader);
|
cx, cy, radius, 0f, p, 0f, shader);
|
||||||
if (mMaskShader == null) {
|
if (mMaskShader == null) {
|
||||||
shader.setShader(null);
|
shader.setShader(null);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -167,6 +167,9 @@ final class RippleShader extends RuntimeShader {
|
|||||||
final float turbulencePhase = (float) ((mProgress + mNoisePhase * 0.333f) * 5f * Math.PI);
|
final float turbulencePhase = (float) ((mProgress + mNoisePhase * 0.333f) * 5f * Math.PI);
|
||||||
setUniform("in_turbulencePhase", turbulencePhase);
|
setUniform("in_turbulencePhase", turbulencePhase);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Keep in sync with: frameworks/base/libs/hwui/pipeline/skia/AnimatedDrawables.h
|
||||||
|
//
|
||||||
final float scale = 1.5f;
|
final float scale = 1.5f;
|
||||||
setUniform("in_tCircle1", new float[]{
|
setUniform("in_tCircle1", new float[]{
|
||||||
(float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.cos(scale * 0.55))),
|
(float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.cos(scale * 0.55))),
|
||||||
|
|||||||
@@ -820,10 +820,11 @@ void SkiaCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x,
|
|||||||
uirenderer::CanvasPropertyPrimitive* radius,
|
uirenderer::CanvasPropertyPrimitive* radius,
|
||||||
uirenderer::CanvasPropertyPaint* paint,
|
uirenderer::CanvasPropertyPaint* paint,
|
||||||
uirenderer::CanvasPropertyPrimitive* progress,
|
uirenderer::CanvasPropertyPrimitive* progress,
|
||||||
|
uirenderer::CanvasPropertyPrimitive* turbulencePhase,
|
||||||
const SkRuntimeShaderBuilder& effectBuilder) {
|
const SkRuntimeShaderBuilder& effectBuilder) {
|
||||||
sk_sp<uirenderer::skiapipeline::AnimatedRipple> drawable(
|
sk_sp<uirenderer::skiapipeline::AnimatedRipple> drawable(
|
||||||
new uirenderer::skiapipeline::AnimatedRipple(x, y, radius, paint, progress,
|
new uirenderer::skiapipeline::AnimatedRipple(x, y, radius, paint, progress,
|
||||||
effectBuilder));
|
turbulencePhase, effectBuilder));
|
||||||
mCanvas->drawDrawable(drawable.get());
|
mCanvas->drawDrawable(drawable.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ public:
|
|||||||
uirenderer::CanvasPropertyPrimitive* radius,
|
uirenderer::CanvasPropertyPrimitive* radius,
|
||||||
uirenderer::CanvasPropertyPaint* paint,
|
uirenderer::CanvasPropertyPaint* paint,
|
||||||
uirenderer::CanvasPropertyPrimitive* progress,
|
uirenderer::CanvasPropertyPrimitive* progress,
|
||||||
|
uirenderer::CanvasPropertyPrimitive* turbulencePhase,
|
||||||
const SkRuntimeShaderBuilder& effectBuilder) override;
|
const SkRuntimeShaderBuilder& effectBuilder) override;
|
||||||
|
|
||||||
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
|
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
|
||||||
|
|||||||
@@ -152,32 +152,66 @@ struct CanvasOp<CanvasOpType::DrawRippleProperty> {
|
|||||||
sp<uirenderer::CanvasPropertyPrimitive> radius;
|
sp<uirenderer::CanvasPropertyPrimitive> radius;
|
||||||
sp<uirenderer::CanvasPropertyPaint> paint;
|
sp<uirenderer::CanvasPropertyPaint> paint;
|
||||||
sp<uirenderer::CanvasPropertyPrimitive> progress;
|
sp<uirenderer::CanvasPropertyPrimitive> progress;
|
||||||
|
sp<uirenderer::CanvasPropertyPrimitive> turbulencePhase;
|
||||||
sk_sp<SkRuntimeEffect> effect;
|
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);
|
||||||
|
|
||||||
void draw(SkCanvas* canvas) const {
|
void draw(SkCanvas* canvas) const {
|
||||||
SkRuntimeShaderBuilder runtimeEffectBuilder(effect);
|
SkRuntimeShaderBuilder runtimeEffectBuilder(effect);
|
||||||
|
|
||||||
SkRuntimeShaderBuilder::BuilderUniform center = runtimeEffectBuilder.uniform("in_origin");
|
setUniform2f(runtimeEffectBuilder, "in_origin", x->value, y->value);
|
||||||
if (center.fVar != nullptr) {
|
setUniform(runtimeEffectBuilder, "in_radius", radius);
|
||||||
center = SkV2{x->value, y->value};
|
setUniform(runtimeEffectBuilder, "in_progress", progress);
|
||||||
}
|
setUniform(runtimeEffectBuilder, "in_turbulencePhase", turbulencePhase);
|
||||||
|
|
||||||
SkRuntimeShaderBuilder::BuilderUniform radiusU =
|
//
|
||||||
runtimeEffectBuilder.uniform("in_radius");
|
// Keep in sync with:
|
||||||
if (radiusU.fVar != nullptr) {
|
// frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java
|
||||||
radiusU = radius->value;
|
//
|
||||||
}
|
const float turbulence = turbulencePhase->value;
|
||||||
|
setUniform2f(runtimeEffectBuilder, "in_tCircle1", SCALE * 0.5 + (turbulence * CIRCLE_X_1),
|
||||||
SkRuntimeShaderBuilder::BuilderUniform progressU =
|
SCALE * 0.5 + (turbulence * CIRCLE_Y_1));
|
||||||
runtimeEffectBuilder.uniform("in_progress");
|
setUniform2f(runtimeEffectBuilder, "in_tCircle2", SCALE * 0.2 + (turbulence * CIRCLE_X_2),
|
||||||
if (progressU.fVar != nullptr) {
|
SCALE * 0.2 + (turbulence * CIRCLE_Y_2));
|
||||||
progressU = progress->value;
|
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;
|
SkPaint paintMod = paint->value;
|
||||||
paintMod.setShader(runtimeEffectBuilder.makeShader(nullptr, false));
|
paintMod.setShader(runtimeEffectBuilder.makeShader(nullptr, false));
|
||||||
canvas->drawCircle(x->value, y->value, radius->value, paintMod);
|
canvas->drawCircle(x->value, y->value, radius->value, paintMod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
ASSERT_DRAWABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ public:
|
|||||||
uirenderer::CanvasPropertyPrimitive* radius,
|
uirenderer::CanvasPropertyPrimitive* radius,
|
||||||
uirenderer::CanvasPropertyPaint* paint,
|
uirenderer::CanvasPropertyPaint* paint,
|
||||||
uirenderer::CanvasPropertyPrimitive* progress,
|
uirenderer::CanvasPropertyPrimitive* progress,
|
||||||
|
uirenderer::CanvasPropertyPrimitive* turbulencePhase,
|
||||||
const SkRuntimeShaderBuilder& effectBuilder) = 0;
|
const SkRuntimeShaderBuilder& effectBuilder) = 0;
|
||||||
|
|
||||||
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
|
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
|
||||||
|
|||||||
@@ -141,20 +141,22 @@ static void android_view_DisplayListCanvas_drawCircleProps(CRITICAL_JNI_PARAMS_C
|
|||||||
canvas->drawCircle(xProp, yProp, radiusProp, paintProp);
|
canvas->drawCircle(xProp, yProp, radiusProp, paintProp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void android_view_DisplayListCanvas_drawRippleProps(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr,
|
static void android_view_DisplayListCanvas_drawRippleProps(
|
||||||
jlong xPropPtr, jlong yPropPtr,
|
CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong xPropPtr, jlong yPropPtr,
|
||||||
jlong radiusPropPtr, jlong paintPropPtr,
|
jlong radiusPropPtr, jlong paintPropPtr, jlong progressPropPtr, jlong turbulencePhasePtr,
|
||||||
jlong progressPropPtr,
|
jlong builderPtr) {
|
||||||
jlong builderPtr) {
|
|
||||||
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
|
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
|
||||||
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
|
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
|
||||||
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
|
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
|
||||||
CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
|
CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
|
||||||
|
CanvasPropertyPrimitive* turbulencePhaseProp =
|
||||||
|
reinterpret_cast<CanvasPropertyPrimitive*>(turbulencePhasePtr);
|
||||||
CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
|
CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
|
||||||
CanvasPropertyPrimitive* progressProp =
|
CanvasPropertyPrimitive* progressProp =
|
||||||
reinterpret_cast<CanvasPropertyPrimitive*>(progressPropPtr);
|
reinterpret_cast<CanvasPropertyPrimitive*>(progressPropPtr);
|
||||||
SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(builderPtr);
|
SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(builderPtr);
|
||||||
canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, *builder);
|
canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, turbulencePhaseProp,
|
||||||
|
*builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) {
|
static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) {
|
||||||
@@ -169,19 +171,22 @@ static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAM
|
|||||||
const char* const kClassPathName = "android/graphics/RecordingCanvas";
|
const char* const kClassPathName = "android/graphics/RecordingCanvas";
|
||||||
|
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
// ------------ @CriticalNative --------------
|
// ------------ @CriticalNative --------------
|
||||||
{ "nCreateDisplayListCanvas", "(JII)J", (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
|
{"nCreateDisplayListCanvas", "(JII)J",
|
||||||
{ "nResetDisplayListCanvas", "(JJII)V", (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
|
(void*)android_view_DisplayListCanvas_createDisplayListCanvas},
|
||||||
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureSize },
|
{"nResetDisplayListCanvas", "(JJII)V",
|
||||||
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureSize },
|
(void*)android_view_DisplayListCanvas_resetDisplayListCanvas},
|
||||||
{ "nEnableZ", "(JZ)V", (void*) android_view_DisplayListCanvas_enableZ },
|
{"nGetMaximumTextureWidth", "()I", (void*)android_view_DisplayListCanvas_getMaxTextureSize},
|
||||||
{ "nFinishRecording", "(JJ)V", (void*) android_view_DisplayListCanvas_finishRecording },
|
{"nGetMaximumTextureHeight", "()I",
|
||||||
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_DisplayListCanvas_drawRenderNode },
|
(void*)android_view_DisplayListCanvas_getMaxTextureSize},
|
||||||
{ "nDrawTextureLayer", "(JJ)V", (void*) android_view_DisplayListCanvas_drawTextureLayer },
|
{"nEnableZ", "(JZ)V", (void*)android_view_DisplayListCanvas_enableZ},
|
||||||
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_DisplayListCanvas_drawCircleProps },
|
{"nFinishRecording", "(JJ)V", (void*)android_view_DisplayListCanvas_finishRecording},
|
||||||
{ "nDrawRoundRect", "(JJJJJJJJ)V",(void*) android_view_DisplayListCanvas_drawRoundRectProps },
|
{"nDrawRenderNode", "(JJ)V", (void*)android_view_DisplayListCanvas_drawRenderNode},
|
||||||
{ "nDrawWebViewFunctor", "(JI)V", (void*) android_view_DisplayListCanvas_drawWebViewFunctor },
|
{"nDrawTextureLayer", "(JJ)V", (void*)android_view_DisplayListCanvas_drawTextureLayer},
|
||||||
{ "nDrawRipple", "(JJJJJJJ)V", (void*) android_view_DisplayListCanvas_drawRippleProps },
|
{"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},
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_android_view_DisplayListCanvas(JNIEnv* env) {
|
int register_android_view_DisplayListCanvas(JNIEnv* env) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <SkCanvas.h>
|
#include <SkCanvas.h>
|
||||||
#include <SkDrawable.h>
|
#include <SkDrawable.h>
|
||||||
#include <SkRuntimeEffect.h>
|
#include <SkRuntimeEffect.h>
|
||||||
|
#include <math.h>
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
#include "CanvasProperty.h"
|
#include "CanvasProperty.h"
|
||||||
|
|
||||||
@@ -61,12 +62,14 @@ public:
|
|||||||
uirenderer::CanvasPropertyPrimitive* radius,
|
uirenderer::CanvasPropertyPrimitive* radius,
|
||||||
uirenderer::CanvasPropertyPaint* paint,
|
uirenderer::CanvasPropertyPaint* paint,
|
||||||
uirenderer::CanvasPropertyPrimitive* progress,
|
uirenderer::CanvasPropertyPrimitive* progress,
|
||||||
|
uirenderer::CanvasPropertyPrimitive* turbulencePhase,
|
||||||
const SkRuntimeShaderBuilder& effectBuilder)
|
const SkRuntimeShaderBuilder& effectBuilder)
|
||||||
: mX(x)
|
: mX(x)
|
||||||
, mY(y)
|
, mY(y)
|
||||||
, mRadius(radius)
|
, mRadius(radius)
|
||||||
, mPaint(paint)
|
, mPaint(paint)
|
||||||
, mProgress(progress)
|
, mProgress(progress)
|
||||||
|
, mTurbulencePhase(turbulencePhase)
|
||||||
, mRuntimeEffectBuilder(effectBuilder) {}
|
, mRuntimeEffectBuilder(effectBuilder) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -77,22 +80,28 @@ protected:
|
|||||||
return SkRect::MakeLTRB(x - radius, y - radius, x + radius, y + radius);
|
return SkRect::MakeLTRB(x - radius, y - radius, x + radius, y + radius);
|
||||||
}
|
}
|
||||||
virtual void onDraw(SkCanvas* canvas) override {
|
virtual void onDraw(SkCanvas* canvas) override {
|
||||||
SkRuntimeShaderBuilder::BuilderUniform center = mRuntimeEffectBuilder.uniform("in_origin");
|
setUniform2f("in_origin", mX->value, mY->value);
|
||||||
if (center.fVar != nullptr) {
|
setUniform("in_radius", mRadius);
|
||||||
center = SkV2{mX->value, mY->value};
|
setUniform("in_progress", mProgress);
|
||||||
}
|
setUniform("in_turbulencePhase", mTurbulencePhase);
|
||||||
|
|
||||||
SkRuntimeShaderBuilder::BuilderUniform radiusU =
|
//
|
||||||
mRuntimeEffectBuilder.uniform("in_radius");
|
// Keep in sync with:
|
||||||
if (radiusU.fVar != nullptr) {
|
// frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java
|
||||||
radiusU = mRadius->value;
|
//
|
||||||
}
|
const float turbulencePhase = mTurbulencePhase->value;
|
||||||
|
setUniform2f("in_tCircle1", SCALE * 0.5 + (turbulencePhase * CIRCLE_X_1),
|
||||||
SkRuntimeShaderBuilder::BuilderUniform progressU =
|
SCALE * 0.5 + (turbulencePhase * CIRCLE_Y_1));
|
||||||
mRuntimeEffectBuilder.uniform("in_progress");
|
setUniform2f("in_tCircle2", SCALE * 0.2 + (turbulencePhase * CIRCLE_X_2),
|
||||||
if (progressU.fVar != nullptr) {
|
SCALE * 0.2 + (turbulencePhase * CIRCLE_Y_2));
|
||||||
progressU = mProgress->value;
|
setUniform2f("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));
|
||||||
|
const float rotation2 = turbulencePhase * PI_ROTATE_LEFT + 2 * PI;
|
||||||
|
setUniform2f("in_tRotation2", cos(rotation2), sin(rotation2));
|
||||||
|
const float rotation3 = turbulencePhase * PI_ROTATE_RIGHT + 2.75 * PI;
|
||||||
|
setUniform2f("in_tRotation3", cos(rotation3), sin(rotation3));
|
||||||
|
|
||||||
SkPaint paint = mPaint->value;
|
SkPaint paint = mPaint->value;
|
||||||
paint.setShader(mRuntimeEffectBuilder.makeShader(nullptr, false));
|
paint.setShader(mRuntimeEffectBuilder.makeShader(nullptr, false));
|
||||||
@@ -105,7 +114,35 @@ private:
|
|||||||
sp<uirenderer::CanvasPropertyPrimitive> mRadius;
|
sp<uirenderer::CanvasPropertyPrimitive> mRadius;
|
||||||
sp<uirenderer::CanvasPropertyPaint> mPaint;
|
sp<uirenderer::CanvasPropertyPaint> mPaint;
|
||||||
sp<uirenderer::CanvasPropertyPrimitive> mProgress;
|
sp<uirenderer::CanvasPropertyPrimitive> mProgress;
|
||||||
|
sp<uirenderer::CanvasPropertyPrimitive> mTurbulencePhase;
|
||||||
SkRuntimeShaderBuilder mRuntimeEffectBuilder;
|
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());
|
||||||
|
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());
|
||||||
|
if (uniform.fVar != nullptr) {
|
||||||
|
uniform = SkV2{a, b};
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AnimatedCircle : public SkDrawable {
|
class AnimatedCircle : public SkDrawable {
|
||||||
|
|||||||
@@ -114,9 +114,10 @@ void SkiaRecordingCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x,
|
|||||||
uirenderer::CanvasPropertyPrimitive* radius,
|
uirenderer::CanvasPropertyPrimitive* radius,
|
||||||
uirenderer::CanvasPropertyPaint* paint,
|
uirenderer::CanvasPropertyPaint* paint,
|
||||||
uirenderer::CanvasPropertyPrimitive* progress,
|
uirenderer::CanvasPropertyPrimitive* progress,
|
||||||
|
uirenderer::CanvasPropertyPrimitive* turbulencePhase,
|
||||||
const SkRuntimeShaderBuilder& effectBuilder) {
|
const SkRuntimeShaderBuilder& effectBuilder) {
|
||||||
drawDrawable(mDisplayList->allocateDrawable<AnimatedRipple>(x, y, radius, paint, progress,
|
drawDrawable(mDisplayList->allocateDrawable<AnimatedRipple>(x, y, radius, paint, progress,
|
||||||
effectBuilder));
|
turbulencePhase, effectBuilder));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkiaRecordingCanvas::enableZ(bool enableZ) {
|
void SkiaRecordingCanvas::enableZ(bool enableZ) {
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ public:
|
|||||||
uirenderer::CanvasPropertyPrimitive* radius,
|
uirenderer::CanvasPropertyPrimitive* radius,
|
||||||
uirenderer::CanvasPropertyPaint* paint,
|
uirenderer::CanvasPropertyPaint* paint,
|
||||||
uirenderer::CanvasPropertyPrimitive* progress,
|
uirenderer::CanvasPropertyPrimitive* progress,
|
||||||
|
uirenderer::CanvasPropertyPrimitive* turbulencePhase,
|
||||||
const SkRuntimeShaderBuilder& effectBuilder) override;
|
const SkRuntimeShaderBuilder& effectBuilder) override;
|
||||||
|
|
||||||
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
|
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public class RippleActivity extends Activity {
|
|||||||
CanvasProperty<Float> mY;
|
CanvasProperty<Float> mY;
|
||||||
CanvasProperty<Float> mRadius;
|
CanvasProperty<Float> mRadius;
|
||||||
CanvasProperty<Float> mProgress;
|
CanvasProperty<Float> mProgress;
|
||||||
|
CanvasProperty<Float> mNoisePhase;
|
||||||
CanvasProperty<Paint> mPaint;
|
CanvasProperty<Paint> mPaint;
|
||||||
RuntimeShader mRuntimeShader;
|
RuntimeShader mRuntimeShader;
|
||||||
|
|
||||||
@@ -99,6 +100,7 @@ public class RippleActivity extends Activity {
|
|||||||
mY = CanvasProperty.createFloat(200.0f);
|
mY = CanvasProperty.createFloat(200.0f);
|
||||||
mRadius = CanvasProperty.createFloat(150.0f);
|
mRadius = CanvasProperty.createFloat(150.0f);
|
||||||
mProgress = CanvasProperty.createFloat(0.0f);
|
mProgress = CanvasProperty.createFloat(0.0f);
|
||||||
|
mNoisePhase = CanvasProperty.createFloat(0.0f);
|
||||||
|
|
||||||
Paint p = new Paint();
|
Paint p = new Paint();
|
||||||
p.setAntiAlias(true);
|
p.setAntiAlias(true);
|
||||||
@@ -115,7 +117,8 @@ public class RippleActivity extends Activity {
|
|||||||
|
|
||||||
if (canvas.isHardwareAccelerated()) {
|
if (canvas.isHardwareAccelerated()) {
|
||||||
RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
|
RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
|
||||||
recordingCanvas.drawRipple(mX, mY, mRadius, mPaint, mProgress, mRuntimeShader);
|
recordingCanvas.drawRipple(mX, mY, mRadius, mPaint, mProgress, mNoisePhase,
|
||||||
|
mRuntimeShader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +143,9 @@ public class RippleActivity extends Activity {
|
|||||||
mRunningAnimations.add(new RenderNodeAnimator(
|
mRunningAnimations.add(new RenderNodeAnimator(
|
||||||
mProgress, mToggle ? 1.0f : 0.0f));
|
mProgress, mToggle ? 1.0f : 0.0f));
|
||||||
|
|
||||||
|
mRunningAnimations.add(new RenderNodeAnimator(
|
||||||
|
mNoisePhase, DURATION));
|
||||||
|
|
||||||
mRunningAnimations.add(new RenderNodeAnimator(
|
mRunningAnimations.add(new RenderNodeAnimator(
|
||||||
mPaint, RenderNodeAnimator.PAINT_ALPHA, 64.0f));
|
mPaint, RenderNodeAnimator.PAINT_ALPHA, 64.0f));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user