[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 #include <dali/internal/adaptor/common/thread-controller-interface.h>
45
46 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
47 #include <dali/internal/graphics/gles/egl-graphics.h> // Temporary until Core is abstracted
48
49 #include <dali/devel-api/text-abstraction/font-client.h>
50
51 #include <dali/internal/system/common/callback-manager.h>
52 #include <dali/internal/accessibility/common/tts-player-impl.h>
53 #include <dali/internal/accessibility/common/accessibility-adaptor-impl.h>
54 #include <dali/internal/window-system/common/event-handler.h>
55 #include <dali/internal/graphics/gles/gl-proxy-implementation.h>
56 #include <dali/internal/graphics/gles/gl-implementation.h>
57 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
58 #include <dali/internal/graphics/common/egl-image-extensions.h>
59 #include <dali/internal/clipboard/common/clipboard-impl.h>
60 #include <dali/internal/system/common/object-profiler.h>
61 #include <dali/internal/window-system/common/display-connection.h>
62 #include <dali/internal/window-system/common/window-impl.h>
63 #include <dali/internal/window-system/common/window-render-surface.h>
64
65 #include <dali/internal/system/common/logging.h>
66
67 #include <dali/internal/system/common/locale-utils.h>
68 #include <dali/internal/imaging/common/image-loader-plugin-proxy.h>
69 #include <dali/internal/imaging/common/image-loader.h>
70
71 #include <dali/devel-api/adaptor-framework/file-stream.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 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
89 } // unnamed namespace
90
91 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
92 {
93   Dali::Adaptor* adaptor = new Dali::Adaptor;
94   Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions );
95   adaptor->mImpl = impl;
96
97   Dali::Internal::Adaptor::AdaptorBuilder* mAdaptorBuilder = new AdaptorBuilder();
98   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
99
100   impl->Initialize( graphicsFactory, configuration );
101   delete mAdaptorBuilder; // Not needed anymore as the graphics interface has now been created
102
103   return adaptor;
104 }
105
106 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
107 {
108   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
109   Dali::Adaptor* adaptor = New( window, windowImpl.GetSurface(), configuration, environmentOptions );
110   windowImpl.SetAdaptor( *adaptor );
111   return adaptor;
112 }
113
114 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
115 {
116   Dali::Adaptor* adaptor = new Dali::Adaptor; // Public adaptor
117   Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions ); // Impl adaptor
118   adaptor->mImpl = impl;
119
120   impl->Initialize( graphicsFactory, configuration );
121
122   return adaptor;
123 } // Called second
124
125 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
126 {
127   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
128   Dali::Adaptor* adaptor = New( graphicsFactory, window, windowImpl.GetSurface(), configuration, environmentOptions );
129   windowImpl.SetAdaptor( *adaptor );
130   return adaptor;
131 } // Called first
132
133 void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration::ContextLoss configuration )
134 {
135   // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
136   Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
137   mEnvironmentOptions->SetLogFunction( logFunction );
138   mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
139
140   mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
141
142   std::string path;
143   GetDataStoragePath( path );
144   mPlatformAbstraction->SetDataStoragePath( path );
145
146   ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
147   if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
148   {
149     dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
150   }
151
152   // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from files automatically.
153
154   if( mEnvironmentOptions->PerformanceServerRequired() )
155   {
156     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
157   }
158
159   mEnvironmentOptions->CreateTraceManager( mPerformanceInterface );
160   mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
161
162   mCallbackManager = CallbackManager::New();
163
164   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
165
166   DALI_ASSERT_DEBUG( defaultWindow->GetSurface() && "Surface not initialized" );
167
168   mGraphics = &( graphicsFactory.Create() );
169   mGraphics->Initialize( mEnvironmentOptions );
170
171   auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
172
173   // This will only be created once
174   eglGraphics->Create();
175
176   GlImplementation& mGLES = eglGraphics->GetGlesInterface();
177   EglSyncImplementation& eglSyncImpl = eglGraphics->GetSyncImplementation();
178   EglContextHelperImplementation& eglContextHelperImpl = eglGraphics->GetContextHelperImplementation();
179
180   mCore = Integration::Core::New( *this,
181                                   *mPlatformAbstraction,
182                                   mGLES,
183                                   eglSyncImpl,
184                                   eglContextHelperImpl,
185                                   dataRetentionPolicy ,
186                                   ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
187                                   mGraphics->GetDepthBufferRequired(),
188                                   mGraphics->GetStencilBufferRequired(),
189                                   mGraphics->PartialUpdateAvailable() );
190
191   defaultWindow->SetAdaptor( Get() );
192
193   Dali::Integration::SceneHolder defaultSceneHolder( defaultWindow );
194
195   mWindowCreatedSignal.Emit( defaultSceneHolder );
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.empty() )
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.empty() )
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   mWindowCreatedSignal.Emit( childWindow );
649
650   return true;
651 }
652
653 bool Adaptor::RemoveWindow( Dali::Integration::SceneHolder* childWindow )
654 {
655   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( *childWindow );
656   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
657   {
658     if( *iter == &windowImpl )
659     {
660       mWindows.erase( iter );
661       return true;
662     }
663   }
664
665   return false;
666 }
667
668 bool Adaptor::RemoveWindow( std::string childWindowName )
669 {
670   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
671   {
672     if( ( *iter )->GetName() == childWindowName )
673     {
674       mWindows.erase( iter );
675       return true;
676     }
677   }
678
679   return false;
680 }
681
682 bool Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* childWindow )
683 {
684   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
685   {
686     if( ( *iter )->GetId() == childWindow->GetId() )
687     {
688       mWindows.erase( iter );
689       return true;
690     }
691   }
692
693   return false;
694 }
695
696 Dali::Adaptor& Adaptor::Get()
697 {
698   DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
699   return gThreadLocalAdaptor->mAdaptor;
700 }
701
702 bool Adaptor::IsAvailable()
703 {
704   return gThreadLocalAdaptor != NULL;
705 }
706
707 void Adaptor::SceneCreated()
708 {
709   mCore->SceneCreated();
710 }
711
712 Dali::Integration::Core& Adaptor::GetCore()
713 {
714   return *mCore;
715 }
716
717 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
718 {
719   mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
720 }
721
722 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
723 {
724   DALI_ASSERT_DEBUG( mDisplayConnection && "Display connection not created" );
725   return *mDisplayConnection;
726 }
727
728 GraphicsInterface& Adaptor::GetGraphicsInterface()
729 {
730   DALI_ASSERT_DEBUG( mGraphics && "Graphics interface not created" );
731   return *mGraphics;
732 }
733
734 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
735 {
736   return *mPlatformAbstraction;
737 }
738
739 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
740 {
741   return *mNotificationTrigger;
742 }
743
744 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
745 {
746   return mTriggerEventFactory;
747 }
748
749 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
750 {
751   return mSocketFactory;
752 }
753
754 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
755 {
756   if( !mWindows.empty() )
757   {
758     return mWindows.front()->GetSurface();
759   }
760
761   return nullptr;
762 }
763
764 TraceInterface& Adaptor::GetKernelTraceInterface()
765 {
766   return mKernelTracer;
767 }
768
769 TraceInterface& Adaptor::GetSystemTraceInterface()
770 {
771   return mSystemTracer;
772 }
773
774 PerformanceInterface* Adaptor::GetPerformanceInterface()
775 {
776   return mPerformanceInterface;
777 }
778
779 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
780 {
781   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
782   return *mPlatformAbstraction;
783 }
784
785 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
786 {
787   if( mTtsPlayers[mode] )
788   {
789     mTtsPlayers[mode].Reset();
790   }
791 }
792
793 Any Adaptor::GetNativeWindowHandle()
794 {
795   return mWindows.front()->GetNativeHandle();
796 }
797
798 Any Adaptor::GetNativeWindowHandle( Dali::Actor actor )
799 {
800   Any nativeWindowHandle;
801
802   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
803
804   for( auto sceneHolder : mWindows )
805   {
806     if ( scene == sceneHolder->GetScene() )
807     {
808       nativeWindowHandle = sceneHolder->GetNativeHandle();
809       break;
810     }
811   }
812
813   return nativeWindowHandle;
814 }
815
816 Any Adaptor::GetGraphicsDisplay()
817 {
818   Any display;
819
820   if (mGraphics)
821   {
822     auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
823
824     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
825     display = eglImpl.GetDisplay();
826   }
827
828   return display;
829 }
830
831 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
832 {
833   mUseRemoteSurface = useRemoteSurface;
834 }
835
836 void Adaptor::AddObserver( LifeCycleObserver& observer )
837 {
838   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
839
840   if ( match == mObservers.end() )
841   {
842     mObservers.push_back( &observer );
843   }
844 }
845
846 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
847 {
848   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
849
850   if ( match != mObservers.end() )
851   {
852     mObservers.erase( match );
853   }
854 }
855
856 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
857 {
858   if( mCore )
859   {
860     mCore->QueueEvent(event);
861   }
862 }
863
864 void Adaptor::ProcessCoreEvents()
865 {
866   if( mCore )
867   {
868     if( mPerformanceInterface )
869     {
870       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
871     }
872
873     mCore->ProcessEvents();
874
875     if( mPerformanceInterface )
876     {
877       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
878     }
879   }
880 }
881
882 void Adaptor::RequestUpdate( bool forceUpdate )
883 {
884   switch( mState )
885   {
886     case RUNNING:
887     {
888       mThreadController->RequestUpdate();
889       break;
890     }
891     case PAUSED:
892     case PAUSED_WHILE_HIDDEN:
893     {
894       if( forceUpdate )
895       {
896         // Update (and resource upload) without rendering
897         mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
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( UpdateMode::NORMAL );
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