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, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
149 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
150 if( 0u < timeInterval )
152 mObjectProfiler = new ObjectProfiler( timeInterval );
155 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
157 mVSyncMonitor = new VSyncMonitor;
159 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
161 // Should be called after Core creation
162 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
164 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
166 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
168 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
170 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
172 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
174 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
176 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
178 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
180 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
182 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
184 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
186 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
188 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
190 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
192 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
195 // Set max texture size
196 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
198 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
201 SetupSystemInformation();
206 // Ensure stop status
209 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
210 gThreadLocalAdaptor = NULL;
212 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
214 (*iter)->OnDestroy();
217 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
218 delete mVSyncMonitor;
219 delete mEventHandler;
220 delete mObjectProfiler;
225 delete mGestureManager;
226 delete mPlatformAbstraction;
227 delete mCallbackManager;
228 delete mPerformanceInterface;
230 // uninstall it on this thread (main actor thread)
231 Dali::Integration::Log::UninstallLogFunction();
233 // Delete environment options if we own it
234 if( mEnvironmentOptionsOwned )
236 delete mEnvironmentOptions;
240 void Adaptor::Start()
242 // it doesn't support restart after stop at this moment
243 // to support restarting, need more testing
244 if( READY != mState )
249 // Start the callback manager
250 mCallbackManager->Start();
252 // create event handler
253 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
255 if( mDeferredRotationObserver != NULL )
257 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
258 mDeferredRotationObserver = NULL;
261 unsigned int dpiHor, dpiVer;
263 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
265 // tell core about the DPI value
266 mCore->SetDpi(dpiHor, dpiVer);
268 // set the DPI value for font rendering
269 FontClient fontClient = FontClient::Get();
270 fontClient.SetDpi( dpiHor, dpiVer );
272 // Tell the core the size of the surface just before we start the render-thread
273 PositionSize size = mSurface->GetPositionSize();
274 mCore->SurfaceResized( size.width, size.height );
276 // Initialize the thread controller
277 mThreadController->Initialize();
281 ProcessCoreEvents(); // Ensure any startup messages are processed.
283 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
289 // Dali::Internal::Adaptor::Adaptor::Pause
290 void Adaptor::Pause()
292 // Only pause the adaptor if we're actually running.
293 if( RUNNING == mState )
295 // Inform observers that we are about to be paused.
296 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
301 // Reset the event handler when adaptor paused
304 mEventHandler->Pause();
307 mThreadController->Pause();
310 // Process remained events and rendering in the update thread
315 // Dali::Internal::Adaptor::Adaptor::Resume
316 void Adaptor::Resume()
318 // Only resume the adaptor if we are in the suspended state.
319 if( PAUSED == mState )
323 // Reset the event handler when adaptor resumed
326 mEventHandler->Resume();
329 // Inform observers that we have resumed.
330 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
335 // trigger processing of events queued up while paused
336 mCore->ProcessEvents();
338 // Do at end to ensure our first update/render after resumption includes the processed messages as well
339 mThreadController->Resume();
345 if( RUNNING == mState ||
347 PAUSED_WHILE_HIDDEN == mState )
349 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
354 mThreadController->Stop();
356 // Delete the TTS player
357 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
361 mTtsPlayers[i].Reset();
365 delete mEventHandler;
366 mEventHandler = NULL;
368 delete mNotificationTrigger;
369 mNotificationTrigger = NULL;
371 mCallbackManager->Stop();
377 void Adaptor::ContextLost()
379 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
382 void Adaptor::ContextRegained()
384 // Inform core, so that texture resources can be reloaded
385 mCore->RecoverFromContextLoss();
387 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
390 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
392 mEventHandler->FeedTouchPoint( point, timeStamp );
395 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
397 mEventHandler->FeedWheelEvent( wheelEvent );
400 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
402 mEventHandler->FeedKeyEvent( keyEvent );
405 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
407 PositionSize positionSize = surface.GetPositionSize();
409 // let the core know the surface size has changed
410 mCore->SurfaceResized( positionSize.width, positionSize.height );
412 mResizedSignal.Emit( mAdaptor );
414 mNativeWindow = nativeWindow;
417 // flush the event queue to give the update-render thread chance
418 // to start processing messages for new camera setup etc as soon as possible
421 // this method blocks until the render thread has completed the replace.
422 mThreadController->ReplaceSurface(mSurface);
425 RenderSurface& Adaptor::GetSurface() const
430 void Adaptor::ReleaseSurfaceLock()
432 mSurface->ReleaseLock();
435 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
437 if(!mTtsPlayers[mode])
439 // Create the TTS player when it needed, because it can reduce launching time.
440 mTtsPlayers[mode] = TtsPlayer::New(mode);
443 return mTtsPlayers[mode];
446 bool Adaptor::AddIdle( CallbackBase* callback, bool forceAdd )
448 bool idleAdded(false);
450 // Only add an idle if the Adaptor is actually running
451 if( RUNNING == mState || forceAdd )
453 idleAdded = mCallbackManager->AddIdleCallback( callback );
459 void Adaptor::RemoveIdle( CallbackBase* callback )
461 mCallbackManager->RemoveIdleCallback( callback );
464 Dali::Adaptor& Adaptor::Get()
466 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
467 return gThreadLocalAdaptor->mAdaptor;
470 bool Adaptor::IsAvailable()
472 return gThreadLocalAdaptor != NULL;
475 void Adaptor::SceneCreated()
477 mCore->SceneCreated();
480 Dali::Integration::Core& Adaptor::GetCore()
485 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
487 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
490 void Adaptor::SetUseHardwareVSync( bool useHardware )
492 mVSyncMonitor->SetUseHardwareVSync( useHardware );
495 EglFactory& Adaptor::GetEGLFactory() const
497 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
501 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
506 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
508 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
512 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
514 return *mPlatformAbstraction;
517 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
522 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
524 return *mNotificationTrigger;
527 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
529 return mTriggerEventFactory;
532 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
534 return mSocketFactory;
537 RenderSurface* Adaptor::GetRenderSurfaceInterface()
542 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
544 return mVSyncMonitor;
547 TraceInterface& Adaptor::GetKernelTraceInterface()
549 return mKernelTracer;
552 TraceInterface& Adaptor::GetSystemTraceInterface()
554 return mSystemTracer;
557 PerformanceInterface* Adaptor::GetPerformanceInterface()
559 return mPerformanceInterface;
562 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
564 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
565 return *mPlatformAbstraction;
568 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
570 mDragAndDropDetector = detector;
574 mEventHandler->SetDragAndDropDetector( detector );
578 void Adaptor::SetRotationObserver( RotationObserver* observer )
582 mEventHandler->SetRotationObserver( observer );
584 else if( mState == READY )
586 // Set once event handler exists
587 mDeferredRotationObserver = observer;
591 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
593 if(mTtsPlayers[mode])
595 mTtsPlayers[mode].Reset();
599 void Adaptor::SetMinimumPinchDistance(float distance)
601 if( mGestureManager )
603 mGestureManager->SetMinimumPinchDistance(distance);
607 Any Adaptor::GetNativeWindowHandle()
609 return mNativeWindow;
612 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
614 mUseRemoteSurface = useRemoteSurface;
617 void Adaptor::AddObserver( LifeCycleObserver& observer )
619 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
621 if ( match == mObservers.end() )
623 mObservers.push_back( &observer );
627 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
629 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
631 if ( match != mObservers.end() )
633 mObservers.erase( match );
637 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
641 mCore->QueueEvent(event);
645 void Adaptor::ProcessCoreEvents()
649 if( mPerformanceInterface )
651 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
654 mCore->ProcessEvents();
656 if( mPerformanceInterface )
658 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
663 void Adaptor::RequestUpdate( bool forceUpdate )
669 mThreadController->RequestUpdate();
673 case PAUSED_WHILE_HIDDEN:
675 // When Dali applications are partially visible behind the lock-screen,
676 // the indicator must be updated (therefore allow updates in the PAUSED state)
679 mThreadController->RequestUpdateOnce();
691 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
693 // Only request a notification if the Adaptor is actually running
694 // and we haven't installed the idle notification
695 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || forceProcess ) )
697 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
701 void Adaptor::OnWindowShown()
703 if ( PAUSED_WHILE_HIDDEN == mState )
705 // Adaptor can now be resumed
710 // Force a render task
715 void Adaptor::OnWindowHidden()
717 if ( STOPPED != mState )
721 // Adaptor cannot be resumed until the window is shown
722 mState = PAUSED_WHILE_HIDDEN;
726 // Dali::Internal::Adaptor::Adaptor::OnDamaged
727 void Adaptor::OnDamaged( const DamageArea& area )
729 // This is needed for the case where Dali window is partially obscured
730 RequestUpdate( false );
733 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
735 // let the core know the surface size has changed
736 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
738 mResizedSignal.Emit( mAdaptor );
741 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
743 // flush the event queue to give the update-render thread chance
744 // to start processing messages for new camera setup etc as soon as possible
747 // this method blocks until the render thread has completed the resizing.
748 mThreadController->ResizeSurface();
751 void Adaptor::NotifySceneCreated()
753 GetCore().SceneCreated();
755 // Start thread controller after the scene has been created
756 mThreadController->Start();
758 // process after surface is created (registering to remote surface provider if required)
759 SurfaceInitialized();
762 void Adaptor::NotifyLanguageChanged()
764 mLanguageChangedSignal.Emit( mAdaptor );
767 void Adaptor::RenderOnce()
772 void Adaptor::RequestUpdateOnce()
774 if( mThreadController )
776 mThreadController->RequestUpdateOnce();
780 void Adaptor::IndicatorSizeChanged(int height)
782 // let the core know the indicator height is changed
783 mCore->SetTopMargin(height);
786 void Adaptor::ProcessCoreEventsFromIdle()
790 // the idle handle automatically un-installs itself
791 mNotificationOnIdleInstalled = false;
794 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
796 mLanguageChangedSignal(),
800 mThreadController( NULL ),
801 mVSyncMonitor( NULL ),
805 mNativeWindow( nativeWindow ),
807 mPlatformAbstraction( NULL ),
808 mEventHandler( NULL ),
809 mCallbackManager( NULL ),
810 mNotificationOnIdleInstalled( false ),
811 mNotificationTrigger( NULL ),
812 mGestureManager( NULL ),
813 mDaliFeedbackPlugin(),
814 mFeedbackController( NULL ),
817 mDragAndDropDetector(),
818 mDeferredRotationObserver( NULL ),
819 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
820 mPerformanceInterface( NULL ),
823 mTriggerEventFactory(),
824 mObjectProfiler( NULL ),
827 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
828 mUseRemoteSurface( false )
830 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
831 gThreadLocalAdaptor = this;
836 void Adaptor::SetViewMode( ViewMode viewMode )
838 mSurface->SetViewMode( viewMode );
839 mCore->SetViewMode( viewMode );
842 ViewMode Adaptor::GetViewMode() const
844 return mCore->GetViewMode();
847 void Adaptor::SetStereoBase( float stereoBase )
849 mCore->SetStereoBase( stereoBase );
852 float Adaptor::GetStereoBase() const
854 return mCore->GetStereoBase();
857 void Adaptor::SetRootLayoutDirection( std::string locale )
859 Dali::Stage stage = Dali::Stage::GetCurrent();
861 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
862 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
865 void Adaptor::SetWindow( Dali::Window window )
870 Dali::Window Adaptor::GetWindow()
875 } // namespace Adaptor
877 } // namespace Internal