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