blob: 4a8c12230eeba845d846d8ae2dce0a9475a26bd6 [file] [log] [blame]
John Recke45b1fd2014-04-15 09:50:16 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "RT-Animator"
18
19#include "Animator.h"
20
John Reck68bfe0a2014-06-24 15:34:58 -070021#include <inttypes.h>
John Recke45b1fd2014-04-15 09:50:16 -070022#include <set>
23
John Reck52244ff2014-05-01 21:27:37 -070024#include "RenderNode.h"
John Recke45b1fd2014-04-15 09:50:16 -070025#include "RenderProperties.h"
26
27namespace android {
28namespace uirenderer {
29
30/************************************************************
John Reckff941dc2014-05-14 16:34:14 -070031 * BaseRenderNodeAnimator
John Recke45b1fd2014-04-15 09:50:16 -070032 ************************************************************/
33
John Reckff941dc2014-05-14 16:34:14 -070034BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
35 : mFinalValue(finalValue)
36 , mDeltaValue(0)
37 , mFromValue(0)
38 , mInterpolator(0)
John Reck68bfe0a2014-06-24 15:34:58 -070039 , mStagingPlayState(NOT_STARTED)
40 , mPlayState(NOT_STARTED)
41 , mHasStartValue(false)
John Recke45b1fd2014-04-15 09:50:16 -070042 , mStartTime(0)
Alan Viverettead2f8e32014-05-16 13:28:33 -070043 , mDuration(300)
44 , mStartDelay(0) {
John Recke45b1fd2014-04-15 09:50:16 -070045}
46
John Reckff941dc2014-05-14 16:34:14 -070047BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
John Reck68bfe0a2014-06-24 15:34:58 -070048 delete mInterpolator;
49}
50
51void BaseRenderNodeAnimator::checkMutable() {
52 // Should be impossible to hit as the Java-side also has guards for this
53 LOG_ALWAYS_FATAL_IF(mStagingPlayState != NOT_STARTED,
54 "Animator has already been started!");
John Recke45b1fd2014-04-15 09:50:16 -070055}
56
John Reckff941dc2014-05-14 16:34:14 -070057void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
John Reck68bfe0a2014-06-24 15:34:58 -070058 checkMutable();
John Recke45b1fd2014-04-15 09:50:16 -070059 delete mInterpolator;
60 mInterpolator = interpolator;
61}
62
John Reckff941dc2014-05-14 16:34:14 -070063void BaseRenderNodeAnimator::setStartValue(float value) {
John Reck68bfe0a2014-06-24 15:34:58 -070064 checkMutable();
65 doSetStartValue(value);
John Reckff941dc2014-05-14 16:34:14 -070066}
67
John Reck68bfe0a2014-06-24 15:34:58 -070068void BaseRenderNodeAnimator::doSetStartValue(float value) {
69 mFromValue = value;
70 mDeltaValue = (mFinalValue - mFromValue);
71 mHasStartValue = true;
John Reckff941dc2014-05-14 16:34:14 -070072}
73
Alan Viverettead2f8e32014-05-16 13:28:33 -070074void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
John Reck68bfe0a2014-06-24 15:34:58 -070075 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070076 mDuration = duration;
77}
78
79void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
John Reck68bfe0a2014-06-24 15:34:58 -070080 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070081 mStartDelay = startDelay;
82}
83
John Reck68bfe0a2014-06-24 15:34:58 -070084void BaseRenderNodeAnimator::pushStaging(RenderNode* target, TreeInfo& info) {
85 if (!mHasStartValue) {
86 doSetStartValue(getValue(target));
Alan Viverettead2f8e32014-05-16 13:28:33 -070087 }
John Reck68bfe0a2014-06-24 15:34:58 -070088 if (mStagingPlayState > mPlayState) {
89 mPlayState = mStagingPlayState;
90 // Oh boy, we're starting! Man the battle stations!
91 if (mPlayState == RUNNING) {
92 transitionToRunning(info);
John Recke45b1fd2014-04-15 09:50:16 -070093 }
John Recke45b1fd2014-04-15 09:50:16 -070094 }
John Reck68bfe0a2014-06-24 15:34:58 -070095}
96
97void BaseRenderNodeAnimator::transitionToRunning(TreeInfo& info) {
98 LOG_ALWAYS_FATAL_IF(info.frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", info.frameTimeMs);
99 if (mStartDelay < 0 || mStartDelay > 50000) {
100 ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
101 }
102 mStartTime = info.frameTimeMs + mStartDelay;
103 if (mStartTime < 0) {
104 ALOGW("Ended up with a really weird start time of %" PRId64
105 " with frame time %" PRId64 " and start delay %" PRId64,
106 mStartTime, info.frameTimeMs, mStartDelay);
107 // Set to 0 so that the animate() basically instantly finishes
108 mStartTime = 0;
109 }
110 // No interpolator was set, use the default
111 if (!mInterpolator) {
112 setInterpolator(Interpolator::createDefaultInterpolator());
113 }
114 if (mDuration < 0 || mDuration > 50000) {
115 ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
116 }
117}
118
119bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
120 if (mPlayState < RUNNING) {
121 return false;
122 }
123
124 if (mStartTime > info.frameTimeMs) {
125 info.out.hasAnimations |= true;
126 return false;
127 }
John Recke45b1fd2014-04-15 09:50:16 -0700128
129 float fraction = 1.0f;
John Reck68bfe0a2014-06-24 15:34:58 -0700130 if (mPlayState == RUNNING && mDuration > 0) {
131 fraction = (float)(info.frameTimeMs - mStartTime) / mDuration;
John Recke45b1fd2014-04-15 09:50:16 -0700132 }
John Reck68bfe0a2014-06-24 15:34:58 -0700133 if (fraction >= 1.0f) {
134 fraction = 1.0f;
135 mPlayState = FINISHED;
136 }
137
John Recke45b1fd2014-04-15 09:50:16 -0700138 fraction = mInterpolator->interpolate(fraction);
John Reckff941dc2014-05-14 16:34:14 -0700139 setValue(target, mFromValue + (mDeltaValue * fraction));
John Recke45b1fd2014-04-15 09:50:16 -0700140
141 if (mPlayState == FINISHED) {
John Reck52244ff2014-05-01 21:27:37 -0700142 callOnFinishedListener(info);
John Recke45b1fd2014-04-15 09:50:16 -0700143 return true;
144 }
John Reck68bfe0a2014-06-24 15:34:58 -0700145
146 info.out.hasAnimations |= true;
John Recke45b1fd2014-04-15 09:50:16 -0700147 return false;
148}
149
John Reckff941dc2014-05-14 16:34:14 -0700150void BaseRenderNodeAnimator::callOnFinishedListener(TreeInfo& info) {
John Reck52244ff2014-05-01 21:27:37 -0700151 if (mListener.get()) {
152 if (!info.animationHook) {
153 mListener->onAnimationFinished(this);
154 } else {
155 info.animationHook->callOnFinished(this, mListener.get());
156 }
157 }
158}
159
160/************************************************************
John Recke45b1fd2014-04-15 09:50:16 -0700161 * RenderPropertyAnimator
162 ************************************************************/
163
John Reckff941dc2014-05-14 16:34:14 -0700164struct RenderPropertyAnimator::PropertyAccessors {
165 RenderNode::DirtyPropertyMask dirtyMask;
166 GetFloatProperty getter;
167 SetFloatProperty setter;
John Reck52244ff2014-05-01 21:27:37 -0700168};
169
John Reckff941dc2014-05-14 16:34:14 -0700170// Maps RenderProperty enum to accessors
171const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
172 {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
173 {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
174 {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
175 {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
176 {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
177 {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
178 {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
179 {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
180 {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
181 {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
182 {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
183 {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
184};
185
186RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
187 : BaseRenderNodeAnimator(finalValue)
188 , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
John Recke45b1fd2014-04-15 09:50:16 -0700189}
190
John Reckff941dc2014-05-14 16:34:14 -0700191void RenderPropertyAnimator::onAttached(RenderNode* target) {
John Reck68bfe0a2014-06-24 15:34:58 -0700192 if (!mHasStartValue
John Reckc6b32642014-06-02 11:00:09 -0700193 && target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
John Reckff941dc2014-05-14 16:34:14 -0700194 setStartValue((target->stagingProperties().*mPropertyAccess->getter)());
195 }
196 (target->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
John Recke45b1fd2014-04-15 09:50:16 -0700197}
198
John Reck22184722014-06-20 07:19:30 -0700199uint32_t RenderPropertyAnimator::dirtyMask() {
200 return mPropertyAccess->dirtyMask;
201}
202
John Reckff941dc2014-05-14 16:34:14 -0700203float RenderPropertyAnimator::getValue(RenderNode* target) const {
204 return (target->properties().*mPropertyAccess->getter)();
205}
206
207void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
208 (target->animatorProperties().*mPropertyAccess->setter)(value);
John Recke45b1fd2014-04-15 09:50:16 -0700209}
210
John Reck52244ff2014-05-01 21:27:37 -0700211/************************************************************
212 * CanvasPropertyPrimitiveAnimator
213 ************************************************************/
John Recke45b1fd2014-04-15 09:50:16 -0700214
John Reck52244ff2014-05-01 21:27:37 -0700215CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
John Reckff941dc2014-05-14 16:34:14 -0700216 CanvasPropertyPrimitive* property, float finalValue)
217 : BaseRenderNodeAnimator(finalValue)
John Reck52244ff2014-05-01 21:27:37 -0700218 , mProperty(property) {
219}
220
John Reckff941dc2014-05-14 16:34:14 -0700221float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700222 return mProperty->value;
223}
224
John Reckff941dc2014-05-14 16:34:14 -0700225void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700226 mProperty->value = value;
227}
228
229/************************************************************
230 * CanvasPropertySkPaintAnimator
231 ************************************************************/
232
233CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
John Reckff941dc2014-05-14 16:34:14 -0700234 CanvasPropertyPaint* property, PaintField field, float finalValue)
235 : BaseRenderNodeAnimator(finalValue)
John Reck52244ff2014-05-01 21:27:37 -0700236 , mProperty(property)
237 , mField(field) {
238}
239
John Reckff941dc2014-05-14 16:34:14 -0700240float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700241 switch (mField) {
242 case STROKE_WIDTH:
243 return mProperty->value.getStrokeWidth();
244 case ALPHA:
245 return mProperty->value.getAlpha();
John Recke45b1fd2014-04-15 09:50:16 -0700246 }
John Reck52244ff2014-05-01 21:27:37 -0700247 LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
248 return -1;
John Recke45b1fd2014-04-15 09:50:16 -0700249}
250
John Reck531ee702014-05-13 10:06:08 -0700251static uint8_t to_uint8(float value) {
252 int c = (int) (value + .5f);
253 return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
254}
255
John Reckff941dc2014-05-14 16:34:14 -0700256void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700257 switch (mField) {
258 case STROKE_WIDTH:
259 mProperty->value.setStrokeWidth(value);
260 return;
261 case ALPHA:
John Reck531ee702014-05-13 10:06:08 -0700262 mProperty->value.setAlpha(to_uint8(value));
John Reck52244ff2014-05-01 21:27:37 -0700263 return;
264 }
265 LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
John Recke45b1fd2014-04-15 09:50:16 -0700266}
267
268} /* namespace uirenderer */
269} /* namespace android */