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();
93 Window& windowImpl = Dali::GetImplementation(window);
94 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
95 windowImpl.SetAdaptor(*adaptor);
99 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
101 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
102 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
103 mEnvironmentOptions->SetLogFunction( logFunction );
104 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
106 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
109 GetDataStoragePath( path );
110 mPlatformAbstraction->SetDataStoragePath( path );
112 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
113 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
115 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
117 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
118 // files automatically.
120 if( mEnvironmentOptions->PerformanceServerRequired() )
122 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
125 mCallbackManager = CallbackManager::New();
127 PositionSize size = mSurface->GetPositionSize();
129 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
131 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
133 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
137 mGLES = new GlImplementation();
140 mEglFactory = new EglFactory( mEnvironmentOptions->GetMultiSamplingLevel() );
142 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
144 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
146 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
147 if( 0u < timeInterval )
149 mObjectProfiler = new ObjectProfiler( timeInterval );
152 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
154 mVSyncMonitor = new VSyncMonitor;
156 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
158 // Should be called after Core creation
159 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
161 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
163 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
165 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
167 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
169 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
171 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
173 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
175 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
177 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
179 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
181 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
183 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
185 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
187 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
189 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
192 // Set max texture size
193 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
195 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
198 SetupSystemInformation();
203 // Ensure stop status
206 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
207 gThreadLocalAdaptor = NULL;
209 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
211 (*iter)->OnDestroy();
214 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
215 delete mVSyncMonitor;
216 delete mEventHandler;
217 delete mObjectProfiler;
222 delete mGestureManager;
223 delete mPlatformAbstraction;
224 delete mCallbackManager;
225 delete mPerformanceInterface;
227 // uninstall it on this thread (main actor thread)
228 Dali::Integration::Log::UninstallLogFunction();
230 // Delete environment options if we own it
231 if( mEnvironmentOptionsOwned )
233 delete mEnvironmentOptions;
237 void Adaptor::Start()
239 // it doesn't support restart after stop at this moment
240 // to support restarting, need more testing
241 if( READY != mState )
246 // Start the callback manager
247 mCallbackManager->Start();
249 // create event handler
250 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
252 if( mDeferredRotationObserver != NULL )
254 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
255 mDeferredRotationObserver = NULL;
258 unsigned int dpiHor, dpiVer;
260 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
262 // tell core about the DPI value
263 mCore->SetDpi(dpiHor, dpiVer);
265 // set the DPI value for font rendering
266 FontClient fontClient = FontClient::Get();
267 fontClient.SetDpi( dpiHor, dpiVer );
269 // Tell the core the size of the surface just before we start the render-thread
270 PositionSize size = mSurface->GetPositionSize();
271 mCore->SurfaceResized( size.width, size.height );
273 // Initialize the thread controller
274 mThreadController->Initialize();
278 ProcessCoreEvents(); // Ensure any startup messages are processed.
280 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
286 // Dali::Internal::Adaptor::Adaptor::Pause
287 void Adaptor::Pause()
289 // Only pause the adaptor if we're actually running.
290 if( RUNNING == mState )
292 // Inform observers that we are about to be paused.
293 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
298 // Reset the event handler when adaptor paused
301 mEventHandler->Pause();
304 mThreadController->Pause();
308 // Process remained events and rendering in the update thread
313 // Dali::Internal::Adaptor::Adaptor::Resume
314 void Adaptor::Resume()
316 // Only resume the adaptor if we are in the suspended state.
317 if( PAUSED == mState )
321 // Reset the event handler when adaptor resumed
324 mEventHandler->Resume();
327 // Inform observers that we have resumed.
328 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
333 // Resume core so it processes any requests as well
336 // Do at end to ensure our first update/render after resumption includes the processed messages as well
337 mThreadController->Resume();
343 if( RUNNING == mState ||
345 PAUSED_WHILE_HIDDEN == mState )
347 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
352 mThreadController->Stop();
355 // Delete the TTS player
356 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
360 mTtsPlayers[i].Reset();
364 delete mEventHandler;
365 mEventHandler = NULL;
367 delete mNotificationTrigger;
368 mNotificationTrigger = NULL;
370 mCallbackManager->Stop();
376 void Adaptor::ContextLost()
378 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
381 void Adaptor::ContextRegained()
383 // Inform core, so that texture resources can be reloaded
384 mCore->RecoverFromContextLoss();
386 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
389 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
391 mEventHandler->FeedTouchPoint( point, timeStamp );
394 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
396 mEventHandler->FeedWheelEvent( wheelEvent );
399 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
401 mEventHandler->FeedKeyEvent( keyEvent );
404 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
406 PositionSize positionSize = surface.GetPositionSize();
408 // let the core know the surface size has changed
409 mCore->SurfaceResized( positionSize.width, positionSize.height );
411 mResizedSignal.Emit( mAdaptor );
413 mNativeWindow = nativeWindow;
416 // flush the event queue to give the update-render thread chance
417 // to start processing messages for new camera setup etc as soon as possible
420 // this method blocks until the render thread has completed the replace.
421 mThreadController->ReplaceSurface(mSurface);
424 RenderSurface& Adaptor::GetSurface() const
429 void Adaptor::ReleaseSurfaceLock()
431 mSurface->ReleaseLock();
434 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
436 if(!mTtsPlayers[mode])
438 // Create the TTS player when it needed, because it can reduce launching time.
439 mTtsPlayers[mode] = TtsPlayer::New(mode);
442 return mTtsPlayers[mode];
445 bool Adaptor::AddIdle( CallbackBase* callback )
447 bool idleAdded(false);
449 // Only add an idle if the Adaptor is actually running
450 if( RUNNING == mState )
452 idleAdded = mCallbackManager->AddIdleCallback( callback );
458 void Adaptor::RemoveIdle( CallbackBase* callback )
460 mCallbackManager->RemoveIdleCallback( callback );
463 Dali::Adaptor& Adaptor::Get()
465 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
466 return gThreadLocalAdaptor->mAdaptor;
469 bool Adaptor::IsAvailable()
471 return gThreadLocalAdaptor != NULL;
474 void Adaptor::SceneCreated()
476 mCore->SceneCreated();
479 Dali::Integration::Core& Adaptor::GetCore()
484 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
486 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
489 void Adaptor::SetUseHardwareVSync( bool useHardware )
491 mVSyncMonitor->SetUseHardwareVSync( useHardware );
494 EglFactory& Adaptor::GetEGLFactory() const
496 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
500 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
505 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
507 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
511 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
513 return *mPlatformAbstraction;
516 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
521 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
523 return *mNotificationTrigger;
526 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
528 return mTriggerEventFactory;
531 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
533 return mSocketFactory;
536 RenderSurface* Adaptor::GetRenderSurfaceInterface()
541 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
543 return mVSyncMonitor;
546 TraceInterface& Adaptor::GetKernelTraceInterface()
548 return mKernelTracer;
551 TraceInterface& Adaptor::GetSystemTraceInterface()
553 return mSystemTracer;
556 PerformanceInterface* Adaptor::GetPerformanceInterface()
558 return mPerformanceInterface;
561 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
563 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
564 return *mPlatformAbstraction;
567 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
569 mDragAndDropDetector = detector;
573 mEventHandler->SetDragAndDropDetector( detector );
577 void Adaptor::SetRotationObserver( RotationObserver* observer )
581 mEventHandler->SetRotationObserver( observer );
583 else if( mState == READY )
585 // Set once event handler exists
586 mDeferredRotationObserver = observer;
590 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
592 if(mTtsPlayers[mode])
594 mTtsPlayers[mode].Reset();
598 void Adaptor::SetMinimumPinchDistance(float distance)
600 if( mGestureManager )
602 mGestureManager->SetMinimumPinchDistance(distance);
606 Any Adaptor::GetNativeWindowHandle()
608 return mNativeWindow;
611 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
613 mUseRemoteSurface = useRemoteSurface;
616 void Adaptor::AddObserver( LifeCycleObserver& observer )
618 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
620 if ( match == mObservers.end() )
622 mObservers.push_back( &observer );
626 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
628 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
630 if ( match != mObservers.end() )
632 mObservers.erase( match );
636 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
640 mCore->QueueEvent(event);
644 void Adaptor::ProcessCoreEvents()
648 if( mPerformanceInterface )
650 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
653 mCore->ProcessEvents();
655 if( mPerformanceInterface )
657 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
662 void Adaptor::RequestUpdate()
664 // When Dali applications are partially visible behind the lock-screen,
665 // the indicator must be updated (therefore allow updates in the PAUSED state)
666 if ( PAUSED == mState ||
669 mThreadController->RequestUpdate();
673 void Adaptor::RequestProcessEventsOnIdle()
675 // Only request a notification if the Adaptor is actually running
676 // and we haven't installed the idle notification
677 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
679 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
683 void Adaptor::OnWindowShown()
685 if ( PAUSED_WHILE_HIDDEN == mState )
687 // Adaptor can now be resumed
692 // Force a render task
697 void Adaptor::OnWindowHidden()
699 if ( STOPPED != mState )
703 // Adaptor cannot be resumed until the window is shown
704 mState = PAUSED_WHILE_HIDDEN;
708 // Dali::Internal::Adaptor::Adaptor::OnDamaged
709 void Adaptor::OnDamaged( const DamageArea& area )
711 // This is needed for the case where Dali window is partially obscured
715 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
717 // let the core know the surface size has changed
718 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
720 mResizedSignal.Emit( mAdaptor );
723 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
725 // flush the event queue to give the update-render thread chance
726 // to start processing messages for new camera setup etc as soon as possible
729 // this method blocks until the render thread has completed the resizing.
730 mThreadController->ResizeSurface();
733 void Adaptor::NotifySceneCreated()
735 GetCore().SceneCreated();
737 // Start thread controller after the scene has been created
738 mThreadController->Start();
740 // process after surface is created (registering to remote surface provider if required)
741 SurfaceInitialized();
744 void Adaptor::NotifyLanguageChanged()
746 mLanguageChangedSignal.Emit( mAdaptor );
749 void Adaptor::RenderOnce()
754 void Adaptor::RequestUpdateOnce()
756 if( PAUSED_WHILE_HIDDEN != mState )
758 if( mThreadController )
760 mThreadController->RequestUpdateOnce();
765 void Adaptor::IndicatorSizeChanged(int height)
767 // let the core know the indicator height is changed
768 mCore->SetTopMargin(height);
771 void Adaptor::ProcessCoreEventsFromIdle()
775 // the idle handle automatically un-installs itself
776 mNotificationOnIdleInstalled = false;
779 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
781 mLanguageChangedSignal(),
785 mThreadController( NULL ),
786 mVSyncMonitor( NULL ),
790 mNativeWindow( nativeWindow ),
792 mPlatformAbstraction( NULL ),
793 mEventHandler( NULL ),
794 mCallbackManager( NULL ),
795 mNotificationOnIdleInstalled( false ),
796 mNotificationTrigger( NULL ),
797 mGestureManager( NULL ),
798 mDaliFeedbackPlugin(),
799 mFeedbackController( NULL ),
802 mDragAndDropDetector(),
803 mDeferredRotationObserver( NULL ),
804 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
805 mPerformanceInterface( NULL ),
808 mTriggerEventFactory(),
809 mObjectProfiler( NULL ),
811 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
812 mUseRemoteSurface( false )
814 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
815 gThreadLocalAdaptor = this;
820 void Adaptor::SetViewMode( ViewMode viewMode )
822 mSurface->SetViewMode( viewMode );
823 mCore->SetViewMode( viewMode );
826 ViewMode Adaptor::GetViewMode() const
828 return mCore->GetViewMode();
831 void Adaptor::SetStereoBase( float stereoBase )
833 mCore->SetStereoBase( stereoBase );
836 float Adaptor::GetStereoBase() const
838 return mCore->GetStereoBase();
841 void Adaptor::SetRootLayoutDirection( std::string locale )
843 Dali::Stage stage = Dali::Stage::GetCurrent();
845 stage.GetRootLayer().SetProperty( DevelActor::Property::LAYOUT_DIRECTION,
846 static_cast< DevelActor::LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
849 } // namespace Adaptor
851 } // namespace Internal