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