[dali_2.3.29] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / adaptor-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/adaptor/common/adaptor-builder-impl.h>
20 #include <dali/internal/adaptor/common/adaptor-impl.h>
21 #include <dali/internal/addons/common/addon-manager-factory.h>
22 #include <dali/internal/addons/common/addon-manager-impl.h>
23
24 // EXTERNAL INCLUDES
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/devel-api/common/stage.h>
27 #include <dali/integration-api/addon-manager.h>
28 #include <dali/integration-api/context-notifier.h>
29 #include <dali/integration-api/core.h>
30 #include <dali/integration-api/debug.h>
31 #include <dali/integration-api/events/key-event-integ.h>
32 #include <dali/integration-api/events/touch-event-integ.h>
33 #include <dali/integration-api/events/wheel-event-integ.h>
34 #include <dali/integration-api/input-options.h>
35 #include <dali/integration-api/processor-interface.h>
36 #include <dali/integration-api/profiling.h>
37 #include <dali/integration-api/trace.h>
38 #include <dali/public-api/actors/layer.h>
39 #include <dali/public-api/events/wheel-event.h>
40 #include <dali/public-api/object/any.h>
41 #include <dali/public-api/object/object-registry.h>
42 #include <errno.h>
43 #include <sys/stat.h>
44
45 // INTERNAL INCLUDES
46 #include <dali/internal/adaptor/common/lifecycle-observer.h>
47 #include <dali/internal/adaptor/common/thread-controller-interface.h>
48 #include <dali/internal/system/common/performance-interface-factory.h>
49 #include <dali/internal/system/common/thread-controller.h>
50 #include <dali/public-api/dali-adaptor-common.h>
51
52 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
53 #include <dali/internal/graphics/gles/egl-graphics.h>
54
55 #include <dali/devel-api/text-abstraction/font-client.h>
56
57 #include <dali/internal/accessibility/common/tts-player-impl.h>
58 #include <dali/internal/graphics/common/egl-image-extensions.h>
59 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
60 #include <dali/internal/graphics/gles/gl-implementation.h>
61 #include <dali/internal/graphics/gles/gl-proxy-implementation.h>
62 #include <dali/internal/system/common/callback-manager.h>
63 #include <dali/internal/system/common/object-profiler.h>
64 #include <dali/internal/system/common/system-factory.h>
65 #include <dali/internal/window-system/common/display-connection.h>
66 #include <dali/internal/window-system/common/display-utils.h> // For Utils::MakeUnique
67 #include <dali/internal/window-system/common/event-handler.h>
68 #include <dali/internal/window-system/common/window-impl.h>
69 #include <dali/internal/window-system/common/window-render-surface.h>
70 #include <dali/internal/window-system/common/window-system.h>
71
72 #include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
73 #include <dali/internal/system/common/logging.h>
74
75 #include <dali/internal/imaging/common/image-loader-plugin-proxy.h>
76 #include <dali/internal/imaging/common/image-loader.h>
77 #include <dali/internal/system/common/locale-utils.h>
78
79 #include <dali/devel-api/adaptor-framework/environment-variable.h>
80 #include <dali/internal/system/common/configuration-manager.h>
81 #include <dali/internal/system/common/environment-variables.h>
82
83 using Dali::TextAbstraction::FontClient;
84
85 extern std::string GetSystemCachePath();
86
87 namespace Dali
88 {
89 namespace Internal
90 {
91 namespace Adaptor
92 {
93 namespace
94 {
95 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
96
97 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
98 } // unnamed namespace
99
100 Dali::Adaptor* Adaptor::New(Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions, ThreadMode threadMode)
101 {
102   Dali::Adaptor* adaptor = new Dali::Adaptor;
103   Adaptor*       impl    = new Adaptor(window, *adaptor, surface, environmentOptions, threadMode);
104   adaptor->mImpl         = impl;
105
106   Dali::Internal::Adaptor::AdaptorBuilder* mAdaptorBuilder = new AdaptorBuilder(*(impl->mEnvironmentOptions));
107   auto                                     graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
108
109   impl->Initialize(graphicsFactory);
110   delete mAdaptorBuilder; // Not needed anymore as the graphics interface has now been created
111
112   return adaptor;
113 }
114
115 Dali::Adaptor* Adaptor::New(Dali::Integration::SceneHolder window, EnvironmentOptions* environmentOptions)
116 {
117   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(window);
118   Dali::Adaptor*                  adaptor    = New(window, windowImpl.GetSurface(), environmentOptions, ThreadMode::NORMAL);
119   windowImpl.SetAdaptor(*adaptor);
120   return adaptor;
121 }
122
123 Dali::Adaptor* Adaptor::New(GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions, ThreadMode threadMode)
124 {
125   Dali::Adaptor* adaptor = new Dali::Adaptor;                                                      // Public adaptor
126   Adaptor*       impl    = new Adaptor(window, *adaptor, surface, environmentOptions, threadMode); // Impl adaptor
127   adaptor->mImpl         = impl;
128
129   impl->Initialize(graphicsFactory);
130
131   return adaptor;
132 } // Called second
133
134 Dali::Adaptor* Adaptor::New(GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, EnvironmentOptions* environmentOptions)
135 {
136   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(window);
137   Dali::Adaptor*                  adaptor    = New(graphicsFactory, window, windowImpl.GetSurface(), environmentOptions, ThreadMode::NORMAL);
138   windowImpl.SetAdaptor(*adaptor);
139   return adaptor;
140 } // Called first
141
142 void Adaptor::Initialize(GraphicsFactory& graphicsFactory)
143 {
144   // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
145   Dali::Integration::Log::LogFunction logFunction(Dali::TizenPlatform::LogMessage);
146   mEnvironmentOptions->SetLogFunction(logFunction);
147   mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
148
149   mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
150
151   std::string path;
152   GetDataStoragePath(path);
153   mPlatformAbstraction->SetDataStoragePath(path);
154
155   if(mEnvironmentOptions->PerformanceServerRequired())
156   {
157     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface(*this, *mEnvironmentOptions);
158   }
159
160   mEnvironmentOptions->CreateTraceManager(mPerformanceInterface);
161   mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
162
163   mCallbackManager = Dali::Internal::Adaptor::GetSystemFactory()->CreateCallbackManager();
164
165   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
166
167   DALI_ASSERT_DEBUG(defaultWindow->GetSurface() && "Surface not initialized");
168
169   mGraphics = std::unique_ptr<GraphicsInterface>(&graphicsFactory.Create());
170
171   // Create the AddOnManager
172   mAddOnManager.reset(Dali::Internal::AddOnManagerFactory::CreateAddOnManager());
173
174   Integration::CorePolicyFlags corePolicyFlags = Integration::CorePolicyFlags::DEFAULT;
175   if(0u != mEnvironmentOptions->GetRenderToFboInterval())
176   {
177     corePolicyFlags |= Integration::CorePolicyFlags::RENDER_TO_FRAME_BUFFER;
178   }
179   if(Integration::DepthBufferAvailable::TRUE == mGraphics->GetDepthBufferRequired())
180   {
181     corePolicyFlags |= Integration::CorePolicyFlags::DEPTH_BUFFER_AVAILABLE;
182   }
183   if(Integration::StencilBufferAvailable::TRUE == mGraphics->GetStencilBufferRequired())
184   {
185     corePolicyFlags |= Integration::CorePolicyFlags::STENCIL_BUFFER_AVAILABLE;
186   }
187   if(Integration::PartialUpdateAvailable::TRUE == mGraphics->GetPartialUpdateRequired())
188   {
189     corePolicyFlags |= Integration::CorePolicyFlags::PARTIAL_UPDATE_AVAILABLE;
190   }
191
192   mCore = Integration::Core::New(*this,
193                                  *mPlatformAbstraction,
194                                  mGraphics->GetController(),
195                                  corePolicyFlags);
196
197   // Create TextureUploadManager after mCore created
198   mTextureUploadManager = Dali::Devel::TextureUploadManager::Get();
199
200   defaultWindow->SetAdaptor(Get());
201
202   Dali::Integration::SceneHolder defaultSceneHolder(defaultWindow);
203
204   mWindowCreatedSignal.Emit(defaultSceneHolder);
205
206   const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
207   if(0u < timeInterval)
208   {
209     mObjectProfiler = new ObjectProfiler(mCore->GetObjectRegistry(), timeInterval);
210   }
211
212   const uint32_t poolTimeInterval = mEnvironmentOptions->GetMemoryPoolInterval();
213   if(0u < poolTimeInterval)
214   {
215     mMemoryPoolTimer = Dali::Timer::New(poolTimeInterval * 1000);
216     mMemoryPoolTimer.TickSignal().Connect(mMemoryPoolTimerSlotDelegate, &Adaptor::MemoryPoolTimeout);
217     mMemoryPoolTimer.Start();
218   }
219
220   mNotificationTrigger = TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &Adaptor::ProcessCoreEvents), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
221
222   mDisplayConnection = Dali::DisplayConnection::New(*mGraphics, defaultWindow->GetSurface()->GetSurfaceType());
223
224   mThreadController = new ThreadController(*this, *mEnvironmentOptions, mThreadMode);
225
226   // Should be called after Core creation
227   if(mEnvironmentOptions->GetPanGestureLoggingLevel())
228   {
229     Integration::EnableProfiling(Dali::Integration::PROFILING_TYPE_PAN_GESTURE);
230   }
231   if(mEnvironmentOptions->GetPanGesturePredictionMode() >= 0)
232   {
233     Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
234   }
235   if(mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0)
236   {
237     Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
238   }
239   if(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0)
240   {
241     Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
242   }
243   if(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0)
244   {
245     Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
246   }
247   if(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0)
248   {
249     Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
250   }
251   if(mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0)
252   {
253     Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
254   }
255   if(mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f)
256   {
257     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
258   }
259   if(mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0)
260   {
261     Integration::SetPanGestureUseActualTimes(mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false);
262   }
263   if(mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0)
264   {
265     Integration::SetPanGestureInterpolationTimeRange(mEnvironmentOptions->GetPanGestureInterpolationTimeRange());
266   }
267   if(mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0)
268   {
269     Integration::SetPanGestureScalarOnlyPredictionEnabled(mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false);
270   }
271   if(mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0)
272   {
273     Integration::SetPanGestureTwoPointPredictionEnabled(mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false);
274   }
275   if(mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0)
276   {
277     Integration::SetPanGestureTwoPointInterpolatePastTime(mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime());
278   }
279   if(mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f)
280   {
281     Integration::SetPanGestureTwoPointVelocityBias(mEnvironmentOptions->GetPanGestureTwoPointVelocityBias());
282   }
283   if(mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f)
284   {
285     Integration::SetPanGestureTwoPointAccelerationBias(mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias());
286   }
287   if(mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0)
288   {
289     Integration::SetPanGestureMultitapSmoothingRange(mEnvironmentOptions->GetPanGestureMultitapSmoothingRange());
290   }
291   if(mEnvironmentOptions->GetMinimumPanDistance() >= 0)
292   {
293     Integration::SetPanGestureMinimumDistance(mEnvironmentOptions->GetMinimumPanDistance());
294   }
295   if(mEnvironmentOptions->GetMinimumPanEvents() >= 0)
296   {
297     Integration::SetPanGestureMinimumPanEvents(mEnvironmentOptions->GetMinimumPanEvents());
298   }
299   if(mEnvironmentOptions->GetMinimumPinchDistance() >= 0)
300   {
301     Integration::SetPinchGestureMinimumDistance(mEnvironmentOptions->GetMinimumPinchDistance());
302   }
303   if(mEnvironmentOptions->GetMinimumPinchTouchEvents() >= 0)
304   {
305     Integration::SetPinchGestureMinimumTouchEvents(mEnvironmentOptions->GetMinimumPinchTouchEvents());
306   }
307   if(mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() >= 0)
308   {
309     Integration::SetPinchGestureMinimumTouchEventsAfterStart(mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart());
310   }
311   if(mEnvironmentOptions->GetMinimumRotationTouchEvents() >= 0)
312   {
313     Integration::SetRotationGestureMinimumTouchEvents(mEnvironmentOptions->GetMinimumRotationTouchEvents());
314   }
315   if(mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() >= 0)
316   {
317     Integration::SetRotationGestureMinimumTouchEventsAfterStart(mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart());
318   }
319   if(mEnvironmentOptions->GetLongPressMinimumHoldingTime() >= 0)
320   {
321     Integration::SetLongPressMinimumHoldingTime(mEnvironmentOptions->GetLongPressMinimumHoldingTime());
322   }
323   if(mEnvironmentOptions->GetTapMaximumAllowedTime() > 0)
324   {
325     Integration::SetTapMaximumAllowedTime(mEnvironmentOptions->GetTapMaximumAllowedTime());
326   }
327
328   std::string systemCachePath = GetSystemCachePath();
329   if(!systemCachePath.empty())
330   {
331     const int dir_err = mkdir(systemCachePath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
332     if(0 != dir_err && errno != EEXIST)
333     {
334       DALI_LOG_ERROR("Error creating system cache directory: %s!\n", systemCachePath.c_str());
335     }
336   }
337
338   mConfigurationManager = Utils::MakeUnique<ConfigurationManager>(systemCachePath, mGraphics.get(), mThreadController);
339 }
340
341 Adaptor::~Adaptor()
342 {
343   Accessibility::Bridge::GetCurrentBridge()->Terminate();
344
345   // Ensure stop status
346   Stop();
347
348   // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
349   gThreadLocalAdaptor = NULL;
350
351   for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
352   {
353     (*iter)->OnDestroy();
354   }
355
356   // Clear out all the handles to Windows
357   mWindows.clear();
358
359   delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
360   delete mObjectProfiler;
361
362   delete mCore;
363
364   delete mDisplayConnection;
365   delete mPlatformAbstraction;
366
367   mCallbackManager.reset();
368
369   delete mPerformanceInterface;
370
371   mGraphics->Destroy();
372
373   // uninstall it on this thread (main actor thread)
374   Dali::Integration::Log::UninstallLogFunction();
375
376   // Delete environment options if we own it
377   if(mEnvironmentOptionsOwned)
378   {
379     delete mEnvironmentOptions;
380   }
381 }
382
383 void Adaptor::Start()
384 {
385   // It doesn't support restart after stop at this moment to support restarting, need more testing
386   if(READY != mState)
387   {
388     return;
389   }
390
391   mCore->Initialize();
392
393   SetupSystemInformation();
394
395   // Start the callback manager
396   mCallbackManager->Start();
397
398   // Initialize accessibility bridge after callback manager is started to use Idler callback
399   auto appName = GetApplicationPackageName();
400   auto bridge  = Accessibility::Bridge::GetCurrentBridge();
401   bridge->SetApplicationName(appName);
402   bridge->Initialize();
403
404   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
405
406   unsigned int dpiHor, dpiVer;
407   dpiHor = dpiVer = 0;
408
409   defaultWindow->GetSurface()->GetDpi(dpiHor, dpiVer);
410   Dali::Internal::Adaptor::WindowSystem::SetDpi(dpiHor, dpiVer);
411
412   // Initialize the thread controller
413   mThreadController->Initialize();
414
415   // Set max texture size
416   if(mEnvironmentOptions->GetMaxTextureSize() > 0)
417   {
418     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize(mEnvironmentOptions->GetMaxTextureSize());
419   }
420   else
421   {
422     unsigned int maxTextureSize = mConfigurationManager->GetMaxTextureSize();
423     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize(maxTextureSize);
424   }
425
426   // cache advanced blending and shader language version
427   mGraphics->CacheConfigurations(*mConfigurationManager.get());
428
429   ProcessCoreEvents(); // Ensure any startup messages are processed.
430
431   // Initialize the image loader plugin
432   auto enablePluginString = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_ENABLE_IMAGE_LOADER_PLUGIN);
433   bool enablePlugin       = enablePluginString ? std::atoi(enablePluginString) : false;
434   if(enablePlugin)
435   {
436     Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
437   }
438
439   for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
440   {
441     (*iter)->OnStart();
442   }
443
444   if(mAddOnManager)
445   {
446     mAddOnManager->Start();
447   }
448 }
449
450 // Dali::Internal::Adaptor::Adaptor::Pause
451 void Adaptor::Pause()
452 {
453   // Only pause the adaptor if we're actually running.
454   if(RUNNING == mState)
455   {
456     // Inform observers that we are about to be paused.
457     for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
458     {
459       (*iter)->OnPause();
460     }
461
462     // Extensions
463     if(mAddOnManager)
464     {
465       mAddOnManager->Pause();
466     }
467
468     // Pause all windows event handlers when adaptor paused
469     for(auto window : mWindows)
470     {
471       window->Pause();
472     }
473
474     mThreadController->Pause();
475     mState = PAUSED;
476
477     // Ensure any messages queued during pause callbacks are processed by doing another update.
478     RequestUpdateOnce();
479
480     DALI_LOG_RELEASE_INFO("Adaptor::Pause: Paused\n");
481   }
482   else
483   {
484     DALI_LOG_RELEASE_INFO("Adaptor::Pause: Not paused [%d]\n", mState);
485   }
486 }
487
488 // Dali::Internal::Adaptor::Adaptor::Resume
489 void Adaptor::Resume()
490 {
491   // Only resume the adaptor if we are in the suspended state.
492   if(PAUSED == mState)
493   {
494     mState = RUNNING;
495
496     // Reset the event handlers when adaptor resumed
497     for(auto window : mWindows)
498     {
499       window->Resume();
500     }
501
502     // Resume AddOnManager
503     if(mAddOnManager)
504     {
505       mAddOnManager->Resume();
506     }
507
508     // Inform observers that we have resumed.
509     for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
510     {
511       (*iter)->OnResume();
512     }
513
514     // Trigger processing of events queued up while paused
515     mCore->ProcessEvents();
516
517     // Do at end to ensure our first update/render after resumption includes the processed messages as well
518     mThreadController->Resume();
519
520     DALI_LOG_RELEASE_INFO("Adaptor::Resume: Resumed\n");
521   }
522   else
523   {
524     DALI_LOG_RELEASE_INFO("Adaptor::Resume: Not resumed [%d]\n", mState);
525   }
526 }
527
528 void Adaptor::Stop()
529 {
530   if(RUNNING == mState ||
531      PAUSED == mState ||
532      PAUSED_WHILE_HIDDEN == mState)
533   {
534     for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
535     {
536       (*iter)->OnStop();
537     }
538
539     if(mAddOnManager)
540     {
541       mAddOnManager->Stop();
542     }
543
544     mThreadController->Stop();
545
546     // Delete the TTS player
547     for(int i = 0; i < Dali::TtsPlayer::MODE_NUM; i++)
548     {
549       if(mTtsPlayers[i])
550       {
551         mTtsPlayers[i].Reset();
552       }
553     }
554
555     // Destroy the image loader plugin
556     auto enablePluginString = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_ENABLE_IMAGE_LOADER_PLUGIN);
557     bool enablePlugin       = enablePluginString ? std::atoi(enablePluginString) : false;
558     if(enablePlugin)
559     {
560       Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
561     }
562
563     delete mNotificationTrigger;
564     mNotificationTrigger = NULL;
565
566     mCallbackManager->Stop();
567
568     mCore->UnregisterProcessors();
569
570     RemoveSystemInformation();
571
572     // Note: Must change the state at end of function.
573     mState = STOPPED;
574
575     DALI_LOG_RELEASE_INFO("Adaptor::Stop\n");
576   }
577 }
578
579 void Adaptor::ContextLost()
580 {
581   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
582 }
583
584 void Adaptor::ContextRegained()
585 {
586   // Inform core, so that texture resources can be reloaded
587   mCore->RecoverFromContextLoss();
588
589   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
590 }
591
592 void Adaptor::FeedTouchPoint(TouchPoint& point, int timeStamp)
593 {
594   Integration::Point convertedPoint(point);
595   mWindows.front()->FeedTouchPoint(convertedPoint, timeStamp);
596 }
597
598 void Adaptor::FeedWheelEvent(Dali::WheelEvent& wheelEvent)
599 {
600   Integration::WheelEvent event(static_cast<Integration::WheelEvent::Type>(wheelEvent.GetType()), wheelEvent.GetDirection(), wheelEvent.GetModifiers(), wheelEvent.GetPoint(), wheelEvent.GetDelta(), wheelEvent.GetTime());
601   mWindows.front()->FeedWheelEvent(event);
602 }
603
604 void Adaptor::FeedKeyEvent(Dali::KeyEvent& keyEvent)
605 {
606   Integration::KeyEvent convertedEvent(keyEvent.GetKeyName(), keyEvent.GetLogicalKey(), keyEvent.GetKeyString(), keyEvent.GetKeyCode(), keyEvent.GetKeyModifier(), keyEvent.GetTime(), static_cast<Integration::KeyEvent::State>(keyEvent.GetState()), keyEvent.GetCompose(), keyEvent.GetDeviceName(), keyEvent.GetDeviceClass(), keyEvent.GetDeviceSubclass());
607   mWindows.front()->FeedKeyEvent(convertedEvent);
608 }
609
610 void Adaptor::ReplaceSurface(Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface)
611 {
612   Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation(window);
613   for(auto windowPtr : mWindows)
614   {
615     if(windowPtr == windowImpl) // the window is not deleted
616     {
617       mResizedSignal.Emit(mAdaptor);
618
619       windowImpl->SetSurface(&newSurface);
620
621       // Flush the event queue to give the update-render thread chance
622       // to start processing messages for new camera setup etc as soon as possible
623       ProcessCoreEvents();
624
625       // This method blocks until the render thread has completed the replace.
626       mThreadController->ReplaceSurface(&newSurface);
627       break;
628     }
629   }
630 }
631
632 void Adaptor::DeleteSurface(Dali::RenderSurfaceInterface& surface)
633 {
634   // Flush the event queue to give the update-render thread chance
635   // to start processing messages for new camera setup etc as soon as possible
636   ProcessCoreEvents();
637
638   // This method blocks until the render thread has finished rendering the current surface.
639   mThreadController->DeleteSurface(&surface);
640 }
641
642 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
643 {
644   return *mWindows.front()->GetSurface();
645 }
646
647 void Adaptor::ReleaseSurfaceLock()
648 {
649   mWindows.front()->GetSurface()->ReleaseLock();
650 }
651
652 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
653 {
654   if(!mTtsPlayers[mode])
655   {
656     // Create the TTS player when it needed, because it can reduce launching time.
657     mTtsPlayers[mode] = TtsPlayer::New(mode);
658   }
659
660   return mTtsPlayers[mode];
661 }
662
663 bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue)
664 {
665   bool idleAdded(false);
666
667   // We want to run the processes even when paused
668   if(STOPPED != mState)
669   {
670     idleAdded = mCallbackManager->AddIdleCallback(callback, hasReturnValue);
671   }
672
673   if(!idleAdded)
674   {
675     // Delete callback
676     delete callback;
677   }
678
679   return idleAdded;
680 }
681
682 void Adaptor::RemoveIdle(CallbackBase* callback)
683 {
684   mCallbackManager->RemoveIdleCallback(callback);
685 }
686
687 void Adaptor::ProcessIdle()
688 {
689   bool idleProcessed           = mCallbackManager->ProcessIdle();
690   mNotificationOnIdleInstalled = mNotificationOnIdleInstalled && !idleProcessed;
691 }
692
693 void Adaptor::SetPreRenderCallback(CallbackBase* callback)
694 {
695   mThreadController->SetPreRenderCallback(callback);
696 }
697
698 bool Adaptor::AddWindow(Dali::Integration::SceneHolder childWindow)
699 {
700   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(childWindow);
701   windowImpl.SetAdaptor(Get());
702
703   // ChildWindow is set to the layout direction of the default window.
704   windowImpl.GetRootLayer().SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection);
705
706   // Add the new Window to the container - the order is not important
707   {
708     Dali::Mutex::ScopedLock lock(mMutex);
709     mWindows.push_back(&windowImpl);
710   }
711
712   Dali::RenderSurfaceInterface* surface = windowImpl.GetSurface();
713
714   mThreadController->AddSurface(surface);
715
716   mWindowCreatedSignal.Emit(childWindow);
717
718   return true;
719 }
720
721 bool Adaptor::RemoveWindow(Dali::Integration::SceneHolder* childWindow)
722 {
723   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(*childWindow);
724   for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
725   {
726     if(*iter == &windowImpl)
727     {
728       Dali::Mutex::ScopedLock lock(mMutex);
729       mWindows.erase(iter);
730       return true;
731     }
732   }
733
734   return false;
735 }
736
737 bool Adaptor::RemoveWindow(std::string childWindowName)
738 {
739   for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
740   {
741     if((*iter)->GetName() == childWindowName)
742     {
743       Dali::Mutex::ScopedLock lock(mMutex);
744       mWindows.erase(iter);
745       return true;
746     }
747   }
748
749   return false;
750 }
751
752 bool Adaptor::RemoveWindow(Internal::Adaptor::SceneHolder* childWindow)
753 {
754   for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
755   {
756     if((*iter)->GetId() == childWindow->GetId())
757     {
758       Dali::Mutex::ScopedLock lock(mMutex);
759       mWindows.erase(iter);
760       return true;
761     }
762   }
763
764   return false;
765 }
766
767 Dali::Adaptor& Adaptor::Get()
768 {
769   DALI_ASSERT_ALWAYS((gThreadLocalAdaptor != NULL) && "Adaptor not instantiated");
770   return gThreadLocalAdaptor->mAdaptor;
771 }
772
773 bool Adaptor::IsAvailable()
774 {
775   return gThreadLocalAdaptor != NULL && (gThreadLocalAdaptor->mState != Adaptor::State::STOPPED);
776 }
777
778 void Adaptor::SceneCreated()
779 {
780   mCore->SceneCreated();
781 }
782
783 Dali::Integration::Core& Adaptor::GetCore()
784 {
785   return *mCore;
786 }
787
788 void Adaptor::SetRenderRefreshRate(unsigned int numberOfVSyncsPerRender)
789 {
790   mThreadController->SetRenderRefreshRate(numberOfVSyncsPerRender);
791 }
792
793 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
794 {
795   DALI_ASSERT_DEBUG(mDisplayConnection && "Display connection not created");
796   return *mDisplayConnection;
797 }
798
799 GraphicsInterface& Adaptor::GetGraphicsInterface()
800 {
801   DALI_ASSERT_DEBUG(mGraphics && "Graphics interface not created");
802   return *(mGraphics.get());
803 }
804
805 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
806 {
807   return *mPlatformAbstraction;
808 }
809
810 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
811 {
812   return *mNotificationTrigger;
813 }
814
815 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
816 {
817   return mSocketFactory;
818 }
819
820 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
821 {
822   if(!mWindows.empty())
823   {
824     return mWindows.front()->GetSurface();
825   }
826
827   return nullptr;
828 }
829
830 TraceInterface& Adaptor::GetKernelTraceInterface()
831 {
832   return mKernelTracer;
833 }
834
835 TraceInterface& Adaptor::GetSystemTraceInterface()
836 {
837   return mSystemTracer;
838 }
839
840 PerformanceInterface* Adaptor::GetPerformanceInterface()
841 {
842   return mPerformanceInterface;
843 }
844
845 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
846 {
847   DALI_ASSERT_DEBUG(mPlatformAbstraction && "PlatformAbstraction not created");
848   return *mPlatformAbstraction;
849 }
850
851 void Adaptor::GetWindowContainerInterface(WindowContainer& windows)
852 {
853   Dali::Mutex::ScopedLock lock(mMutex);
854   windows = mWindows;
855 }
856
857 Devel::TextureUploadManager& Adaptor::GetTextureUploadManager()
858 {
859   return mTextureUploadManager;
860 }
861
862 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
863 {
864   if(mTtsPlayers[mode])
865   {
866     mTtsPlayers[mode].Reset();
867   }
868 }
869
870 Any Adaptor::GetNativeWindowHandle()
871 {
872   return mWindows.front()->GetNativeHandle();
873 }
874
875 Any Adaptor::GetNativeWindowHandle(Dali::Actor actor)
876 {
877   Any nativeWindowHandle;
878
879   Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
880
881   for(auto sceneHolder : mWindows)
882   {
883     if(scene == sceneHolder->GetScene())
884     {
885       nativeWindowHandle = sceneHolder->GetNativeHandle();
886       break;
887     }
888   }
889
890   return nativeWindowHandle;
891 }
892
893 Any Adaptor::GetGraphicsDisplay()
894 {
895   Any display;
896
897   if(mGraphics)
898   {
899     GraphicsInterface* graphics    = mGraphics.get(); // This interface is temporary until Core has been updated to match
900     auto               eglGraphics = static_cast<EglGraphics*>(graphics);
901
902     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
903     display                    = eglImpl.GetDisplay();
904   }
905
906   return display;
907 }
908
909 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
910 {
911   mUseRemoteSurface = useRemoteSurface;
912 }
913
914 void Adaptor::AddObserver(LifeCycleObserver& observer)
915 {
916   ObserverContainer::iterator match(find(mObservers.begin(), mObservers.end(), &observer));
917
918   if(match == mObservers.end())
919   {
920     mObservers.push_back(&observer);
921   }
922 }
923
924 void Adaptor::RemoveObserver(LifeCycleObserver& observer)
925 {
926   ObserverContainer::iterator match(find(mObservers.begin(), mObservers.end(), &observer));
927
928   if(match != mObservers.end())
929   {
930     mObservers.erase(match);
931   }
932 }
933
934 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
935 {
936   if(mCore)
937   {
938     mCore->QueueEvent(event);
939   }
940 }
941
942 void Adaptor::FlushUpdateMessages()
943 {
944   if(mCore)
945   {
946     DALI_TRACE_SCOPE(gTraceFilter, "DALI_FLUSH_UPDATE_MESSAGES");
947
948     mCore->ForceRelayout();
949   }
950 }
951
952 void Adaptor::ProcessCoreEvents()
953 {
954   if(mCore)
955   {
956     DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_CORE_EVENTS");
957
958     if(mPerformanceInterface)
959     {
960       mPerformanceInterface->AddMarker(PerformanceInterface::PROCESS_EVENTS_START);
961     }
962
963     mCore->ProcessEvents();
964
965     if(mPerformanceInterface)
966     {
967       mPerformanceInterface->AddMarker(PerformanceInterface::PROCESS_EVENTS_END);
968     }
969   }
970 }
971
972 void Adaptor::RequestUpdate()
973 {
974   switch(mState)
975   {
976     case RUNNING:
977     {
978       mThreadController->RequestUpdate();
979       break;
980     }
981     case PAUSED:
982     case PAUSED_WHILE_HIDDEN:
983     {
984       // Update (and resource upload) without rendering
985       mThreadController->RequestUpdateOnce(UpdateMode::SKIP_RENDER);
986       break;
987     }
988     default:
989     {
990       // Do nothing
991       break;
992     }
993   }
994 }
995
996 void Adaptor::RequestProcessEventsOnIdle()
997 {
998   // We want to run the processes even when paused
999   if(STOPPED != mState)
1000   {
1001     if(!mNotificationOnIdleInstalled)
1002     {
1003       // If we haven't installed the idle notification, install it idle enterer.
1004       mNotificationOnIdleInstalled = AddIdleEnterer(MakeCallback(this, &Adaptor::ProcessCoreEventsFromIdle));
1005     }
1006     else
1007     {
1008       // Request comes during ProcessCoreEventsFromIdle running.
1009       // Mark as we need to call ProcessEvents in next idle events.
1010       mRequiredIdleRepeat = true;
1011     }
1012   }
1013 }
1014
1015 void Adaptor::OnWindowShown()
1016 {
1017   if(PAUSED_WHILE_HIDDEN == mState)
1018   {
1019     // Adaptor can now be resumed
1020     mState = PAUSED;
1021
1022     Resume();
1023
1024     // Force a render task
1025     RequestUpdateOnce();
1026   }
1027   else if(RUNNING == mState)
1028   {
1029     // Force a render task
1030     RequestUpdateOnce();
1031
1032     DALI_LOG_RELEASE_INFO("Adaptor::OnWindowShown: Update requested.\n");
1033   }
1034   else if(PAUSED_WHILE_INITIALIZING == mState)
1035   {
1036     // Change the state to READY again. It will be changed to RUNNING after the adaptor is started.
1037     mState = READY;
1038   }
1039   else
1040   {
1041     DALI_LOG_RELEASE_INFO("Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState);
1042   }
1043 }
1044
1045 void Adaptor::OnWindowHidden()
1046 {
1047   if(RUNNING == mState || READY == mState)
1048   {
1049     bool allWindowsHidden = true;
1050
1051     for(auto window : mWindows)
1052     {
1053       if(window->IsVisible())
1054       {
1055         allWindowsHidden = false;
1056         break;
1057       }
1058     }
1059
1060     // Only pause the adaptor when all the windows are hidden
1061     if(allWindowsHidden)
1062     {
1063       if(mState == RUNNING)
1064       {
1065         Pause();
1066
1067         // Adaptor cannot be resumed until any window is shown
1068         mState = PAUSED_WHILE_HIDDEN;
1069       }
1070       else // mState is READY
1071       {
1072         // Pause the adaptor after the state gets RUNNING
1073         mState = PAUSED_WHILE_INITIALIZING;
1074       }
1075     }
1076     else
1077     {
1078       DALI_LOG_RELEASE_INFO("Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n");
1079     }
1080   }
1081   else
1082   {
1083     DALI_LOG_RELEASE_INFO("Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState);
1084   }
1085 }
1086
1087 // Dali::Internal::Adaptor::Adaptor::OnDamaged
1088 void Adaptor::OnDamaged(const DamageArea& area)
1089 {
1090   // This is needed for the case where Dali window is partially obscured
1091   RequestUpdate();
1092 }
1093
1094 void Adaptor::SurfaceResizePrepare(Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize)
1095 {
1096   mResizedSignal.Emit(mAdaptor);
1097 }
1098
1099 void Adaptor::SurfaceResizeComplete(Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize)
1100 {
1101   // Nofify surface resizing before flushing event queue
1102   mThreadController->ResizeSurface();
1103
1104   // Flush the event queue to give the update-render thread chance
1105   // to start processing messages for new camera setup etc as soon as possible
1106   ProcessCoreEvents();
1107 }
1108
1109 void Adaptor::IncreaseSurfaceResizeCounter()
1110 {
1111   // Nofify surface resizing before flushing event queue
1112   if(mThreadController)
1113   {
1114     mThreadController->ResizeSurface();
1115   }
1116 }
1117
1118 void Adaptor::NotifySceneCreated()
1119 {
1120   GetCore().SceneCreated();
1121
1122   // Flush the event queue to give the update-render thread chance
1123   // to start processing messages for new camera setup etc as soon as possible
1124   ProcessCoreEvents();
1125
1126   // Start thread controller after the scene has been created
1127   mThreadController->Start();
1128
1129   // Process after surface is created (registering to remote surface provider if required)
1130   SurfaceInitialized();
1131
1132   if(mState != PAUSED_WHILE_INITIALIZING)
1133   {
1134     mState = RUNNING;
1135
1136     DALI_LOG_RELEASE_INFO("Adaptor::NotifySceneCreated: Adaptor is running\n");
1137   }
1138   else
1139   {
1140     mState = RUNNING;
1141
1142     Pause();
1143
1144     mState = PAUSED_WHILE_HIDDEN;
1145
1146     DALI_LOG_RELEASE_INFO("Adaptor::NotifySceneCreated: Adaptor is paused\n");
1147   }
1148 }
1149
1150 void Adaptor::NotifyLanguageChanged()
1151 {
1152   mLanguageChangedSignal.Emit(mAdaptor);
1153 }
1154
1155 void Adaptor::RenderOnce()
1156 {
1157   if(mThreadController)
1158   {
1159     UpdateMode updateMode;
1160     if(mThreadMode == ThreadMode::NORMAL)
1161     {
1162       updateMode = UpdateMode::NORMAL;
1163     }
1164     else
1165     {
1166       updateMode = UpdateMode::FORCE_RENDER;
1167
1168       ProcessCoreEvents();
1169     }
1170
1171     // Force rendering
1172     for(auto&& iter : mWindows)
1173     {
1174       iter->GetSurface()->SetFullSwapNextFrame();
1175     }
1176
1177     mThreadController->RequestUpdateOnce(updateMode);
1178   }
1179 }
1180
1181 const LogFactoryInterface& Adaptor::GetLogFactory()
1182 {
1183   return *mEnvironmentOptions;
1184 }
1185
1186 const TraceFactoryInterface& Adaptor::GetTraceFactory()
1187 {
1188   return *mEnvironmentOptions;
1189 }
1190
1191 void Adaptor::RegisterProcessor(Integration::Processor& processor, bool postProcessor)
1192 {
1193   GetCore().RegisterProcessor(processor, postProcessor);
1194 }
1195
1196 void Adaptor::UnregisterProcessor(Integration::Processor& processor, bool postProcessor)
1197 {
1198   GetCore().UnregisterProcessor(processor, postProcessor);
1199 }
1200
1201 bool Adaptor::IsMultipleWindowSupported() const
1202 {
1203   return mConfigurationManager->IsMultipleWindowSupported();
1204 }
1205
1206 int32_t Adaptor::GetRenderThreadId() const
1207 {
1208   if(mThreadController)
1209   {
1210     return mThreadController->GetThreadId();
1211   }
1212   return 0;
1213 }
1214
1215 void Adaptor::RequestUpdateOnce()
1216 {
1217   if(mThreadController)
1218   {
1219     mThreadController->RequestUpdateOnce(UpdateMode::NORMAL);
1220   }
1221 }
1222
1223 bool Adaptor::ProcessCoreEventsFromIdle()
1224 {
1225   // Reset repeat idler flag.
1226   mRequiredIdleRepeat = false;
1227   ProcessCoreEvents();
1228
1229   // If someone request ProcessCoreEvents during above ProcessCoreEvents call, we might need to run idle one more times.
1230   // Else, the idle handle automatically un-installs itself
1231   mNotificationOnIdleInstalled = mRequiredIdleRepeat;
1232
1233   if(mRequiredIdleRepeat)
1234   {
1235     DALI_LOG_DEBUG_INFO("Required ProcessCoreEvents one more times\n");
1236   }
1237
1238   return mRequiredIdleRepeat;
1239 }
1240
1241 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow(Dali::Actor& actor)
1242 {
1243   Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
1244
1245   for(auto window : mWindows)
1246   {
1247     if(scene == window->GetScene())
1248     {
1249       return window;
1250     }
1251   }
1252
1253   return nullptr;
1254 }
1255
1256 Dali::WindowContainer Adaptor::GetWindows() const
1257 {
1258   Dali::WindowContainer windows;
1259
1260   for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
1261   {
1262     // Downcast to Dali::Window
1263     Dali::Window window(dynamic_cast<Dali::Internal::Adaptor::Window*>(*iter));
1264     if(window)
1265     {
1266       windows.push_back(window);
1267     }
1268   }
1269
1270   return windows;
1271 }
1272
1273 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1274 {
1275   Dali::SceneHolderList sceneHolderList;
1276
1277   for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
1278   {
1279     sceneHolderList.push_back(Dali::Integration::SceneHolder(*iter));
1280   }
1281
1282   return sceneHolderList;
1283 }
1284
1285 Dali::ObjectRegistry Adaptor::GetObjectRegistry() const
1286 {
1287   Dali::ObjectRegistry registry;
1288   if(mCore)
1289   {
1290     registry = mCore->GetObjectRegistry();
1291   }
1292   return registry;
1293 }
1294
1295 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions, ThreadMode threadMode)
1296 : mResizedSignal(),
1297   mLanguageChangedSignal(),
1298   mWindowCreatedSignal(),
1299   mAdaptor(adaptor),
1300   mState(READY),
1301   mCore(nullptr),
1302   mThreadController(nullptr),
1303   mGraphics(nullptr),
1304   mDisplayConnection(nullptr),
1305   mWindows(),
1306   mConfigurationManager(nullptr),
1307   mPlatformAbstraction(nullptr),
1308   mCallbackManager(nullptr),
1309   mNotificationOnIdleInstalled(false),
1310   mRequiredIdleRepeat(false),
1311   mNotificationTrigger(nullptr),
1312   mDaliFeedbackPlugin(),
1313   mFeedbackController(nullptr),
1314   mTtsPlayers(),
1315   mObservers(),
1316   mEnvironmentOptions(environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1317   mPerformanceInterface(nullptr),
1318   mKernelTracer(),
1319   mSystemTracer(),
1320   mTextureUploadManager(),
1321   mObjectProfiler(nullptr),
1322   mMemoryPoolTimerSlotDelegate(this),
1323   mSocketFactory(),
1324   mMutex(),
1325   mThreadMode(threadMode),
1326   mEnvironmentOptionsOwned(environmentOptions ? false : true /* If not provided then we own the object */),
1327   mUseRemoteSurface(false),
1328   mRootLayoutDirection(Dali::LayoutDirection::LEFT_TO_RIGHT)
1329 {
1330   DALI_ASSERT_ALWAYS(!IsAvailable() && "Cannot create more than one Adaptor per thread");
1331   mWindows.insert(mWindows.begin(), &Dali::GetImplementation(window));
1332
1333   gThreadLocalAdaptor = this;
1334 }
1335
1336 void Adaptor::SetRootLayoutDirection(std::string locale)
1337 {
1338   mRootLayoutDirection = static_cast<LayoutDirection::Type>(Internal::Adaptor::Locale::GetDirection(std::string(locale)));
1339   for(auto& window : mWindows)
1340   {
1341     Dali::Actor root = window->GetRootLayer();
1342     root.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection);
1343   }
1344 }
1345
1346 bool Adaptor::AddIdleEnterer(CallbackBase* callback)
1347 {
1348   bool idleAdded(false);
1349
1350   // We want to run the processes even when paused
1351   if(STOPPED != mState)
1352   {
1353     idleAdded = mCallbackManager->AddIdleEntererCallback(callback);
1354   }
1355
1356   if(!idleAdded)
1357   {
1358     // Delete callback
1359     delete callback;
1360   }
1361
1362   return idleAdded;
1363 }
1364
1365 void Adaptor::RemoveIdleEnterer(CallbackBase* callback)
1366 {
1367   mCallbackManager->RemoveIdleEntererCallback(callback);
1368 }
1369
1370 bool Adaptor::MemoryPoolTimeout()
1371 {
1372   mCore->LogMemoryPools();
1373   return true; // Keep logging forever
1374 }
1375
1376 } // namespace Adaptor
1377
1378 } // namespace Internal
1379
1380 } // namespace Dali