diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/hwui/AnimationContext.h | 2 | ||||
| -rw-r--r-- | libs/hwui/Animator.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/Animator.h | 12 | ||||
| -rw-r--r-- | libs/hwui/DisplayList.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/DisplayList.h | 21 | ||||
| -rw-r--r-- | libs/hwui/DisplayListCanvas.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/PropertyValuesAnimatorSet.cpp | 21 | ||||
| -rw-r--r-- | libs/hwui/PropertyValuesAnimatorSet.h | 14 | ||||
| -rw-r--r-- | libs/hwui/PropertyValuesHolder.cpp | 65 | ||||
| -rw-r--r-- | libs/hwui/PropertyValuesHolder.h | 117 | ||||
| -rw-r--r-- | libs/hwui/RecordingCanvas.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/RenderNode.cpp | 14 | ||||
| -rw-r--r-- | libs/hwui/RenderNode.h | 6 | ||||
| -rw-r--r-- | libs/hwui/VectorDrawable.h | 19 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/RenderNodeTests.cpp | 41 |
16 files changed, 237 insertions, 107 deletions
diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h index 909ed36a2127..801fd8719a14 100644 --- a/libs/hwui/AnimationContext.h +++ b/libs/hwui/AnimationContext.h @@ -100,6 +100,8 @@ public: ANDROID_API virtual void destroy(); + ANDROID_API virtual void detachAnimators() {} + private: friend class AnimationHandle; void addAnimationHandle(AnimationHandle* handle); diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index 4d65782f684b..dc180188100b 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -274,6 +274,10 @@ bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) { return playTime >= mDuration; } +nsecs_t BaseRenderNodeAnimator::getRemainingPlayTime() { + return mPlayState == PlayState::Reversing ? mPlayTime : mDuration - mPlayTime; +} + void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) { if (mPlayState < PlayState::Finished) { mPlayState = PlayState::Finished; diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index fdae0f32d4e6..9476750afd52 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -62,19 +62,23 @@ public: } bool mayRunAsync() { return mMayRunAsync; } ANDROID_API void start(); - ANDROID_API void reset(); + ANDROID_API virtual void reset(); ANDROID_API void reverse(); // Terminates the animation at its current progress. ANDROID_API void cancel(); // Terminates the animation and skip to the end of the animation. - ANDROID_API void end(); + ANDROID_API virtual void end(); void attach(RenderNode* target); virtual void onAttached() {} void detach() { mTarget = nullptr; } - void pushStaging(AnimationContext& context); - bool animate(AnimationContext& context); + ANDROID_API void pushStaging(AnimationContext& context); + ANDROID_API bool animate(AnimationContext& context); + + // Returns the remaining time in ms for the animation. Note this should only be called during + // an animation on RenderThread. + ANDROID_API nsecs_t getRemainingPlayTime(); bool isRunning() { return mPlayState == PlayState::Running || mPlayState == PlayState::Reversing; } diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index b572bdaccb86..28be05c52cfc 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -45,7 +45,7 @@ DisplayList::DisplayList() , regions(stdAllocator) , referenceHolders(stdAllocator) , functors(stdAllocator) - , pushStagingFunctors(stdAllocator) + , vectorDrawables(stdAllocator) , hasDrawOps(false) { } diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index 5b3227b7db97..ccf71c6d360b 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -69,6 +69,11 @@ typedef DisplayListOp BaseOpType; typedef DrawRenderNodeOp NodeOpType; #endif +namespace VectorDrawable { +class Tree; +}; +typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; + /** * Holds data used in the playback a tree of DisplayLists. */ @@ -110,16 +115,6 @@ struct ReplayStateStruct : public PlaybackStateStruct { LinearAllocator mReplayAllocator; }; -/** - * Functor that can be used for objects with data in both UI thread and RT to keep the data - * in sync. This functor, when added to DisplayList, will be call during DisplayList sync. - */ -struct PushStagingFunctor { - PushStagingFunctor() {} - virtual ~PushStagingFunctor() {} - virtual void operator ()() {} -}; - struct FunctorContainer { Functor* functor; GlFunctorLifecycleListener* listener; @@ -161,7 +156,7 @@ public: const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; } const LsaVector<FunctorContainer>& getFunctors() const { return functors; } - const LsaVector<PushStagingFunctor*>& getPushStagingFunctors() { return pushStagingFunctors; } + const LsaVector<VectorDrawableRoot*>& getVectorDrawables() { return vectorDrawables; } size_t addChild(NodeOpType* childOp); @@ -203,10 +198,10 @@ private: // List of functors LsaVector<FunctorContainer> functors; - // List of functors that need to be notified of pushStaging. Note that this list gets nothing + // List of VectorDrawables that need to be notified of pushStaging. Note that this list gets nothing // but a callback during sync DisplayList, unlike the list of functors defined above, which // gets special treatment exclusive for webview. - LsaVector<PushStagingFunctor*> pushStagingFunctors; + LsaVector<VectorDrawableRoot*> vectorDrawables; bool hasDrawOps; // only used if !HWUI_NEW_OPS diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp index ca968cef91b2..bec662959f91 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -417,7 +417,7 @@ void DisplayListCanvas::drawPoints(const float* points, int count, const SkPaint void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { mDisplayList->ref(tree); - mDisplayList->pushStagingFunctors.push_back(tree->getFunctor()); + mDisplayList->vectorDrawables.push_back(tree); addDrawOp(new (alloc()) DrawVectorDrawableOp(tree, tree->stagingProperties()->getBounds())); } diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp index b29f91ff34aa..796c73b9c3e7 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.cpp +++ b/libs/hwui/PropertyValuesAnimatorSet.cpp @@ -29,7 +29,11 @@ void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* proper PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder, interpolator, startDelay, duration, repeatCount); mAnimators.emplace_back(animator); - setListener(new PropertyAnimatorSetListener(this)); + + // Check whether any child animator is infinite after adding it them to the set. + if (repeatCount == -1) { + mIsInfinite = true; + } } PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() @@ -37,6 +41,7 @@ PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() setStartValue(0); mLastFraction = 0.0f; setInterpolator(new LinearInterpolator()); + setListener(new PropertyAnimatorSetListener(this)); } void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) { @@ -78,15 +83,27 @@ void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { void PropertyValuesAnimatorSet::start(AnimationListener* listener) { init(); mOneShotListener = listener; + mRequestId++; BaseRenderNodeAnimator::start(); } void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { init(); mOneShotListener = listener; + mRequestId++; BaseRenderNodeAnimator::reverse(); } +void PropertyValuesAnimatorSet::reset() { + mRequestId++; + BaseRenderNodeAnimator::reset(); +} + +void PropertyValuesAnimatorSet::end() { + mRequestId++; + BaseRenderNodeAnimator::end(); +} + void PropertyValuesAnimatorSet::init() { if (mInitialized) { return; @@ -98,7 +115,7 @@ void PropertyValuesAnimatorSet::init() { std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) { return a->getTotalDuration() < b->getTotalDuration(); }); - mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration(); + mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration(); mInitialized = true; } diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h index c7ae7c0e8ce1..49021bc82825 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.h +++ b/libs/hwui/PropertyValuesAnimatorSet.h @@ -43,6 +43,7 @@ private: float mLatestFraction = 0.0f; }; +// TODO: This class should really be named VectorDrawableAnimator class ANDROID_API PropertyValuesAnimatorSet : public BaseRenderNodeAnimator { public: friend class PropertyAnimatorSetListener; @@ -50,11 +51,19 @@ public: void start(AnimationListener* listener); void reverse(AnimationListener* listener); + virtual void reset() override; + virtual void end() override; void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, Interpolator* interpolators, int64_t startDelays, nsecs_t durations, int repeatCount); virtual uint32_t dirtyMask(); + bool isInfinite() { return mIsInfinite; } + void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; } + VectorDrawableRoot* getVectorDrawable() const { return mVectorDrawable; } + AnimationListener* getOneShotListener() { return mOneShotListener.get(); } + void clearOneShotListener() { mOneShotListener = nullptr; } + uint32_t getRequestId() const { return mRequestId; } protected: virtual float getValue(RenderNode* target) const override; @@ -69,6 +78,11 @@ private: std::vector< std::unique_ptr<PropertyAnimator> > mAnimators; float mLastFraction = 0.0f; bool mInitialized = false; + VectorDrawableRoot* mVectorDrawable = nullptr; + bool mIsInfinite = false; + // This request id gets incremented (on UI thread only) when a new request to modfiy the + // lifecycle of an animation happens, namely when start/end/reset/reverse is called. + uint32_t mRequestId = 0; }; class PropertyAnimatorSetListener : public AnimationListener { diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp index 0932d653fd5e..6ba0ab59a88c 100644 --- a/libs/hwui/PropertyValuesHolder.cpp +++ b/libs/hwui/PropertyValuesHolder.cpp @@ -25,7 +25,27 @@ namespace uirenderer { using namespace VectorDrawable; -float PropertyValuesHolder::getValueFromData(float fraction) { +inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) { + return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction); +} + +// TODO: Add a test for this +void ColorEvaluator::evaluate(SkColor* outColor, + const SkColor& fromColor, const SkColor& toColor, float fraction) const { + U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction); + U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction); + U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction); + U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction); + *outColor = SkColorSetARGB(alpha, red, green, blue); +} + +void PathEvaluator::evaluate(PathData* out, + const PathData& from, const PathData& to, float fraction) const { + VectorDrawableUtils::interpolatePaths(out, from, to, fraction); +} + +template<typename T> +const T PropertyValuesHolderImpl<T>::getValueFromData(float fraction) const { if (mDataSource.size() == 0) { LOG_ALWAYS_FATAL("No data source is defined"); return 0; @@ -41,57 +61,44 @@ float PropertyValuesHolder::getValueFromData(float fraction) { int lowIndex = floor(fraction); fraction -= lowIndex; - float value = mDataSource[lowIndex] * (1.0f - fraction) - + mDataSource[lowIndex + 1] * fraction; + T value; + mEvaluator->evaluate(&value, mDataSource[lowIndex], mDataSource[lowIndex + 1], fraction); return value; } -void GroupPropertyValuesHolder::setFraction(float fraction) { - float animatedValue; +template<typename T> +const T PropertyValuesHolderImpl<T>::calculateAnimatedValue(float fraction) const { if (mDataSource.size() > 0) { - animatedValue = getValueFromData(fraction); + return getValueFromData(fraction); } else { - animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; + T value; + mEvaluator->evaluate(&value, mStartValue, mEndValue, fraction); + return value; } - mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue); } -inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) { - return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction); -} - -// TODO: Add a test for this -SkColor FullPathColorPropertyValuesHolder::interpolateColors(SkColor fromColor, SkColor toColor, - float fraction) { - U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction); - U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction); - U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction); - U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction); - return SkColorSetARGB(alpha, red, green, blue); +void GroupPropertyValuesHolder::setFraction(float fraction) { + float animatedValue = calculateAnimatedValue(fraction); + mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue); } void FullPathColorPropertyValuesHolder::setFraction(float fraction) { - SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction); + SkColor animatedValue = calculateAnimatedValue(fraction); mFullPath->mutateProperties()->setColorPropertyValue(mPropertyId, animatedValue); } void FullPathPropertyValuesHolder::setFraction(float fraction) { - float animatedValue; - if (mDataSource.size() > 0) { - animatedValue = getValueFromData(fraction); - } else { - animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; - } + float animatedValue = calculateAnimatedValue(fraction); mFullPath->mutateProperties()->setPropertyValue(mPropertyId, animatedValue); } void PathDataPropertyValuesHolder::setFraction(float fraction) { - VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction); + mEvaluator->evaluate(&mPathData, mStartValue, mEndValue, fraction); mPath->mutateProperties()->setData(mPathData); } void RootAlphaPropertyValuesHolder::setFraction(float fraction) { - float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; + float animatedValue = calculateAnimatedValue(fraction); mTree->mutateProperties()->setRootAlpha(animatedValue); } diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h index b905faef104c..432f8ba82afb 100644 --- a/libs/hwui/PropertyValuesHolder.h +++ b/libs/hwui/PropertyValuesHolder.h @@ -31,91 +31,130 @@ namespace uirenderer { class ANDROID_API PropertyValuesHolder { public: virtual void setFraction(float fraction) = 0; - void setPropertyDataSource(float* dataSource, int length) { + virtual ~PropertyValuesHolder() {} +}; + +template <typename T> +class Evaluator { +public: + virtual void evaluate(T* out, const T& from, const T& to, float fraction) const {}; + virtual ~Evaluator() {} +}; + +class FloatEvaluator : public Evaluator<float> { +public: + virtual void evaluate(float* out, const float& from, const float& to, float fraction) + const override { + *out = from * (1 - fraction) + to * fraction; + } +}; + +class ANDROID_API ColorEvaluator : public Evaluator<SkColor> { +public: + virtual void evaluate(SkColor* outColor, const SkColor& from, const SkColor& to, + float fraction) const override; +}; + +class ANDROID_API PathEvaluator : public Evaluator<PathData> { + virtual void evaluate(PathData* out, const PathData& from, const PathData& to, float fraction) + const override; +}; + +template <typename T> +class ANDROID_API PropertyValuesHolderImpl : public PropertyValuesHolder { +public: + PropertyValuesHolderImpl(const T& startValue, const T& endValue) + : mStartValue(startValue) + , mEndValue(endValue) {} + void setPropertyDataSource(T* dataSource, int length) { mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length); } - float getValueFromData(float fraction); - virtual ~PropertyValuesHolder() {} + // Calculate the animated value from the data source. + const T getValueFromData(float fraction) const; + // Convenient method to favor getting animated value from data source. If no data source is set + // fall back to linear interpolation. + const T calculateAnimatedValue(float fraction) const; protected: - std::vector<float> mDataSource; + std::unique_ptr<Evaluator<T>> mEvaluator = nullptr; + // This contains uniformly sampled data throughout the animation duration. The first element + // should be the start value and the last should be the end value of the animation. When the + // data source is set, we'll favor data source over the linear interpolation of start/end value + // for calculation of animated value. + std::vector<T> mDataSource; + T mStartValue; + T mEndValue; }; -class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolderImpl<float> { public: GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue, float endValue) - : mGroup(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue){ + : PropertyValuesHolderImpl(startValue, endValue) + , mGroup(ptr) + , mPropertyId(propertyId) { + mEvaluator.reset(new FloatEvaluator()); } void setFraction(float fraction) override; private: VectorDrawable::Group* mGroup; int mPropertyId; - float mStartValue; - float mEndValue; }; -class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolderImpl<SkColor> { public: - FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, int32_t startValue, - int32_t endValue) - : mFullPath(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue) {}; + FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, + SkColor startValue, SkColor endValue) + : PropertyValuesHolderImpl(startValue, endValue) + , mFullPath(ptr) + , mPropertyId(propertyId) { + mEvaluator.reset(new ColorEvaluator()); + } void setFraction(float fraction) override; static SkColor interpolateColors(SkColor fromColor, SkColor toColor, float fraction); private: VectorDrawable::FullPath* mFullPath; int mPropertyId; - int32_t mStartValue; - int32_t mEndValue; }; -class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolderImpl<float> { public: FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue, float endValue) - : mFullPath(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue) {}; + : PropertyValuesHolderImpl(startValue, endValue) + , mFullPath(ptr) + , mPropertyId(propertyId) { + mEvaluator.reset(new FloatEvaluator()); + }; void setFraction(float fraction) override; private: VectorDrawable::FullPath* mFullPath; int mPropertyId; - float mStartValue; - float mEndValue; }; -class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolderImpl<PathData> { public: PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue, PathData* endValue) - : mPath(ptr) - , mStartValue(*startValue) - , mEndValue(*endValue) {}; + : PropertyValuesHolderImpl(*startValue, *endValue) + , mPath(ptr) { + mEvaluator.reset(new PathEvaluator()); + }; void setFraction(float fraction) override; private: VectorDrawable::Path* mPath; PathData mPathData; - PathData mStartValue; - PathData mEndValue; }; -class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolderImpl<float> { public: RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue) - : mTree(tree) - , mStartValue(startValue) - , mEndValue(endValue) {} + : PropertyValuesHolderImpl(startValue, endValue) + , mTree(tree) { + mEvaluator.reset(new FloatEvaluator()); + } void setFraction(float fraction) override; private: VectorDrawable::Tree* mTree; - float mStartValue; - float mEndValue; }; } } diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index b49f9b529989..b35c92612a42 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -440,8 +440,8 @@ void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) { } void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { - mDisplayList->pushStagingFunctors.push_back(tree->getFunctor()); mDisplayList->ref(tree); + mDisplayList->vectorDrawables.push_back(tree); addOp(alloc().create_trivial<VectorDrawableOp>( tree, Rect(tree->stagingProperties()->getBounds()), diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index d48d54438ae9..f8797bf63442 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -421,6 +421,16 @@ void RenderNode::prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer) { prepareSubTree(info, childFunctorsNeedLayer, mDisplayList); pushLayerUpdate(info); + if (mDisplayList) { + for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) { + // If any vector drawable in the display list needs update, damage the node. + if (vectorDrawable->isDirty()) { + damageSelf(info); + } + vectorDrawable->setPropertyChangeWillBeConsumed(true); + } + } + info.damageAccumulator->popTransform(); } @@ -479,8 +489,8 @@ void RenderNode::syncDisplayList(TreeInfo* info) { for (auto& iter : mDisplayList->getFunctors()) { (*iter.functor)(DrawGlInfo::kModeSync, nullptr); } - for (size_t i = 0; i < mDisplayList->getPushStagingFunctors().size(); i++) { - (*mDisplayList->getPushStagingFunctors()[i])(); + for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) { + vectorDrawable->syncProperties(); } } } diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index f80be5ec9ae9..47fef6da355c 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -232,7 +232,7 @@ public: // the frameNumber to appropriately batch/synchronize these transactions. // There is no other filtering/batching to ensure that only the "final" // state called once per frame. - class ANDROID_API PositionListener { + class ANDROID_API PositionListener : public VirtualLightRefBase { public: virtual ~PositionListener() {} // Called when the RenderNode's position changes @@ -247,7 +247,7 @@ public: // before the RenderNode is used for drawing. // RenderNode takes ownership of the pointer ANDROID_API void setPositionListener(PositionListener* listener) { - mPositionListener.reset(listener); + mPositionListener = listener; } // This is only modified in MODE_FULL, so it can be safely accessed @@ -366,7 +366,7 @@ private: // mDisplayList, not mStagingDisplayList. uint32_t mParentCount; - std::unique_ptr<PositionListener> mPositionListener; + sp<PositionListener> mPositionListener; }; // class RenderNode } /* namespace uirenderer */ diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index a5d1d4b86673..e67dfdd15703 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -673,21 +673,16 @@ public: void onPropertyChanged(TreeProperties* prop); TreeProperties* mutateStagingProperties() { return &mStagingProperties; } const TreeProperties* stagingProperties() const { return &mStagingProperties; } - PushStagingFunctor* getFunctor() { return &mFunctor;} // This should only be called from animations on RT TreeProperties* mutateProperties() { return &mProperties; } + // This should always be called from RT. + bool isDirty() const { return mCache.dirty; } + bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; } + void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; } + private: - class VectorDrawableFunctor : public PushStagingFunctor { - public: - VectorDrawableFunctor(Tree* tree) : mTree(tree) {} - virtual void operator ()() { - mTree->syncProperties(); - } - private: - Tree* mTree; - }; SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop); bool allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height); @@ -704,8 +699,6 @@ private: TreeProperties mProperties = TreeProperties(this); TreeProperties mStagingProperties = TreeProperties(this); - VectorDrawableFunctor mFunctor = VectorDrawableFunctor(this); - SkPaint mPaint; struct Cache { SkBitmap bitmap; @@ -717,6 +710,8 @@ private: PropertyChangedListener mPropertyChangedListener = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty); + + mutable bool mWillBeConsumed = false; }; } // namespace VectorDrawable diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index c626c5452310..ceef9c788fc1 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -282,6 +282,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, void CanvasContext::stopDrawing() { mRenderThread.removeFrameCallback(this); + mAnimationContext->detachAnimators(); } void CanvasContext::notifyFramePending() { @@ -783,6 +784,7 @@ void CanvasContext::enqueueFrameWork(std::function<void()>&& func) { } sp<FuncTask> task(new FuncTask()); task->func = func; + mFrameFences.push_back(task); mFrameWorkProcessor->add(task); } diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp index b2997dfb357f..cf76a8691dcd 100644 --- a/libs/hwui/tests/unit/RenderNodeTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeTests.cpp @@ -16,13 +16,26 @@ #include <gtest/gtest.h> +#include "AnimationContext.h" +#include "DamageAccumulator.h" +#include "IContextFactory.h" #include "RenderNode.h" #include "TreeInfo.h" +#include "renderthread/CanvasContext.h" #include "tests/common/TestUtils.h" #include "utils/Color.h" using namespace android; using namespace android::uirenderer; +using namespace android::uirenderer::renderthread; + +class ContextFactory : public android::uirenderer::IContextFactory { +public: + android::uirenderer::AnimationContext* createAnimationContext + (android::uirenderer::renderthread::TimeLord& clock) override { + return new android::uirenderer::AnimationContext(clock); + } +}; TEST(RenderNode, hasParents) { auto child = TestUtils::createNode(0, 0, 200, 400, @@ -89,3 +102,31 @@ TEST(RenderNode, releasedCallback) { TestUtils::syncHierarchyPropertiesAndDisplayList(node); EXPECT_EQ(0, refcnt); } + +RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) { + ContextFactory contextFactory; + CanvasContext canvasContext(renderThread, false, nullptr, &contextFactory); + TreeInfo info(TreeInfo::MODE_RT_ONLY, canvasContext); + DamageAccumulator damageAccumulator; + info.damageAccumulator = &damageAccumulator; + info.observer = nullptr; + + { + auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400, + [](RenderProperties& props, TestCanvas& canvas) { + canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode); + }); + TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode); + EXPECT_TRUE(nonNullDLNode->getDisplayList()); + nonNullDLNode->prepareTree(info); + } + + { + auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr); + TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode); + EXPECT_FALSE(nullDLNode->getDisplayList()); + nullDLNode->prepareTree(info); + } + + canvasContext.destroy(nullptr); +} |