2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/adaptor/common/adaptor-impl.h>
20 #include <dali/internal/adaptor/common/adaptor-builder-impl.h>
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>
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>
44 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
45 #include <dali/internal/graphics/gles/egl-graphics.h> // Temporary until Core is abstracted
47 #include <dali/devel-api/text-abstraction/font-client.h>
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>
64 #include <dali/internal/system/common/logging.h>
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>
70 #include <dali/internal/system/common/configuration-manager.h>
71 #include <dali/internal/system/common/environment-variables.h>
73 using Dali::TextAbstraction::FontClient;
75 extern std::string GetSystemCachePath();
89 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
91 } // unnamed namespace
93 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
95 Dali::Adaptor* adaptor = new Dali::Adaptor;
96 Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions );
97 adaptor->mImpl = impl;
99 Dali::Internal::Adaptor::AdaptorBuilder* mAdaptorBuilder = new AdaptorBuilder();
100 auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
102 impl->Initialize( graphicsFactory, configuration );
103 delete mAdaptorBuilder; // Not needed anymore as the graphics interface has now been created
108 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
110 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
111 Dali::Adaptor* adaptor = New( window, windowImpl.GetSurface(), configuration, environmentOptions );
112 windowImpl.SetAdaptor( *adaptor );
116 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
118 Dali::Adaptor* adaptor = new Dali::Adaptor; // Public adaptor
119 Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions ); // Impl adaptor
120 adaptor->mImpl = impl;
122 impl->Initialize( graphicsFactory, configuration );
127 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
129 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
130 Dali::Adaptor* adaptor = New( graphicsFactory, window, windowImpl.GetSurface(), configuration, environmentOptions );
131 windowImpl.SetAdaptor( *adaptor );
135 void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration::ContextLoss configuration )
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
142 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
145 GetDataStoragePath( path );
146 mPlatformAbstraction->SetDataStoragePath( path );
148 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
149 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
151 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
154 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from files automatically.
156 if( mEnvironmentOptions->PerformanceServerRequired() )
158 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
161 mEnvironmentOptions->CreateTraceManager( mPerformanceInterface );
162 mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
164 mCallbackManager = CallbackManager::New();
166 Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
168 DALI_ASSERT_DEBUG( defaultWindow->GetSurface() && "Surface not initialized" );
170 mGraphics = &( graphicsFactory.Create() );
171 mGraphics->Initialize( mEnvironmentOptions );
173 auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
175 // This will only be created once
176 eglGraphics->Create();
178 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
179 EglSyncImplementation& eglSyncImpl = eglGraphics->GetSyncImplementation();
180 EglContextHelperImplementation& eglContextHelperImpl = eglGraphics->GetContextHelperImplementation();
182 mCore = Integration::Core::New( *this,
183 *mPlatformAbstraction,
186 eglContextHelperImpl,
187 dataRetentionPolicy ,
188 ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
189 mGraphics->GetDepthBufferRequired(),
190 mGraphics->GetStencilBufferRequired() );
192 defaultWindow->SetAdaptor( Get() );
194 Dali::Integration::SceneHolder defaultSceneHolder( defaultWindow );
196 mWindowCreatedSignal.Emit( defaultSceneHolder );
198 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
199 if( 0u < timeInterval )
201 mObjectProfiler = new ObjectProfiler( timeInterval );
204 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
206 mDisplayConnection = Dali::DisplayConnection::New( *mGraphics, defaultWindow->GetSurface()->GetSurfaceType() );
208 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
210 // Should be called after Core creation
211 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
213 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
215 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
217 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
219 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
221 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
223 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
225 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
227 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
229 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
231 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
233 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
235 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
237 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
239 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
241 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
243 if( mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0 )
245 Integration::SetPanGestureUseActualTimes( mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false );
247 if( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0 )
249 Integration::SetPanGestureInterpolationTimeRange( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() );
251 if( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0 )
253 Integration::SetPanGestureScalarOnlyPredictionEnabled( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false );
255 if( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0 )
257 Integration::SetPanGestureTwoPointPredictionEnabled( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false );
259 if( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0 )
261 Integration::SetPanGestureTwoPointInterpolatePastTime( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() );
263 if( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f )
265 Integration::SetPanGestureTwoPointVelocityBias( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() );
267 if( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f )
269 Integration::SetPanGestureTwoPointAccelerationBias( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() );
271 if( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0 )
273 Integration::SetPanGestureMultitapSmoothingRange( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() );
275 if( mEnvironmentOptions->GetMinimumPanDistance() >= 0 )
277 Integration::SetPanGestureMinimumDistance( mEnvironmentOptions->GetMinimumPanDistance() );
279 if( mEnvironmentOptions->GetMinimumPanEvents() >= 0 )
281 Integration::SetPanGestureMinimumPanEvents( mEnvironmentOptions->GetMinimumPanEvents() );
283 if( mEnvironmentOptions->GetMinimumPinchDistance() >= 0 )
285 Integration::SetPinchGestureMinimumDistance( mEnvironmentOptions->GetMinimumPinchDistance() );
287 if( mEnvironmentOptions->GetMinimumPinchTouchEvents() >= 0 )
289 Integration::SetPinchGestureMinimumTouchEvents( mEnvironmentOptions->GetMinimumPinchTouchEvents() );
291 if( mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() >= 0 )
293 Integration::SetPinchGestureMinimumTouchEventsAfterStart( mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() );
295 if( mEnvironmentOptions->GetMinimumRotationTouchEvents() >= 0 )
297 Integration::SetRotationGestureMinimumTouchEvents( mEnvironmentOptions->GetMinimumRotationTouchEvents() );
299 if( mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() >= 0 )
301 Integration::SetRotationGestureMinimumTouchEventsAfterStart( mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() );
303 if( mEnvironmentOptions->GetLongPressMinimumHoldingTime() >= 0 )
305 Integration::SetLongPressMinimumHoldingTime( mEnvironmentOptions->GetLongPressMinimumHoldingTime() );
308 std::string systemCachePath = GetSystemCachePath();
309 if( ! systemCachePath.empty() )
311 const int dir_err = system( std::string( "mkdir " + systemCachePath ).c_str() );
314 printf( "Error creating system cache directory: %s!\n", systemCachePath.c_str() );
319 mConfigurationManager = Utils::MakeUnique<ConfigurationManager>( systemCachePath, eglGraphics, mThreadController );
324 // Ensure stop status
327 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
328 gThreadLocalAdaptor = NULL;
330 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
332 (*iter)->OnDestroy();
335 // Clear out all the handles to Windows
338 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
339 delete mObjectProfiler;
343 delete mDisplayConnection;
344 delete mPlatformAbstraction;
345 delete mCallbackManager;
346 delete mPerformanceInterface;
348 mGraphics->Destroy();
350 // uninstall it on this thread (main actor thread)
351 Dali::Integration::Log::UninstallLogFunction();
353 // Delete environment options if we own it
354 if( mEnvironmentOptionsOwned )
356 delete mEnvironmentOptions;
360 void Adaptor::Start()
362 // It doesn't support restart after stop at this moment to support restarting, need more testing
363 if( READY != mState )
370 SetupSystemInformation();
372 // Start the callback manager
373 mCallbackManager->Start();
375 Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
377 unsigned int dpiHor, dpiVer;
380 defaultWindow->GetSurface()->GetDpi( dpiHor, dpiVer );
382 // set the DPI value for font rendering
383 FontClient fontClient = FontClient::Get();
384 fontClient.SetDpi( dpiHor, dpiVer );
386 // Initialize the thread controller
387 mThreadController->Initialize();
389 // Set max texture size
390 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
392 Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
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 );
401 ProcessCoreEvents(); // Ensure any startup messages are processed.
403 // Initialize the image loader plugin
404 Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
406 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
412 // Dali::Internal::Adaptor::Adaptor::Pause
413 void Adaptor::Pause()
415 // Only pause the adaptor if we're actually running.
416 if( RUNNING == mState )
418 // Inform observers that we are about to be paused.
419 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
424 // Pause all windows event handlers when adaptor paused
425 for( auto window : mWindows )
430 mThreadController->Pause();
433 // Ensure any messages queued during pause callbacks are processed by doing another update.
436 DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Paused\n" );
440 DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Not paused [%d]\n", mState );
444 // Dali::Internal::Adaptor::Adaptor::Resume
445 void Adaptor::Resume()
447 // Only resume the adaptor if we are in the suspended state.
448 if( PAUSED == mState )
452 // Reset the event handlers when adaptor resumed
453 for( auto window : mWindows )
458 // Inform observers that we have resumed.
459 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
464 // Trigger processing of events queued up while paused
465 mCore->ProcessEvents();
467 // Do at end to ensure our first update/render after resumption includes the processed messages as well
468 mThreadController->Resume();
470 DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Resumed\n");
474 DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Not resumed [%d]\n", mState );
480 if( RUNNING == mState ||
482 PAUSED_WHILE_HIDDEN == mState )
484 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
489 mThreadController->Stop();
491 // Delete the TTS player
492 for( int i =0; i < Dali::TtsPlayer::MODE_NUM; i++ )
496 mTtsPlayers[i].Reset();
500 // Destroy the image loader plugin
501 Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
503 delete mNotificationTrigger;
504 mNotificationTrigger = NULL;
506 mCallbackManager->Stop();
510 DALI_LOG_RELEASE_INFO( "Adaptor::Stop\n" );
514 void Adaptor::ContextLost()
516 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
519 void Adaptor::ContextRegained()
521 // Inform core, so that texture resources can be reloaded
522 mCore->RecoverFromContextLoss();
524 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
527 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
529 Integration::Point convertedPoint( point );
530 mWindows.front()->FeedTouchPoint( convertedPoint, timeStamp );
533 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
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 );
539 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
541 Integration::KeyEvent convertedEvent( keyEvent );
542 mWindows.front()->FeedKeyEvent( convertedEvent );
545 void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface )
547 Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation( window );
548 for( auto windowPtr : mWindows )
550 if( windowPtr == windowImpl ) // the window is not deleted
552 mResizedSignal.Emit( mAdaptor );
554 windowImpl->SetSurface( &newSurface );
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
560 // This method blocks until the render thread has completed the replace.
561 mThreadController->ReplaceSurface( &newSurface );
567 void Adaptor::DeleteSurface( Dali::RenderSurfaceInterface& surface )
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
573 // This method blocks until the render thread has finished rendering the current surface.
574 mThreadController->DeleteSurface( &surface );
577 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
579 return *mWindows.front()->GetSurface();
582 void Adaptor::ReleaseSurfaceLock()
584 mWindows.front()->GetSurface()->ReleaseLock();
587 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
589 if( !mTtsPlayers[mode] )
591 // Create the TTS player when it needed, because it can reduce launching time.
592 mTtsPlayers[mode] = TtsPlayer::New(mode);
595 return mTtsPlayers[mode];
598 bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue, bool forceAdd )
600 bool idleAdded(false);
602 // Only add an idle if the Adaptor is actually running
603 if( RUNNING == mState || READY == mState || forceAdd )
605 idleAdded = mCallbackManager->AddIdleCallback( callback, hasReturnValue );
611 void Adaptor::RemoveIdle( CallbackBase* callback )
613 mCallbackManager->RemoveIdleCallback( callback );
616 void Adaptor::SetPreRenderCallback( CallbackBase* callback )
618 mThreadController->SetPreRenderCallback( callback );
621 bool Adaptor::AddWindow( Dali::Integration::SceneHolder childWindow, const std::string& childWindowName, const std::string& childWindowClassName, bool childWindowMode )
623 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( childWindow );
624 windowImpl.SetAdaptor( Get() );
626 // Add the new Window to the container - the order is not important
627 mWindows.push_back( &windowImpl );
629 Dali::RenderSurfaceInterface* surface = windowImpl.GetSurface();
631 mThreadController->AddSurface( surface );
633 mWindowCreatedSignal.Emit( childWindow );
638 bool Adaptor::RemoveWindow( Dali::Integration::SceneHolder* childWindow )
640 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( *childWindow );
641 for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
643 if( *iter == &windowImpl )
645 mWindows.erase( iter );
653 bool Adaptor::RemoveWindow( std::string childWindowName )
655 for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
657 if( ( *iter )->GetName() == childWindowName )
659 mWindows.erase( iter );
667 bool Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* childWindow )
669 for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
671 if( ( *iter )->GetId() == childWindow->GetId() )
673 mWindows.erase( iter );
681 Dali::Adaptor& Adaptor::Get()
683 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
684 return gThreadLocalAdaptor->mAdaptor;
687 bool Adaptor::IsAvailable()
689 return gThreadLocalAdaptor != NULL;
692 void Adaptor::SceneCreated()
694 mCore->SceneCreated();
697 Dali::Integration::Core& Adaptor::GetCore()
702 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
704 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
707 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
709 DALI_ASSERT_DEBUG( mDisplayConnection && "Display connection not created" );
710 return *mDisplayConnection;
713 GraphicsInterface& Adaptor::GetGraphicsInterface()
715 DALI_ASSERT_DEBUG( mGraphics && "Graphics interface not created" );
719 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
721 return *mPlatformAbstraction;
724 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
726 return *mNotificationTrigger;
729 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
731 return mTriggerEventFactory;
734 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
736 return mSocketFactory;
739 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
741 if( !mWindows.empty() )
743 return mWindows.front()->GetSurface();
749 TraceInterface& Adaptor::GetKernelTraceInterface()
751 return mKernelTracer;
754 TraceInterface& Adaptor::GetSystemTraceInterface()
756 return mSystemTracer;
759 PerformanceInterface* Adaptor::GetPerformanceInterface()
761 return mPerformanceInterface;
764 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
766 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
767 return *mPlatformAbstraction;
770 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
772 if( mTtsPlayers[mode] )
774 mTtsPlayers[mode].Reset();
778 Any Adaptor::GetNativeWindowHandle()
780 return mWindows.front()->GetNativeHandle();
783 Any Adaptor::GetNativeWindowHandle( Dali::Actor actor )
785 Any nativeWindowHandle;
787 Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
789 for( auto sceneHolder : mWindows )
791 if ( scene == sceneHolder->GetScene() )
793 nativeWindowHandle = sceneHolder->GetNativeHandle();
798 return nativeWindowHandle;
801 Any Adaptor::GetGraphicsDisplay()
807 auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
809 EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
810 display = eglImpl.GetDisplay();
816 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
818 mUseRemoteSurface = useRemoteSurface;
821 void Adaptor::AddObserver( LifeCycleObserver& observer )
823 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
825 if ( match == mObservers.end() )
827 mObservers.push_back( &observer );
831 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
833 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
835 if ( match != mObservers.end() )
837 mObservers.erase( match );
841 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
845 mCore->QueueEvent(event);
849 void Adaptor::ProcessCoreEvents()
853 if( mPerformanceInterface )
855 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
858 mCore->ProcessEvents();
860 if( mPerformanceInterface )
862 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
867 void Adaptor::RequestUpdate( bool forceUpdate )
873 mThreadController->RequestUpdate();
877 case PAUSED_WHILE_HIDDEN:
881 // Update (and resource upload) without rendering
882 mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
894 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
896 // Only request a notification if the Adaptor is actually running
897 // and we haven't installed the idle notification
898 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
900 mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
904 void Adaptor::OnWindowShown()
906 if( PAUSED_WHILE_HIDDEN == mState )
908 // Adaptor can now be resumed
913 // Force a render task
916 else if( RUNNING == mState )
918 // Force a render task
921 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
925 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
929 void Adaptor::OnWindowHidden()
931 if( RUNNING == mState || READY == mState )
933 bool allWindowsHidden = true;
935 for( auto window : mWindows )
937 if ( window->IsVisible() )
939 allWindowsHidden = false;
944 // Only pause the adaptor when all the windows are hidden
945 if( allWindowsHidden )
947 if( mState == RUNNING )
951 // Adaptor cannot be resumed until any window is shown
952 mState = PAUSED_WHILE_HIDDEN;
954 else // mState is READY
956 // Pause the adaptor after the state gets RUNNING
957 mState = PAUSED_WHILE_INITIALIZING;
962 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
967 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
971 // Dali::Internal::Adaptor::Adaptor::OnDamaged
972 void Adaptor::OnDamaged( const DamageArea& area )
974 // This is needed for the case where Dali window is partially obscured
975 RequestUpdate( false );
978 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
980 mResizedSignal.Emit( mAdaptor );
983 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
985 // Flush the event queue to give the update-render thread chance
986 // to start processing messages for new camera setup etc as soon as possible
989 mThreadController->ResizeSurface();
992 void Adaptor::NotifySceneCreated()
994 GetCore().SceneCreated();
996 // Flush the event queue to give the update-render thread chance
997 // to start processing messages for new camera setup etc as soon as possible
1000 // Start thread controller after the scene has been created
1001 mThreadController->Start();
1003 // Process after surface is created (registering to remote surface provider if required)
1004 SurfaceInitialized();
1006 if( mState != PAUSED_WHILE_INITIALIZING )
1010 DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
1018 mState = PAUSED_WHILE_HIDDEN;
1020 DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1024 void Adaptor::NotifyLanguageChanged()
1026 mLanguageChangedSignal.Emit( mAdaptor );
1029 void Adaptor::RenderOnce()
1031 RequestUpdateOnce();
1034 const LogFactoryInterface& Adaptor::GetLogFactory()
1036 return *mEnvironmentOptions;
1039 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1041 GetCore().RegisterProcessor(processor);
1044 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1046 GetCore().UnregisterProcessor(processor);
1049 bool Adaptor::IsMultipleWindowSupported() const
1051 return mConfigurationManager->IsMultipleWindowSupported();
1054 void Adaptor::RequestUpdateOnce()
1056 if( mThreadController )
1058 mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1062 bool Adaptor::ProcessCoreEventsFromIdle()
1064 ProcessCoreEvents();
1066 // the idle handle automatically un-installs itself
1067 mNotificationOnIdleInstalled = false;
1072 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1074 Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1076 for( auto window : mWindows )
1078 if ( scene == window->GetScene() )
1087 Dali::WindowContainer Adaptor::GetWindows() const
1089 Dali::WindowContainer windows;
1091 for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1093 // Downcast to Dali::Window
1094 Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1097 windows.push_back( window );
1104 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1106 Dali::SceneHolderList sceneHolderList;
1108 for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1110 sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1113 return sceneHolderList;
1116 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1118 mLanguageChangedSignal(),
1119 mWindowCreatedSignal(),
1120 mAdaptor( adaptor ),
1123 mThreadController( nullptr ),
1124 mGraphics( nullptr ),
1125 mDisplayConnection( nullptr ),
1127 mConfigurationManager( nullptr ),
1128 mPlatformAbstraction( nullptr ),
1129 mCallbackManager( nullptr ),
1130 mNotificationOnIdleInstalled( false ),
1131 mNotificationTrigger( nullptr ),
1132 mDaliFeedbackPlugin(),
1133 mFeedbackController( nullptr ),
1136 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1137 mPerformanceInterface( nullptr ),
1140 mTriggerEventFactory(),
1141 mObjectProfiler( nullptr ),
1143 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1144 mUseRemoteSurface( false )
1146 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1147 mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1149 gThreadLocalAdaptor = this;
1152 void Adaptor::SetRootLayoutDirection( std::string locale )
1154 Dali::Stage stage = Dali::Stage::GetCurrent();
1156 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1157 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1160 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1162 bool idleAdded( false );
1164 // Only add an idle if the Adaptor is actually running
1165 if( RUNNING == mState || READY == mState || forceAdd )
1167 idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1173 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1175 mCallbackManager->RemoveIdleEntererCallback( callback );
1178 } // namespace Adaptor
1180 } // namespace Internal