Print the number of loop count when we trace iteration
[platform/core/uifw/dali-core.git] / dali / internal / common / core-impl.cpp
index 6d129e6..e9da296 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/events/event.h>
 #include <dali/integration-api/gl-context-helper-abstraction.h>
-#include <dali/integration-api/gl-sync-abstraction.h>
 #include <dali/integration-api/platform-abstraction.h>
 #include <dali/integration-api/processor-interface.h>
 #include <dali/integration-api/render-controller.h>
+#include <dali/integration-api/trace.h>
 
 #include <dali/internal/event/actors/actor-impl.h>
 #include <dali/internal/event/animation/animation-playlist.h>
@@ -49,9 +49,7 @@
 
 #include <dali/internal/render/common/performance-monitor.h>
 #include <dali/internal/render/common/render-manager.h>
-#include <dali/internal/render/gl-resources/context.h>
 
-using Dali::Internal::SceneGraph::DiscardQueue;
 using Dali::Internal::SceneGraph::RenderManager;
 using Dali::Internal::SceneGraph::RenderQueue;
 using Dali::Internal::SceneGraph::UpdateManager;
@@ -61,6 +59,8 @@ namespace
 // The Update for frame N+1 may be processed whilst frame N is being rendered.
 const uint32_t MAXIMUM_UPDATE_COUNT = 2u;
 
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
+
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gCoreFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CORE");
 #endif
@@ -73,7 +73,6 @@ namespace Internal
 using Integration::Event;
 using Integration::GlAbstraction;
 using Integration::GlContextHelperAbstraction;
-using Integration::GlSyncAbstraction;
 using Integration::PlatformAbstraction;
 using Integration::RenderController;
 using Integration::RenderStatus;
@@ -90,7 +89,9 @@ Core::Core(RenderController&                   renderController,
   mPlatform(platform),
   mGraphicsController(graphicsController),
   mProcessingEvent(false),
-  mForceNextUpdate(false)
+  mProcessorUnregistered(false),
+  mPostProcessorUnregistered(false),
+  mRelayoutFlush(false)
 {
   // Create the thread local storage
   CreateThreadLocalStorage();
@@ -110,12 +111,9 @@ Core::Core(RenderController&                   renderController,
 
   RenderQueue& renderQueue = mRenderManager->GetRenderQueue();
 
-  mDiscardQueue = new DiscardQueue(renderQueue);
-
   mUpdateManager = new UpdateManager(*mNotificationManager,
                                      *mAnimationPlaylist,
                                      *mPropertyNotificationManager,
-                                     *mDiscardQueue,
                                      renderController,
                                      *mRenderManager,
                                      renderQueue,
@@ -136,6 +134,10 @@ Core::Core(RenderController&                   renderController,
   mUpdateManager->SetShaderSaver(*mShaderFactory);
 
   GetImplementation(Dali::TypeRegistry::Get()).CallInitFunctions();
+
+  DALI_LOG_RELEASE_INFO("Node size: %lu\n", sizeof(Dali::Internal::SceneGraph::Node));
+  DALI_LOG_RELEASE_INFO("Renderer size: %lu\n", sizeof(Dali::Internal::SceneGraph::Renderer));
+  DALI_LOG_RELEASE_INFO("RenderItem size: %lu\n", sizeof(Dali::Internal::SceneGraph::RenderItem));
 }
 
 Core::~Core()
@@ -182,15 +184,13 @@ void Core::RecoverFromContextLoss()
 
 void Core::ContextCreated()
 {
-  mRenderManager->ContextCreated();
 }
 
 void Core::ContextDestroyed()
 {
-  mRenderManager->ContextDestroyed();
 }
 
-void Core::Update(float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds, Integration::UpdateStatus& status, bool renderToFboEnabled, bool isRenderingToFbo)
+void Core::Update(float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds, Integration::UpdateStatus& status, bool renderToFboEnabled, bool isRenderingToFbo, bool uploadOnly)
 {
   // set the time delta so adaptor can easily print FPS with a release build with 0 as
   // it is cached by frametime
@@ -202,7 +202,8 @@ void Core::Update(float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint
                                                lastVSyncTimeMilliseconds,
                                                nextVSyncTimeMilliseconds,
                                                renderToFboEnabled,
-                                               isRenderingToFbo);
+                                               isRenderingToFbo,
+                                               uploadOnly);
 
   // Check the Notification Manager message queue to set needsNotification
   status.needsNotification = mNotificationManager->MessagesToProcess();
@@ -211,9 +212,9 @@ void Core::Update(float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint
   // Any message to update will wake it up anyways
 }
 
-void Core::PreRender(RenderStatus& status, bool forceClear, bool uploadOnly)
+void Core::PreRender(RenderStatus& status, bool forceClear)
 {
-  mRenderManager->PreRender(status, forceClear, uploadOnly);
+  mRenderManager->PreRender(status, forceClear);
 }
 
 void Core::PreRender(Integration::Scene& scene, std::vector<Rect<int>>& damagedRects)
@@ -231,9 +232,10 @@ void Core::RenderScene(RenderStatus& status, Integration::Scene& scene, bool ren
   mRenderManager->RenderScene(status, scene, renderToFbo, clippingRect);
 }
 
-void Core::PostRender(bool uploadOnly)
+void Core::PostRender()
 {
-  mRenderManager->PostRender(uploadOnly);
+  mUpdateManager->PostRender();
+  mRenderManager->PostRender();
 }
 
 void Core::SceneCreated()
@@ -257,13 +259,28 @@ void Core::QueueEvent(const Integration::Event& event)
   }
 }
 
+void Core::ForceRelayout()
+{
+  if(mRelayoutFlush)
+  {
+    DALI_LOG_ERROR("ForceRelayout should not be called from within RelayoutAndFlush!\n");
+    return;
+  }
+
+  // Scene could be added or removed while processing the events
+  // Copy the Scene container locally to avoid possibly invalid iterator
+  SceneContainer scenes = mScenes;
+
+  RelayoutAndFlush(scenes);
+}
+
 void Core::ProcessEvents()
 {
   // Guard against calls to ProcessEvents() during ProcessEvents()
   if(mProcessingEvent)
   {
     DALI_LOG_ERROR("ProcessEvents should not be called from within ProcessEvents!\n");
-    mRenderController.RequestProcessEventsOnIdle(false);
+    mRenderController.RequestProcessEventsOnIdle();
     return;
   }
 
@@ -291,6 +308,47 @@ void Core::ProcessEvents()
     scene->EmitEventProcessingFinishedSignal();
   }
 
+  RelayoutAndFlush(scenes);
+
+  mUpdateManager->EventProcessingFinished();
+
+  // Check if the touch or gestures require updates.
+  const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
+
+  if(gestureNeedsUpdate)
+  {
+    // tell the render controller to keep update thread running
+    mRenderController.RequestUpdate();
+  }
+
+  mRelayoutController->SetProcessingCoreEvents(false);
+
+  // ProcessEvents() may now be called again
+  mProcessingEvent = false;
+}
+
+void Core::RelayoutAndFlush(SceneContainer& scenes)
+{
+  if(mRelayoutFlush)
+  {
+    DALI_LOG_ERROR("RelayoutAndFlush should not be called from within RelayoutAndFlush!\n");
+    return;
+  }
+
+  const bool isProcessEvents = mProcessingEvent;
+
+  if(!isProcessEvents)
+  {
+    // Fake that we are in ProcessEvents()
+    mProcessingEvent = true;
+    mRelayoutController->SetProcessingCoreEvents(true);
+
+    // Signal that any messages received will be flushed soon
+    mUpdateManager->EventProcessingStarted();
+  }
+
+  mRelayoutFlush = true;
+
   // Run any registered processors
   RunProcessors();
 
@@ -301,7 +359,7 @@ void Core::ProcessEvents()
   RunPostProcessors();
 
   // Rebuild depth tree after event processing has finished
-  for(auto scene : scenes)
+  for(auto& scene : scenes)
   {
     scene->RebuildDepthTree();
   }
@@ -309,21 +367,22 @@ void Core::ProcessEvents()
   // Flush any queued messages for the update-thread
   const bool messagesToProcess = mUpdateManager->FlushQueue();
 
-  // Check if the touch or gestures require updates.
-  const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
-  // Check if the next update is forced.
-  const bool forceUpdate = IsNextUpdateForced();
-
-  if(messagesToProcess || gestureNeedsUpdate || forceUpdate)
+  if(messagesToProcess)
   {
     // tell the render controller to keep update thread running
-    mRenderController.RequestUpdate(forceUpdate);
+    mRenderController.RequestUpdate();
   }
 
-  mRelayoutController->SetProcessingCoreEvents(false);
+  mRelayoutFlush = false;
 
-  // ProcessEvents() may now be called again
-  mProcessingEvent = false;
+  if(!isProcessEvents)
+  {
+    // Revert fake informations
+    mProcessingEvent = false;
+    mRelayoutController->SetProcessingCoreEvents(false);
+
+    mUpdateManager->EventProcessingFinished();
+  }
 }
 
 uint32_t Core::GetMaximumUpdateCount() const
@@ -351,6 +410,7 @@ void Core::UnregisterProcessor(Integration::Processor& processor, bool postProce
     if(iter != mPostProcessors.End())
     {
       mPostProcessors.Erase(iter);
+      mPostProcessorUnregistered = true;
     }
   }
   else
@@ -359,35 +419,119 @@ void Core::UnregisterProcessor(Integration::Processor& processor, bool postProce
     if(iter != mProcessors.End())
     {
       mProcessors.Erase(iter);
+      mProcessorUnregistered = true;
     }
   }
 }
 
 void Core::RunProcessors()
 {
-  // Copy processor pointers to prevent changes to vector affecting loop iterator.
-  Dali::Vector<Integration::Processor*> processors(mProcessors);
-
-  for(auto processor : processors)
+  if(mProcessors.Count() != 0)
   {
-    if(processor)
+#ifdef TRACE_ENABLED
+    if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+    {
+      std::ostringstream stream;
+      stream << "[" << mProcessors.Count() << "]";
+      DALI_TRACE_BEGIN_WITH_MESSAGE(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", stream.str().c_str());
+    }
+#endif
+
+    // Copy processor pointers to prevent changes to vector affecting loop iterator.
+    Dali::Vector<Integration::Processor*> processors(mProcessors);
+
+    // To prevent accessing processor unregistered during the loop
+    mProcessorUnregistered = false;
+
+    for(auto processor : processors)
     {
-      processor->Process(false);
+      if(processor)
+      {
+        if(!mProcessorUnregistered)
+        {
+          processor->Process(false);
+        }
+        else
+        {
+          // Run processor if the processor is still in the list.
+          // It may be removed during the loop.
+          auto iter = std::find(mProcessors.Begin(), mProcessors.End(), processor);
+          if(iter != mProcessors.End())
+          {
+            processor->Process(false);
+          }
+        }
+      }
     }
+#ifdef TRACE_ENABLED
+    if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+    {
+      std::ostringstream stream;
+      stream << "[" << mProcessors.Count();
+      if(mProcessorUnregistered)
+      {
+        stream << ", processor changed";
+      }
+      stream << "]";
+      DALI_TRACE_END_WITH_MESSAGE(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", stream.str().c_str());
+    }
+#endif
   }
 }
 
 void Core::RunPostProcessors()
 {
-  // Copy processor pointers to prevent changes to vector affecting loop iterator.
-  Dali::Vector<Integration::Processor*> processors(mPostProcessors);
-
-  for(auto processor : processors)
+  if(mPostProcessors.Count() != 0)
   {
-    if(processor)
+#ifdef TRACE_ENABLED
+    if(gTraceFilter && gTraceFilter->IsTraceEnabled())
+    {
+      std::ostringstream stream;
+      stream << "[" << mPostProcessors.Count() << "]";
+      DALI_TRACE_BEGIN_WITH_MESSAGE(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", stream.str().c_str());
+    }
+#endif
+
+    // Copy processor pointers to prevent changes to vector affecting loop iterator.
+    Dali::Vector<Integration::Processor*> processors(mPostProcessors);
+
+    // To prevent accessing processor unregistered during the loop
+    mPostProcessorUnregistered = false;
+
+    for(auto processor : processors)
+    {
+      if(processor)
+      {
+        if(!mPostProcessorUnregistered)
+        {
+          processor->Process(true);
+        }
+        else
+        {
+          // Run processor if the processor is still in the list.
+          // It may be removed during the loop.
+          auto iter = std::find(mPostProcessors.Begin(), mPostProcessors.End(), processor);
+          if(iter != mPostProcessors.End())
+          {
+            processor->Process(true);
+          }
+        }
+      }
+    }
+
+#ifdef TRACE_ENABLED
+    if(gTraceFilter && gTraceFilter->IsTraceEnabled())
     {
-      processor->Process(true);
+      std::ostringstream stream;
+      stream << "[" << mPostProcessors.Count();
+      if(mPostProcessorUnregistered)
+      {
+        stream << ", post processor changed";
+      }
+      stream << "]";
+      DALI_TRACE_END_WITH_MESSAGE(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", stream.str().c_str());
     }
+#endif
   }
 }
 
@@ -436,6 +580,47 @@ ObjectRegistry& Core::GetObjectRegistry() const
   return *(mObjectRegistry.Get());
 }
 
+void Core::LogMemoryPools() const
+{
+  uint32_t animationPoolCapacity    = SceneGraph::Animation::GetMemoryPoolCapacity();
+  uint32_t renderItemPoolCapacity   = SceneGraph::RenderItem::GetMemoryPoolCapacity();
+  uint32_t relayoutItemPoolCapacity = mRelayoutController->GetMemoryPoolCapacity();
+  uint32_t rendererPoolCapacity     = SceneGraph::Renderer::GetMemoryPoolCapacity();
+  uint32_t textureSetPoolCapacity   = SceneGraph::TextureSet::GetMemoryPoolCapacity();
+  uint32_t renderTaskPoolCapacity   = SceneGraph::RenderTaskList::GetMemoryPoolCapacity();
+  uint32_t nodePoolCapacity         = SceneGraph::Node::GetMemoryPoolCapacity();
+
+  DALI_LOG_RELEASE_INFO(
+    "\nMemory Pool capacities:\n"
+    "  Animations:    %lu\n"
+    "  RenderItems:   %lu\n"
+    "  RelayoutItems: %lu\n"
+    "  Renderers:     %lu\n"
+    "  TextureSets:   %lu\n"
+    "  RenderTasks:   %lu\n"
+    "  Nodes:         %lu\n",
+    animationPoolCapacity,
+    renderItemPoolCapacity,
+    relayoutItemPoolCapacity,
+    rendererPoolCapacity,
+    textureSetPoolCapacity,
+    renderTaskPoolCapacity,
+    nodePoolCapacity);
+
+  uint32_t updateQCapacity = mUpdateManager->GetUpdateMessageQueueCapacity();
+  uint32_t renderQCapacity = mUpdateManager->GetRenderMessageQueueCapacity();
+
+  DALI_LOG_RELEASE_INFO(
+    "\nMessage Queue capacities:\n"
+    "  UpdateQueue: %lu\n"
+    "  RenderQueue: %lu\n",
+    updateQCapacity,
+    renderQCapacity);
+
+  size_t renderInstructionCapacity = mUpdateManager->GetRenderInstructionCapacity();
+  DALI_LOG_RELEASE_INFO("\nRenderInstruction capacity: %lu\n", renderInstructionCapacity);
+}
+
 EventThreadServices& Core::GetEventThreadServices()
 {
   return *this;
@@ -505,18 +690,6 @@ BufferIndex Core::GetEventBufferIndex() const
   return mUpdateManager->GetEventBufferIndex();
 }
 
-void Core::ForceNextUpdate()
-{
-  mForceNextUpdate = true;
-}
-
-bool Core::IsNextUpdateForced()
-{
-  bool nextUpdateForced = mForceNextUpdate;
-  mForceNextUpdate      = false;
-  return nextUpdateForced;
-}
-
 } // namespace Internal
 
 } // namespace Dali