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