[Tizen] Implement partial update
[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   ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
149   if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
150   {
151     dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
152   }
153
154   // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from files automatically.
155
156   if( mEnvironmentOptions->PerformanceServerRequired() )
157   {
158     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
159   }
160
161   mEnvironmentOptions->CreateTraceManager( mPerformanceInterface );
162   mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
163
164   mCallbackManager = CallbackManager::New();
165
166   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
167
168   DALI_ASSERT_DEBUG( defaultWindow->GetSurface() && "Surface not initialized" );
169
170   mGraphics = &( graphicsFactory.Create() );
171   mGraphics->Initialize( mEnvironmentOptions );
172
173   auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
174
175   // This will only be created once
176   eglGraphics->Create();
177
178   GlImplementation& mGLES = eglGraphics->GetGlesInterface();
179   EglSyncImplementation& eglSyncImpl = eglGraphics->GetSyncImplementation();
180   EglContextHelperImplementation& eglContextHelperImpl = eglGraphics->GetContextHelperImplementation();
181
182   mCore = Integration::Core::New( *this,
183                                   *mPlatformAbstraction,
184                                   mGLES,
185                                   eglSyncImpl,
186                                   eglContextHelperImpl,
187                                   dataRetentionPolicy ,
188                                   ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
189                                   mGraphics->GetDepthBufferRequired(),
190                                   mGraphics->GetStencilBufferRequired(),
191                                   mGraphics->PartialUpdateAvailable() );
192
193   defaultWindow->SetAdaptor( Get() );
194
195   Dali::Integration::SceneHolder defaultSceneHolder( defaultWindow );
196
197   mWindowCreatedSignal.Emit( defaultSceneHolder );
198
199   const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
200   if( 0u < timeInterval )
201   {
202     mObjectProfiler = new ObjectProfiler( timeInterval );
203   }
204
205   mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
206
207   mDisplayConnection = Dali::DisplayConnection::New( *mGraphics, defaultWindow->GetSurface()->GetSurfaceType() );
208
209   mThreadController = new ThreadController( *this, *mEnvironmentOptions );
210
211   // Should be called after Core creation
212   if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
213   {
214     Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
215   }
216   if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
217   {
218     Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
219   }
220   if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
221   {
222     Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
223   }
224   if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
225   {
226     Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
227   }
228   if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
229   {
230     Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
231   }
232   if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
233   {
234     Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
235   }
236   if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
237   {
238     Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
239   }
240   if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
241   {
242     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
243   }
244   if( mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0 )
245   {
246     Integration::SetPanGestureUseActualTimes( mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false );
247   }
248   if( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0 )
249   {
250     Integration::SetPanGestureInterpolationTimeRange( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() );
251   }
252   if( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0 )
253   {
254     Integration::SetPanGestureScalarOnlyPredictionEnabled( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false  );
255   }
256   if( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0 )
257   {
258     Integration::SetPanGestureTwoPointPredictionEnabled( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false  );
259   }
260   if( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0 )
261   {
262     Integration::SetPanGestureTwoPointInterpolatePastTime( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() );
263   }
264   if( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f )
265   {
266     Integration::SetPanGestureTwoPointVelocityBias( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() );
267   }
268   if( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f )
269   {
270     Integration::SetPanGestureTwoPointAccelerationBias( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() );
271   }
272   if( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0 )
273   {
274     Integration::SetPanGestureMultitapSmoothingRange( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() );
275   }
276   if( mEnvironmentOptions->GetMinimumPanDistance() >= 0 )
277   {
278     Integration::SetPanGestureMinimumDistance( mEnvironmentOptions->GetMinimumPanDistance() );
279   }
280   if( mEnvironmentOptions->GetMinimumPanEvents() >= 0 )
281   {
282     Integration::SetPanGestureMinimumPanEvents( mEnvironmentOptions->GetMinimumPanEvents() );
283   }
284   if( mEnvironmentOptions->GetMinimumPinchDistance() >= 0 )
285   {
286     Integration::SetPinchGestureMinimumDistance( mEnvironmentOptions->GetMinimumPinchDistance() );
287   }
288   if( mEnvironmentOptions->GetLongPressMinimumHoldingTime() >= 0 )
289   {
290     Integration::SetLongPressMinimumHoldingTime( mEnvironmentOptions->GetLongPressMinimumHoldingTime() );
291   }
292
293   std::string systemCachePath = GetSystemCachePath();
294   if( ! systemCachePath.empty() )
295   {
296     const int dir_err = system( std::string( "mkdir " + systemCachePath ).c_str() );
297     if (-1 == dir_err)
298     {
299         printf( "Error creating system cache directory: %s!\n", systemCachePath.c_str() );
300         exit(1);
301     }
302   }
303
304   mConfigurationManager = Utils::MakeUnique<ConfigurationManager>( systemCachePath, eglGraphics, mThreadController );
305 }
306
307 Adaptor::~Adaptor()
308 {
309   // Ensure stop status
310   Stop();
311
312   // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
313   gThreadLocalAdaptor = NULL;
314
315   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
316   {
317     (*iter)->OnDestroy();
318   }
319
320   // Clear out all the handles to Windows
321   mWindows.clear();
322
323   delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
324   delete mObjectProfiler;
325
326   delete mCore;
327
328   delete mDisplayConnection;
329   delete mPlatformAbstraction;
330   delete mCallbackManager;
331   delete mPerformanceInterface;
332
333   mGraphics->Destroy();
334
335   // uninstall it on this thread (main actor thread)
336   Dali::Integration::Log::UninstallLogFunction();
337
338   // Delete environment options if we own it
339   if( mEnvironmentOptionsOwned )
340   {
341     delete mEnvironmentOptions;
342   }
343 }
344
345 void Adaptor::Start()
346 {
347   // It doesn't support restart after stop at this moment to support restarting, need more testing
348   if( READY != mState )
349   {
350     return;
351   }
352
353   mCore->Initialize();
354
355   SetupSystemInformation();
356
357   // Start the callback manager
358   mCallbackManager->Start();
359
360   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
361
362   unsigned int dpiHor, dpiVer;
363   dpiHor = dpiVer = 0;
364
365   defaultWindow->GetSurface()->GetDpi( dpiHor, dpiVer );
366
367   // set the DPI value for font rendering
368   FontClient fontClient = FontClient::Get();
369   fontClient.SetDpi( dpiHor, dpiVer );
370
371   // Initialize the thread controller
372   mThreadController->Initialize();
373
374   // Set max texture size
375   if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
376   {
377     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
378   }
379   else
380   {
381     unsigned int maxTextureSize = mConfigurationManager->GetMaxTextureSize();
382     setenv( DALI_ENV_MAX_TEXTURE_SIZE, std::to_string( maxTextureSize ).c_str(), 1 );
383     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( maxTextureSize );
384   }
385
386   ProcessCoreEvents(); // Ensure any startup messages are processed.
387
388   // Initialize the image loader plugin
389   Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
390
391   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
392   {
393     (*iter)->OnStart();
394   }
395 }
396
397 // Dali::Internal::Adaptor::Adaptor::Pause
398 void Adaptor::Pause()
399 {
400   // Only pause the adaptor if we're actually running.
401   if( RUNNING == mState )
402   {
403     // Inform observers that we are about to be paused.
404     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
405     {
406       (*iter)->OnPause();
407     }
408
409     // Pause all windows event handlers when adaptor paused
410     for( auto window : mWindows )
411     {
412       window->Pause();
413     }
414
415     mThreadController->Pause();
416     mState = PAUSED;
417
418     // Ensure any messages queued during pause callbacks are processed by doing another update.
419     RequestUpdateOnce();
420
421     DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Paused\n" );
422   }
423   else
424   {
425     DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Not paused [%d]\n", mState );
426   }
427 }
428
429 // Dali::Internal::Adaptor::Adaptor::Resume
430 void Adaptor::Resume()
431 {
432   // Only resume the adaptor if we are in the suspended state.
433   if( PAUSED == mState )
434   {
435     mState = RUNNING;
436
437     // Reset the event handlers when adaptor resumed
438     for( auto window : mWindows )
439     {
440       window->Resume();
441     }
442
443     // Inform observers that we have resumed.
444     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
445     {
446       (*iter)->OnResume();
447     }
448
449     // Trigger processing of events queued up while paused
450     mCore->ProcessEvents();
451
452     // Do at end to ensure our first update/render after resumption includes the processed messages as well
453     mThreadController->Resume();
454
455     DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Resumed\n");
456   }
457   else
458   {
459     DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Not resumed [%d]\n", mState );
460   }
461 }
462
463 void Adaptor::Stop()
464 {
465   if( RUNNING == mState ||
466       PAUSED  == mState ||
467       PAUSED_WHILE_HIDDEN == mState )
468   {
469     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
470     {
471       (*iter)->OnStop();
472     }
473
474     mThreadController->Stop();
475
476     // Delete the TTS player
477     for( int i =0; i < Dali::TtsPlayer::MODE_NUM; i++ )
478     {
479       if( mTtsPlayers[i] )
480       {
481         mTtsPlayers[i].Reset();
482       }
483     }
484
485     // Destroy the image loader plugin
486     Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
487
488     delete mNotificationTrigger;
489     mNotificationTrigger = NULL;
490
491     mCallbackManager->Stop();
492
493     mState = STOPPED;
494
495     DALI_LOG_RELEASE_INFO( "Adaptor::Stop\n" );
496   }
497 }
498
499 void Adaptor::ContextLost()
500 {
501   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
502 }
503
504 void Adaptor::ContextRegained()
505 {
506   // Inform core, so that texture resources can be reloaded
507   mCore->RecoverFromContextLoss();
508
509   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
510 }
511
512 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
513 {
514   Integration::Point convertedPoint( point );
515   mWindows.front()->FeedTouchPoint( convertedPoint, timeStamp );
516 }
517
518 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
519 {
520   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
521   mWindows.front()->FeedWheelEvent( event );
522 }
523
524 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
525 {
526   Integration::KeyEvent convertedEvent( keyEvent );
527   mWindows.front()->FeedKeyEvent( convertedEvent );
528 }
529
530 void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface )
531 {
532   Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation( window );
533   for( auto windowPtr : mWindows )
534   {
535     if( windowPtr == windowImpl ) // the window is not deleted
536     {
537       mResizedSignal.Emit( mAdaptor );
538
539       windowImpl->SetSurface( &newSurface );
540
541       // Flush the event queue to give the update-render thread chance
542       // to start processing messages for new camera setup etc as soon as possible
543       ProcessCoreEvents();
544
545       // This method blocks until the render thread has completed the replace.
546       mThreadController->ReplaceSurface( &newSurface );
547       break;
548     }
549   }
550 }
551
552 void Adaptor::DeleteSurface( Dali::RenderSurfaceInterface& surface )
553 {
554   // Flush the event queue to give the update-render thread chance
555   // to start processing messages for new camera setup etc as soon as possible
556   ProcessCoreEvents();
557
558   // This method blocks until the render thread has finished rendering the current surface.
559   mThreadController->DeleteSurface( &surface );
560 }
561
562 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
563 {
564   return *mWindows.front()->GetSurface();
565 }
566
567 void Adaptor::ReleaseSurfaceLock()
568 {
569   mWindows.front()->GetSurface()->ReleaseLock();
570 }
571
572 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
573 {
574   if( !mTtsPlayers[mode] )
575   {
576     // Create the TTS player when it needed, because it can reduce launching time.
577     mTtsPlayers[mode] = TtsPlayer::New(mode);
578   }
579
580   return mTtsPlayers[mode];
581 }
582
583 bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue, bool forceAdd )
584 {
585   bool idleAdded(false);
586
587   // Only add an idle if the Adaptor is actually running
588   if( RUNNING == mState || READY == mState || forceAdd )
589   {
590     idleAdded = mCallbackManager->AddIdleCallback( callback, hasReturnValue );
591   }
592
593   return idleAdded;
594 }
595
596 void Adaptor::RemoveIdle( CallbackBase* callback )
597 {
598   mCallbackManager->RemoveIdleCallback( callback );
599 }
600
601 void Adaptor::SetPreRenderCallback( CallbackBase* callback )
602 {
603   mThreadController->SetPreRenderCallback( callback );
604 }
605
606 bool Adaptor::AddWindow( Dali::Integration::SceneHolder childWindow, const std::string& childWindowName, const std::string& childWindowClassName, bool childWindowMode )
607 {
608   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( childWindow );
609   windowImpl.SetAdaptor( Get() );
610
611   // Add the new Window to the container - the order is not important
612   mWindows.push_back( &windowImpl );
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 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
711 {
712   return mTriggerEventFactory;
713 }
714
715 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
716 {
717   return mSocketFactory;
718 }
719
720 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
721 {
722   if( !mWindows.empty() )
723   {
724     return mWindows.front()->GetSurface();
725   }
726
727   return nullptr;
728 }
729
730 TraceInterface& Adaptor::GetKernelTraceInterface()
731 {
732   return mKernelTracer;
733 }
734
735 TraceInterface& Adaptor::GetSystemTraceInterface()
736 {
737   return mSystemTracer;
738 }
739
740 PerformanceInterface* Adaptor::GetPerformanceInterface()
741 {
742   return mPerformanceInterface;
743 }
744
745 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
746 {
747   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
748   return *mPlatformAbstraction;
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   // Flush the event queue to give the update-render thread chance
967   // to start processing messages for new camera setup etc as soon as possible
968   ProcessCoreEvents();
969
970   mThreadController->ResizeSurface();
971 }
972
973 void Adaptor::NotifySceneCreated()
974 {
975   GetCore().SceneCreated();
976
977   // Flush the event queue to give the update-render thread chance
978   // to start processing messages for new camera setup etc as soon as possible
979   ProcessCoreEvents();
980
981   // Start thread controller after the scene has been created
982   mThreadController->Start();
983
984   // Process after surface is created (registering to remote surface provider if required)
985   SurfaceInitialized();
986
987   if( mState != PAUSED_WHILE_INITIALIZING )
988   {
989     mState = RUNNING;
990
991     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
992   }
993   else
994   {
995     mState = RUNNING;
996
997     Pause();
998
999     mState = PAUSED_WHILE_HIDDEN;
1000
1001     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1002   }
1003 }
1004
1005 void Adaptor::NotifyLanguageChanged()
1006 {
1007   mLanguageChangedSignal.Emit( mAdaptor );
1008 }
1009
1010 void Adaptor::RenderOnce()
1011 {
1012   RequestUpdateOnce();
1013 }
1014
1015 const LogFactoryInterface& Adaptor::GetLogFactory()
1016 {
1017   return *mEnvironmentOptions;
1018 }
1019
1020 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1021 {
1022   GetCore().RegisterProcessor(processor);
1023 }
1024
1025 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1026 {
1027   GetCore().UnregisterProcessor(processor);
1028 }
1029
1030 bool Adaptor::IsMultipleWindowSupported() const
1031 {
1032   return mConfigurationManager->IsMultipleWindowSupported();
1033 }
1034
1035 void Adaptor::RequestUpdateOnce()
1036 {
1037   if( mThreadController )
1038   {
1039     mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1040   }
1041 }
1042
1043 bool Adaptor::ProcessCoreEventsFromIdle()
1044 {
1045   ProcessCoreEvents();
1046
1047   // the idle handle automatically un-installs itself
1048   mNotificationOnIdleInstalled = false;
1049
1050   return false;
1051 }
1052
1053 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1054 {
1055   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1056
1057   for( auto window : mWindows )
1058   {
1059     if ( scene == window->GetScene() )
1060     {
1061       return window;
1062     }
1063   }
1064
1065   return nullptr;
1066 }
1067
1068 Dali::WindowContainer Adaptor::GetWindows() const
1069 {
1070   Dali::WindowContainer windows;
1071
1072   for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1073   {
1074     // Downcast to Dali::Window
1075     Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1076     if ( window )
1077     {
1078       windows.push_back( window );
1079     }
1080   }
1081
1082   return windows;
1083 }
1084
1085 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1086 {
1087   Dali::SceneHolderList sceneHolderList;
1088
1089   for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1090   {
1091     sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1092   }
1093
1094   return sceneHolderList;
1095 }
1096
1097 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1098 : mResizedSignal(),
1099   mLanguageChangedSignal(),
1100   mWindowCreatedSignal(),
1101   mAdaptor( adaptor ),
1102   mState( READY ),
1103   mCore( nullptr ),
1104   mThreadController( nullptr ),
1105   mGraphics( nullptr ),
1106   mDisplayConnection( nullptr ),
1107   mWindows(),
1108   mConfigurationManager( nullptr ),
1109   mPlatformAbstraction( nullptr ),
1110   mCallbackManager( nullptr ),
1111   mNotificationOnIdleInstalled( false ),
1112   mNotificationTrigger( nullptr ),
1113   mDaliFeedbackPlugin(),
1114   mFeedbackController( nullptr ),
1115   mTtsPlayers(),
1116   mObservers(),
1117   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1118   mPerformanceInterface( nullptr ),
1119   mKernelTracer(),
1120   mSystemTracer(),
1121   mTriggerEventFactory(),
1122   mObjectProfiler( nullptr ),
1123   mSocketFactory(),
1124   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1125   mUseRemoteSurface( false )
1126 {
1127   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1128   mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1129
1130   gThreadLocalAdaptor = this;
1131 }
1132
1133 void Adaptor::SetRootLayoutDirection( std::string locale )
1134 {
1135   Dali::Stage stage = Dali::Stage::GetCurrent();
1136
1137   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1138                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1139 }
1140
1141 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1142 {
1143   bool idleAdded( false );
1144
1145   // Only add an idle if the Adaptor is actually running
1146   if( RUNNING == mState || READY == mState || forceAdd )
1147   {
1148     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1149   }
1150
1151   return idleAdded;
1152 }
1153
1154 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1155 {
1156   mCallbackManager->RemoveIdleEntererCallback( callback );
1157 }
1158
1159 } // namespace Adaptor
1160
1161 } // namespace Internal
1162
1163 } // namespace Dali