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