Make relayout temperal vector as member.
[platform/core/uifw/dali-core.git] / dali / internal / event / size-negotiation / relayout-controller-impl.cpp
index 653b20a..2d639f5 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.
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include "relayout-controller-impl.h"
+#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
 
 // EXTERNAL INCLUDES
 #if defined(DEBUG_ENABLED)
@@ -26,6 +26,7 @@
 // INTERNAL INCLUDES
 #include <dali/integration-api/debug.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/common/stage-impl.h>
 #include <dali/internal/event/common/thread-local-storage.h>
@@ -38,6 +39,8 @@ namespace Internal
 {
 namespace
 {
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
+
 #if defined(DEBUG_ENABLED)
 
 Integration::Log::Filter* gLogFilter(Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_CONTROLLER"));
@@ -116,16 +119,23 @@ RelayoutController::RelayoutController(Integration::RenderController& controller
 {
   // Make space for 32 controls to avoid having to copy construct a lot in the beginning
   mRelayoutStack->Reserve(32);
+  mPotentialRedundantSubRoots.reserve(32);
+  mTopOfSubTreeStack.reserve(32);
 }
 
-RelayoutController::~RelayoutController()
-{
-  delete mRelayoutStack;
-}
+RelayoutController::~RelayoutController() = default;
 
 RelayoutController* RelayoutController::Get()
 {
-  return &ThreadLocalStorage::Get().GetRelayoutController();
+  // There was crash when destroying actors and the ResizePolicy is USE_NATURAL_SIZE
+  // The ThreadLocalStorage::Get() only retrieve STL without checking if it exists.
+  // The caller of RelayoutController::Get() should check if RelayoutController is not null.
+  if(ThreadLocalStorage::Created())
+  {
+    return &ThreadLocalStorage::Get().GetRelayoutController();
+  }
+
+  return nullptr;
 }
 
 void RelayoutController::QueueActor(Internal::Actor* actor, RelayoutContainer& actors, Vector2 size)
@@ -144,8 +154,11 @@ void RelayoutController::RequestRelayout(Dali::Actor& actor, Dimension::Type dim
     return;
   }
 
-  std::vector<Dali::Actor> potentialRedundantSubRoots;
-  std::vector<Dali::Actor> topOfSubTreeStack;
+  std::vector<Dali::Actor>& potentialRedundantSubRoots = mPotentialRedundantSubRoots;
+  std::vector<Dali::Actor>& topOfSubTreeStack          = mTopOfSubTreeStack;
+
+  DALI_ASSERT_ALWAYS(potentialRedundantSubRoots.empty() && "potentialRedundantSubRoots must be empty before RequestRelayout!");
+  DALI_ASSERT_ALWAYS(topOfSubTreeStack.empty() && "topOfSubTreeStack must be empty before RequestRelayout!");
 
   topOfSubTreeStack.push_back(actor);
 
@@ -186,6 +199,8 @@ void RelayoutController::RequestRelayout(Dali::Actor& actor, Dimension::Type dim
     RemoveRequest(subRoot);
   }
 
+  potentialRedundantSubRoots.clear();
+
   if(!mProcessingCoreEvents)
   {
     mRenderController.RequestProcessEventsOnIdle(false);
@@ -361,9 +376,9 @@ void RelayoutController::AddRequest(Dali::Actor& actor)
   Internal::Actor* actorPtr = &GetImplementation(actor);
 
   // Only add the rootActor if it is not already recorded
-  auto itr = std::find(mDirtyLayoutSubTrees.begin(), mDirtyLayoutSubTrees.end(), actorPtr);
+  auto iter = mDirtyLayoutSubTrees.Find(actorPtr);
 
-  if(itr == mDirtyLayoutSubTrees.end())
+  if(iter == mDirtyLayoutSubTrees.End())
   {
     mDirtyLayoutSubTrees.PushBack(actorPtr);
   }
@@ -372,11 +387,7 @@ void RelayoutController::AddRequest(Dali::Actor& actor)
 void RelayoutController::RemoveRequest(Dali::Actor& actor)
 {
   Internal::Actor* actorPtr = &GetImplementation(actor);
-
-  mDirtyLayoutSubTrees.Erase(std::remove(mDirtyLayoutSubTrees.begin(),
-                                         mDirtyLayoutSubTrees.end(),
-                                         actorPtr),
-                             mDirtyLayoutSubTrees.end());
+  mDirtyLayoutSubTrees.EraseObject(actorPtr);
 }
 
 void RelayoutController::Request()
@@ -393,8 +404,7 @@ void RelayoutController::Request()
 
 void RelayoutController::OnObjectDestroyed(const Dali::RefObject* object)
 {
-  // Search for and null the object if found in the following lists
-  FindAndZero(mDirtyLayoutSubTrees, object);
+  mDirtyLayoutSubTrees.EraseObject(static_cast<const Dali::Internal::Actor*>(object));
 }
 
 void RelayoutController::Relayout()
@@ -428,27 +438,25 @@ void RelayoutController::Relayout()
     // 2. Iterate through the stack until it's empty.
     if(mRelayoutStack->Size() > 0)
     {
+      DALI_TRACE_SCOPE(gTraceFilter, "DALI_RELAYOUT");
       PRINT_HIERARCHY;
 
       while(mRelayoutStack->Size() > 0)
       {
         Dali::Actor actor;
         Vector2     size;
-        mRelayoutStack->Get(mRelayoutStack->Size() - 1, actor, size);
+
+        mRelayoutStack->GetBack(actor, size);
         Actor& actorImpl = GetImplementation(actor);
         mRelayoutStack->PopBack();
 
-        if(actorImpl.RelayoutRequired())
+        if(actorImpl.RelayoutRequired() && actorImpl.OnScene())
         {
           DALI_LOG_INFO(gLogFilter, Debug::General, "[Internal::RelayoutController::Relayout] Negotiating %p %s %s (%.2f, %.2f)\n", &actorImpl, actor.GetTypeName().c_str(), actor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str(), size.width, size.height);
 
           // 3. Negotiate the size with the current actor. Pass it an empty container which the actor
           //    has to fill with all the actors it has not done any size negotiation for.
-
           actorImpl.NegotiateSize(size, *mRelayoutStack);
-
-          // Reset the flag so that size negotiation will respect the actor's original resize policy
-          actorImpl.SetUseAssignedSize(false);
         }
       }
 
@@ -479,16 +487,9 @@ void RelayoutController::SetProcessingCoreEvents(bool processingEvents)
   mProcessingCoreEvents = processingEvents;
 }
 
-void RelayoutController::FindAndZero(const RawActorList& list, const Dali::RefObject* object)
+uint32_t RelayoutController::GetMemoryPoolCapacity()
 {
-  // Object has been destroyed so clear it from this list
-  for(auto& actor : list)
-  {
-    if(actor && (actor == object))
-    {
-      actor = nullptr; // Reset the pointer in the list. We don't want to remove it in case something is iterating over the list.
-    }
-  }
+  return mRelayoutInfoAllocator.GetCapacity();
 }
 
 } // namespace Internal