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