Suspend window deletion while rendering
[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::SetPreRenderCallback( CallbackBase* callback )
598 {
599   mThreadController->SetPreRenderCallback( callback );
600 }
601
602 bool Adaptor::AddWindow( Dali::Integration::SceneHolder childWindow, const std::string& childWindowName, const std::string& childWindowClassName, bool childWindowMode )
603 {
604   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( childWindow );
605   windowImpl.SetAdaptor( Get() );
606
607   // Add the new Window to the container - the order is not important
608   mWindows.push_back( &windowImpl );
609
610   Dali::RenderSurfaceInterface* surface = windowImpl.GetSurface();
611
612   mThreadController->AddSurface( surface );
613
614   mWindowCreatedSignal.Emit( childWindow );
615
616   return true;
617 }
618
619 bool Adaptor::RemoveWindow( Dali::Integration::SceneHolder* childWindow )
620 {
621   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( *childWindow );
622   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
623   {
624     if( *iter == &windowImpl )
625     {
626       mWindows.erase( iter );
627       return true;
628     }
629   }
630
631   return false;
632 }
633
634 bool Adaptor::RemoveWindow( std::string childWindowName )
635 {
636   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
637   {
638     if( ( *iter )->GetName() == childWindowName )
639     {
640       mWindows.erase( iter );
641       return true;
642     }
643   }
644
645   return false;
646 }
647
648 bool Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* childWindow )
649 {
650   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
651   {
652     if( ( *iter )->GetId() == childWindow->GetId() )
653     {
654       mWindows.erase( iter );
655       return true;
656     }
657   }
658
659   return false;
660 }
661
662 Dali::Adaptor& Adaptor::Get()
663 {
664   DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
665   return gThreadLocalAdaptor->mAdaptor;
666 }
667
668 bool Adaptor::IsAvailable()
669 {
670   return gThreadLocalAdaptor != NULL;
671 }
672
673 void Adaptor::SceneCreated()
674 {
675   mCore->SceneCreated();
676 }
677
678 Dali::Integration::Core& Adaptor::GetCore()
679 {
680   return *mCore;
681 }
682
683 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
684 {
685   mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
686 }
687
688 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
689 {
690   DALI_ASSERT_DEBUG( mDisplayConnection && "Display connection not created" );
691   return *mDisplayConnection;
692 }
693
694 GraphicsInterface& Adaptor::GetGraphicsInterface()
695 {
696   DALI_ASSERT_DEBUG( mGraphics && "Graphics interface not created" );
697   return *mGraphics;
698 }
699
700 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
701 {
702   return *mPlatformAbstraction;
703 }
704
705 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
706 {
707   return *mNotificationTrigger;
708 }
709
710 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
711 {
712   return mSocketFactory;
713 }
714
715 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
716 {
717   if( !mWindows.empty() )
718   {
719     return mWindows.front()->GetSurface();
720   }
721
722   return nullptr;
723 }
724
725 TraceInterface& Adaptor::GetKernelTraceInterface()
726 {
727   return mKernelTracer;
728 }
729
730 TraceInterface& Adaptor::GetSystemTraceInterface()
731 {
732   return mSystemTracer;
733 }
734
735 PerformanceInterface* Adaptor::GetPerformanceInterface()
736 {
737   return mPerformanceInterface;
738 }
739
740 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
741 {
742   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
743   return *mPlatformAbstraction;
744 }
745
746 void Adaptor::GetWindowContainerInterface( WindowContainer& windows )
747 {
748   windows = mWindows;
749 }
750
751 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
752 {
753   if( mTtsPlayers[mode] )
754   {
755     mTtsPlayers[mode].Reset();
756   }
757 }
758
759 Any Adaptor::GetNativeWindowHandle()
760 {
761   return mWindows.front()->GetNativeHandle();
762 }
763
764 Any Adaptor::GetNativeWindowHandle( Dali::Actor actor )
765 {
766   Any nativeWindowHandle;
767
768   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
769
770   for( auto sceneHolder : mWindows )
771   {
772     if ( scene == sceneHolder->GetScene() )
773     {
774       nativeWindowHandle = sceneHolder->GetNativeHandle();
775       break;
776     }
777   }
778
779   return nativeWindowHandle;
780 }
781
782 Any Adaptor::GetGraphicsDisplay()
783 {
784   Any display;
785
786   if (mGraphics)
787   {
788     auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
789
790     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
791     display = eglImpl.GetDisplay();
792   }
793
794   return display;
795 }
796
797 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
798 {
799   mUseRemoteSurface = useRemoteSurface;
800 }
801
802 void Adaptor::AddObserver( LifeCycleObserver& observer )
803 {
804   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
805
806   if ( match == mObservers.end() )
807   {
808     mObservers.push_back( &observer );
809   }
810 }
811
812 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
813 {
814   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
815
816   if ( match != mObservers.end() )
817   {
818     mObservers.erase( match );
819   }
820 }
821
822 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
823 {
824   if( mCore )
825   {
826     mCore->QueueEvent(event);
827   }
828 }
829
830 void Adaptor::ProcessCoreEvents()
831 {
832   if( mCore )
833   {
834     if( mPerformanceInterface )
835     {
836       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
837     }
838
839     mCore->ProcessEvents();
840
841     if( mPerformanceInterface )
842     {
843       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
844     }
845   }
846 }
847
848 void Adaptor::RequestUpdate( bool forceUpdate )
849 {
850   switch( mState )
851   {
852     case RUNNING:
853     {
854       mThreadController->RequestUpdate();
855       break;
856     }
857     case PAUSED:
858     case PAUSED_WHILE_HIDDEN:
859     {
860       if( forceUpdate )
861       {
862         // Update (and resource upload) without rendering
863         mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
864       }
865       break;
866     }
867     default:
868     {
869       // Do nothing
870       break;
871     }
872   }
873 }
874
875 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
876 {
877   // Only request a notification if the Adaptor is actually running
878   // and we haven't installed the idle notification
879   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
880   {
881     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
882   }
883 }
884
885 void Adaptor::OnWindowShown()
886 {
887   if( PAUSED_WHILE_HIDDEN == mState )
888   {
889     // Adaptor can now be resumed
890     mState = PAUSED;
891
892     Resume();
893
894     // Force a render task
895     RequestUpdateOnce();
896   }
897   else if( RUNNING == mState )
898   {
899     // Force a render task
900     RequestUpdateOnce();
901
902     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
903   }
904   else
905   {
906     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
907   }
908 }
909
910 void Adaptor::OnWindowHidden()
911 {
912   if( RUNNING == mState || READY == mState )
913   {
914     bool allWindowsHidden = true;
915
916     for( auto window : mWindows )
917     {
918       if ( window->IsVisible() )
919       {
920         allWindowsHidden = false;
921         break;
922       }
923     }
924
925     // Only pause the adaptor when all the windows are hidden
926     if( allWindowsHidden )
927     {
928       if( mState == RUNNING )
929       {
930         Pause();
931
932         // Adaptor cannot be resumed until any window is shown
933         mState = PAUSED_WHILE_HIDDEN;
934       }
935       else  // mState is READY
936       {
937         // Pause the adaptor after the state gets RUNNING
938         mState = PAUSED_WHILE_INITIALIZING;
939       }
940     }
941     else
942     {
943       DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
944     }
945   }
946   else
947   {
948     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
949   }
950 }
951
952 // Dali::Internal::Adaptor::Adaptor::OnDamaged
953 void Adaptor::OnDamaged( const DamageArea& area )
954 {
955   // This is needed for the case where Dali window is partially obscured
956   RequestUpdate( false );
957 }
958
959 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
960 {
961   mResizedSignal.Emit( mAdaptor );
962 }
963
964 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
965 {
966   // Nofify surface resizing before flushing event queue
967   mThreadController->ResizeSurface();
968
969   // Flush the event queue to give the update-render thread chance
970   // to start processing messages for new camera setup etc as soon as possible
971   ProcessCoreEvents();
972 }
973
974 void Adaptor::NotifySceneCreated()
975 {
976   GetCore().SceneCreated();
977
978   // Flush the event queue to give the update-render thread chance
979   // to start processing messages for new camera setup etc as soon as possible
980   ProcessCoreEvents();
981
982   // Start thread controller after the scene has been created
983   mThreadController->Start();
984
985   // Process after surface is created (registering to remote surface provider if required)
986   SurfaceInitialized();
987
988   if( mState != PAUSED_WHILE_INITIALIZING )
989   {
990     mState = RUNNING;
991
992     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
993   }
994   else
995   {
996     mState = RUNNING;
997
998     Pause();
999
1000     mState = PAUSED_WHILE_HIDDEN;
1001
1002     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1003   }
1004 }
1005
1006 void Adaptor::NotifyLanguageChanged()
1007 {
1008   mLanguageChangedSignal.Emit( mAdaptor );
1009 }
1010
1011 void Adaptor::RenderOnce()
1012 {
1013   RequestUpdateOnce();
1014 }
1015
1016 const LogFactoryInterface& Adaptor::GetLogFactory()
1017 {
1018   return *mEnvironmentOptions;
1019 }
1020
1021 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1022 {
1023   GetCore().RegisterProcessor(processor);
1024 }
1025
1026 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1027 {
1028   GetCore().UnregisterProcessor(processor);
1029 }
1030
1031 bool Adaptor::IsMultipleWindowSupported() const
1032 {
1033   return mConfigurationManager->IsMultipleWindowSupported();
1034 }
1035
1036 bool Adaptor::IsRenderingWindows() const
1037 {
1038   return ( mThreadController && mThreadController->IsRenderingWindows() );
1039 }
1040
1041 void Adaptor::RequestUpdateOnce()
1042 {
1043   if( mThreadController )
1044   {
1045     mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1046   }
1047 }
1048
1049 bool Adaptor::ProcessCoreEventsFromIdle()
1050 {
1051   ProcessCoreEvents();
1052
1053   // the idle handle automatically un-installs itself
1054   mNotificationOnIdleInstalled = false;
1055
1056   return false;
1057 }
1058
1059 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1060 {
1061   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1062
1063   for( auto window : mWindows )
1064   {
1065     if ( scene == window->GetScene() )
1066     {
1067       return window;
1068     }
1069   }
1070
1071   return nullptr;
1072 }
1073
1074 Dali::WindowContainer Adaptor::GetWindows() const
1075 {
1076   Dali::WindowContainer windows;
1077
1078   for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1079   {
1080     // Downcast to Dali::Window
1081     Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1082     if ( window )
1083     {
1084       windows.push_back( window );
1085     }
1086   }
1087
1088   return windows;
1089 }
1090
1091 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1092 {
1093   Dali::SceneHolderList sceneHolderList;
1094
1095   for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1096   {
1097     sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1098   }
1099
1100   return sceneHolderList;
1101 }
1102
1103 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1104 : mResizedSignal(),
1105   mLanguageChangedSignal(),
1106   mWindowCreatedSignal(),
1107   mAdaptor( adaptor ),
1108   mState( READY ),
1109   mCore( nullptr ),
1110   mThreadController( nullptr ),
1111   mGraphics( nullptr ),
1112   mDisplayConnection( nullptr ),
1113   mWindows(),
1114   mConfigurationManager( nullptr ),
1115   mPlatformAbstraction( nullptr ),
1116   mCallbackManager( nullptr ),
1117   mNotificationOnIdleInstalled( false ),
1118   mNotificationTrigger( nullptr ),
1119   mDaliFeedbackPlugin(),
1120   mFeedbackController( nullptr ),
1121   mTtsPlayers(),
1122   mObservers(),
1123   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1124   mPerformanceInterface( nullptr ),
1125   mKernelTracer(),
1126   mSystemTracer(),
1127   mObjectProfiler( nullptr ),
1128   mSocketFactory(),
1129   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1130   mUseRemoteSurface( false )
1131 {
1132   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1133   mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1134
1135   gThreadLocalAdaptor = this;
1136 }
1137
1138 void Adaptor::SetRootLayoutDirection( std::string locale )
1139 {
1140   Dali::Stage stage = Dali::Stage::GetCurrent();
1141
1142   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1143                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1144 }
1145
1146 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1147 {
1148   bool idleAdded( false );
1149
1150   // Only add an idle if the Adaptor is actually running
1151   if( RUNNING == mState || READY == mState || forceAdd )
1152   {
1153     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1154   }
1155
1156   return idleAdded;
1157 }
1158
1159 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1160 {
1161   mCallbackManager->RemoveIdleEntererCallback( callback );
1162 }
1163
1164 } // namespace Adaptor
1165
1166 } // namespace Internal
1167
1168 } // namespace Dali