/*
- * Copyright (c) 2021 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.
{
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
: mAnimationTasks(),
mCompletedTasks(),
mWorkingTasks(),
- mRasterizers(GetNumberOfThreads(NUMBER_OF_RASTERIZE_THREADS_ENV, DEFAULT_NUMBER_OF_RASTERIZE_THREADS), [&]() { return RasterizeHelper(*this); }),
mSleepThread(MakeCallback(this, &VectorAnimationThread::OnAwakeFromSleep)),
mConditionalWait(),
mNeedToSleep(false),
mDestroyThread(false),
mLogFactory(Dali::Adaptor::Get().GetLogFactory())
{
+ mAsyncTaskManager = Dali::AsyncTaskManager::Get();
mSleepThread.Start();
+
+ mEventTrigger = std::unique_ptr<EventThreadCallback>(new EventThreadCallback(MakeCallback(this, &VectorAnimationThread::OnEventCallbackTriggered)));
}
VectorAnimationThread::~VectorAnimationThread()
{
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
}
}
-void VectorAnimationThread::OnTaskCompleted(VectorAnimationTaskPtr task, bool keepAnimation)
+void VectorAnimationThread::OnTaskCompleted(VectorAnimationTaskPtr task, bool success, bool keepAnimation)
{
if(!mDestroyThread)
{
needRasterize = true;
}
- if(keepAnimation)
+ if(keepAnimation && success)
{
if(mCompletedTasks.end() == std::find(mCompletedTasks.begin(), mCompletedTasks.end(), task))
{
}
}
+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");
{
VectorAnimationTaskPtr nextTask = *it;
- auto currentTime = std::chrono::system_clock::now();
+ auto currentTime = std::chrono::steady_clock::now();
auto nextFrameTime = nextTask->GetNextFrameTime();
#if defined(DEBUG_ENABLED)
- auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(nextFrameTime - currentTime);
+// auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(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
// 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
{
}
}
-VectorAnimationThread::RasterizeHelper::RasterizeHelper(VectorAnimationThread& animationThread)
-: RasterizeHelper(std::unique_ptr<VectorRasterizeThread>(new VectorRasterizeThread()), animationThread)
-{
-}
-
-VectorAnimationThread::RasterizeHelper::RasterizeHelper(RasterizeHelper&& rhs)
-: RasterizeHelper(std::move(rhs.mRasterizer), rhs.mAnimationThread)
+void VectorAnimationThread::OnEventCallbackTriggered()
{
+ while(CallbackBase* callback = GetNextEventCallback())
+ {
+ CallbackBase::Execute(*callback);
+ }
}
-VectorAnimationThread::RasterizeHelper::RasterizeHelper(std::unique_ptr<VectorRasterizeThread> rasterizer, VectorAnimationThread& animationThread)
-: mRasterizer(std::move(rasterizer)),
- mAnimationThread(animationThread)
+CallbackBase* VectorAnimationThread::GetNextEventCallback()
{
- mRasterizer->SetCompletedCallback(MakeCallback(&mAnimationThread, &VectorAnimationThread::OnTaskCompleted));
-}
+ ConditionalWait::ScopedLock lock(mConditionalWait);
-void VectorAnimationThread::RasterizeHelper::Rasterize(VectorAnimationTaskPtr task)
-{
- if(task)
+ if(!mTriggerEventCallbacks.empty())
{
- mRasterizer->AddTask(task);
+ auto iter = mTriggerEventCallbacks.begin();
+ CallbackBase* callback = *iter;
+ mTriggerEventCallbacks.erase(iter);
+ return callback;
}
+ mEventTriggered = false;
+ return nullptr;
}
VectorAnimationThread::SleepThread::SleepThread(CallbackBase* callback)
Join();
}
-void VectorAnimationThread::SleepThread::SleepUntil(std::chrono::time_point<std::chrono::system_clock> timeToSleepUntil)
+void VectorAnimationThread::SleepThread::SleepUntil(std::chrono::time_point<std::chrono::steady_clock> timeToSleepUntil)
{
ConditionalWait::ScopedLock lock(mConditionalWait);
mSleepTimePoint = timeToSleepUntil;
while(!mDestroyThread)
{
bool needToSleep;
- std::chrono::time_point<std::chrono::system_clock> sleepTimePoint;
+ std::chrono::time_point<std::chrono::steady_clock> sleepTimePoint;
{
ConditionalWait::ScopedLock lock(mConditionalWait);
if(needToSleep)
{
#if defined(DEBUG_ENABLED)
- auto sleepDuration = std::chrono::duration_cast<std::chrono::milliseconds>(mSleepTimePoint - std::chrono::system_clock::now());
+// auto sleepDuration = std::chrono::duration_cast<std::chrono::milliseconds>(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);