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 );
96 windowImpl.SetAdaptor(*adaptor);
100 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
102 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
103 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
104 mEnvironmentOptions->SetLogFunction( logFunction );
105 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
107 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
110 GetDataStoragePath( path );
111 mPlatformAbstraction->SetDataStoragePath( path );
113 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
114 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
116 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
118 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
119 // files automatically.
121 if( mEnvironmentOptions->PerformanceServerRequired() )
123 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
126 mCallbackManager = CallbackManager::New();
128 PositionSize size = mSurface->GetPositionSize();
130 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
132 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
134 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
138 mGLES = new GlImplementation();
141 mEglFactory = new EglFactory( mEnvironmentOptions->GetMultiSamplingLevel() );
143 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
145 mCore = Integration::Core::New( *this,
146 *mPlatformAbstraction,
150 dataRetentionPolicy ,
151 0u != mEnvironmentOptions->GetRenderToFboInterval() );
153 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
154 if( 0u < timeInterval )
156 mObjectProfiler = new ObjectProfiler( timeInterval );
159 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
161 mVSyncMonitor = new VSyncMonitor;
163 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
165 // Should be called after Core creation
166 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
168 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
170 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
172 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
174 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
176 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
178 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
180 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
182 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
184 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
186 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
188 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
190 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
192 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
194 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
196 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
199 // Set max texture size
200 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
202 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
205 SetupSystemInformation();
210 // Ensure stop status
213 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
214 gThreadLocalAdaptor = NULL;
216 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
218 (*iter)->OnDestroy();
221 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
222 delete mVSyncMonitor;
223 delete mEventHandler;
224 delete mObjectProfiler;
229 delete mGestureManager;
230 delete mPlatformAbstraction;
231 delete mCallbackManager;
232 delete mPerformanceInterface;
234 // uninstall it on this thread (main actor thread)
235 Dali::Integration::Log::UninstallLogFunction();
237 // Delete environment options if we own it
238 if( mEnvironmentOptionsOwned )
240 delete mEnvironmentOptions;
244 void Adaptor::Start()
246 // it doesn't support restart after stop at this moment
247 // to support restarting, need more testing
248 if( READY != mState )
253 // Start the callback manager
254 mCallbackManager->Start();
256 // create event handler
257 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
259 if( mDeferredRotationObserver != NULL )
261 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
262 mDeferredRotationObserver = NULL;
265 unsigned int dpiHor, dpiVer;
267 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
269 // tell core about the DPI value
270 mCore->SetDpi(dpiHor, dpiVer);
272 // set the DPI value for font rendering
273 FontClient fontClient = FontClient::Get();
274 fontClient.SetDpi( dpiHor, dpiVer );
276 // Tell the core the size of the surface just before we start the render-thread
277 PositionSize size = mSurface->GetPositionSize();
278 mCore->SurfaceResized( size.width, size.height );
280 // Initialize the thread controller
281 mThreadController->Initialize();
283 ProcessCoreEvents(); // Ensure any startup messages are processed.
285 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
291 // Dali::Internal::Adaptor::Adaptor::Pause
292 void Adaptor::Pause()
294 // Only pause the adaptor if we're actually running.
295 if( RUNNING == mState )
297 // Inform observers that we are about to be paused.
298 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
303 // Reset the event handler when adaptor paused
306 mEventHandler->Pause();
309 mThreadController->Pause();
314 // Dali::Internal::Adaptor::Adaptor::Resume
315 void Adaptor::Resume()
317 // Only resume the adaptor if we are in the suspended state.
318 if( PAUSED == mState )
322 // Reset the event handler when adaptor resumed
325 mEventHandler->Resume();
328 // Inform observers that we have resumed.
329 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
334 // trigger processing of events queued up while paused
335 mCore->ProcessEvents();
337 // Do at end to ensure our first update/render after resumption includes the processed messages as well
338 mThreadController->Resume();
344 if( RUNNING == mState ||
346 PAUSED_WHILE_HIDDEN == mState )
348 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
353 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, bool forceAdd )
447 bool idleAdded(false);
449 // Only add an idle if the Adaptor is actually running
450 if( RUNNING == mState || forceAdd )
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( bool forceUpdate )
668 mThreadController->RequestUpdate();
672 case PAUSED_WHILE_HIDDEN:
674 // When Dali applications are partially visible behind the lock-screen,
675 // the indicator must be updated (therefore allow updates in the PAUSED state)
678 mThreadController->RequestUpdateOnce();
690 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
692 // Only request a notification if the Adaptor is actually running
693 // and we haven't installed the idle notification
694 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || forceProcess ) )
696 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
700 void Adaptor::OnWindowShown()
702 if ( PAUSED_WHILE_HIDDEN == mState )
704 // Adaptor can now be resumed
709 // Force a render task
714 void Adaptor::OnWindowHidden()
716 if ( RUNNING == mState )
720 // Adaptor cannot be resumed until the window is shown
721 mState = PAUSED_WHILE_HIDDEN;
725 // Dali::Internal::Adaptor::Adaptor::OnDamaged
726 void Adaptor::OnDamaged( const DamageArea& area )
728 // This is needed for the case where Dali window is partially obscured
729 RequestUpdate( false );
732 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
734 // let the core know the surface size has changed
735 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
737 mResizedSignal.Emit( mAdaptor );
740 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
742 // flush the event queue to give the update-render thread chance
743 // to start processing messages for new camera setup etc as soon as possible
746 // this method blocks until the render thread has completed the resizing.
747 mThreadController->ResizeSurface();
750 void Adaptor::NotifySceneCreated()
752 GetCore().SceneCreated();
754 // Start thread controller after the scene has been created
755 mThreadController->Start();
757 // process after surface is created (registering to remote surface provider if required)
758 SurfaceInitialized();
763 void Adaptor::NotifyLanguageChanged()
765 mLanguageChangedSignal.Emit( mAdaptor );
768 void Adaptor::RenderOnce()
773 void Adaptor::RequestUpdateOnce()
775 if( mThreadController )
777 mThreadController->RequestUpdateOnce();
781 void Adaptor::IndicatorSizeChanged(int height)
783 // let the core know the indicator height is changed
784 mCore->SetTopMargin(height);
787 void Adaptor::ProcessCoreEventsFromIdle()
791 // the idle handle automatically un-installs itself
792 mNotificationOnIdleInstalled = false;
795 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
797 mLanguageChangedSignal(),
801 mThreadController( NULL ),
802 mVSyncMonitor( NULL ),
806 mNativeWindow( nativeWindow ),
808 mPlatformAbstraction( NULL ),
809 mEventHandler( NULL ),
810 mCallbackManager( NULL ),
811 mNotificationOnIdleInstalled( false ),
812 mNotificationTrigger( NULL ),
813 mGestureManager( NULL ),
814 mDaliFeedbackPlugin(),
815 mFeedbackController( NULL ),
818 mDragAndDropDetector(),
819 mDeferredRotationObserver( NULL ),
820 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
821 mPerformanceInterface( NULL ),
824 mTriggerEventFactory(),
825 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 } // namespace Adaptor
867 } // namespace Internal