Revert "[Tizen](ATSPI) squashed implementation"
[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.empty() )
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.empty() )
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::GetNativeWindowHandle( Dali::Actor actor )
804 {
805   Any nativeWindowHandle;
806
807   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
808
809   for( auto sceneHolder : mWindows )
810   {
811     if ( scene == sceneHolder->GetScene() )
812     {
813       nativeWindowHandle = sceneHolder->GetNativeHandle();
814       break;
815     }
816   }
817
818   return nativeWindowHandle;
819 }
820
821 Any Adaptor::GetGraphicsDisplay()
822 {
823   Any display;
824
825   if (mGraphics)
826   {
827     auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
828
829     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
830     display = eglImpl.GetDisplay();
831   }
832
833   return display;
834 }
835
836 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
837 {
838   mUseRemoteSurface = useRemoteSurface;
839 }
840
841 void Adaptor::AddObserver( LifeCycleObserver& observer )
842 {
843   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
844
845   if ( match == mObservers.end() )
846   {
847     mObservers.push_back( &observer );
848   }
849 }
850
851 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
852 {
853   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
854
855   if ( match != mObservers.end() )
856   {
857     mObservers.erase( match );
858   }
859 }
860
861 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
862 {
863   if( mCore )
864   {
865     mCore->QueueEvent(event);
866   }
867 }
868
869 void Adaptor::ProcessCoreEvents()
870 {
871   if( mCore )
872   {
873     if( mPerformanceInterface )
874     {
875       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
876     }
877
878     mCore->ProcessEvents();
879
880     if( mPerformanceInterface )
881     {
882       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
883     }
884   }
885 }
886
887 void Adaptor::RequestUpdate( bool forceUpdate )
888 {
889   switch( mState )
890   {
891     case RUNNING:
892     {
893       mThreadController->RequestUpdate();
894       break;
895     }
896     case PAUSED:
897     case PAUSED_WHILE_HIDDEN:
898     {
899       // When Dali applications are partially visible behind the lock-screen,
900       // the indicator must be updated (therefore allow updates in the PAUSED state)
901       if( forceUpdate )
902       {
903         mThreadController->RequestUpdateOnce();
904       }
905       break;
906     }
907     default:
908     {
909       // Do nothing
910       break;
911     }
912   }
913 }
914
915 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
916 {
917   // Only request a notification if the Adaptor is actually running
918   // and we haven't installed the idle notification
919   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
920   {
921     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
922   }
923 }
924
925 void Adaptor::OnWindowShown()
926 {
927   if( PAUSED_WHILE_HIDDEN == mState )
928   {
929     // Adaptor can now be resumed
930     mState = PAUSED;
931
932     Resume();
933
934     // Force a render task
935     RequestUpdateOnce();
936   }
937   else if( RUNNING == mState )
938   {
939     // Force a render task
940     RequestUpdateOnce();
941
942     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
943   }
944   else
945   {
946     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
947   }
948 }
949
950 void Adaptor::OnWindowHidden()
951 {
952   if( RUNNING == mState || READY == mState )
953   {
954     bool allWindowsHidden = true;
955
956     for( auto window : mWindows )
957     {
958       if ( window->IsVisible() )
959       {
960         allWindowsHidden = false;
961         break;
962       }
963     }
964
965     // Only pause the adaptor when all the windows are hidden
966     if( allWindowsHidden )
967     {
968       if( mState == RUNNING )
969       {
970         Pause();
971
972         // Adaptor cannot be resumed until any window is shown
973         mState = PAUSED_WHILE_HIDDEN;
974       }
975       else  // mState is READY
976       {
977         // Pause the adaptor after the state gets RUNNING
978         mState = PAUSED_WHILE_INITIALIZING;
979       }
980     }
981     else
982     {
983       DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
984     }
985   }
986   else
987   {
988     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
989   }
990 }
991
992 // Dali::Internal::Adaptor::Adaptor::OnDamaged
993 void Adaptor::OnDamaged( const DamageArea& area )
994 {
995   // This is needed for the case where Dali window is partially obscured
996   RequestUpdate( false );
997 }
998
999 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
1000 {
1001   mResizedSignal.Emit( mAdaptor );
1002 }
1003
1004 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
1005 {
1006   // Flush the event queue to give the update-render thread chance
1007   // to start processing messages for new camera setup etc as soon as possible
1008   ProcessCoreEvents();
1009
1010   mThreadController->ResizeSurface();
1011 }
1012
1013 void Adaptor::NotifySceneCreated()
1014 {
1015   GetCore().SceneCreated();
1016
1017   // Flush the event queue to give the update-render thread chance
1018   // to start processing messages for new camera setup etc as soon as possible
1019   ProcessCoreEvents();
1020
1021   // Start thread controller after the scene has been created
1022   mThreadController->Start();
1023
1024   // Process after surface is created (registering to remote surface provider if required)
1025   SurfaceInitialized();
1026
1027   if( mState != PAUSED_WHILE_INITIALIZING )
1028   {
1029     mState = RUNNING;
1030
1031     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
1032   }
1033   else
1034   {
1035     mState = RUNNING;
1036
1037     Pause();
1038
1039     mState = PAUSED_WHILE_HIDDEN;
1040
1041     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1042   }
1043 }
1044
1045 void Adaptor::NotifyLanguageChanged()
1046 {
1047   mLanguageChangedSignal.Emit( mAdaptor );
1048 }
1049
1050 void Adaptor::RenderOnce()
1051 {
1052   RequestUpdateOnce();
1053 }
1054
1055 const LogFactoryInterface& Adaptor::GetLogFactory()
1056 {
1057   return *mEnvironmentOptions;
1058 }
1059
1060 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1061 {
1062   GetCore().RegisterProcessor(processor);
1063 }
1064
1065 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1066 {
1067   GetCore().UnregisterProcessor(processor);
1068 }
1069
1070 void Adaptor::RequestUpdateOnce()
1071 {
1072   if( mThreadController )
1073   {
1074     mThreadController->RequestUpdateOnce();
1075   }
1076 }
1077
1078 bool Adaptor::ProcessCoreEventsFromIdle()
1079 {
1080   ProcessCoreEvents();
1081
1082   // the idle handle automatically un-installs itself
1083   mNotificationOnIdleInstalled = false;
1084
1085   return false;
1086 }
1087
1088 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1089 {
1090   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1091
1092   for( auto window : mWindows )
1093   {
1094     if ( scene == window->GetScene() )
1095     {
1096       return window;
1097     }
1098   }
1099
1100   return nullptr;
1101 }
1102
1103 Dali::WindowContainer Adaptor::GetWindows() const
1104 {
1105   Dali::WindowContainer windows;
1106
1107   for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1108   {
1109     // Downcast to Dali::Window
1110     Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1111     if ( window )
1112     {
1113       windows.push_back( window );
1114     }
1115   }
1116
1117   return windows;
1118 }
1119
1120 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1121 : mResizedSignal(),
1122   mLanguageChangedSignal(),
1123   mWindowCreatedSignal(),
1124   mAdaptor( adaptor ),
1125   mState( READY ),
1126   mCore( nullptr ),
1127   mThreadController( nullptr ),
1128   mGraphics( nullptr ),
1129   mDisplayConnection( nullptr ),
1130   mWindows(),
1131   mPlatformAbstraction( nullptr ),
1132   mCallbackManager( nullptr ),
1133   mNotificationOnIdleInstalled( false ),
1134   mNotificationTrigger( nullptr ),
1135   mDaliFeedbackPlugin(),
1136   mFeedbackController( nullptr ),
1137   mTtsPlayers(),
1138   mObservers(),
1139   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1140   mPerformanceInterface( nullptr ),
1141   mKernelTracer(),
1142   mSystemTracer(),
1143   mTriggerEventFactory(),
1144   mObjectProfiler( nullptr ),
1145   mSocketFactory(),
1146   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1147   mUseRemoteSurface( false )
1148 {
1149   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1150   mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1151
1152   gThreadLocalAdaptor = this;
1153 }
1154
1155 void Adaptor::SetRootLayoutDirection( std::string locale )
1156 {
1157   Dali::Stage stage = Dali::Stage::GetCurrent();
1158
1159   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1160                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1161 }
1162
1163 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1164 {
1165   bool idleAdded( false );
1166
1167   // Only add an idle if the Adaptor is actually running
1168   if( RUNNING == mState || READY == mState || forceAdd )
1169   {
1170     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1171   }
1172
1173   return idleAdded;
1174 }
1175
1176 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1177 {
1178   mCallbackManager->RemoveIdleEntererCallback( callback );
1179 }
1180
1181 } // namespace Adaptor
1182
1183 } // namespace Internal
1184
1185 } // namespace Dali