Revert "[Tizen] Print logs if dali skip rendering"
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-manager.cpp
index 2723a7b..d7771cc 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.
@@ -224,6 +224,7 @@ struct UpdateManager::Impl
       (*iter)->OnDestroy();
       Node::Delete(*iter);
     }
+    nodeIdMap.clear();
 
     for(auto&& scene : scenes)
     {
@@ -275,6 +276,8 @@ struct UpdateManager::Impl
 
   Vector<Node*> nodes; ///< A container of all instantiated nodes
 
+  std::unordered_map<uint32_t, Node*> nodeIdMap; ///< A container of nodes map by id.
+
   Vector<Camera*> cameras; ///< A container of cameras. Note : these cameras are owned by Impl::nodes.
 
   OwnerContainer<PropertyOwner*> customObjects; ///< A container of owned objects (with custom properties)
@@ -294,6 +297,8 @@ struct UpdateManager::Impl
   DiscardQueue<MemoryPoolKey<Renderer>, OwnerKeyContainer<Renderer>> rendererDiscardQueue;
   DiscardQueue<Scene*, OwnerContainer<Scene*>>                       sceneDiscardQueue;
 
+  CompleteNotificationInterface::ParameterList notifyRequiredAnimations; ///< A temperal container of complete notify required animations, like animation finished, stopped, or loop completed.
+
   OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
 
   MessageQueue                         messageQueue;          ///< The messages queued from the event-thread
@@ -358,6 +363,10 @@ void UpdateManager::InstallRoot(OwnerPointer<Layer>& layer)
 
   rootLayer->AddInitializeResetter(*this);
 
+  // Do not allow to insert duplicated nodes.
+  // It could be happened if node id is overflowed.
+  DALI_ASSERT_ALWAYS(mImpl->nodeIdMap.insert({rootLayer->GetId(), rootLayer}).second);
+
   mImpl->scenes.emplace_back(new Impl::SceneInfo(rootLayer));
 }
 
@@ -375,6 +384,8 @@ void UpdateManager::UninstallRoot(Layer* layer)
     }
   }
 
+  mImpl->nodeIdMap.erase(layer->GetId());
+
   mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), layer);
 
   // Notify the layer about impending destruction
@@ -394,7 +405,12 @@ void UpdateManager::AddNode(OwnerPointer<Node>& node)
     AddCamera(static_cast<Camera*>(rawNode));
   }
 
+  // Do not allow to insert duplicated nodes.
+  // It could be happened if node id is overflowed.
+  DALI_ASSERT_ALWAYS(mImpl->nodeIdMap.insert({rawNode->GetId(), rawNode}).second);
+
   mImpl->nodes.PushBack(rawNode);
+
   rawNode->CreateTransform(&mImpl->transformManager);
 }
 
@@ -406,6 +422,7 @@ void UpdateManager::ConnectNode(Node* parent, Node* node)
 
   DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] ConnectNode\n", node);
 
+  parent->SetDirtyFlag(NodePropertyFlags::DESCENDENT_HIERARCHY_CHANGED); // make parent dirty so that render items dont get reused
   parent->ConnectChild(node);
 
   node->AddInitializeResetter(*this);
@@ -423,7 +440,7 @@ void UpdateManager::DisconnectNode(Node* node)
 
   Node* parent = node->GetParent();
   DALI_ASSERT_ALWAYS(nullptr != parent);
-  parent->SetDirtyFlag(NodePropertyFlags::CHILD_DELETED); // make parent dirty so that render items dont get reused
+  parent->SetDirtyFlag(NodePropertyFlags::CHILD_DELETED | NodePropertyFlags::DESCENDENT_HIERARCHY_CHANGED); // make parent dirty so that render items dont get reused
 
   parent->DisconnectChild(mSceneGraphBuffers.GetUpdateBufferIndex(), *node);
 
@@ -458,6 +475,8 @@ void UpdateManager::DestroyNode(Node* node)
     RemoveCamera(static_cast<Camera*>(node));
   }
 
+  mImpl->nodeIdMap.erase(node->GetId());
+
   mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), node);
 
   // Notify the Node about impending destruction
@@ -571,9 +590,23 @@ void UpdateManager::StopAnimation(Animation* animation)
 
   bool animationFinished = animation->Stop(mSceneGraphBuffers.GetUpdateBufferIndex());
 
+  // Queue this animation into notify required animations. Since we need to send Finished signal
+  mImpl->notifyRequiredAnimations.PushBack(animation->GetNotifyId());
+
   mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
 }
 
+void UpdateManager::ClearAnimation(Animation* animation)
+{
+  DALI_ASSERT_DEBUG(animation && "NULL animation called to clear");
+
+  animation->Clear(mSceneGraphBuffers.GetUpdateBufferIndex());
+
+  // We should remove all notify lists what we requests before clear.
+  // TODO : Could we do this more faster?
+  Dali::EraseIf(mImpl->notifyRequiredAnimations, [&animation](const NotifierInterface::NotifyId& key) { return key == animation->GetNotifyId(); });
+}
+
 void UpdateManager::RemoveAnimation(Animation* animation)
 {
   DALI_ASSERT_DEBUG(animation && "NULL animation called to remove");
@@ -581,6 +614,8 @@ void UpdateManager::RemoveAnimation(Animation* animation)
   animation->OnDestroy(mSceneGraphBuffers.GetUpdateBufferIndex());
 
   DALI_ASSERT_DEBUG(animation->GetState() == Animation::Destroyed);
+
+  // Do not remove from container now. Destroyed animation will be removed at Animate.
 }
 
 bool UpdateManager::IsAnimationRunning() const
@@ -627,7 +662,11 @@ void UpdateManager::AddPropertyNotification(OwnerPointer<PropertyNotification>&
 
 void UpdateManager::RemovePropertyNotification(PropertyNotification* propertyNotification)
 {
-  mImpl->propertyNotifications.EraseObject(propertyNotification);
+  auto iter = std::find(mImpl->propertyNotifications.Begin(), mImpl->propertyNotifications.End(), propertyNotification);
+  if(iter != mImpl->propertyNotifications.End())
+  {
+    mImpl->propertyNotifications.Erase(iter);
+  }
 }
 
 void UpdateManager::PropertyNotificationSetNotify(PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode)
@@ -734,6 +773,11 @@ void UpdateManager::EventProcessingStarted()
   mImpl->messageQueue.EventProcessingStarted();
 }
 
+void UpdateManager::EventProcessingFinished()
+{
+  mImpl->messageQueue.EventProcessingFinished();
+}
+
 bool UpdateManager::FlushQueue()
 {
   return mImpl->messageQueue.FlushQueue();
@@ -786,9 +830,9 @@ bool UpdateManager::ProcessGestures(BufferIndex bufferIndex, uint32_t lastVSyncT
 bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds)
 {
   bool animationActive = false;
+  bool animationLooped = false;
 
-  auto&& iter            = mImpl->animations.Begin();
-  bool   animationLooped = false;
+  auto&& iter = mImpl->animations.Begin();
 
   while(iter != mImpl->animations.End())
   {
@@ -802,12 +846,18 @@ bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds)
 
     if(progressMarkerReached)
     {
-      mImpl->notificationManager.QueueMessage(Internal::NotifyProgressReachedMessage(mImpl->animationPlaylist, animation));
+      mImpl->notificationManager.QueueMessage(Internal::NotifyProgressReachedMessage(mImpl->animationPlaylist, animation->GetNotifyId()));
     }
 
     mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
     animationLooped                      = animationLooped || looped;
 
+    // queue the notification on finished or stoped
+    if(finished)
+    {
+      mImpl->notifyRequiredAnimations.PushBack(animation->GetNotifyId());
+    }
+
     // Remove animations that had been destroyed but were still waiting for an update
     if(animation->GetState() == Animation::Destroyed)
     {
@@ -819,11 +869,10 @@ bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds)
     }
   }
 
-  // queue the notification on finished or looped (to update loop count)
-  if(mImpl->animationFinishedDuringUpdate || animationLooped)
+  // The application should be notified by NotificationManager, in another thread
+  if(!mImpl->notifyRequiredAnimations.Empty())
   {
-    // The application should be notified by NotificationManager, in another thread
-    mImpl->notificationManager.QueueCompleteNotification(&mImpl->animationPlaylist);
+    mImpl->notificationManager.QueueNotification(&mImpl->animationPlaylist, std::move(mImpl->notifyRequiredAnimations));
   }
 
   return animationActive;
@@ -882,7 +931,7 @@ void UpdateManager::ProcessPropertyNotifications(BufferIndex bufferIndex)
     bool valid = notification->Check(bufferIndex);
     if(valid)
     {
-      mImpl->notificationManager.QueueMessage(PropertyChangedMessage(mImpl->propertyNotifier, notification, notification->GetValidity()));
+      mImpl->notificationManager.QueueMessage(PropertyChangedMessage(mImpl->propertyNotifier, notification->GetNotifyId(), notification->GetValidity()));
     }
   }
 }
@@ -1035,7 +1084,7 @@ uint32_t UpdateManager::Update(float    elapsedSeconds,
     // Call the frame-callback-processor if set
     if(mImpl->frameCallbackProcessor)
     {
-      mImpl->frameCallbackProcessor->Update(bufferIndex, elapsedSeconds);
+      keepRendererRendering |= mImpl->frameCallbackProcessor->Update(bufferIndex, elapsedSeconds);
     }
 
     // Update node hierarchy, apply constraints,
@@ -1132,15 +1181,17 @@ uint32_t UpdateManager::Update(float    elapsedSeconds,
 
   if(!uploadOnly)
   {
+    // check the countdown and notify
+    mImpl->renderTaskWaiting = false;
+
     for(auto&& scene : mImpl->scenes)
     {
       if(scene && scene->root && scene->taskList)
       {
         RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
 
-        // check the countdown and notify
-        bool doRenderOnceNotify  = false;
-        mImpl->renderTaskWaiting = false;
+        CompleteNotificationInterface::ParameterList notifyRequiredRenderTasks;
+
         for(auto&& renderTask : tasks)
         {
           renderTask->UpdateState();
@@ -1153,14 +1204,14 @@ uint32_t UpdateManager::Update(float    elapsedSeconds,
 
           if(renderTask->HasRendered())
           {
-            doRenderOnceNotify = true;
+            notifyRequiredRenderTasks.PushBack(renderTask->GetNotifyId());
           }
         }
 
-        if(doRenderOnceNotify)
+        if(!notifyRequiredRenderTasks.Empty())
         {
           DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
-          mImpl->notificationManager.QueueCompleteNotification(scene->taskList->GetCompleteNotificationInterface());
+          mImpl->notificationManager.QueueNotification(scene->taskList->GetCompleteNotificationInterface(), std::move(notifyRequiredRenderTasks));
         }
       }
     }
@@ -1200,7 +1251,7 @@ void UpdateManager::PostRender()
   // Reset dirty flag
   for(auto&& renderer : mImpl->renderers)
   {
-    renderer->ResetDirtyFlag();
+    renderer->SetUpdated(false);
   }
 
   for(auto&& shader : mImpl->shaders)
@@ -1258,7 +1309,10 @@ void UpdateManager::KeepRendering(float durationSeconds)
 {
   for(auto&& scene : mImpl->scenes)
   {
-    scene->scene->KeepRendering(durationSeconds);
+    if(scene->scene)
+    {
+      scene->scene->KeepRendering(durationSeconds);
+    }
   }
 }
 
@@ -1272,6 +1326,17 @@ void UpdateManager::RequestRendering()
   mImpl->renderingRequired = true;
 }
 
+Node* UpdateManager::GetNodePointerById(uint32_t nodeId) const
+{
+  Node* foundNodePointer = nullptr;
+  auto  iter             = mImpl->nodeIdMap.find(nodeId);
+  if(iter != mImpl->nodeIdMap.end())
+  {
+    foundNodePointer = iter->second;
+  }
+  return foundNodePointer;
+}
+
 void UpdateManager::SetLayerDepths(const SortedLayerPointers& layers, const Layer* rootLayer)
 {
   for(auto&& scene : mImpl->scenes)
@@ -1289,9 +1354,13 @@ void UpdateManager::SetDepthIndices(OwnerPointer<NodeDepths>& nodeDepths)
   // note, this vector is already in depth order.
   // So if we reverse iterate, we can assume that
   // my descendant node's depth index are updated.
+
+  // And also, This API is the last flushed message.
+  // We can now setup the DESCENDENT_HIERARCHY_CHANGED flag here.
   for(auto rIter = nodeDepths->nodeDepths.rbegin(), rEndIter = nodeDepths->nodeDepths.rend(); rIter != rEndIter; rIter++)
   {
     auto* node = rIter->node;
+    node->PropagateDescendentFlags();
     node->SetDepthIndex(rIter->sortedDepth);
     if(node->IsChildrenReorderRequired())
     {
@@ -1312,6 +1381,11 @@ void UpdateManager::RemoveFrameCallback(FrameCallbackInterface* frameCallback)
   mImpl->GetFrameCallbackProcessor(*this).RemoveFrameCallback(frameCallback);
 }
 
+void UpdateManager::NotifyFrameCallback(FrameCallbackInterface* frameCallback, Dali::UpdateProxy::NotifySyncPoint syncPoint)
+{
+  mImpl->GetFrameCallbackProcessor(*this).NotifyFrameCallback(frameCallback, syncPoint);
+}
+
 void UpdateManager::AddSampler(OwnerPointer<Render::Sampler>& sampler)
 {
   // Message has ownership of Sampler while in transit from update to render
@@ -1523,9 +1597,9 @@ void UpdateManager::RemoveTexture(const Render::TextureKey& texture)
   new(slot) DerivedType(&mImpl->renderManager, &RenderManager::RemoveTexture, texture);
 }
 
-void UpdateManager::UploadTexture(const Render::TextureKey& texture, PixelDataPtr pixelData, const Texture::UploadParams& params)
+void UpdateManager::UploadTexture(const Render::TextureKey& texture, PixelDataPtr pixelData, const Graphics::UploadParams& params)
 {
-  using DerivedType = MessageValue3<RenderManager, Render::TextureKey, PixelDataPtr, Texture::UploadParams>;
+  using DerivedType = MessageValue3<RenderManager, Render::TextureKey, PixelDataPtr, Graphics::UploadParams>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
@@ -1545,6 +1619,28 @@ void UpdateManager::GenerateMipmaps(const Render::TextureKey& texture)
   new(slot) DerivedType(&mImpl->renderManager, &RenderManager::GenerateMipmaps, texture);
 }
 
+void UpdateManager::SetTextureSize(const Render::TextureKey& texture, const Dali::ImageDimensions& size)
+{
+  using DerivedType = MessageValue2<RenderManager, Render::TextureKey, Dali::ImageDimensions>;
+
+  // Reserve some memory inside the render queue
+  uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetTextureSize, texture, size);
+}
+
+void UpdateManager::SetTextureFormat(const Render::TextureKey& texture, Dali::Pixel::Format pixelFormat)
+{
+  using DerivedType = MessageValue2<RenderManager, Render::TextureKey, Dali::Pixel::Format>;
+
+  // Reserve some memory inside the render queue
+  uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetTextureFormat, texture, pixelFormat);
+}
+
 void UpdateManager::AddFrameBuffer(OwnerPointer<Render::FrameBuffer>& frameBuffer)
 {
   using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::FrameBuffer>>;