2 * Copyright (c) 2019 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>
40 #include <dali/public-api/dali-adaptor-common.h>
41 #include <dali/internal/system/common/thread-controller.h>
42 #include <dali/internal/system/common/performance-interface-factory.h>
43 #include <dali/internal/adaptor/common/lifecycle-observer.h>
44 #include <dali/internal/adaptor/common/thread-controller-interface.h>
46 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
47 #include <dali/internal/graphics/gles/egl-graphics.h> // Temporary until Core is abstracted
49 #include <dali/devel-api/text-abstraction/font-client.h>
51 #include <dali/internal/system/common/callback-manager.h>
52 #include <dali/internal/accessibility/common/tts-player-impl.h>
53 #include <dali/internal/accessibility/common/accessibility-adaptor-impl.h>
54 #include <dali/internal/window-system/common/event-handler.h>
55 #include <dali/internal/graphics/gles/gl-proxy-implementation.h>
56 #include <dali/internal/graphics/gles/gl-implementation.h>
57 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
58 #include <dali/internal/graphics/common/egl-image-extensions.h>
59 #include <dali/internal/clipboard/common/clipboard-impl.h>
60 #include <dali/internal/system/common/object-profiler.h>
61 #include <dali/internal/window-system/common/display-connection.h>
62 #include <dali/internal/window-system/common/window-impl.h>
63 #include <dali/internal/window-system/common/window-render-surface.h>
65 #include <dali/internal/system/common/logging.h>
67 #include <dali/internal/system/common/locale-utils.h>
68 #include <dali/internal/imaging/common/image-loader-plugin-proxy.h>
69 #include <dali/internal/imaging/common/image-loader.h>
71 #include <dali/devel-api/adaptor-framework/file-stream.h>
73 using Dali::TextAbstraction::FontClient;
75 extern std::string GetSystemCachePath();
88 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
89 } // unnamed namespace
91 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
93 Dali::Adaptor* adaptor = new Dali::Adaptor;
94 Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions );
95 adaptor->mImpl = impl;
97 Dali::Internal::Adaptor::AdaptorBuilder* mAdaptorBuilder = new AdaptorBuilder();
98 auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
100 impl->Initialize( graphicsFactory, configuration );
101 delete mAdaptorBuilder; // Not needed anymore as the graphics interface has now been created
106 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
108 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
109 Dali::Adaptor* adaptor = New( window, windowImpl.GetSurface(), configuration, environmentOptions );
110 windowImpl.SetAdaptor( *adaptor );
114 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
116 Dali::Adaptor* adaptor = new Dali::Adaptor; // Public adaptor
117 Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions ); // Impl adaptor
118 adaptor->mImpl = impl;
120 impl->Initialize( graphicsFactory, configuration );
125 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
127 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
128 Dali::Adaptor* adaptor = New( graphicsFactory, window, windowImpl.GetSurface(), configuration, environmentOptions );
129 windowImpl.SetAdaptor( *adaptor );
133 void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration::ContextLoss configuration )
135 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
136 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
137 mEnvironmentOptions->SetLogFunction( logFunction );
138 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
140 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
143 GetDataStoragePath( path );
144 mPlatformAbstraction->SetDataStoragePath( path );
146 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
147 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
149 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
152 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from files automatically.
154 if( mEnvironmentOptions->PerformanceServerRequired() )
156 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
159 mEnvironmentOptions->CreateTraceManager( mPerformanceInterface );
160 mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
162 mCallbackManager = CallbackManager::New();
164 Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
166 DALI_ASSERT_DEBUG( defaultWindow->GetSurface() && "Surface not initialized" );
168 mGraphics = &( graphicsFactory.Create() );
169 mGraphics->Initialize( mEnvironmentOptions );
171 auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
173 // This will only be created once
174 eglGraphics->Create();
176 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
177 EglSyncImplementation& eglSyncImpl = eglGraphics->GetSyncImplementation();
178 EglContextHelperImplementation& eglContextHelperImpl = eglGraphics->GetContextHelperImplementation();
180 mCore = Integration::Core::New( *this,
181 *mPlatformAbstraction,
184 eglContextHelperImpl,
185 dataRetentionPolicy ,
186 ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
187 mGraphics->GetDepthBufferRequired(),
188 mGraphics->GetStencilBufferRequired() );
190 defaultWindow->SetAdaptor( Get() );
192 Dali::Integration::SceneHolder defaultSceneHolder( defaultWindow );
194 mWindowCreatedSignal.Emit( defaultSceneHolder );
196 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
197 if( 0u < timeInterval )
199 mObjectProfiler = new ObjectProfiler( timeInterval );
202 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
204 mDisplayConnection = Dali::DisplayConnection::New( *mGraphics, defaultWindow->GetSurface()->GetSurfaceType() );
206 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
208 // Should be called after Core creation
209 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
211 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
213 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
215 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
217 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
219 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
221 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
223 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
225 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
227 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
229 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
231 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
233 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
235 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
237 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
239 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
241 if( mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0 )
243 Integration::SetPanGestureUseActualTimes( mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false );
245 if( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0 )
247 Integration::SetPanGestureInterpolationTimeRange( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() );
249 if( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0 )
251 Integration::SetPanGestureScalarOnlyPredictionEnabled( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false );
253 if( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0 )
255 Integration::SetPanGestureTwoPointPredictionEnabled( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false );
257 if( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0 )
259 Integration::SetPanGestureTwoPointInterpolatePastTime( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() );
261 if( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f )
263 Integration::SetPanGestureTwoPointVelocityBias( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() );
265 if( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f )
267 Integration::SetPanGestureTwoPointAccelerationBias( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() );
269 if( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0 )
271 Integration::SetPanGestureMultitapSmoothingRange( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() );
273 if( mEnvironmentOptions->GetMinimumPanDistance() >= 0 )
275 Integration::SetPanGestureMinimumDistance( mEnvironmentOptions->GetMinimumPanDistance() );
277 if( mEnvironmentOptions->GetMinimumPanEvents() >= 0 )
279 Integration::SetPanGestureMinimumPanEvents( mEnvironmentOptions->GetMinimumPanEvents() );
281 if( mEnvironmentOptions->GetMinimumPinchDistance() >= 0 )
283 Integration::SetPinchGestureMinimumDistance( mEnvironmentOptions->GetMinimumPinchDistance() );
286 // Set max texture size
287 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
289 Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
292 std::string systemCachePath = GetSystemCachePath();
293 if ( ! systemCachePath.empty() )
295 Dali::FileStream fileStream( systemCachePath + "gpu-environment.conf", Dali::FileStream::READ | Dali::FileStream::TEXT );
296 std::fstream& stream = dynamic_cast<std::fstream&>( fileStream.GetStream() );
297 if( stream.is_open() )
300 while( std::getline( stream, line ) )
302 line.erase( line.find_last_not_of( " \t\r\n" ) + 1 );
303 line.erase( 0, line.find_first_not_of( " \t\r\n" ) );
304 if( '#' == *( line.cbegin() ) || line == "" )
309 std::istringstream stream( line );
310 std::string environmentVariableName, environmentVariableValue;
311 std::getline(stream, environmentVariableName, ' ');
312 if( environmentVariableName == "DALI_ENV_MAX_TEXTURE_SIZE" && mEnvironmentOptions->GetMaxTextureSize() == 0 )
314 std::getline(stream, environmentVariableValue);
315 setenv( environmentVariableName.c_str() , environmentVariableValue.c_str(), 1 );
316 Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( std::atoi( environmentVariableValue.c_str() ) );
322 DALI_LOG_ERROR( "Fail to open file : %s\n", ( systemCachePath + "gpu-environment.conf" ).c_str() );
329 // Ensure stop status
332 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
333 gThreadLocalAdaptor = NULL;
335 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
337 (*iter)->OnDestroy();
340 // Clear out all the handles to Windows
343 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
344 delete mObjectProfiler;
348 delete mDisplayConnection;
349 delete mPlatformAbstraction;
350 delete mCallbackManager;
351 delete mPerformanceInterface;
353 mGraphics->Destroy();
355 // uninstall it on this thread (main actor thread)
356 Dali::Integration::Log::UninstallLogFunction();
358 // Delete environment options if we own it
359 if( mEnvironmentOptionsOwned )
361 delete mEnvironmentOptions;
365 void Adaptor::Start()
367 // It doesn't support restart after stop at this moment to support restarting, need more testing
368 if( READY != mState )
375 SetupSystemInformation();
377 // Start the callback manager
378 mCallbackManager->Start();
380 Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
382 unsigned int dpiHor, dpiVer;
385 defaultWindow->GetSurface()->GetDpi( dpiHor, dpiVer );
387 // set the DPI value for font rendering
388 FontClient fontClient = FontClient::Get();
389 fontClient.SetDpi( dpiHor, dpiVer );
391 // Initialize the thread controller
392 mThreadController->Initialize();
394 if( !Dali::TizenPlatform::ImageLoader::MaxTextureSizeUpdated() )
396 auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
397 GlImplementation& mGLES = eglGraphics->GetGlesInterface();
398 Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( mGLES.GetMaxTextureSize() );
400 std::string systemCachePath = GetSystemCachePath();
401 if( ! systemCachePath.empty() )
403 const int dir_err = system( std::string( "mkdir " + systemCachePath ).c_str() );
406 printf("Error creating directory!n");
410 Dali::FileStream fileStream( systemCachePath + "gpu-environment.conf", Dali::FileStream::WRITE | Dali::FileStream::TEXT );
411 std::fstream& configFile = dynamic_cast<std::fstream&>( fileStream.GetStream() );
412 if( configFile.is_open() )
414 configFile << "DALI_ENV_MAX_TEXTURE_SIZE " << mGLES.GetMaxTextureSize() << std::endl;
419 ProcessCoreEvents(); // Ensure any startup messages are processed.
421 // Initialize the image loader plugin
422 Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
424 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
430 // Dali::Internal::Adaptor::Adaptor::Pause
431 void Adaptor::Pause()
433 // Only pause the adaptor if we're actually running.
434 if( RUNNING == mState )
436 // Inform observers that we are about to be paused.
437 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
442 // Pause all windows event handlers when adaptor paused
443 for( auto window : mWindows )
448 mThreadController->Pause();
451 // Ensure any messages queued during pause callbacks are processed by doing another update.
454 DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Paused\n" );
458 DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Not paused [%d]\n", mState );
462 // Dali::Internal::Adaptor::Adaptor::Resume
463 void Adaptor::Resume()
465 // Only resume the adaptor if we are in the suspended state.
466 if( PAUSED == mState )
470 // Reset the event handlers when adaptor resumed
471 for( auto window : mWindows )
476 // Inform observers that we have resumed.
477 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
482 // Trigger processing of events queued up while paused
483 mCore->ProcessEvents();
485 // Do at end to ensure our first update/render after resumption includes the processed messages as well
486 mThreadController->Resume();
488 DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Resumed\n");
492 DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Not resumed [%d]\n", mState );
498 if( RUNNING == mState ||
500 PAUSED_WHILE_HIDDEN == mState )
502 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
507 mThreadController->Stop();
509 // Delete the TTS player
510 for( int i =0; i < Dali::TtsPlayer::MODE_NUM; i++ )
514 mTtsPlayers[i].Reset();
518 // Destroy the image loader plugin
519 Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
521 delete mNotificationTrigger;
522 mNotificationTrigger = NULL;
524 mCallbackManager->Stop();
528 DALI_LOG_RELEASE_INFO( "Adaptor::Stop\n" );
532 void Adaptor::ContextLost()
534 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
537 void Adaptor::ContextRegained()
539 // Inform core, so that texture resources can be reloaded
540 mCore->RecoverFromContextLoss();
542 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
545 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
547 Integration::Point convertedPoint( point );
548 mWindows.front()->FeedTouchPoint( convertedPoint, timeStamp );
551 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
553 Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
554 mWindows.front()->FeedWheelEvent( event );
557 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
559 Integration::KeyEvent convertedEvent( keyEvent );
560 mWindows.front()->FeedKeyEvent( convertedEvent );
563 void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface )
565 Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation( window );
566 for( auto windowPtr : mWindows )
568 if( windowPtr == windowImpl ) // the window is not deleted
570 mResizedSignal.Emit( mAdaptor );
572 windowImpl->SetSurface( &newSurface );
574 // Flush the event queue to give the update-render thread chance
575 // to start processing messages for new camera setup etc as soon as possible
578 // This method blocks until the render thread has completed the replace.
579 mThreadController->ReplaceSurface( &newSurface );
585 void Adaptor::DeleteSurface( Dali::RenderSurfaceInterface& surface )
587 // Flush the event queue to give the update-render thread chance
588 // to start processing messages for new camera setup etc as soon as possible
591 // This method blocks until the render thread has finished rendering the current surface.
592 mThreadController->DeleteSurface( &surface );
595 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
597 return *mWindows.front()->GetSurface();
600 void Adaptor::ReleaseSurfaceLock()
602 mWindows.front()->GetSurface()->ReleaseLock();
605 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
607 if( !mTtsPlayers[mode] )
609 // Create the TTS player when it needed, because it can reduce launching time.
610 mTtsPlayers[mode] = TtsPlayer::New(mode);
613 return mTtsPlayers[mode];
616 bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue, bool forceAdd )
618 bool idleAdded(false);
620 // Only add an idle if the Adaptor is actually running
621 if( RUNNING == mState || READY == mState || forceAdd )
623 idleAdded = mCallbackManager->AddIdleCallback( callback, hasReturnValue );
629 void Adaptor::RemoveIdle( CallbackBase* callback )
631 mCallbackManager->RemoveIdleCallback( callback );
634 void Adaptor::SetPreRenderCallback( CallbackBase* callback )
636 mThreadController->SetPreRenderCallback( callback );
639 bool Adaptor::AddWindow( Dali::Integration::SceneHolder childWindow, const std::string& childWindowName, const std::string& childWindowClassName, bool childWindowMode )
641 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( childWindow );
642 windowImpl.SetAdaptor( Get() );
644 // Add the new Window to the container - the order is not important
645 mWindows.push_back( &windowImpl );
647 mWindowCreatedSignal.Emit( childWindow );
652 bool Adaptor::RemoveWindow( Dali::Integration::SceneHolder* childWindow )
654 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( *childWindow );
655 for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
657 if( *iter == &windowImpl )
659 mWindows.erase( iter );
667 bool Adaptor::RemoveWindow( std::string childWindowName )
669 for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
671 if( ( *iter )->GetName() == childWindowName )
673 mWindows.erase( iter );
681 bool Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* childWindow )
683 for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
685 if( ( *iter )->GetId() == childWindow->GetId() )
687 mWindows.erase( iter );
695 Dali::Adaptor& Adaptor::Get()
697 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
698 return gThreadLocalAdaptor->mAdaptor;
701 bool Adaptor::IsAvailable()
703 return gThreadLocalAdaptor != NULL;
706 void Adaptor::SceneCreated()
708 mCore->SceneCreated();
711 Dali::Integration::Core& Adaptor::GetCore()
716 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
718 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
721 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
723 DALI_ASSERT_DEBUG( mDisplayConnection && "Display connection not created" );
724 return *mDisplayConnection;
727 GraphicsInterface& Adaptor::GetGraphicsInterface()
729 DALI_ASSERT_DEBUG( mGraphics && "Graphics interface not created" );
733 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
735 return *mPlatformAbstraction;
738 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
740 return *mNotificationTrigger;
743 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
745 return mTriggerEventFactory;
748 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
750 return mSocketFactory;
753 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
755 if( !mWindows.empty() )
757 return mWindows.front()->GetSurface();
763 TraceInterface& Adaptor::GetKernelTraceInterface()
765 return mKernelTracer;
768 TraceInterface& Adaptor::GetSystemTraceInterface()
770 return mSystemTracer;
773 PerformanceInterface* Adaptor::GetPerformanceInterface()
775 return mPerformanceInterface;
778 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
780 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
781 return *mPlatformAbstraction;
784 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
786 if( mTtsPlayers[mode] )
788 mTtsPlayers[mode].Reset();
792 Any Adaptor::GetNativeWindowHandle()
794 return mWindows.front()->GetNativeHandle();
797 Any Adaptor::GetNativeWindowHandle( Dali::Actor actor )
799 Any nativeWindowHandle;
801 Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
803 for( auto sceneHolder : mWindows )
805 if ( scene == sceneHolder->GetScene() )
807 nativeWindowHandle = sceneHolder->GetNativeHandle();
812 return nativeWindowHandle;
815 Any Adaptor::GetGraphicsDisplay()
821 auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
823 EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
824 display = eglImpl.GetDisplay();
830 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
832 mUseRemoteSurface = useRemoteSurface;
835 void Adaptor::AddObserver( LifeCycleObserver& observer )
837 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
839 if ( match == mObservers.end() )
841 mObservers.push_back( &observer );
845 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
847 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
849 if ( match != mObservers.end() )
851 mObservers.erase( match );
855 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
859 mCore->QueueEvent(event);
863 void Adaptor::ProcessCoreEvents()
867 if( mPerformanceInterface )
869 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
872 mCore->ProcessEvents();
874 if( mPerformanceInterface )
876 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
881 void Adaptor::RequestUpdate( bool forceUpdate )
887 mThreadController->RequestUpdate();
891 case PAUSED_WHILE_HIDDEN:
895 // Update (and resource upload) without rendering
896 mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
908 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
910 // Only request a notification if the Adaptor is actually running
911 // and we haven't installed the idle notification
912 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
914 mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
918 void Adaptor::OnWindowShown()
920 if( PAUSED_WHILE_HIDDEN == mState )
922 // Adaptor can now be resumed
927 // Force a render task
930 else if( RUNNING == mState )
932 // Force a render task
935 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
939 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
943 void Adaptor::OnWindowHidden()
945 if( RUNNING == mState || READY == mState )
947 bool allWindowsHidden = true;
949 for( auto window : mWindows )
951 if ( window->IsVisible() )
953 allWindowsHidden = false;
958 // Only pause the adaptor when all the windows are hidden
959 if( allWindowsHidden )
961 if( mState == RUNNING )
965 // Adaptor cannot be resumed until any window is shown
966 mState = PAUSED_WHILE_HIDDEN;
968 else // mState is READY
970 // Pause the adaptor after the state gets RUNNING
971 mState = PAUSED_WHILE_INITIALIZING;
976 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
981 DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
985 // Dali::Internal::Adaptor::Adaptor::OnDamaged
986 void Adaptor::OnDamaged( const DamageArea& area )
988 // This is needed for the case where Dali window is partially obscured
989 RequestUpdate( false );
992 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
994 mResizedSignal.Emit( mAdaptor );
997 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
999 // Flush the event queue to give the update-render thread chance
1000 // to start processing messages for new camera setup etc as soon as possible
1001 ProcessCoreEvents();
1003 mThreadController->ResizeSurface();
1006 void Adaptor::NotifySceneCreated()
1008 GetCore().SceneCreated();
1010 // Flush the event queue to give the update-render thread chance
1011 // to start processing messages for new camera setup etc as soon as possible
1012 ProcessCoreEvents();
1014 // Start thread controller after the scene has been created
1015 mThreadController->Start();
1017 // Process after surface is created (registering to remote surface provider if required)
1018 SurfaceInitialized();
1020 if( mState != PAUSED_WHILE_INITIALIZING )
1024 DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
1032 mState = PAUSED_WHILE_HIDDEN;
1034 DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1038 void Adaptor::NotifyLanguageChanged()
1040 mLanguageChangedSignal.Emit( mAdaptor );
1043 void Adaptor::RenderOnce()
1045 RequestUpdateOnce();
1048 const LogFactoryInterface& Adaptor::GetLogFactory()
1050 return *mEnvironmentOptions;
1053 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1055 GetCore().RegisterProcessor(processor);
1058 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1060 GetCore().UnregisterProcessor(processor);
1063 bool Adaptor::IsMultipleWindowSupported() const
1065 auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
1066 EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
1067 bool ret = eglImpl.IsSurfacelessContextSupported();
1071 void Adaptor::RequestUpdateOnce()
1073 if( mThreadController )
1075 mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1079 bool Adaptor::ProcessCoreEventsFromIdle()
1081 ProcessCoreEvents();
1083 // the idle handle automatically un-installs itself
1084 mNotificationOnIdleInstalled = false;
1089 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1091 Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1093 for( auto window : mWindows )
1095 if ( scene == window->GetScene() )
1104 Dali::WindowContainer Adaptor::GetWindows() const
1106 Dali::WindowContainer windows;
1108 for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1110 // Downcast to Dali::Window
1111 Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1114 windows.push_back( window );
1121 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1123 Dali::SceneHolderList sceneHolderList;
1125 for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1127 sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1130 return sceneHolderList;
1133 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1135 mLanguageChangedSignal(),
1136 mWindowCreatedSignal(),
1137 mAdaptor( adaptor ),
1140 mThreadController( nullptr ),
1141 mGraphics( nullptr ),
1142 mDisplayConnection( nullptr ),
1144 mPlatformAbstraction( nullptr ),
1145 mCallbackManager( nullptr ),
1146 mNotificationOnIdleInstalled( false ),
1147 mNotificationTrigger( nullptr ),
1148 mDaliFeedbackPlugin(),
1149 mFeedbackController( nullptr ),
1152 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1153 mPerformanceInterface( nullptr ),
1156 mTriggerEventFactory(),
1157 mObjectProfiler( nullptr ),
1159 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1160 mUseRemoteSurface( false )
1162 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1163 mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1165 gThreadLocalAdaptor = this;
1168 void Adaptor::SetRootLayoutDirection( std::string locale )
1170 Dali::Stage stage = Dali::Stage::GetCurrent();
1172 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1173 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1176 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1178 bool idleAdded( false );
1180 // Only add an idle if the Adaptor is actually running
1181 if( RUNNING == mState || READY == mState || forceAdd )
1183 idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1189 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1191 mCallbackManager->RemoveIdleEntererCallback( callback );
1194 } // namespace Adaptor
1196 } // namespace Internal