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