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