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