[dali_2.3.37] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / common / core-impl.cpp
1 /*
2  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/common/core-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/graphics-api/graphics-controller.h>
23 #include <dali/integration-api/core.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/integration-api/events/event.h>
26 #include <dali/integration-api/platform-abstraction.h>
27 #include <dali/integration-api/processor-interface.h>
28 #include <dali/integration-api/render-controller.h>
29 #include <dali/integration-api/trace.h>
30
31 #include <dali/internal/event/actors/actor-impl.h>
32 #include <dali/internal/event/animation/animation-playlist.h>
33 #include <dali/internal/event/common/event-thread-services.h>
34 #include <dali/internal/event/common/notification-manager.h>
35 #include <dali/internal/event/common/property-notification-manager.h>
36 #include <dali/internal/event/common/stage-impl.h>
37 #include <dali/internal/event/common/thread-local-storage.h>
38 #include <dali/internal/event/common/type-registry-impl.h>
39 #include <dali/internal/event/effects/shader-factory.h>
40 #include <dali/internal/event/events/event-processor.h>
41 #include <dali/internal/event/events/gesture-event-processor.h>
42 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
43 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
44
45 #include <dali/internal/update/common/discard-queue.h>
46 #include <dali/internal/update/manager/render-task-processor.h>
47 #include <dali/internal/update/manager/update-manager.h>
48
49 #include <dali/internal/render/common/performance-monitor.h>
50 #include <dali/internal/render/common/render-manager.h>
51
52 using Dali::Internal::SceneGraph::RenderManager;
53 using Dali::Internal::SceneGraph::RenderQueue;
54 using Dali::Internal::SceneGraph::UpdateManager;
55
56 namespace
57 {
58 // The Update for frame N+1 may be processed whilst frame N is being rendered.
59 const uint32_t MAXIMUM_UPDATE_COUNT = 2u;
60
61 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
62
63 #if defined(DEBUG_ENABLED)
64 Debug::Filter* gCoreFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CORE");
65 #endif
66 } // namespace
67
68 namespace Dali
69 {
70 namespace Internal
71 {
72 using Integration::Event;
73 using Integration::PlatformAbstraction;
74 using Integration::RenderController;
75 using Integration::RenderStatus;
76 using Integration::UpdateStatus;
77
78 Core::Core(RenderController&            renderController,
79            PlatformAbstraction&         platform,
80            Graphics::Controller&        graphicsController,
81            Integration::CorePolicyFlags corePolicy)
82 : mRenderController(renderController),
83   mPlatform(platform),
84   mGraphicsController(graphicsController),
85   mProcessorOnceIndex(0u),
86   mPostProcessorOnceIndex(0u),
87   mProcessingEvent(false),
88   mProcessorUnregistered(false),
89   mPostProcessorUnregistered(false),
90   mRelayoutFlush(false)
91 {
92   // Create the thread local storage
93   CreateThreadLocalStorage();
94
95   // This does nothing until Core is built with --enable-performance-monitor
96   PERFORMANCE_MONITOR_INIT(platform);
97
98   mNotificationManager = new NotificationManager();
99
100   mAnimationPlaylist = AnimationPlaylist::New();
101
102   mPropertyNotificationManager = PropertyNotificationManager::New();
103
104   mRenderTaskProcessor = new SceneGraph::RenderTaskProcessor();
105
106   mRenderManager = RenderManager::New(graphicsController,
107                                       (corePolicy & Integration::CorePolicyFlags::DEPTH_BUFFER_AVAILABLE) ? Integration::DepthBufferAvailable::TRUE : Integration::DepthBufferAvailable::FALSE,
108                                       (corePolicy & Integration::CorePolicyFlags::STENCIL_BUFFER_AVAILABLE) ? Integration::StencilBufferAvailable::TRUE : Integration::StencilBufferAvailable::FALSE,
109                                       (corePolicy & Integration::CorePolicyFlags::PARTIAL_UPDATE_AVAILABLE) ? Integration::PartialUpdateAvailable::TRUE : Integration::PartialUpdateAvailable::FALSE);
110
111   RenderQueue& renderQueue = mRenderManager->GetRenderQueue();
112
113   mUpdateManager = new UpdateManager(*mNotificationManager,
114                                      *mAnimationPlaylist,
115                                      *mPropertyNotificationManager,
116                                      renderController,
117                                      *mRenderManager,
118                                      renderQueue,
119                                      *mRenderTaskProcessor);
120
121   mRenderManager->SetShaderSaver(*mUpdateManager);
122
123   mObjectRegistry = ObjectRegistry::New();
124
125   mStage = IntrusivePtr<Stage>(Stage::New(*mUpdateManager));
126
127   // This must be called after stage is created but before stage initialization
128   mRelayoutController = IntrusivePtr<RelayoutController>(new RelayoutController(mRenderController));
129
130   mGestureEventProcessor = new GestureEventProcessor(*mUpdateManager, mRenderController);
131
132   mShaderFactory = new ShaderFactory();
133   mUpdateManager->SetShaderSaver(*mShaderFactory);
134
135   GetImplementation(Dali::TypeRegistry::Get()).CallInitFunctions();
136
137   DALI_LOG_RELEASE_INFO("Core policy enum : 0x%x\n", static_cast<uint32_t>(corePolicy));
138 }
139
140 Core::~Core()
141 {
142   /*
143    * The order of destructing these singletons is important!!!
144    */
145
146   // clear the thread local storage first
147   // allows core to be created / deleted many times in the same thread (how TET cases work).
148   // Do this before mStage.Reset() so Stage::IsInstalled() returns false
149   ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
150   if(tls)
151   {
152     tls->Remove();
153     tls->Unreference();
154   }
155
156   mObjectRegistry.Reset();
157
158   // Stop relayout requests being raised on stage destruction
159   mRelayoutController.Reset();
160
161   // remove (last?) reference to stage
162   mStage.Reset();
163 }
164
165 void Core::Initialize()
166 {
167   mStage->Initialize(*mScenes[0]);
168 }
169
170 Integration::ContextNotifierInterface* Core::GetContextNotifier()
171 {
172   return mStage.Get();
173 }
174
175 void Core::RecoverFromContextLoss()
176 {
177   DALI_LOG_INFO(gCoreFilter, Debug::Verbose, "Core::RecoverFromContextLoss()\n");
178
179   mStage->GetRenderTaskList().RecoverFromContextLoss(); // Re-trigger render-tasks
180 }
181
182 void Core::ContextCreated()
183 {
184 }
185
186 void Core::ContextDestroyed()
187 {
188   mRenderManager->ContextDestroyed();
189 }
190
191 void Core::Update(float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds, Integration::UpdateStatus& status, bool renderToFboEnabled, bool isRenderingToFbo, bool uploadOnly)
192 {
193   // set the time delta so adaptor can easily print FPS with a release build with 0 as
194   // it is cached by frametime
195   status.secondsFromLastFrame = elapsedSeconds;
196
197   // Render returns true when there are updates on the stage or one or more animations are completed.
198   // Use the estimated time diff till we render as the elapsed time.
199   status.keepUpdating = mUpdateManager->Update(elapsedSeconds,
200                                                lastVSyncTimeMilliseconds,
201                                                nextVSyncTimeMilliseconds,
202                                                renderToFboEnabled,
203                                                isRenderingToFbo,
204                                                uploadOnly);
205
206   // Check the Notification Manager message queue to set needsNotification
207   status.needsNotification = mNotificationManager->MessagesToProcess();
208
209   // No need to keep update running if there are notifications to process.
210   // Any message to update will wake it up anyways
211 }
212
213 void Core::PreRender(RenderStatus& status, bool forceClear)
214 {
215   mRenderManager->PreRender(status, forceClear);
216 }
217
218 void Core::PreRender(Integration::Scene& scene, std::vector<Rect<int>>& damagedRects)
219 {
220   mRenderManager->PreRender(scene, damagedRects);
221 }
222
223 void Core::RenderScene(RenderStatus& status, Integration::Scene& scene, bool renderToFbo)
224 {
225   mRenderManager->RenderScene(status, scene, renderToFbo);
226 }
227
228 void Core::RenderScene(RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect<int>& clippingRect)
229 {
230   mRenderManager->RenderScene(status, scene, renderToFbo, clippingRect);
231 }
232
233 void Core::PostRender()
234 {
235   mUpdateManager->PostRender();
236   mRenderManager->PostRender();
237 }
238
239 void Core::SceneCreated()
240 {
241   mStage->EmitSceneCreatedSignal();
242
243   mRelayoutController->OnApplicationSceneCreated();
244
245   for(const auto& scene : mScenes)
246   {
247     Dali::Actor sceneRootLayer = scene->GetRootLayer();
248     mRelayoutController->RequestRelayoutTree(sceneRootLayer);
249   }
250 }
251
252 void Core::QueueEvent(const Integration::Event& event)
253 {
254   if(mScenes.size() != 0)
255   {
256     mScenes.front()->QueueEvent(event);
257   }
258 }
259
260 void Core::ForceRelayout()
261 {
262   if(mRelayoutFlush)
263   {
264     DALI_LOG_ERROR("ForceRelayout should not be called from within RelayoutAndFlush!\n");
265     return;
266   }
267
268   // Scene could be added or removed while processing the events
269   // Copy the Scene container locally to avoid possibly invalid iterator
270   SceneContainer scenes = mScenes;
271
272   RelayoutAndFlush(scenes);
273 }
274
275 void Core::ProcessEvents()
276 {
277   // Guard against calls to ProcessEvents() during ProcessEvents()
278   if(mProcessingEvent)
279   {
280     DALI_LOG_ERROR("ProcessEvents should not be called from within ProcessEvents!\n");
281     mRenderController.RequestProcessEventsOnIdle();
282     return;
283   }
284
285   mProcessingEvent = true;
286   mRelayoutController->SetProcessingCoreEvents(true);
287
288   // Signal that any messages received will be flushed soon
289   mUpdateManager->EventProcessingStarted();
290
291   // Scene could be added or removed while processing the events
292   // Copy the Scene container locally to avoid possibly invalid iterator
293   SceneContainer scenes = mScenes;
294
295   // process events in all scenes
296   for(auto scene : scenes)
297   {
298     scene->ProcessEvents();
299   }
300
301   mNotificationManager->ProcessMessages();
302
303   // Emit signal here to inform listeners that event processing has finished.
304   for(auto scene : scenes)
305   {
306     scene->EmitEventProcessingFinishedSignal();
307   }
308
309   RelayoutAndFlush(scenes);
310
311   // Notify to animation play list that event processing has finished.
312   mAnimationPlaylist->EventLoopFinished();
313
314   mUpdateManager->EventProcessingFinished();
315
316   // Check if the touch or gestures require updates.
317   const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
318
319   if(gestureNeedsUpdate)
320   {
321     // tell the render controller to keep update thread running
322     mRenderController.RequestUpdate();
323   }
324
325   mRelayoutController->SetProcessingCoreEvents(false);
326
327   // ProcessEvents() may now be called again
328   mProcessingEvent = false;
329 }
330
331 void Core::RelayoutAndFlush(SceneContainer& scenes)
332 {
333   if(mRelayoutFlush)
334   {
335     DALI_LOG_ERROR("RelayoutAndFlush should not be called from within RelayoutAndFlush!\n");
336     return;
337   }
338
339   const bool isProcessEvents = mProcessingEvent;
340
341   if(!isProcessEvents)
342   {
343     // Fake that we are in ProcessEvents()
344     mProcessingEvent = true;
345     mRelayoutController->SetProcessingCoreEvents(true);
346
347     // Signal that any messages received will be flushed soon
348     mUpdateManager->EventProcessingStarted();
349   }
350
351   mRelayoutFlush = true;
352
353   // Run any registered processors
354   RunProcessors();
355
356   // Run the size negotiation after event processing finished signal
357   mRelayoutController->Relayout();
358
359   // Run any registered post processors
360   RunPostProcessors();
361
362   // Rebuild depth tree after event processing has finished
363   for(auto& scene : scenes)
364   {
365     scene->RebuildDepthTree();
366   }
367
368   // Flush any queued messages for the update-thread
369   const bool messagesToProcess = mUpdateManager->FlushQueue();
370
371   if(messagesToProcess)
372   {
373     // tell the render controller to keep update thread running
374     mRenderController.RequestUpdate();
375   }
376
377   mRelayoutFlush = false;
378
379   if(!isProcessEvents)
380   {
381     // Revert fake informations
382     mProcessingEvent = false;
383     mRelayoutController->SetProcessingCoreEvents(false);
384
385     mUpdateManager->EventProcessingFinished();
386   }
387 }
388
389 uint32_t Core::GetMaximumUpdateCount() const
390 {
391   return MAXIMUM_UPDATE_COUNT;
392 }
393
394 void Core::RegisterProcessor(Integration::Processor& processor, bool postProcessor)
395 {
396   if(postProcessor)
397   {
398     mPostProcessors.PushBack(&processor);
399   }
400   else
401   {
402     mProcessors.PushBack(&processor);
403   }
404 }
405
406 void Core::UnregisterProcessor(Integration::Processor& processor, bool postProcessor)
407 {
408   if(postProcessor)
409   {
410     auto iter = std::find(mPostProcessors.Begin(), mPostProcessors.End(), &processor);
411     if(iter != mPostProcessors.End())
412     {
413       mPostProcessors.Erase(iter);
414       mPostProcessorUnregistered = true;
415     }
416   }
417   else
418   {
419     auto iter = std::find(mProcessors.Begin(), mProcessors.End(), &processor);
420     if(iter != mProcessors.End())
421     {
422       mProcessors.Erase(iter);
423       mProcessorUnregistered = true;
424     }
425   }
426 }
427
428 void Core::RegisterProcessorOnce(Integration::Processor& processor, bool postProcessor)
429 {
430   if(postProcessor)
431   {
432     mPostProcessorsOnce[mPostProcessorOnceIndex].PushBack(&processor);
433   }
434   else
435   {
436     mProcessorsOnce[mProcessorOnceIndex].PushBack(&processor);
437   }
438 }
439
440 void Core::UnregisterProcessorOnce(Integration::Processor& processor, bool postProcessor)
441 {
442   if(postProcessor)
443   {
444     for(uint32_t index = 0; index < 2; ++index)
445     {
446       auto iter = std::find(mPostProcessorsOnce[index].Begin(), mPostProcessorsOnce[index].End(), &processor);
447       if(iter != mPostProcessorsOnce[index].End())
448       {
449         mPostProcessorsOnce[index].Erase(iter);
450         if(index != mPostProcessorOnceIndex)
451         {
452           // Check processor unregistered during processing.
453           mPostProcessorUnregistered = true;
454         }
455       }
456     }
457   }
458   else
459   {
460     for(uint32_t index = 0; index < 2; ++index)
461     {
462       auto iter = std::find(mProcessorsOnce[index].Begin(), mProcessorsOnce[index].End(), &processor);
463       if(iter != mProcessorsOnce[index].End())
464       {
465         mProcessorsOnce[index].Erase(iter);
466         if(index != mProcessorOnceIndex)
467         {
468           // Check processor unregistered during processing.
469           mProcessorUnregistered = true;
470         }
471       }
472     }
473   }
474 }
475
476 void Core::UnregisterProcessors()
477 {
478   mPostProcessors.Clear();
479   mPostProcessorUnregistered = true;
480   mProcessors.Clear();
481   mProcessorUnregistered = true;
482
483   for(uint32_t index = 0; index < 2; ++index)
484   {
485     mPostProcessorsOnce[index].Clear();
486     mProcessorsOnce[index].Clear();
487   }
488 }
489
490 void Core::RunProcessors()
491 {
492   if(mProcessorsOnce[mProcessorOnceIndex].Count() != 0)
493   {
494     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
495       oss << "[" << mProcessorOnceIndex << ":" << mProcessorsOnce[mProcessorOnceIndex].Count() << "]";
496     });
497
498     // Swap processor index.
499     uint32_t currentIndex = mProcessorOnceIndex;
500     mProcessorOnceIndex ^= 1;
501
502     // Copy processor pointers to prevent changes to vector affecting loop iterator.
503     Dali::Vector<Integration::Processor*> processors(mProcessorsOnce[currentIndex]);
504
505     // To prevent accessing processor unregistered during the loop
506     mProcessorUnregistered = false;
507
508     for(auto processor : processors)
509     {
510       if(processor)
511       {
512         if(!mProcessorUnregistered)
513         {
514           processor->Process(false);
515         }
516         else
517         {
518           // Run processor if the processor is still in the list.
519           // It may be removed during the loop.
520           auto iter = std::find(mProcessorsOnce[currentIndex].Begin(), mProcessorsOnce[currentIndex].End(), processor);
521           if(iter != mProcessorsOnce[currentIndex].End())
522           {
523             processor->Process(false);
524           }
525         }
526       }
527     }
528
529     // Clear once processor.
530     mProcessorsOnce[currentIndex].Clear();
531
532     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
533       oss << "[" << currentIndex;
534       if(mProcessorUnregistered)
535       {
536         oss << ", processor changed";
537       }
538       oss << "]";
539     });
540   }
541
542   if(mProcessors.Count() != 0)
543   {
544     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) {
545       oss << "[" << mProcessors.Count() << "]";
546     });
547
548     // Copy processor pointers to prevent changes to vector affecting loop iterator.
549     Dali::Vector<Integration::Processor*> processors(mProcessors);
550
551     // To prevent accessing processor unregistered during the loop
552     mProcessorUnregistered = false;
553
554     for(auto processor : processors)
555     {
556       if(processor)
557       {
558         if(!mProcessorUnregistered)
559         {
560           DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
561             oss << "[" << processor->GetProcessorName() << "]";
562           });
563           processor->Process(false);
564           DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
565             oss << "[" << processor->GetProcessorName() << "]";
566           });
567         }
568         else
569         {
570           // Run processor if the processor is still in the list.
571           // It may be removed during the loop.
572           auto iter = std::find(mProcessors.Begin(), mProcessors.End(), processor);
573           if(iter != mProcessors.End())
574           {
575             DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
576               oss << "[" << processor->GetProcessorName() << "]";
577             });
578             processor->Process(false);
579             DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
580               oss << "[" << processor->GetProcessorName() << "]";
581             });
582           }
583         }
584       }
585     }
586     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) {
587       oss << "[" << mProcessors.Count();
588       if(mProcessorUnregistered)
589       {
590         oss << ", processor changed";
591       }
592       oss << "]";
593     });
594   }
595 }
596
597 void Core::RunPostProcessors()
598 {
599   if(mPostProcessorsOnce[mPostProcessorOnceIndex].Count() != 0)
600   {
601     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
602       oss << "[" << mPostProcessorOnceIndex << ":" << mPostProcessorsOnce[mPostProcessorOnceIndex].Count() << "]";
603     });
604
605     // Swap processor index.
606     uint32_t currentIndex = mPostProcessorOnceIndex;
607     mPostProcessorOnceIndex ^= 1;
608
609     // Copy processor pointers to prevent changes to vector affecting loop iterator.
610     Dali::Vector<Integration::Processor*> processors(mPostProcessorsOnce[currentIndex]);
611
612     // To prevent accessing processor unregistered during the loop
613     mPostProcessorUnregistered = false;
614
615     for(auto processor : processors)
616     {
617       if(processor)
618       {
619         if(!mPostProcessorUnregistered)
620         {
621           processor->Process(true);
622         }
623         else
624         {
625           // Run processor if the processor is still in the list.
626           // It may be removed during the loop.
627           auto iter = std::find(mPostProcessorsOnce[currentIndex].Begin(), mPostProcessorsOnce[currentIndex].End(), processor);
628           if(iter != mPostProcessorsOnce[currentIndex].End())
629           {
630             processor->Process(true);
631           }
632         }
633       }
634     }
635
636     // Clear once processor.
637     mPostProcessorsOnce[currentIndex].Clear();
638
639     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
640       oss << "[" << currentIndex;
641       if(mPostProcessorUnregistered)
642       {
643         oss << ", processor changed";
644       }
645       oss << "]";
646     });
647   }
648
649   if(mPostProcessors.Count() != 0)
650   {
651     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) {
652       oss << "[" << mPostProcessors.Count() << "]";
653     });
654
655     // Copy processor pointers to prevent changes to vector affecting loop iterator.
656     Dali::Vector<Integration::Processor*> processors(mPostProcessors);
657
658     // To prevent accessing processor unregistered during the loop
659     mPostProcessorUnregistered = false;
660
661     for(auto processor : processors)
662     {
663       if(processor)
664       {
665         if(!mPostProcessorUnregistered)
666         {
667           DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
668             oss << "[" << processor->GetProcessorName() << "]";
669           });
670           processor->Process(true);
671           DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
672             oss << "[" << processor->GetProcessorName() << "]";
673           });
674         }
675         else
676         {
677           // Run processor if the processor is still in the list.
678           // It may be removed during the loop.
679           auto iter = std::find(mPostProcessors.Begin(), mPostProcessors.End(), processor);
680           if(iter != mPostProcessors.End())
681           {
682             DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
683               oss << "[" << processor->GetProcessorName() << "]";
684             });
685             processor->Process(true);
686             DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
687               oss << "[" << processor->GetProcessorName() << "]";
688             });
689           }
690         }
691       }
692     }
693
694     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) {
695       oss << "[" << mPostProcessors.Count();
696       if(mPostProcessorUnregistered)
697       {
698         oss << ", processor changed";
699       }
700       oss << "]";
701     });
702   }
703 }
704
705 StagePtr Core::GetCurrentStage()
706 {
707   return mStage.Get();
708 }
709
710 PlatformAbstraction& Core::GetPlatform()
711 {
712   return mPlatform;
713 }
714
715 UpdateManager& Core::GetUpdateManager()
716 {
717   return *(mUpdateManager);
718 }
719
720 RenderManager& Core::GetRenderManager()
721 {
722   return *(mRenderManager);
723 }
724
725 NotificationManager& Core::GetNotificationManager()
726 {
727   return *(mNotificationManager);
728 }
729
730 ShaderFactory& Core::GetShaderFactory()
731 {
732   return *(mShaderFactory);
733 }
734
735 GestureEventProcessor& Core::GetGestureEventProcessor()
736 {
737   return *(mGestureEventProcessor);
738 }
739
740 RelayoutController& Core::GetRelayoutController()
741 {
742   return *(mRelayoutController.Get());
743 }
744
745 ObjectRegistry& Core::GetObjectRegistry() const
746 {
747   return *(mObjectRegistry.Get());
748 }
749
750 void Core::LogMemoryPools() const
751 {
752   uint32_t animationPoolCapacity    = SceneGraph::Animation::GetMemoryPoolCapacity();
753   uint32_t renderItemPoolCapacity   = SceneGraph::RenderItem::GetMemoryPoolCapacity();
754   uint32_t relayoutItemPoolCapacity = mRelayoutController->GetMemoryPoolCapacity();
755   uint32_t rendererPoolCapacity     = SceneGraph::Renderer::GetMemoryPoolCapacity();
756   uint32_t textureSetPoolCapacity   = SceneGraph::TextureSet::GetMemoryPoolCapacity();
757   uint32_t renderTaskPoolCapacity   = SceneGraph::RenderTaskList::GetMemoryPoolCapacity();
758   uint32_t nodePoolCapacity         = SceneGraph::Node::GetMemoryPoolCapacity();
759
760   DALI_LOG_RELEASE_INFO(
761     "\nMemory Pool capacities:\n"
762     "  Animations:    %lu\n"
763     "  RenderItems:   %lu\n"
764     "  RelayoutItems: %lu\n"
765     "  Renderers:     %lu\n"
766     "  TextureSets:   %lu\n"
767     "  RenderTasks:   %lu\n"
768     "  Nodes:         %lu\n",
769     animationPoolCapacity,
770     renderItemPoolCapacity,
771     relayoutItemPoolCapacity,
772     rendererPoolCapacity,
773     textureSetPoolCapacity,
774     renderTaskPoolCapacity,
775     nodePoolCapacity);
776
777   uint32_t updateQCapacity = mUpdateManager->GetUpdateMessageQueueCapacity();
778   uint32_t renderQCapacity = mUpdateManager->GetRenderMessageQueueCapacity();
779
780   DALI_LOG_RELEASE_INFO(
781     "\nMessage Queue capacities:\n"
782     "  UpdateQueue: %lu\n"
783     "  RenderQueue: %lu\n",
784     updateQCapacity,
785     renderQCapacity);
786
787   size_t renderInstructionCapacity = mUpdateManager->GetRenderInstructionCapacity();
788   DALI_LOG_RELEASE_INFO("\nRenderInstruction capacity: %lu\n", renderInstructionCapacity);
789 }
790
791 EventThreadServices& Core::GetEventThreadServices()
792 {
793   return *this;
794 }
795
796 PropertyNotificationManager& Core::GetPropertyNotificationManager() const
797 {
798   return *(mPropertyNotificationManager);
799 }
800
801 AnimationPlaylist& Core::GetAnimationPlaylist() const
802 {
803   return *(mAnimationPlaylist);
804 }
805
806 Integration::GraphicsConfig& Core::GetGraphicsConfig() const
807 {
808   return mGraphicsController.GetGraphicsConfig();
809 }
810
811 void Core::AddScene(Scene* scene)
812 {
813   mScenes.push_back(scene);
814 }
815
816 void Core::RemoveScene(Scene* scene)
817 {
818   auto iter = std::find(mScenes.begin(), mScenes.end(), scene);
819   if(iter != mScenes.end())
820   {
821     mScenes.erase(iter);
822   }
823 }
824
825 void Core::CreateThreadLocalStorage()
826 {
827   // a pointer to the ThreadLocalStorage object will be stored in TLS
828   // The ThreadLocalStorage object should be deleted by the Core destructor
829   ThreadLocalStorage* tls = new ThreadLocalStorage(this);
830   tls->Reference();
831 }
832
833 void Core::RegisterObject(Dali::BaseObject* object)
834 {
835   mObjectRegistry = &ThreadLocalStorage::Get().GetObjectRegistry();
836   mObjectRegistry->RegisterObject(object);
837 }
838
839 void Core::UnregisterObject(Dali::BaseObject* object)
840 {
841   mObjectRegistry = &ThreadLocalStorage::Get().GetObjectRegistry();
842   mObjectRegistry->UnregisterObject(object);
843 }
844
845 Integration::RenderController& Core::GetRenderController()
846 {
847   return mRenderController;
848 }
849
850 uint32_t* Core::ReserveMessageSlot(uint32_t size, bool updateScene)
851 {
852   return mUpdateManager->ReserveMessageSlot(size, updateScene);
853 }
854
855 BufferIndex Core::GetEventBufferIndex() const
856 {
857   return mUpdateManager->GetEventBufferIndex();
858 }
859
860 } // namespace Internal
861
862 } // namespace Dali