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();
316 // Dali::Internal::Adaptor::Adaptor::Resume
317 void Adaptor::Resume()
319 // Only resume the adaptor if we are in the suspended state.
320 if( PAUSED == mState )
324 // Reset the event handler when adaptor resumed
327 mEventHandler->Resume();
330 // Inform observers that we have resumed.
331 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
336 // trigger processing of events queued up while paused
337 mCore->ProcessEvents();
339 // Do at end to ensure our first update/render after resumption includes the processed messages as well
340 mThreadController->Resume();
346 if( RUNNING == mState ||
348 PAUSED_WHILE_HIDDEN == mState )
350 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
355 mThreadController->Stop();
357 // Delete the TTS player
358 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
362 mTtsPlayers[i].Reset();
366 delete mEventHandler;
367 mEventHandler = NULL;
369 delete mNotificationTrigger;
370 mNotificationTrigger = NULL;
372 mCallbackManager->Stop();
378 void Adaptor::ContextLost()
380 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
383 void Adaptor::ContextRegained()
385 // Inform core, so that texture resources can be reloaded
386 mCore->RecoverFromContextLoss();
388 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
391 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
393 mEventHandler->FeedTouchPoint( point, timeStamp );
396 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
398 mEventHandler->FeedWheelEvent( wheelEvent );
401 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
403 mEventHandler->FeedKeyEvent( keyEvent );
406 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
408 PositionSize positionSize = surface.GetPositionSize();
410 // let the core know the surface size has changed
411 mCore->SurfaceResized( positionSize.width, positionSize.height );
413 mResizedSignal.Emit( mAdaptor );
415 mNativeWindow = nativeWindow;
418 // flush the event queue to give the update-render thread chance
419 // to start processing messages for new camera setup etc as soon as possible
422 // this method blocks until the render thread has completed the replace.
423 mThreadController->ReplaceSurface(mSurface);
426 RenderSurface& Adaptor::GetSurface() const
431 void Adaptor::ReleaseSurfaceLock()
433 mSurface->ReleaseLock();
436 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
438 if(!mTtsPlayers[mode])
440 // Create the TTS player when it needed, because it can reduce launching time.
441 mTtsPlayers[mode] = TtsPlayer::New(mode);
444 return mTtsPlayers[mode];
447 bool Adaptor::AddIdle( CallbackBase* callback, bool forceAdd )
449 bool idleAdded(false);
451 // Only add an idle if the Adaptor is actually running
452 if( RUNNING == mState || READY == mState || forceAdd )
454 idleAdded = mCallbackManager->AddIdleCallback( callback );
460 void Adaptor::RemoveIdle( CallbackBase* callback )
462 mCallbackManager->RemoveIdleCallback( callback );
465 Dali::Adaptor& Adaptor::Get()
467 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
468 return gThreadLocalAdaptor->mAdaptor;
471 bool Adaptor::IsAvailable()
473 return gThreadLocalAdaptor != NULL;
476 void Adaptor::SceneCreated()
478 mCore->SceneCreated();
481 Dali::Integration::Core& Adaptor::GetCore()
486 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
488 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
491 void Adaptor::SetUseHardwareVSync( bool useHardware )
493 mVSyncMonitor->SetUseHardwareVSync( useHardware );
496 EglFactory& Adaptor::GetEGLFactory() const
498 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
502 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
507 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
509 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
513 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
515 return *mPlatformAbstraction;
518 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
523 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
525 return *mNotificationTrigger;
528 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
530 return mTriggerEventFactory;
533 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
535 return mSocketFactory;
538 RenderSurface* Adaptor::GetRenderSurfaceInterface()
543 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
545 return mVSyncMonitor;
548 TraceInterface& Adaptor::GetKernelTraceInterface()
550 return mKernelTracer;
553 TraceInterface& Adaptor::GetSystemTraceInterface()
555 return mSystemTracer;
558 PerformanceInterface* Adaptor::GetPerformanceInterface()
560 return mPerformanceInterface;
563 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
565 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
566 return *mPlatformAbstraction;
569 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
571 mDragAndDropDetector = detector;
575 mEventHandler->SetDragAndDropDetector( detector );
579 void Adaptor::SetRotationObserver( RotationObserver* observer )
583 mEventHandler->SetRotationObserver( observer );
585 else if( mState == READY )
587 // Set once event handler exists
588 mDeferredRotationObserver = observer;
592 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
594 if(mTtsPlayers[mode])
596 mTtsPlayers[mode].Reset();
600 void Adaptor::SetMinimumPinchDistance(float distance)
602 if( mGestureManager )
604 mGestureManager->SetMinimumPinchDistance(distance);
608 Any Adaptor::GetNativeWindowHandle()
610 return mNativeWindow;
613 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
615 mUseRemoteSurface = useRemoteSurface;
618 void Adaptor::AddObserver( LifeCycleObserver& observer )
620 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
622 if ( match == mObservers.end() )
624 mObservers.push_back( &observer );
628 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
630 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
632 if ( match != mObservers.end() )
634 mObservers.erase( match );
638 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
642 mCore->QueueEvent(event);
646 void Adaptor::ProcessCoreEvents()
650 if( mPerformanceInterface )
652 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
655 mCore->ProcessEvents();
657 if( mPerformanceInterface )
659 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
664 void Adaptor::RequestUpdate( bool forceUpdate )
670 mThreadController->RequestUpdate();
674 case PAUSED_WHILE_HIDDEN:
676 // When Dali applications are partially visible behind the lock-screen,
677 // the indicator must be updated (therefore allow updates in the PAUSED state)
680 mThreadController->RequestUpdateOnce();
692 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
694 // Only request a notification if the Adaptor is actually running
695 // and we haven't installed the idle notification
696 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
698 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
702 void Adaptor::OnWindowShown()
704 if ( PAUSED_WHILE_HIDDEN == mState )
706 // Adaptor can now be resumed
711 // Force a render task
716 void Adaptor::OnWindowHidden()
718 if ( RUNNING == mState )
722 // Adaptor cannot be resumed until the window is shown
723 mState = PAUSED_WHILE_HIDDEN;
727 // Dali::Internal::Adaptor::Adaptor::OnDamaged
728 void Adaptor::OnDamaged( const DamageArea& area )
730 // This is needed for the case where Dali window is partially obscured
731 RequestUpdate( false );
734 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
736 // let the core know the surface size has changed
737 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
739 mResizedSignal.Emit( mAdaptor );
742 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
744 // flush the event queue to give the update-render thread chance
745 // to start processing messages for new camera setup etc as soon as possible
748 // this method blocks until the render thread has completed the resizing.
749 mThreadController->ResizeSurface();
752 void Adaptor::NotifySceneCreated()
754 GetCore().SceneCreated();
756 // Start thread controller after the scene has been created
757 mThreadController->Start();
759 // process after surface is created (registering to remote surface provider if required)
760 SurfaceInitialized();
765 void Adaptor::NotifyLanguageChanged()
767 mLanguageChangedSignal.Emit( mAdaptor );
770 void Adaptor::RenderOnce()
775 void Adaptor::RequestUpdateOnce()
777 if( mThreadController )
779 mThreadController->RequestUpdateOnce();
783 void Adaptor::IndicatorSizeChanged(int height)
785 // let the core know the indicator height is changed
786 mCore->SetTopMargin(height);
789 void Adaptor::ProcessCoreEventsFromIdle()
793 // the idle handle automatically un-installs itself
794 mNotificationOnIdleInstalled = false;
797 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
799 mLanguageChangedSignal(),
803 mThreadController( NULL ),
804 mVSyncMonitor( NULL ),
808 mNativeWindow( nativeWindow ),
810 mPlatformAbstraction( NULL ),
811 mEventHandler( NULL ),
812 mCallbackManager( NULL ),
813 mNotificationOnIdleInstalled( false ),
814 mNotificationTrigger( NULL ),
815 mGestureManager( NULL ),
816 mDaliFeedbackPlugin(),
817 mFeedbackController( NULL ),
820 mDragAndDropDetector(),
821 mDeferredRotationObserver( NULL ),
822 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
823 mPerformanceInterface( NULL ),
826 mTriggerEventFactory(),
827 mObjectProfiler( NULL ),
830 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
831 mUseRemoteSurface( false )
833 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
834 gThreadLocalAdaptor = this;
839 void Adaptor::SetViewMode( ViewMode viewMode )
841 mSurface->SetViewMode( viewMode );
842 mCore->SetViewMode( viewMode );
845 ViewMode Adaptor::GetViewMode() const
847 return mCore->GetViewMode();
850 void Adaptor::SetStereoBase( float stereoBase )
852 mCore->SetStereoBase( stereoBase );
855 float Adaptor::GetStereoBase() const
857 return mCore->GetStereoBase();
860 void Adaptor::SetRootLayoutDirection( std::string locale )
862 Dali::Stage stage = Dali::Stage::GetCurrent();
864 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
865 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
868 void Adaptor::SetWindow( Dali::Window window )
873 Dali::Window Adaptor::GetWindow()
878 } // namespace Adaptor
880 } // namespace Internal