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