bf43498ce813b248805cd5d7a1b84376b3e24b4d
[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   mUpdateManager->EventProcessingFinished();
312
313   // Check if the touch or gestures require updates.
314   const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
315
316   if(gestureNeedsUpdate)
317   {
318     // tell the render controller to keep update thread running
319     mRenderController.RequestUpdate();
320   }
321
322   mRelayoutController->SetProcessingCoreEvents(false);
323
324   // ProcessEvents() may now be called again
325   mProcessingEvent = false;
326 }
327
328 void Core::RelayoutAndFlush(SceneContainer& scenes)
329 {
330   if(mRelayoutFlush)
331   {
332     DALI_LOG_ERROR("RelayoutAndFlush should not be called from within RelayoutAndFlush!\n");
333     return;
334   }
335
336   const bool isProcessEvents = mProcessingEvent;
337
338   if(!isProcessEvents)
339   {
340     // Fake that we are in ProcessEvents()
341     mProcessingEvent = true;
342     mRelayoutController->SetProcessingCoreEvents(true);
343
344     // Signal that any messages received will be flushed soon
345     mUpdateManager->EventProcessingStarted();
346   }
347
348   mRelayoutFlush = true;
349
350   // Run any registered processors
351   RunProcessors();
352
353   // Run the size negotiation after event processing finished signal
354   mRelayoutController->Relayout();
355
356   // Run any registered post processors
357   RunPostProcessors();
358
359   // Rebuild depth tree after event processing has finished
360   for(auto& scene : scenes)
361   {
362     scene->RebuildDepthTree();
363   }
364
365   // Flush any queued messages for the update-thread
366   const bool messagesToProcess = mUpdateManager->FlushQueue();
367
368   if(messagesToProcess)
369   {
370     // tell the render controller to keep update thread running
371     mRenderController.RequestUpdate();
372   }
373
374   mRelayoutFlush = false;
375
376   if(!isProcessEvents)
377   {
378     // Revert fake informations
379     mProcessingEvent = false;
380     mRelayoutController->SetProcessingCoreEvents(false);
381
382     mUpdateManager->EventProcessingFinished();
383   }
384 }
385
386 uint32_t Core::GetMaximumUpdateCount() const
387 {
388   return MAXIMUM_UPDATE_COUNT;
389 }
390
391 void Core::RegisterProcessor(Integration::Processor& processor, bool postProcessor)
392 {
393   if(postProcessor)
394   {
395     mPostProcessors.PushBack(&processor);
396   }
397   else
398   {
399     mProcessors.PushBack(&processor);
400   }
401 }
402
403 void Core::UnregisterProcessor(Integration::Processor& processor, bool postProcessor)
404 {
405   if(postProcessor)
406   {
407     auto iter = std::find(mPostProcessors.Begin(), mPostProcessors.End(), &processor);
408     if(iter != mPostProcessors.End())
409     {
410       mPostProcessors.Erase(iter);
411       mPostProcessorUnregistered = true;
412     }
413   }
414   else
415   {
416     auto iter = std::find(mProcessors.Begin(), mProcessors.End(), &processor);
417     if(iter != mProcessors.End())
418     {
419       mProcessors.Erase(iter);
420       mProcessorUnregistered = true;
421     }
422   }
423 }
424
425 void Core::RegisterProcessorOnce(Integration::Processor& processor, bool postProcessor)
426 {
427   if(postProcessor)
428   {
429     mPostProcessorsOnce[mPostProcessorOnceIndex].PushBack(&processor);
430   }
431   else
432   {
433     mProcessorsOnce[mProcessorOnceIndex].PushBack(&processor);
434   }
435 }
436
437 void Core::UnregisterProcessorOnce(Integration::Processor& processor, bool postProcessor)
438 {
439   if(postProcessor)
440   {
441     for(uint32_t index = 0; index < 2; ++index)
442     {
443       auto iter = std::find(mPostProcessorsOnce[index].Begin(), mPostProcessorsOnce[index].End(), &processor);
444       if(iter != mPostProcessorsOnce[index].End())
445       {
446         mPostProcessorsOnce[index].Erase(iter);
447         if(index != mPostProcessorOnceIndex)
448         {
449           // Check processor unregistered during processing.
450           mPostProcessorUnregistered = true;
451         }
452       }
453     }
454   }
455   else
456   {
457     for(uint32_t index = 0; index < 2; ++index)
458     {
459       auto iter = std::find(mProcessorsOnce[index].Begin(), mProcessorsOnce[index].End(), &processor);
460       if(iter != mProcessorsOnce[index].End())
461       {
462         mProcessorsOnce[index].Erase(iter);
463         if(index != mProcessorOnceIndex)
464         {
465           // Check processor unregistered during processing.
466           mProcessorUnregistered = true;
467         }
468       }
469     }
470   }
471 }
472
473 void Core::UnregisterProcessors()
474 {
475   mPostProcessors.Clear();
476   mPostProcessorUnregistered = true;
477   mProcessors.Clear();
478   mProcessorUnregistered = true;
479
480   for(uint32_t index = 0; index < 2; ++index)
481   {
482     mPostProcessorsOnce[index].Clear();
483     mProcessorsOnce[index].Clear();
484   }
485 }
486
487 void Core::RunProcessors()
488 {
489   if(mProcessorsOnce[mProcessorOnceIndex].Count() != 0)
490   {
491     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
492       oss << "[" << mProcessorOnceIndex << ":" << mProcessorsOnce[mProcessorOnceIndex].Count() << "]";
493     });
494
495     // Swap processor index.
496     uint32_t currentIndex = mProcessorOnceIndex;
497     mProcessorOnceIndex ^= 1;
498
499     // Copy processor pointers to prevent changes to vector affecting loop iterator.
500     Dali::Vector<Integration::Processor*> processors(mProcessorsOnce[currentIndex]);
501
502     // To prevent accessing processor unregistered during the loop
503     mProcessorUnregistered = false;
504
505     for(auto processor : processors)
506     {
507       if(processor)
508       {
509         if(!mProcessorUnregistered)
510         {
511           DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
512             oss << "[" << processor->GetProcessorName() << "]";
513           });
514           processor->Process(false);
515           DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
516             oss << "[" << processor->GetProcessorName() << "]";
517           });
518         }
519         else
520         {
521           // Run processor if the processor is still in the list.
522           // It may be removed during the loop.
523           auto iter = std::find(mProcessorsOnce[currentIndex].Begin(), mProcessorsOnce[currentIndex].End(), processor);
524           if(iter != mProcessorsOnce[currentIndex].End())
525           {
526             DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
527               oss << "[" << processor->GetProcessorName() << "]";
528             });
529             processor->Process(false);
530             DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
531               oss << "[" << processor->GetProcessorName() << "]";
532             });
533           }
534         }
535       }
536     }
537
538     // Clear once processor.
539     mProcessorsOnce[currentIndex].Clear();
540
541     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
542       oss << "[" << currentIndex;
543       if(mProcessorUnregistered)
544       {
545         oss << ", processor changed";
546       }
547       oss << "]";
548     });
549   }
550
551   if(mProcessors.Count() != 0)
552   {
553     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) {
554       oss << "[" << mProcessors.Count() << "]";
555     });
556
557     // Copy processor pointers to prevent changes to vector affecting loop iterator.
558     Dali::Vector<Integration::Processor*> processors(mProcessors);
559
560     // To prevent accessing processor unregistered during the loop
561     mProcessorUnregistered = false;
562
563     for(auto processor : processors)
564     {
565       if(processor)
566       {
567         if(!mProcessorUnregistered)
568         {
569           DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
570             oss << "[" << processor->GetProcessorName() << "]";
571           });
572           processor->Process(false);
573           DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
574             oss << "[" << processor->GetProcessorName() << "]";
575           });
576         }
577         else
578         {
579           // Run processor if the processor is still in the list.
580           // It may be removed during the loop.
581           auto iter = std::find(mProcessors.Begin(), mProcessors.End(), processor);
582           if(iter != mProcessors.End())
583           {
584             DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
585               oss << "[" << processor->GetProcessorName() << "]";
586             });
587             processor->Process(false);
588             DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSOR", [&](std::ostringstream& oss) {
589               oss << "[" << processor->GetProcessorName() << "]";
590             });
591           }
592         }
593       }
594     }
595     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_PROCESSORS", [&](std::ostringstream& oss) {
596       oss << "[" << mProcessors.Count();
597       if(mProcessorUnregistered)
598       {
599         oss << ", processor changed";
600       }
601       oss << "]";
602     });
603   }
604 }
605
606 void Core::RunPostProcessors()
607 {
608   if(mPostProcessorsOnce[mPostProcessorOnceIndex].Count() != 0)
609   {
610     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
611       oss << "[" << mPostProcessorOnceIndex << ":" << mPostProcessorsOnce[mPostProcessorOnceIndex].Count() << "]";
612     });
613
614     // Swap processor index.
615     uint32_t currentIndex = mPostProcessorOnceIndex;
616     mPostProcessorOnceIndex ^= 1;
617
618     // Copy processor pointers to prevent changes to vector affecting loop iterator.
619     Dali::Vector<Integration::Processor*> processors(mPostProcessorsOnce[currentIndex]);
620
621     // To prevent accessing processor unregistered during the loop
622     mPostProcessorUnregistered = false;
623
624     for(auto processor : processors)
625     {
626       if(processor)
627       {
628         if(!mPostProcessorUnregistered)
629         {
630           DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
631             oss << "[" << processor->GetProcessorName() << "]";
632           });
633           processor->Process(true);
634           DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
635             oss << "[" << processor->GetProcessorName() << "]";
636           });
637         }
638         else
639         {
640           // Run processor if the processor is still in the list.
641           // It may be removed during the loop.
642           auto iter = std::find(mPostProcessorsOnce[currentIndex].Begin(), mPostProcessorsOnce[currentIndex].End(), processor);
643           if(iter != mPostProcessorsOnce[currentIndex].End())
644           {
645             DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
646               oss << "[" << processor->GetProcessorName() << "]";
647             });
648             processor->Process(true);
649             DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR_ONCE", [&](std::ostringstream& oss) {
650               oss << "[" << processor->GetProcessorName() << "]";
651             });
652           }
653         }
654       }
655     }
656
657     // Clear once processor.
658     mPostProcessorsOnce[currentIndex].Clear();
659
660     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS_ONCE", [&](std::ostringstream& oss) {
661       oss << "[" << currentIndex;
662       if(mPostProcessorUnregistered)
663       {
664         oss << ", processor changed";
665       }
666       oss << "]";
667     });
668   }
669
670   if(mPostProcessors.Count() != 0)
671   {
672     DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) {
673       oss << "[" << mPostProcessors.Count() << "]";
674     });
675
676     // Copy processor pointers to prevent changes to vector affecting loop iterator.
677     Dali::Vector<Integration::Processor*> processors(mPostProcessors);
678
679     // To prevent accessing processor unregistered during the loop
680     mPostProcessorUnregistered = false;
681
682     for(auto processor : processors)
683     {
684       if(processor)
685       {
686         if(!mPostProcessorUnregistered)
687         {
688           DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
689             oss << "[" << processor->GetProcessorName() << "]";
690           });
691           processor->Process(true);
692           DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
693             oss << "[" << processor->GetProcessorName() << "]";
694           });
695         }
696         else
697         {
698           // Run processor if the processor is still in the list.
699           // It may be removed during the loop.
700           auto iter = std::find(mPostProcessors.Begin(), mPostProcessors.End(), processor);
701           if(iter != mPostProcessors.End())
702           {
703             DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
704               oss << "[" << processor->GetProcessorName() << "]";
705             });
706             processor->Process(true);
707             DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSOR", [&](std::ostringstream& oss) {
708               oss << "[" << processor->GetProcessorName() << "]";
709             });
710           }
711         }
712       }
713     }
714
715     DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_CORE_RUN_POST_PROCESSORS", [&](std::ostringstream& oss) {
716       oss << "[" << mPostProcessors.Count();
717       if(mPostProcessorUnregistered)
718       {
719         oss << ", processor changed";
720       }
721       oss << "]";
722     });
723   }
724 }
725
726 StagePtr Core::GetCurrentStage()
727 {
728   return mStage.Get();
729 }
730
731 PlatformAbstraction& Core::GetPlatform()
732 {
733   return mPlatform;
734 }
735
736 UpdateManager& Core::GetUpdateManager()
737 {
738   return *(mUpdateManager);
739 }
740
741 RenderManager& Core::GetRenderManager()
742 {
743   return *(mRenderManager);
744 }
745
746 NotificationManager& Core::GetNotificationManager()
747 {
748   return *(mNotificationManager);
749 }
750
751 ShaderFactory& Core::GetShaderFactory()
752 {
753   return *(mShaderFactory);
754 }
755
756 GestureEventProcessor& Core::GetGestureEventProcessor()
757 {
758   return *(mGestureEventProcessor);
759 }
760
761 RelayoutController& Core::GetRelayoutController()
762 {
763   return *(mRelayoutController.Get());
764 }
765
766 ObjectRegistry& Core::GetObjectRegistry() const
767 {
768   return *(mObjectRegistry.Get());
769 }
770
771 void Core::LogMemoryPools() const
772 {
773   uint32_t animationPoolCapacity    = SceneGraph::Animation::GetMemoryPoolCapacity();
774   uint32_t renderItemPoolCapacity   = SceneGraph::RenderItem::GetMemoryPoolCapacity();
775   uint32_t relayoutItemPoolCapacity = mRelayoutController->GetMemoryPoolCapacity();
776   uint32_t rendererPoolCapacity     = SceneGraph::Renderer::GetMemoryPoolCapacity();
777   uint32_t textureSetPoolCapacity   = SceneGraph::TextureSet::GetMemoryPoolCapacity();
778   uint32_t renderTaskPoolCapacity   = SceneGraph::RenderTaskList::GetMemoryPoolCapacity();
779   uint32_t nodePoolCapacity         = SceneGraph::Node::GetMemoryPoolCapacity();
780
781   DALI_LOG_RELEASE_INFO(
782     "\nMemory Pool capacities:\n"
783     "  Animations:    %lu\n"
784     "  RenderItems:   %lu\n"
785     "  RelayoutItems: %lu\n"
786     "  Renderers:     %lu\n"
787     "  TextureSets:   %lu\n"
788     "  RenderTasks:   %lu\n"
789     "  Nodes:         %lu\n",
790     animationPoolCapacity,
791     renderItemPoolCapacity,
792     relayoutItemPoolCapacity,
793     rendererPoolCapacity,
794     textureSetPoolCapacity,
795     renderTaskPoolCapacity,
796     nodePoolCapacity);
797
798   uint32_t updateQCapacity = mUpdateManager->GetUpdateMessageQueueCapacity();
799   uint32_t renderQCapacity = mUpdateManager->GetRenderMessageQueueCapacity();
800
801   DALI_LOG_RELEASE_INFO(
802     "\nMessage Queue capacities:\n"
803     "  UpdateQueue: %lu\n"
804     "  RenderQueue: %lu\n",
805     updateQCapacity,
806     renderQCapacity);
807
808   size_t renderInstructionCapacity = mUpdateManager->GetRenderInstructionCapacity();
809   DALI_LOG_RELEASE_INFO("\nRenderInstruction capacity: %lu\n", renderInstructionCapacity);
810 }
811
812 EventThreadServices& Core::GetEventThreadServices()
813 {
814   return *this;
815 }
816
817 PropertyNotificationManager& Core::GetPropertyNotificationManager() const
818 {
819   return *(mPropertyNotificationManager);
820 }
821
822 AnimationPlaylist& Core::GetAnimationPlaylist() const
823 {
824   return *(mAnimationPlaylist);
825 }
826
827 Integration::GraphicsConfig& Core::GetGraphicsConfig() const
828 {
829   return mGraphicsController.GetGraphicsConfig();
830 }
831
832 void Core::AddScene(Scene* scene)
833 {
834   mScenes.push_back(scene);
835 }
836
837 void Core::RemoveScene(Scene* scene)
838 {
839   auto iter = std::find(mScenes.begin(), mScenes.end(), scene);
840   if(iter != mScenes.end())
841   {
842     mScenes.erase(iter);
843   }
844 }
845
846 void Core::CreateThreadLocalStorage()
847 {
848   // a pointer to the ThreadLocalStorage object will be stored in TLS
849   // The ThreadLocalStorage object should be deleted by the Core destructor
850   ThreadLocalStorage* tls = new ThreadLocalStorage(this);
851   tls->Reference();
852 }
853
854 void Core::RegisterObject(Dali::BaseObject* object)
855 {
856   mObjectRegistry = &ThreadLocalStorage::Get().GetObjectRegistry();
857   mObjectRegistry->RegisterObject(object);
858 }
859
860 void Core::UnregisterObject(Dali::BaseObject* object)
861 {
862   mObjectRegistry = &ThreadLocalStorage::Get().GetObjectRegistry();
863   mObjectRegistry->UnregisterObject(object);
864 }
865
866 Integration::RenderController& Core::GetRenderController()
867 {
868   return mRenderController;
869 }
870
871 uint32_t* Core::ReserveMessageSlot(uint32_t size, bool updateScene)
872 {
873   return mUpdateManager->ReserveMessageSlot(size, updateScene);
874 }
875
876 BufferIndex Core::GetEventBufferIndex() const
877 {
878   return mUpdateManager->GetEventBufferIndex();
879 }
880
881 } // namespace Internal
882
883 } // namespace Dali