[dali_2.3.22] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / vector-animation-thread.cpp
index 08b52d6..5638ec3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 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.
@@ -45,9 +45,13 @@ VectorAnimationThread::VectorAnimationThread()
   mWorkingTasks(),
   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();
@@ -60,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();
@@ -150,25 +161,43 @@ void VectorAnimationThread::OnAwakeFromSleep()
   }
 }
 
-void VectorAnimationThread::AddEventTriggerCallback(CallbackBase* callback)
+void VectorAnimationThread::AddEventTriggerCallback(CallbackBase* callback, uint32_t argument)
 {
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-  mTriggerEventCallbacks.push_back(callback);
+  Mutex::ScopedLock lock(mEventTriggerMutex);
+  if(!mDestroyThread)
+  {
+    mTriggerEventCallbacks.emplace_back(callback, argument);
+
+    if(!mEventTriggered)
+    {
+      mEventTrigger->Trigger();
+      mEventTriggered = true;
+    }
+  }
+}
 
-  if(!mEventTriggered)
+void VectorAnimationThread::RemoveEventTriggerCallbacks(CallbackBase* callback)
+{
+  Mutex::ScopedLock lock(mEventTriggerMutex);
+  if(!mDestroyThread)
   {
-    mEventTrigger->Trigger();
-    mEventTriggered = true;
+    auto iter = std::remove_if(mTriggerEventCallbacks.begin(), mTriggerEventCallbacks.end(), [&callback](std::pair<CallbackBase*, uint32_t>& item) { return item.first == callback; });
+    mTriggerEventCallbacks.erase(iter, mTriggerEventCallbacks.end());
   }
 }
 
-void VectorAnimationThread::RemoveEventTriggerCallback(CallbackBase* callback)
+void VectorAnimationThread::RequestForceRenderOnce()
 {
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-  auto                        iter = std::find(mTriggerEventCallbacks.begin(), mTriggerEventCallbacks.end(), callback);
-  if(iter != mTriggerEventCallbacks.end())
+  Mutex::ScopedLock lock(mEventTriggerMutex);
+  if(!mDestroyThread)
   {
-    mTriggerEventCallbacks.erase(iter);
+    mForceRenderOnce = true;
+
+    if(!mEventTriggered)
+    {
+      mEventTrigger->Trigger();
+      mEventTriggered = true;
+    }
   }
 }
 
@@ -176,6 +205,7 @@ void VectorAnimationThread::Run()
 {
   SetThreadName("VectorAnimationThread");
   mLogFactory.InstallLogFunction();
+  mTraceFactory.InstallTraceFunction();
 
   while(!mDestroyThread)
   {
@@ -263,15 +293,44 @@ void VectorAnimationThread::Rasterize()
 
 void VectorAnimationThread::OnEventCallbackTriggered()
 {
-  ConditionalWait::ScopedLock lock(mConditionalWait);
-
-  for(auto&& iter : mTriggerEventCallbacks)
+  while(true)
   {
-    CallbackBase::Execute(*iter);
+    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();
+      }
+    }
+  }
+}
 
-  mTriggerEventCallbacks.clear();
-  mEventTriggered = false;
+std::pair<CallbackBase*, uint32_t> VectorAnimationThread::GetNextEventCallback()
+{
+  Mutex::ScopedLock lock(mEventTriggerMutex);
+  if(!mDestroyThread)
+  {
+    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)
@@ -279,6 +338,7 @@ VectorAnimationThread::SleepThread::SleepThread(CallbackBase* callback)
   mAwakeCallback(std::unique_ptr<CallbackBase>(callback)),
   mSleepTimePoint(),
   mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
+  mTraceFactory(Dali::Adaptor::Get().GetTraceFactory()),
   mNeedToSleep(false),
   mDestroyThread(false)
 {
@@ -308,6 +368,7 @@ void VectorAnimationThread::SleepThread::Run()
 {
   SetThreadName("VectorSleepThread");
   mLogFactory.InstallLogFunction();
+  mTraceFactory.InstallTraceFunction();
 
   while(!mDestroyThread)
   {