2 * Copyright (c) 2017 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 "adaptor-impl.h"
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/public-api/common/stage.h>
24 #include <dali/public-api/actors/layer.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/integration-api/debug.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/integration-api/context-notifier.h>
29 #include <dali/integration-api/profiling.h>
30 #include <dali/integration-api/input-options.h>
31 #include <dali/integration-api/events/touch-event-integ.h>
34 #include <base/thread-controller.h>
35 #include <base/performance-logging/performance-interface-factory.h>
36 #include <base/lifecycle-observer.h>
38 #include <dali/devel-api/text-abstraction/font-client.h>
40 #include <callback-manager.h>
41 #include <render-surface.h>
42 #include <tts-player-impl.h>
43 #include <accessibility-adaptor-impl.h>
44 #include <events/gesture-manager.h>
45 #include <events/event-handler.h>
46 #include <gl/gl-proxy-implementation.h>
47 #include <gl/gl-implementation.h>
48 #include <gl/egl-sync-implementation.h>
49 #include <gl/egl-image-extensions.h>
50 #include <gl/egl-factory.h>
51 #include <imf-manager-impl.h>
52 #include <clipboard-impl.h>
53 #include <vsync-monitor.h>
54 #include <object-profiler.h>
55 #include <base/display-connection.h>
56 #include <window-impl.h>
58 #include <tizen-logging.h>
59 #include <image-loading.h>
61 #include <locale-utils.h>
63 using Dali::TextAbstraction::FontClient;
76 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
77 } // unnamed namespace
79 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
81 Dali::Adaptor* adaptor = new Dali::Adaptor;
82 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
83 adaptor->mImpl = impl;
85 impl->Initialize(configuration);
90 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
92 Any winId = window.GetNativeHandle();
94 Window& windowImpl = Dali::GetImplementation(window);
95 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
97 Internal::Adaptor::Adaptor::GetImplementation( *adaptor ).SetWindow( window );
98 windowImpl.SetAdaptor(*adaptor);
102 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
104 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
105 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
106 mEnvironmentOptions->SetLogFunction( logFunction );
107 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
109 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
112 GetDataStoragePath( path );
113 mPlatformAbstraction->SetDataStoragePath( path );
115 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
116 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
118 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
120 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
121 // files automatically.
123 if( mEnvironmentOptions->PerformanceServerRequired() )
125 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
128 mCallbackManager = CallbackManager::New();
130 PositionSize size = mSurface->GetPositionSize();
132 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
134 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
136 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
140 mGLES = new GlImplementation();
143 mEglFactory = new EglFactory( mEnvironmentOptions->GetMultiSamplingLevel() );
145 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
147 mCore = Integration::Core::New( *this,
148 *mPlatformAbstraction,
152 dataRetentionPolicy ,
153 0u != mEnvironmentOptions->GetRenderToFboInterval() );
155 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
156 if( 0u < timeInterval )
158 mObjectProfiler = new ObjectProfiler( timeInterval );
161 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
163 mVSyncMonitor = new VSyncMonitor;
165 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
167 // Should be called after Core creation
168 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
170 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
172 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
174 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
176 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
178 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
180 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
182 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
184 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
186 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
188 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
190 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
192 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
194 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
196 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
198 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
201 // Set max texture size
202 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
204 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
207 SetupSystemInformation();
212 // Ensure stop status
215 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
216 gThreadLocalAdaptor = NULL;
218 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
220 (*iter)->OnDestroy();
223 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
224 delete mVSyncMonitor;
225 delete mEventHandler;
226 delete mObjectProfiler;
231 delete mGestureManager;
232 delete mPlatformAbstraction;
233 delete mCallbackManager;
234 delete mPerformanceInterface;
236 // uninstall it on this thread (main actor thread)
237 Dali::Integration::Log::UninstallLogFunction();
239 // Delete environment options if we own it
240 if( mEnvironmentOptionsOwned )
242 delete mEnvironmentOptions;
246 void Adaptor::Start()
248 // it doesn't support restart after stop at this moment
249 // to support restarting, need more testing
250 if( READY != mState )
255 // Start the callback manager
256 mCallbackManager->Start();
258 // create event handler
259 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
261 if( mDeferredRotationObserver != NULL )
263 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
264 mDeferredRotationObserver = NULL;
267 unsigned int dpiHor, dpiVer;
269 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
271 // tell core about the DPI value
272 mCore->SetDpi(dpiHor, dpiVer);
274 // set the DPI value for font rendering
275 FontClient fontClient = FontClient::Get();
276 fontClient.SetDpi( dpiHor, dpiVer );
278 // Tell the core the size of the surface just before we start the render-thread
279 PositionSize size = mSurface->GetPositionSize();
280 mCore->SurfaceResized( size.width, size.height );
282 // Initialize the thread controller
283 mThreadController->Initialize();
285 ProcessCoreEvents(); // Ensure any startup messages are processed.
287 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
293 // Dali::Internal::Adaptor::Adaptor::Pause
294 void Adaptor::Pause()
296 // Only pause the adaptor if we're actually running.
297 if( RUNNING == mState )
299 // Inform observers that we are about to be paused.
300 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
305 // Reset the event handler when adaptor paused
308 mEventHandler->Pause();
311 mThreadController->Pause();
314 // Process remained events and rendering in the update thread
319 // Dali::Internal::Adaptor::Adaptor::Resume
320 void Adaptor::Resume()
322 // Only resume the adaptor if we are in the suspended state.
323 if( PAUSED == mState )
327 // Reset the event handler when adaptor resumed
330 mEventHandler->Resume();
333 // Inform observers that we have resumed.
334 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
339 // trigger processing of events queued up while paused
340 mCore->ProcessEvents();
342 // Do at end to ensure our first update/render after resumption includes the processed messages as well
343 mThreadController->Resume();
349 if( RUNNING == mState ||
351 PAUSED_WHILE_HIDDEN == mState )
353 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
358 mThreadController->Stop();
360 // Delete the TTS player
361 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
365 mTtsPlayers[i].Reset();
369 delete mEventHandler;
370 mEventHandler = NULL;
372 delete mNotificationTrigger;
373 mNotificationTrigger = NULL;
375 mCallbackManager->Stop();
381 void Adaptor::ContextLost()
383 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
386 void Adaptor::ContextRegained()
388 // Inform core, so that texture resources can be reloaded
389 mCore->RecoverFromContextLoss();
391 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
394 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
396 mEventHandler->FeedTouchPoint( point, timeStamp );
399 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
401 mEventHandler->FeedWheelEvent( wheelEvent );
404 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
406 mEventHandler->FeedKeyEvent( keyEvent );
409 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
411 PositionSize positionSize = surface.GetPositionSize();
413 // let the core know the surface size has changed
414 mCore->SurfaceResized( positionSize.width, positionSize.height );
416 mResizedSignal.Emit( mAdaptor );
418 mNativeWindow = nativeWindow;
421 // flush the event queue to give the update-render thread chance
422 // to start processing messages for new camera setup etc as soon as possible
425 // this method blocks until the render thread has completed the replace.
426 mThreadController->ReplaceSurface(mSurface);
429 RenderSurface& Adaptor::GetSurface() const
434 void Adaptor::ReleaseSurfaceLock()
436 mSurface->ReleaseLock();
439 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
441 if(!mTtsPlayers[mode])
443 // Create the TTS player when it needed, because it can reduce launching time.
444 mTtsPlayers[mode] = TtsPlayer::New(mode);
447 return mTtsPlayers[mode];
450 bool Adaptor::AddIdle( CallbackBase* callback, bool forceAdd )
452 bool idleAdded(false);
454 // Only add an idle if the Adaptor is actually running
455 if( RUNNING == mState || forceAdd )
457 idleAdded = mCallbackManager->AddIdleCallback( callback );
463 void Adaptor::RemoveIdle( CallbackBase* callback )
465 mCallbackManager->RemoveIdleCallback( callback );
468 Dali::Adaptor& Adaptor::Get()
470 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
471 return gThreadLocalAdaptor->mAdaptor;
474 bool Adaptor::IsAvailable()
476 return gThreadLocalAdaptor != NULL;
479 void Adaptor::SceneCreated()
481 mCore->SceneCreated();
484 Dali::Integration::Core& Adaptor::GetCore()
489 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
491 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
494 void Adaptor::SetUseHardwareVSync( bool useHardware )
496 mVSyncMonitor->SetUseHardwareVSync( useHardware );
499 EglFactory& Adaptor::GetEGLFactory() const
501 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
505 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
510 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
512 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
516 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
518 return *mPlatformAbstraction;
521 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
526 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
528 return *mNotificationTrigger;
531 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
533 return mTriggerEventFactory;
536 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
538 return mSocketFactory;
541 RenderSurface* Adaptor::GetRenderSurfaceInterface()
546 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
548 return mVSyncMonitor;
551 TraceInterface& Adaptor::GetKernelTraceInterface()
553 return mKernelTracer;
556 TraceInterface& Adaptor::GetSystemTraceInterface()
558 return mSystemTracer;
561 PerformanceInterface* Adaptor::GetPerformanceInterface()
563 return mPerformanceInterface;
566 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
568 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
569 return *mPlatformAbstraction;
572 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
574 mDragAndDropDetector = detector;
578 mEventHandler->SetDragAndDropDetector( detector );
582 void Adaptor::SetRotationObserver( RotationObserver* observer )
586 mEventHandler->SetRotationObserver( observer );
588 else if( mState == READY )
590 // Set once event handler exists
591 mDeferredRotationObserver = observer;
595 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
597 if(mTtsPlayers[mode])
599 mTtsPlayers[mode].Reset();
603 void Adaptor::SetMinimumPinchDistance(float distance)
605 if( mGestureManager )
607 mGestureManager->SetMinimumPinchDistance(distance);
611 Any Adaptor::GetNativeWindowHandle()
613 return mNativeWindow;
616 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
618 mUseRemoteSurface = useRemoteSurface;
621 void Adaptor::AddObserver( LifeCycleObserver& observer )
623 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
625 if ( match == mObservers.end() )
627 mObservers.push_back( &observer );
631 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
633 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
635 if ( match != mObservers.end() )
637 mObservers.erase( match );
641 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
645 mCore->QueueEvent(event);
649 void Adaptor::ProcessCoreEvents()
653 if( mPerformanceInterface )
655 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
658 mCore->ProcessEvents();
660 if( mPerformanceInterface )
662 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
667 void Adaptor::RequestUpdate( bool forceUpdate )
673 mThreadController->RequestUpdate();
677 case PAUSED_WHILE_HIDDEN:
679 // When Dali applications are partially visible behind the lock-screen,
680 // the indicator must be updated (therefore allow updates in the PAUSED state)
683 mThreadController->RequestUpdateOnce();
695 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
697 // Only request a notification if the Adaptor is actually running
698 // and we haven't installed the idle notification
699 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || forceProcess ) )
701 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
705 void Adaptor::OnWindowShown()
707 if ( PAUSED_WHILE_HIDDEN == mState )
709 // Adaptor can now be resumed
714 // Force a render task
719 void Adaptor::OnWindowHidden()
721 if ( RUNNING == mState )
725 // Adaptor cannot be resumed until the window is shown
726 mState = PAUSED_WHILE_HIDDEN;
730 // Dali::Internal::Adaptor::Adaptor::OnDamaged
731 void Adaptor::OnDamaged( const DamageArea& area )
733 // This is needed for the case where Dali window is partially obscured
734 RequestUpdate( false );
737 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
739 // let the core know the surface size has changed
740 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
742 mResizedSignal.Emit( mAdaptor );
745 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
747 // flush the event queue to give the update-render thread chance
748 // to start processing messages for new camera setup etc as soon as possible
751 // this method blocks until the render thread has completed the resizing.
752 mThreadController->ResizeSurface();
755 void Adaptor::NotifySceneCreated()
757 GetCore().SceneCreated();
759 // Start thread controller after the scene has been created
760 mThreadController->Start();
762 // process after surface is created (registering to remote surface provider if required)
763 SurfaceInitialized();
768 void Adaptor::NotifyLanguageChanged()
770 mLanguageChangedSignal.Emit( mAdaptor );
773 void Adaptor::RenderOnce()
778 void Adaptor::RequestUpdateOnce()
780 if( mThreadController )
782 mThreadController->RequestUpdateOnce();
786 void Adaptor::IndicatorSizeChanged(int height)
788 // let the core know the indicator height is changed
789 mCore->SetTopMargin(height);
792 void Adaptor::ProcessCoreEventsFromIdle()
796 // the idle handle automatically un-installs itself
797 mNotificationOnIdleInstalled = false;
800 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
802 mLanguageChangedSignal(),
806 mThreadController( NULL ),
807 mVSyncMonitor( NULL ),
811 mNativeWindow( nativeWindow ),
813 mPlatformAbstraction( NULL ),
814 mEventHandler( NULL ),
815 mCallbackManager( NULL ),
816 mNotificationOnIdleInstalled( false ),
817 mNotificationTrigger( NULL ),
818 mGestureManager( NULL ),
819 mDaliFeedbackPlugin(),
820 mFeedbackController( NULL ),
823 mDragAndDropDetector(),
824 mDeferredRotationObserver( NULL ),
825 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
826 mPerformanceInterface( NULL ),
829 mTriggerEventFactory(),
830 mObjectProfiler( NULL ),
833 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
834 mUseRemoteSurface( false )
836 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
837 gThreadLocalAdaptor = this;
842 void Adaptor::SetViewMode( ViewMode viewMode )
844 mSurface->SetViewMode( viewMode );
845 mCore->SetViewMode( viewMode );
848 ViewMode Adaptor::GetViewMode() const
850 return mCore->GetViewMode();
853 void Adaptor::SetStereoBase( float stereoBase )
855 mCore->SetStereoBase( stereoBase );
858 float Adaptor::GetStereoBase() const
860 return mCore->GetStereoBase();
863 void Adaptor::SetRootLayoutDirection( std::string locale )
865 Dali::Stage stage = Dali::Stage::GetCurrent();
867 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
868 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
871 void Adaptor::SetWindow( Dali::Window window )
876 Dali::Window Adaptor::GetWindow()
881 } // namespace Adaptor
883 } // namespace Internal