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