From 56491a0fbf1309f91720deda08029667944a452b Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Tue, 13 Jun 2023 16:33:48 +0900 Subject: [PATCH] (Vector) Use one EventThreadCallback EventThreadCallback uses an fd internally and some systems have a limit on the number of fd. So reduce the number of fd Change-Id: I55f6e7f5211d0bc567a1b2362c782e9fc2a74b90 --- .../utc-Dali-AnimatedVectorImageVisual.cpp | 65 ++++++++++++++++------ .../animated-vector-image-visual.cpp | 2 +- .../vector-animation-task.cpp | 26 ++++----- .../animated-vector-image/vector-animation-task.h | 6 +- .../vector-animation-thread.cpp | 37 ++++++++++++ .../vector-animation-thread.h | 45 +++++++++++---- 6 files changed, 136 insertions(+), 45 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index 92cc203..6a5a089 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -974,8 +974,7 @@ int UtcDaliAnimatedVectorImageVisualAnimationFinishedSignal(void) Property::Map propertyMap; propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE) - .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME) - .Add(DevelImageVisual::Property::LOOP_COUNT, 3); + .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME); Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap); DALI_TEST_CHECK(visual); @@ -991,14 +990,24 @@ int UtcDaliAnimatedVectorImageVisualAnimationFinishedSignal(void) application.GetScene().Add(actor); + application.SendNotification(); + application.Render(); + + // Trigger count is 1 - render a frame + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + propertyMap.Clear(); + propertyMap.Add(DevelImageVisual::Property::LOOP_COUNT, 3); + DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, propertyMap); + Property::Map attributes; DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes); application.SendNotification(); application.Render(); - // Wait for animation finish - render, finish - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION); + // Wait for animation finish + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); Property::Map map = actor.GetProperty(DummyControl::Property::TEST_VISUAL); Property::Value* value = map.Find(DevelImageVisual::Property::PLAY_STATE); @@ -1269,8 +1278,6 @@ int UtcDaliAnimatedVectorImageVisualStopBehavior(void) Property::Map propertyMap; propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE) .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME) - .Add(DevelImageVisual::Property::LOOP_COUNT, 3) - .Add(DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::FIRST_FRAME) .Add(ImageVisual::Property::SYNCHRONOUS_LOADING, false); Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap); @@ -1285,14 +1292,25 @@ int UtcDaliAnimatedVectorImageVisualStopBehavior(void) application.GetScene().Add(actor); + application.SendNotification(); + application.Render(); + + // Trigger count is 2 - load & render a frame + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION); + + propertyMap.Clear(); + propertyMap.Add(DevelImageVisual::Property::LOOP_COUNT, 3); + propertyMap.Add(DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::FIRST_FRAME); + DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, propertyMap); + Property::Map attributes; DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes); application.SendNotification(); application.Render(); - // Trigger count is 3 - load, render, animation finished - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION); + // Trigger count is 1 - animation finished + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); Property::Map map = actor.GetProperty(DummyControl::Property::TEST_VISUAL); Property::Value* value = map.Find(DevelImageVisual::Property::CURRENT_FRAME_NUMBER); @@ -1377,9 +1395,6 @@ int UtcDaliAnimatedVectorImageVisualLoopingMode(void) Property::Map propertyMap; propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE) .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME) - .Add(DevelImageVisual::Property::LOOP_COUNT, 3) - .Add(DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME) - .Add(DevelImageVisual::Property::LOOPING_MODE, DevelImageVisual::LoopingMode::AUTO_REVERSE) .Add(ImageVisual::Property::SYNCHRONOUS_LOADING, false); Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap); @@ -1394,14 +1409,26 @@ int UtcDaliAnimatedVectorImageVisualLoopingMode(void) application.GetScene().Add(actor); + application.SendNotification(); + application.Render(); + + // Trigger count is 2 - load, render + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION); + + propertyMap.Clear(); + propertyMap.Add(DevelImageVisual::Property::LOOP_COUNT, 3); + propertyMap.Add(DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME); + propertyMap.Add(DevelImageVisual::Property::LOOPING_MODE, DevelImageVisual::LoopingMode::AUTO_REVERSE); + DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, propertyMap); + Property::Map attributes; DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes); application.SendNotification(); application.Render(); - // Trigger count is 3 - load, render, animation finished - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION); + // Trigger count is 1 - animation finished + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); Property::Map map = actor.GetProperty(DummyControl::Property::TEST_VISUAL); Property::Value* value = map.Find(DevelImageVisual::Property::CURRENT_FRAME_NUMBER); @@ -1566,6 +1593,12 @@ int UtcDaliAnimatedVectorImageVisualMultipleInstances(void) application.GetScene().Add(actor1); + application.SendNotification(); + application.Render(); + + // Trigger count is 2 - load & render a frame + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION); + propertyMap.Clear(); propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE) .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME) @@ -1585,8 +1618,8 @@ int UtcDaliAnimatedVectorImageVisualMultipleInstances(void) application.SendNotification(); application.Render(); - // Trigger count is 4 - load & render a frame for each instance - DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(4), true, TEST_LOCATION); + // Trigger count is 2 - load & render a frame + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION); DevelControl::DoAction(actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, Property::Map()); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index 5d987b9..8a4ada9 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -377,7 +377,7 @@ void AnimatedVectorImageVisual::DoSetProperty(Property::Index index, const Prope void AnimatedVectorImageVisual::OnInitialize(void) { mVectorAnimationTask->ResourceReadySignal().Connect(this, &AnimatedVectorImageVisual::OnResourceReady); - mVectorAnimationTask->SetAnimationFinishedCallback(new EventThreadCallback(MakeCallback(this, &AnimatedVectorImageVisual::OnAnimationFinished))); + mVectorAnimationTask->SetAnimationFinishedCallback(MakeCallback(this, &AnimatedVectorImageVisual::OnAnimationFinished)); mVectorAnimationTask->RequestLoad(mUrl.GetUrl(), IsSynchronousLoadingRequired()); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index 40f1a64..6d4b2ef 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -53,8 +53,7 @@ VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache) mVectorAnimationThread(factoryCache.GetVectorAnimationManager().GetVectorAnimationThread()), mConditionalWait(), mResourceReadySignal(), - mAnimationFinishedTrigger(), - mLoadCompletedTrigger(new EventThreadCallback(MakeCallback(this, &VectorAnimationTask::OnLoadCompleted))), + mLoadCompletedCallback(MakeCallback(this, &VectorAnimationTask::OnLoadCompleted)), mPlayState(PlayState::STOPPED), mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME), mLoopingMode(DevelImageVisual::LoopingMode::RESTART), @@ -104,13 +103,13 @@ void VectorAnimationTask::Finalize() ConditionalWait::ScopedLock lock(mConditionalWait); // Release some objects in the main thread - if(mAnimationFinishedTrigger) + if(mAnimationFinishedCallback) { - mAnimationFinishedTrigger.reset(); + mVectorAnimationThread.RemoveEventTriggerCallback(mAnimationFinishedCallback.get()); } - if(mLoadCompletedTrigger) + if(mLoadCompletedCallback) { - mLoadCompletedTrigger.reset(); + mVectorAnimationThread.RemoveEventTriggerCallback(mLoadCompletedCallback.get()); } mVectorRenderer.Finalize(); @@ -142,7 +141,7 @@ bool VectorAnimationTask::Load(bool synchronousLoading) mLoadFailed = true; if(!synchronousLoading) { - mLoadCompletedTrigger->Trigger(); + mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get()); } return false; } @@ -157,7 +156,7 @@ bool VectorAnimationTask::Load(bool synchronousLoading) mLoadRequest = false; if(!synchronousLoading) { - mLoadCompletedTrigger->Trigger(); + mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get()); } DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Load: file = %s [%d frames, %f fps] [%p]\n", mUrl.c_str(), mTotalFrame, mFrameRate, this); @@ -263,13 +262,10 @@ void VectorAnimationTask::PauseAnimation() } } -void VectorAnimationTask::SetAnimationFinishedCallback(EventThreadCallback* callback) +void VectorAnimationTask::SetAnimationFinishedCallback(CallbackBase* callback) { ConditionalWait::ScopedLock lock(mConditionalWait); - if(callback) - { - mAnimationFinishedTrigger = std::unique_ptr(callback); - } + mAnimationFinishedCallback = std::unique_ptr(callback); } void VectorAnimationTask::SetLoopCount(int32_t count) @@ -547,9 +543,9 @@ bool VectorAnimationTask::Rasterize() // Animation is finished { ConditionalWait::ScopedLock lock(mConditionalWait); - if(mNeedAnimationFinishedTrigger && mAnimationFinishedTrigger) + if(mNeedAnimationFinishedTrigger && mAnimationFinishedCallback) { - mAnimationFinishedTrigger->Trigger(); + mVectorAnimationThread.AddEventTriggerCallback(mAnimationFinishedCallback.get()); } } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h index 0b2c43e..e1b80c3 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h @@ -181,7 +181,7 @@ public: * @brief This callback is called after the animation is finished. * @param[in] callback The animation finished callback */ - void SetAnimationFinishedCallback(EventThreadCallback* callback); + void SetAnimationFinishedCallback(CallbackBase* callback); /** * @brief Gets the playing range in frame number. @@ -361,8 +361,8 @@ private: VectorAnimationThread& mVectorAnimationThread; ConditionalWait mConditionalWait; ResourceReadySignalType mResourceReadySignal; - std::unique_ptr mAnimationFinishedTrigger; - std::unique_ptr mLoadCompletedTrigger; + std::unique_ptr mAnimationFinishedCallback{}; + std::unique_ptr mLoadCompletedCallback{}; PlayState mPlayState; DevelImageVisual::StopBehavior::Type mStopBehavior; DevelImageVisual::LoopingMode::Type mLoopingMode; diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp index 02198f0..08b52d6 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp @@ -51,6 +51,8 @@ VectorAnimationThread::VectorAnimationThread() { mAsyncTaskManager = Dali::AsyncTaskManager::Get(); mSleepThread.Start(); + + mEventTrigger = std::unique_ptr(new EventThreadCallback(MakeCallback(this, &VectorAnimationThread::OnEventCallbackTriggered))); } VectorAnimationThread::~VectorAnimationThread() @@ -148,6 +150,28 @@ void VectorAnimationThread::OnAwakeFromSleep() } } +void VectorAnimationThread::AddEventTriggerCallback(CallbackBase* callback) +{ + ConditionalWait::ScopedLock lock(mConditionalWait); + mTriggerEventCallbacks.push_back(callback); + + if(!mEventTriggered) + { + mEventTrigger->Trigger(); + mEventTriggered = true; + } +} + +void VectorAnimationThread::RemoveEventTriggerCallback(CallbackBase* callback) +{ + ConditionalWait::ScopedLock lock(mConditionalWait); + auto iter = std::find(mTriggerEventCallbacks.begin(), mTriggerEventCallbacks.end(), callback); + if(iter != mTriggerEventCallbacks.end()) + { + mTriggerEventCallbacks.erase(iter); + } +} + void VectorAnimationThread::Run() { SetThreadName("VectorAnimationThread"); @@ -237,6 +261,19 @@ void VectorAnimationThread::Rasterize() } } +void VectorAnimationThread::OnEventCallbackTriggered() +{ + ConditionalWait::ScopedLock lock(mConditionalWait); + + for(auto&& iter : mTriggerEventCallbacks) + { + CallbackBase::Execute(*iter); + } + + mTriggerEventCallbacks.clear(); + mEventTriggered = false; +} + VectorAnimationThread::SleepThread::SleepThread(CallbackBase* callback) : mConditionalWait(), mAwakeCallback(std::unique_ptr(callback)), diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h index 0fd37e4..79d1a48 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h @@ -51,7 +51,7 @@ public: ~VectorAnimationThread() override; /** - * Add a animation task into the vector animation thread, called by main thread. + * @brief Add a animation task into the vector animation thread, called by main thread. * * @param[in] task The task added to the thread. */ @@ -59,6 +59,7 @@ public: /** * @brief Called when the rasterization is completed from the rasterize thread. + * * @param[in] task The completed task * @param[in] success true if the task succeeded, false otherwise. * @param[in] keepAnimation true if the animation is running, false otherwise. @@ -70,6 +71,22 @@ public: */ void OnAwakeFromSleep(); + /** + * @brief Add an event trigger callback. + * + * @param callback The callback to add + * @note Ownership of the callback is NOT passed onto this class. + * @note The callback will be excuted in the main thread. + */ + void AddEventTriggerCallback(CallbackBase* callback); + + /** + * @brief Remove an event trigger callback. + * + * @param callback The callback to remove + */ + void RemoveEventTriggerCallback(CallbackBase* callback); + protected: /** * @brief The entry function of the animation thread. @@ -83,6 +100,11 @@ private: void Rasterize(); /** + * @brief Called when the event callback is triggered. + */ + void OnEventCallbackTriggered(); + + /** * @brief The thread to sleep until the next frame time. */ class SleepThread : public Thread @@ -130,15 +152,18 @@ private: VectorAnimationThread& operator=(const VectorAnimationThread& thread) = delete; private: - std::vector mAnimationTasks; - std::vector mCompletedTasks; - std::vector mWorkingTasks; - SleepThread mSleepThread; - ConditionalWait mConditionalWait; - bool mNeedToSleep; - bool mDestroyThread; - const Dali::LogFactoryInterface& mLogFactory; - Dali::AsyncTaskManager mAsyncTaskManager; + std::vector mAnimationTasks; + std::vector mCompletedTasks; + std::vector mWorkingTasks; + std::vector mTriggerEventCallbacks{}; // Callbacks are not owned + SleepThread mSleepThread; + ConditionalWait mConditionalWait; + std::unique_ptr mEventTrigger{}; + bool mNeedToSleep; + bool mDestroyThread; + bool mEventTriggered{false}; + const Dali::LogFactoryInterface& mLogFactory; + Dali::AsyncTaskManager mAsyncTaskManager; }; } // namespace Internal -- 2.7.4