X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-vector-image%2Fvector-animation-thread.cpp;h=5638ec3a0bb060c62c82cc0ac972a67845fff626;hb=HEAD;hp=97634f6f13690fe3198049428cddff6e90926bc1;hpb=6f585409b0bfdb37162aaf8234255751e80c6e0e;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git 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 97634f6..5638ec3 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -33,19 +33,6 @@ namespace Internal { namespace { -constexpr auto DEFAULT_NUMBER_OF_RASTERIZE_THREADS = size_t{4u}; -constexpr auto NUMBER_OF_RASTERIZE_THREADS_ENV = "DALI_VECTOR_RASTERIZE_THREADS"; - -size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue) -{ - using Dali::EnvironmentVariable::GetEnvironmentVariable; - auto numberString = GetEnvironmentVariable(environmentVariable); - auto numberOfThreads = numberString ? std::strtoul(numberString, nullptr, 10) : 0; - constexpr auto MAX_NUMBER_OF_THREADS = 100u; - DALI_ASSERT_DEBUG(numberOfThreads < MAX_NUMBER_OF_THREADS); - return (numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS) ? numberOfThreads : defaultValue; -} - #if defined(DEBUG_ENABLED) Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION"); #endif @@ -56,14 +43,20 @@ VectorAnimationThread::VectorAnimationThread() : mAnimationTasks(), mCompletedTasks(), mWorkingTasks(), - mRasterizers(GetNumberOfThreads(NUMBER_OF_RASTERIZE_THREADS_ENV, DEFAULT_NUMBER_OF_RASTERIZE_THREADS), [&]() { return RasterizeHelper(*this); }), mSleepThread(MakeCallback(this, &VectorAnimationThread::OnAwakeFromSleep)), mConditionalWait(), + mEventTriggerMutex(), + mLogFactory(Dali::Adaptor::Get().GetLogFactory()), + mTraceFactory(Dali::Adaptor::Get().GetTraceFactory()), mNeedToSleep(false), mDestroyThread(false), - mLogFactory(Dali::Adaptor::Get().GetLogFactory()) + mEventTriggered(false), + mForceRenderOnce(false) { + mAsyncTaskManager = Dali::AsyncTaskManager::Get(); mSleepThread.Start(); + + mEventTrigger = std::unique_ptr(new EventThreadCallback(MakeCallback(this, &VectorAnimationThread::OnEventCallbackTriggered))); } VectorAnimationThread::~VectorAnimationThread() @@ -71,11 +64,18 @@ VectorAnimationThread::~VectorAnimationThread() // Stop the thread { ConditionalWait::ScopedLock lock(mConditionalWait); - mDestroyThread = true; - mNeedToSleep = false; + // Wait until some event thread trigger relative job finished. + { + Mutex::ScopedLock lock(mEventTriggerMutex); + mDestroyThread = true; + } + mNeedToSleep = false; mConditionalWait.Notify(lock); } + // Stop event trigger + mEventTrigger.reset(); + DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::~VectorAnimationThread: Join [%p]\n", this); Join(); @@ -85,7 +85,9 @@ void VectorAnimationThread::AddTask(VectorAnimationTaskPtr task) { ConditionalWait::ScopedLock lock(mConditionalWait); - if(mAnimationTasks.end() == std::find(mAnimationTasks.begin(), mAnimationTasks.end(), task)) + // Find if the task is already in the list except loading task + auto iter = std::find_if(mAnimationTasks.begin(), mAnimationTasks.end(), [task](VectorAnimationTaskPtr& element) { return (element == task && !element->IsLoadRequested()); }); + if(iter == mAnimationTasks.end()) { auto currentTime = task->CalculateNextFrameTime(true); // Rasterize as soon as possible @@ -112,7 +114,7 @@ void VectorAnimationThread::AddTask(VectorAnimationTaskPtr task) } } -void VectorAnimationThread::OnTaskCompleted(VectorAnimationTaskPtr task, bool keepAnimation) +void VectorAnimationThread::OnTaskCompleted(VectorAnimationTaskPtr task, bool success, bool keepAnimation) { if(!mDestroyThread) { @@ -131,7 +133,7 @@ void VectorAnimationThread::OnTaskCompleted(VectorAnimationTaskPtr task, bool ke needRasterize = true; } - if(keepAnimation) + if(keepAnimation && success) { if(mCompletedTasks.end() == std::find(mCompletedTasks.begin(), mCompletedTasks.end(), task)) { @@ -159,10 +161,51 @@ void VectorAnimationThread::OnAwakeFromSleep() } } +void VectorAnimationThread::AddEventTriggerCallback(CallbackBase* callback, uint32_t argument) +{ + Mutex::ScopedLock lock(mEventTriggerMutex); + if(!mDestroyThread) + { + mTriggerEventCallbacks.emplace_back(callback, argument); + + if(!mEventTriggered) + { + mEventTrigger->Trigger(); + mEventTriggered = true; + } + } +} + +void VectorAnimationThread::RemoveEventTriggerCallbacks(CallbackBase* callback) +{ + Mutex::ScopedLock lock(mEventTriggerMutex); + if(!mDestroyThread) + { + auto iter = std::remove_if(mTriggerEventCallbacks.begin(), mTriggerEventCallbacks.end(), [&callback](std::pair& item) { return item.first == callback; }); + mTriggerEventCallbacks.erase(iter, mTriggerEventCallbacks.end()); + } +} + +void VectorAnimationThread::RequestForceRenderOnce() +{ + Mutex::ScopedLock lock(mEventTriggerMutex); + if(!mDestroyThread) + { + mForceRenderOnce = true; + + if(!mEventTriggered) + { + mEventTrigger->Trigger(); + mEventTriggered = true; + } + } +} + void VectorAnimationThread::Run() { SetThreadName("VectorAnimationThread"); mLogFactory.InstallLogFunction(); + mTraceFactory.InstallTraceFunction(); while(!mDestroyThread) { @@ -220,11 +263,10 @@ void VectorAnimationThread::Rasterize() auto nextFrameTime = nextTask->GetNextFrameTime(); #if defined(DEBUG_ENABLED) - auto duration = std::chrono::duration_cast(nextFrameTime - currentTime); +// auto duration = std::chrono::duration_cast(nextFrameTime - currentTime); - DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::Rasterize: [next time = %lld]\n", duration.count()); +// DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::Rasterize: [next time = %lld]\n", duration.count()); #endif - if(nextFrameTime <= currentTime) { // If the task is not in the working list @@ -234,11 +276,7 @@ void VectorAnimationThread::Rasterize() // Add it to the working list mWorkingTasks.push_back(nextTask); - - auto rasterizerHelperIt = mRasterizers.GetNext(); - DALI_ASSERT_ALWAYS(rasterizerHelperIt != mRasterizers.End()); - - rasterizerHelperIt->Rasterize(nextTask); + mAsyncTaskManager.AddTask(nextTask); } else { @@ -253,29 +291,46 @@ void VectorAnimationThread::Rasterize() } } -VectorAnimationThread::RasterizeHelper::RasterizeHelper(VectorAnimationThread& animationThread) -: RasterizeHelper(std::unique_ptr(new VectorRasterizeThread()), animationThread) -{ -} - -VectorAnimationThread::RasterizeHelper::RasterizeHelper(RasterizeHelper&& rhs) -: RasterizeHelper(std::move(rhs.mRasterizer), rhs.mAnimationThread) -{ -} - -VectorAnimationThread::RasterizeHelper::RasterizeHelper(std::unique_ptr rasterizer, VectorAnimationThread& animationThread) -: mRasterizer(std::move(rasterizer)), - mAnimationThread(animationThread) +void VectorAnimationThread::OnEventCallbackTriggered() { - mRasterizer->SetCompletedCallback(MakeCallback(&mAnimationThread, &VectorAnimationThread::OnTaskCompleted)); + while(true) + { + auto callbackPair = GetNextEventCallback(); + if(callbackPair.first == nullptr) + { + break; + } + CallbackBase::Execute(*callbackPair.first, callbackPair.second); + } + // Request update once if we need. + { + Mutex::ScopedLock lock(mEventTriggerMutex); + if(!mDestroyThread && mForceRenderOnce) + { + mForceRenderOnce = false; + if(Dali::Adaptor::IsAvailable()) + { + Dali::Adaptor::Get().UpdateOnce(); + } + } + } } -void VectorAnimationThread::RasterizeHelper::Rasterize(VectorAnimationTaskPtr task) +std::pair VectorAnimationThread::GetNextEventCallback() { - if(task) + Mutex::ScopedLock lock(mEventTriggerMutex); + if(!mDestroyThread) { - mRasterizer->AddTask(task); + if(!mTriggerEventCallbacks.empty()) + { + auto iter = mTriggerEventCallbacks.begin(); + auto callbackIdPair = *iter; + mTriggerEventCallbacks.erase(iter); + return callbackIdPair; + } + mEventTriggered = false; } + return std::make_pair(nullptr, 0u); } VectorAnimationThread::SleepThread::SleepThread(CallbackBase* callback) @@ -283,6 +338,7 @@ VectorAnimationThread::SleepThread::SleepThread(CallbackBase* callback) mAwakeCallback(std::unique_ptr(callback)), mSleepTimePoint(), mLogFactory(Dali::Adaptor::Get().GetLogFactory()), + mTraceFactory(Dali::Adaptor::Get().GetTraceFactory()), mNeedToSleep(false), mDestroyThread(false) { @@ -312,6 +368,7 @@ void VectorAnimationThread::SleepThread::Run() { SetThreadName("VectorSleepThread"); mLogFactory.InstallLogFunction(); + mTraceFactory.InstallTraceFunction(); while(!mDestroyThread) { @@ -330,9 +387,9 @@ void VectorAnimationThread::SleepThread::Run() if(needToSleep) { #if defined(DEBUG_ENABLED) - auto sleepDuration = std::chrono::duration_cast(mSleepTimePoint - std::chrono::steady_clock::now()); +// auto sleepDuration = std::chrono::duration_cast(mSleepTimePoint - std::chrono::steady_clock::now()); - DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::SleepThread::Run: [sleep duration = %lld]\n", sleepDuration.count()); +// DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::SleepThread::Run: [sleep duration = %lld]\n", sleepDuration.count()); #endif std::this_thread::sleep_until(sleepTimePoint);