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