[dali_1.4.52] Merge branch 'devel/master'
[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
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       if( forceUpdate )
894       {
895         // Update (and resource upload) without rendering
896         mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
897       }
898       break;
899     }
900     default:
901     {
902       // Do nothing
903       break;
904     }
905   }
906 }
907
908 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
909 {
910   // Only request a notification if the Adaptor is actually running
911   // and we haven't installed the idle notification
912   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
913   {
914     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
915   }
916 }
917
918 void Adaptor::OnWindowShown()
919 {
920   if( PAUSED_WHILE_HIDDEN == mState )
921   {
922     // Adaptor can now be resumed
923     mState = PAUSED;
924
925     Resume();
926
927     // Force a render task
928     RequestUpdateOnce();
929   }
930   else if( RUNNING == mState )
931   {
932     // Force a render task
933     RequestUpdateOnce();
934
935     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
936   }
937   else
938   {
939     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
940   }
941 }
942
943 void Adaptor::OnWindowHidden()
944 {
945   if( RUNNING == mState || READY == mState )
946   {
947     bool allWindowsHidden = true;
948
949     for( auto window : mWindows )
950     {
951       if ( window->IsVisible() )
952       {
953         allWindowsHidden = false;
954         break;
955       }
956     }
957
958     // Only pause the adaptor when all the windows are hidden
959     if( allWindowsHidden )
960     {
961       if( mState == RUNNING )
962       {
963         Pause();
964
965         // Adaptor cannot be resumed until any window is shown
966         mState = PAUSED_WHILE_HIDDEN;
967       }
968       else  // mState is READY
969       {
970         // Pause the adaptor after the state gets RUNNING
971         mState = PAUSED_WHILE_INITIALIZING;
972       }
973     }
974     else
975     {
976       DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
977     }
978   }
979   else
980   {
981     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
982   }
983 }
984
985 // Dali::Internal::Adaptor::Adaptor::OnDamaged
986 void Adaptor::OnDamaged( const DamageArea& area )
987 {
988   // This is needed for the case where Dali window is partially obscured
989   RequestUpdate( false );
990 }
991
992 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
993 {
994   mResizedSignal.Emit( mAdaptor );
995 }
996
997 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
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   mThreadController->ResizeSurface();
1004 }
1005
1006 void Adaptor::NotifySceneCreated()
1007 {
1008   GetCore().SceneCreated();
1009
1010   // Flush the event queue to give the update-render thread chance
1011   // to start processing messages for new camera setup etc as soon as possible
1012   ProcessCoreEvents();
1013
1014   // Start thread controller after the scene has been created
1015   mThreadController->Start();
1016
1017   // Process after surface is created (registering to remote surface provider if required)
1018   SurfaceInitialized();
1019
1020   if( mState != PAUSED_WHILE_INITIALIZING )
1021   {
1022     mState = RUNNING;
1023
1024     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
1025   }
1026   else
1027   {
1028     mState = RUNNING;
1029
1030     Pause();
1031
1032     mState = PAUSED_WHILE_HIDDEN;
1033
1034     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1035   }
1036 }
1037
1038 void Adaptor::NotifyLanguageChanged()
1039 {
1040   mLanguageChangedSignal.Emit( mAdaptor );
1041 }
1042
1043 void Adaptor::RenderOnce()
1044 {
1045   RequestUpdateOnce();
1046 }
1047
1048 const LogFactoryInterface& Adaptor::GetLogFactory()
1049 {
1050   return *mEnvironmentOptions;
1051 }
1052
1053 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1054 {
1055   GetCore().RegisterProcessor(processor);
1056 }
1057
1058 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1059 {
1060   GetCore().UnregisterProcessor(processor);
1061 }
1062
1063 bool Adaptor::IsMultipleWindowSupported() const
1064 {
1065   auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
1066   EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
1067   bool ret = eglImpl.IsSurfacelessContextSupported();
1068   return ret;
1069 }
1070
1071 void Adaptor::RequestUpdateOnce()
1072 {
1073   if( mThreadController )
1074   {
1075     mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1076   }
1077 }
1078
1079 bool Adaptor::ProcessCoreEventsFromIdle()
1080 {
1081   ProcessCoreEvents();
1082
1083   // the idle handle automatically un-installs itself
1084   mNotificationOnIdleInstalled = false;
1085
1086   return false;
1087 }
1088
1089 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1090 {
1091   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1092
1093   for( auto window : mWindows )
1094   {
1095     if ( scene == window->GetScene() )
1096     {
1097       return window;
1098     }
1099   }
1100
1101   return nullptr;
1102 }
1103
1104 Dali::WindowContainer Adaptor::GetWindows() const
1105 {
1106   Dali::WindowContainer windows;
1107
1108   for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1109   {
1110     // Downcast to Dali::Window
1111     Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1112     if ( window )
1113     {
1114       windows.push_back( window );
1115     }
1116   }
1117
1118   return windows;
1119 }
1120
1121 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1122 {
1123   Dali::SceneHolderList sceneHolderList;
1124
1125   for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1126   {
1127     sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1128   }
1129
1130   return sceneHolderList;
1131 }
1132
1133 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1134 : mResizedSignal(),
1135   mLanguageChangedSignal(),
1136   mWindowCreatedSignal(),
1137   mAdaptor( adaptor ),
1138   mState( READY ),
1139   mCore( nullptr ),
1140   mThreadController( nullptr ),
1141   mGraphics( nullptr ),
1142   mDisplayConnection( nullptr ),
1143   mWindows(),
1144   mPlatformAbstraction( nullptr ),
1145   mCallbackManager( nullptr ),
1146   mNotificationOnIdleInstalled( false ),
1147   mNotificationTrigger( nullptr ),
1148   mDaliFeedbackPlugin(),
1149   mFeedbackController( nullptr ),
1150   mTtsPlayers(),
1151   mObservers(),
1152   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1153   mPerformanceInterface( nullptr ),
1154   mKernelTracer(),
1155   mSystemTracer(),
1156   mTriggerEventFactory(),
1157   mObjectProfiler( nullptr ),
1158   mSocketFactory(),
1159   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1160   mUseRemoteSurface( false )
1161 {
1162   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1163   mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1164
1165   gThreadLocalAdaptor = this;
1166 }
1167
1168 void Adaptor::SetRootLayoutDirection( std::string locale )
1169 {
1170   Dali::Stage stage = Dali::Stage::GetCurrent();
1171
1172   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1173                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1174 }
1175
1176 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1177 {
1178   bool idleAdded( false );
1179
1180   // Only add an idle if the Adaptor is actually running
1181   if( RUNNING == mState || READY == mState || forceAdd )
1182   {
1183     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1184   }
1185
1186   return idleAdded;
1187 }
1188
1189 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1190 {
1191   mCallbackManager->RemoveIdleEntererCallback( callback );
1192 }
1193
1194 } // namespace Adaptor
1195
1196 } // namespace Internal
1197
1198 } // namespace Dali