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();
310 // Dali::Internal::Adaptor::Adaptor::Resume
311 void Adaptor::Resume()
313 // Only resume the adaptor if we are in the suspended state.
314 if( PAUSED == mState )
318 // Reset the event handler when adaptor resumed
321 mEventHandler->Resume();
324 // Inform observers that we have resumed.
325 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
330 // Resume core so it processes any requests as well
333 // Do at end to ensure our first update/render after resumption includes the processed messages as well
334 mThreadController->Resume();
340 if( RUNNING == mState ||
342 PAUSED_WHILE_HIDDEN == mState )
344 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
349 mThreadController->Stop();
352 // Delete the TTS player
353 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
357 mTtsPlayers[i].Reset();
361 delete mEventHandler;
362 mEventHandler = NULL;
364 delete mNotificationTrigger;
365 mNotificationTrigger = NULL;
367 mCallbackManager->Stop();
373 void Adaptor::ContextLost()
375 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
378 void Adaptor::ContextRegained()
380 // Inform core, so that texture resources can be reloaded
381 mCore->RecoverFromContextLoss();
383 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
386 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
388 mEventHandler->FeedTouchPoint( point, timeStamp );
391 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
393 mEventHandler->FeedWheelEvent( wheelEvent );
396 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
398 mEventHandler->FeedKeyEvent( keyEvent );
401 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
403 PositionSize positionSize = surface.GetPositionSize();
405 // let the core know the surface size has changed
406 mCore->SurfaceResized( positionSize.width, positionSize.height );
408 mResizedSignal.Emit( mAdaptor );
410 mNativeWindow = nativeWindow;
413 // flush the event queue to give the update-render thread chance
414 // to start processing messages for new camera setup etc as soon as possible
417 // this method blocks until the render thread has completed the replace.
418 mThreadController->ReplaceSurface(mSurface);
421 RenderSurface& Adaptor::GetSurface() const
426 void Adaptor::ReleaseSurfaceLock()
428 mSurface->ReleaseLock();
431 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
433 if(!mTtsPlayers[mode])
435 // Create the TTS player when it needed, because it can reduce launching time.
436 mTtsPlayers[mode] = TtsPlayer::New(mode);
439 return mTtsPlayers[mode];
442 bool Adaptor::AddIdle( CallbackBase* callback )
444 bool idleAdded(false);
446 // Only add an idle if the Adaptor is actually running
447 if( RUNNING == mState )
449 idleAdded = mCallbackManager->AddIdleCallback( callback );
455 void Adaptor::RemoveIdle( CallbackBase* callback )
457 mCallbackManager->RemoveIdleCallback( callback );
460 Dali::Adaptor& Adaptor::Get()
462 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
463 return gThreadLocalAdaptor->mAdaptor;
466 bool Adaptor::IsAvailable()
468 return gThreadLocalAdaptor != NULL;
471 void Adaptor::SceneCreated()
473 mCore->SceneCreated();
476 Dali::Integration::Core& Adaptor::GetCore()
481 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
483 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
486 void Adaptor::SetUseHardwareVSync( bool useHardware )
488 mVSyncMonitor->SetUseHardwareVSync( useHardware );
491 EglFactory& Adaptor::GetEGLFactory() const
493 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
497 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
502 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
504 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
508 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
510 return *mPlatformAbstraction;
513 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
518 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
520 return *mNotificationTrigger;
523 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
525 return mTriggerEventFactory;
528 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
530 return mSocketFactory;
533 RenderSurface* Adaptor::GetRenderSurfaceInterface()
538 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
540 return mVSyncMonitor;
543 TraceInterface& Adaptor::GetKernelTraceInterface()
545 return mKernelTracer;
548 TraceInterface& Adaptor::GetSystemTraceInterface()
550 return mSystemTracer;
553 PerformanceInterface* Adaptor::GetPerformanceInterface()
555 return mPerformanceInterface;
558 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
560 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
561 return *mPlatformAbstraction;
564 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
566 mDragAndDropDetector = detector;
570 mEventHandler->SetDragAndDropDetector( detector );
574 void Adaptor::SetRotationObserver( RotationObserver* observer )
578 mEventHandler->SetRotationObserver( observer );
580 else if( mState == READY )
582 // Set once event handler exists
583 mDeferredRotationObserver = observer;
587 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
589 if(mTtsPlayers[mode])
591 mTtsPlayers[mode].Reset();
595 void Adaptor::SetMinimumPinchDistance(float distance)
597 if( mGestureManager )
599 mGestureManager->SetMinimumPinchDistance(distance);
603 Any Adaptor::GetNativeWindowHandle()
605 return mNativeWindow;
608 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
610 mUseRemoteSurface = useRemoteSurface;
613 void Adaptor::AddObserver( LifeCycleObserver& observer )
615 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
617 if ( match == mObservers.end() )
619 mObservers.push_back( &observer );
623 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
625 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
627 if ( match != mObservers.end() )
629 mObservers.erase( match );
633 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
637 mCore->QueueEvent(event);
641 void Adaptor::ProcessCoreEvents()
645 if( mPerformanceInterface )
647 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
650 mCore->ProcessEvents();
652 if( mPerformanceInterface )
654 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
659 void Adaptor::RequestUpdate()
661 // When Dali applications are partially visible behind the lock-screen,
662 // the indicator must be updated (therefore allow updates in the PAUSED state)
663 if ( PAUSED == mState ||
666 mThreadController->RequestUpdate();
670 void Adaptor::RequestProcessEventsOnIdle()
672 // Only request a notification if the Adaptor is actually running
673 // and we haven't installed the idle notification
674 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
676 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
680 void Adaptor::OnWindowShown()
682 if ( PAUSED_WHILE_HIDDEN == mState )
684 // Adaptor can now be resumed
689 // Force a render task
694 void Adaptor::OnWindowHidden()
696 if ( STOPPED != mState )
700 // Adaptor cannot be resumed until the window is shown
701 mState = PAUSED_WHILE_HIDDEN;
705 // Dali::Internal::Adaptor::Adaptor::OnDamaged
706 void Adaptor::OnDamaged( const DamageArea& area )
708 // This is needed for the case where Dali window is partially obscured
712 void Adaptor::SurfaceResizePrepare( Dali::Adaptor::SurfaceSize surfaceSize )
714 // let the core know the surface size has changed
715 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
717 mResizedSignal.Emit( mAdaptor );
720 void Adaptor::SurfaceResizeComplete( Dali::Adaptor::SurfaceSize surfaceSize )
722 // flush the event queue to give the update-render thread chance
723 // to start processing messages for new camera setup etc as soon as possible
726 // this method blocks until the render thread has completed the resizing.
727 mThreadController->ResizeSurface();
730 void Adaptor::NotifySceneCreated()
732 GetCore().SceneCreated();
734 // Start thread controller after the scene has been created
735 mThreadController->Start();
737 // process after surface is created (registering to remote surface provider if required)
738 SurfaceInitialized();
741 void Adaptor::NotifyLanguageChanged()
743 mLanguageChangedSignal.Emit( mAdaptor );
746 void Adaptor::RequestUpdateOnce()
748 if( PAUSED_WHILE_HIDDEN != mState )
750 if( mThreadController )
752 mThreadController->RequestUpdateOnce();
757 void Adaptor::IndicatorSizeChanged(int height)
759 // let the core know the indicator height is changed
760 mCore->SetTopMargin(height);
763 void Adaptor::ProcessCoreEventsFromIdle()
767 // the idle handle automatically un-installs itself
768 mNotificationOnIdleInstalled = false;
771 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
773 mLanguageChangedSignal(),
777 mThreadController( NULL ),
778 mVSyncMonitor( NULL ),
782 mNativeWindow( nativeWindow ),
784 mPlatformAbstraction( NULL ),
785 mEventHandler( NULL ),
786 mCallbackManager( NULL ),
787 mNotificationOnIdleInstalled( false ),
788 mNotificationTrigger( NULL ),
789 mGestureManager( NULL ),
790 mDaliFeedbackPlugin(),
791 mFeedbackController( NULL ),
794 mDragAndDropDetector(),
795 mDeferredRotationObserver( NULL ),
796 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
797 mPerformanceInterface( NULL ),
800 mTriggerEventFactory(),
801 mObjectProfiler( NULL ),
803 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
804 mUseRemoteSurface( false )
806 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
807 gThreadLocalAdaptor = this;
812 void Adaptor::SetViewMode( ViewMode viewMode )
814 mSurface->SetViewMode( viewMode );
815 mCore->SetViewMode( viewMode );
818 ViewMode Adaptor::GetViewMode() const
820 return mCore->GetViewMode();
823 void Adaptor::SetStereoBase( float stereoBase )
825 mCore->SetStereoBase( stereoBase );
828 float Adaptor::GetStereoBase() const
830 return mCore->GetStereoBase();
833 void Adaptor::SetRootLayoutDirection( std::string locale )
835 Dali::Stage stage = Dali::Stage::GetCurrent();
837 stage.GetRootLayer().SetProperty( DevelActor::Property::LAYOUT_DIRECTION, Internal::Adaptor::Locale::GetLayoutDirection( locale ) );
840 } // namespace Adaptor
842 } // namespace Internal