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