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, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
147 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
148 if( 0u < timeInterval )
150 mObjectProfiler = new ObjectProfiler( timeInterval );
153 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
155 mVSyncMonitor = new VSyncMonitor;
157 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
159 // Should be called after Core creation
160 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
162 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
164 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
166 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
168 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
170 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
172 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
174 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
176 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
178 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
180 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
182 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
184 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
186 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
188 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
190 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
193 // Set max texture size
194 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
196 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
199 SetupSystemInformation();
204 // Ensure stop status
207 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
208 gThreadLocalAdaptor = NULL;
210 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
212 (*iter)->OnDestroy();
215 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
216 delete mVSyncMonitor;
217 delete mEventHandler;
218 delete mObjectProfiler;
223 delete mGestureManager;
224 delete mPlatformAbstraction;
225 delete mCallbackManager;
226 delete mPerformanceInterface;
228 // uninstall it on this thread (main actor thread)
229 Dali::Integration::Log::UninstallLogFunction();
231 // Delete environment options if we own it
232 if( mEnvironmentOptionsOwned )
234 delete mEnvironmentOptions;
238 void Adaptor::Start()
240 // it doesn't support restart after stop at this moment
241 // to support restarting, need more testing
242 if( READY != mState )
247 // Start the callback manager
248 mCallbackManager->Start();
250 // create event handler
251 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
253 if( mDeferredRotationObserver != NULL )
255 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
256 mDeferredRotationObserver = NULL;
259 unsigned int dpiHor, dpiVer;
261 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
263 // tell core about the DPI value
264 mCore->SetDpi(dpiHor, dpiVer);
266 // set the DPI value for font rendering
267 FontClient fontClient = FontClient::Get();
268 fontClient.SetDpi( dpiHor, dpiVer );
270 // Tell the core the size of the surface just before we start the render-thread
271 PositionSize size = mSurface->GetPositionSize();
272 mCore->SurfaceResized( size.width, size.height );
274 // Initialize the thread controller
275 mThreadController->Initialize();
279 ProcessCoreEvents(); // Ensure any startup messages are processed.
281 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
287 // Dali::Internal::Adaptor::Adaptor::Pause
288 void Adaptor::Pause()
290 // Only pause the adaptor if we're actually running.
291 if( RUNNING == mState )
293 // Inform observers that we are about to be paused.
294 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
299 // Reset the event handler when adaptor paused
302 mEventHandler->Pause();
305 mThreadController->Pause();
311 // Dali::Internal::Adaptor::Adaptor::Resume
312 void Adaptor::Resume()
314 // Only resume the adaptor if we are in the suspended state.
315 if( PAUSED == mState )
319 // Reset the event handler when adaptor resumed
322 mEventHandler->Resume();
325 // Inform observers that we have resumed.
326 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
331 // Resume core so it processes any requests as well
334 // Do at end to ensure our first update/render after resumption includes the processed messages as well
335 mThreadController->Resume();
341 if( RUNNING == mState ||
343 PAUSED_WHILE_HIDDEN == mState )
345 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
350 mThreadController->Stop();
353 // Delete the TTS player
354 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
358 mTtsPlayers[i].Reset();
362 delete mEventHandler;
363 mEventHandler = NULL;
365 delete mNotificationTrigger;
366 mNotificationTrigger = NULL;
368 mCallbackManager->Stop();
374 void Adaptor::ContextLost()
376 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
379 void Adaptor::ContextRegained()
381 // Inform core, so that texture resources can be reloaded
382 mCore->RecoverFromContextLoss();
384 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
387 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
389 mEventHandler->FeedTouchPoint( point, timeStamp );
392 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
394 mEventHandler->FeedWheelEvent( wheelEvent );
397 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
399 mEventHandler->FeedKeyEvent( keyEvent );
402 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
404 PositionSize positionSize = surface.GetPositionSize();
406 // let the core know the surface size has changed
407 mCore->SurfaceResized( positionSize.width, positionSize.height );
409 mResizedSignal.Emit( mAdaptor );
411 mNativeWindow = nativeWindow;
414 // flush the event queue to give the update-render thread chance
415 // to start processing messages for new camera setup etc as soon as possible
418 // this method blocks until the render thread has completed the replace.
419 mThreadController->ReplaceSurface(mSurface);
422 RenderSurface& Adaptor::GetSurface() const
427 void Adaptor::ReleaseSurfaceLock()
429 mSurface->ReleaseLock();
432 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
434 if(!mTtsPlayers[mode])
436 // Create the TTS player when it needed, because it can reduce launching time.
437 mTtsPlayers[mode] = TtsPlayer::New(mode);
440 return mTtsPlayers[mode];
443 bool Adaptor::AddIdle( CallbackBase* callback )
445 bool idleAdded(false);
447 // Only add an idle if the Adaptor is actually running
448 if( RUNNING == mState )
450 idleAdded = mCallbackManager->AddIdleCallback( callback );
456 void Adaptor::RemoveIdle( CallbackBase* callback )
458 mCallbackManager->RemoveIdleCallback( callback );
461 Dali::Adaptor& Adaptor::Get()
463 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
464 return gThreadLocalAdaptor->mAdaptor;
467 bool Adaptor::IsAvailable()
469 return gThreadLocalAdaptor != NULL;
472 void Adaptor::SceneCreated()
474 mCore->SceneCreated();
477 Dali::Integration::Core& Adaptor::GetCore()
482 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
484 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
487 void Adaptor::SetUseHardwareVSync( bool useHardware )
489 mVSyncMonitor->SetUseHardwareVSync( useHardware );
492 EglFactory& Adaptor::GetEGLFactory() const
494 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
498 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
503 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
505 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
509 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
511 return *mPlatformAbstraction;
514 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
519 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
521 return *mNotificationTrigger;
524 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
526 return mTriggerEventFactory;
529 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
531 return mSocketFactory;
534 RenderSurface* Adaptor::GetRenderSurfaceInterface()
539 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
541 return mVSyncMonitor;
544 TraceInterface& Adaptor::GetKernelTraceInterface()
546 return mKernelTracer;
549 TraceInterface& Adaptor::GetSystemTraceInterface()
551 return mSystemTracer;
554 PerformanceInterface* Adaptor::GetPerformanceInterface()
556 return mPerformanceInterface;
559 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
561 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
562 return *mPlatformAbstraction;
565 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
567 mDragAndDropDetector = detector;
571 mEventHandler->SetDragAndDropDetector( detector );
575 void Adaptor::SetRotationObserver( RotationObserver* observer )
579 mEventHandler->SetRotationObserver( observer );
581 else if( mState == READY )
583 // Set once event handler exists
584 mDeferredRotationObserver = observer;
588 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
590 if(mTtsPlayers[mode])
592 mTtsPlayers[mode].Reset();
596 void Adaptor::SetMinimumPinchDistance(float distance)
598 if( mGestureManager )
600 mGestureManager->SetMinimumPinchDistance(distance);
604 Any Adaptor::GetNativeWindowHandle()
606 return mNativeWindow;
609 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
611 mUseRemoteSurface = useRemoteSurface;
614 void Adaptor::AddObserver( LifeCycleObserver& observer )
616 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
618 if ( match == mObservers.end() )
620 mObservers.push_back( &observer );
624 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
626 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
628 if ( match != mObservers.end() )
630 mObservers.erase( match );
634 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
638 mCore->QueueEvent(event);
642 void Adaptor::ProcessCoreEvents()
646 if( mPerformanceInterface )
648 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
651 mCore->ProcessEvents();
653 if( mPerformanceInterface )
655 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
660 void Adaptor::RequestUpdate()
662 // When Dali applications are partially visible behind the lock-screen,
663 // the indicator must be updated (therefore allow updates in the PAUSED state)
664 if ( PAUSED == mState ||
667 mThreadController->RequestUpdate();
671 void Adaptor::RequestProcessEventsOnIdle()
673 // Only request a notification if the Adaptor is actually running
674 // and we haven't installed the idle notification
675 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
677 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
681 void Adaptor::OnWindowShown()
683 if ( PAUSED_WHILE_HIDDEN == mState )
685 // Adaptor can now be resumed
690 // Force a render task
695 void Adaptor::OnWindowHidden()
697 if ( STOPPED != mState )
701 // Adaptor cannot be resumed until the window is shown
702 mState = PAUSED_WHILE_HIDDEN;
706 // Dali::Internal::Adaptor::Adaptor::OnDamaged
707 void Adaptor::OnDamaged( const DamageArea& area )
709 // This is needed for the case where Dali window is partially obscured
713 void Adaptor::SurfaceResizePrepare( Dali::Adaptor::SurfaceSize surfaceSize )
715 // let the core know the surface size has changed
716 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
718 mResizedSignal.Emit( mAdaptor );
721 void Adaptor::SurfaceResizeComplete( Dali::Adaptor::SurfaceSize surfaceSize )
723 // flush the event queue to give the update-render thread chance
724 // to start processing messages for new camera setup etc as soon as possible
727 // this method blocks until the render thread has completed the resizing.
728 mThreadController->ResizeSurface();
731 void Adaptor::NotifySceneCreated()
733 GetCore().SceneCreated();
735 // Start thread controller after the scene has been created
736 mThreadController->Start();
738 // process after surface is created (registering to remote surface provider if required)
739 SurfaceInitialized();
742 void Adaptor::NotifyLanguageChanged()
744 mLanguageChangedSignal.Emit( mAdaptor );
747 void Adaptor::RenderOnce()
752 void Adaptor::RequestUpdateOnce()
754 if( PAUSED_WHILE_HIDDEN != mState )
756 if( mThreadController )
758 mThreadController->RequestUpdateOnce();
763 void Adaptor::IndicatorSizeChanged(int height)
765 // let the core know the indicator height is changed
766 mCore->SetTopMargin(height);
769 void Adaptor::ProcessCoreEventsFromIdle()
773 // the idle handle automatically un-installs itself
774 mNotificationOnIdleInstalled = false;
777 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
779 mLanguageChangedSignal(),
783 mThreadController( NULL ),
784 mVSyncMonitor( NULL ),
788 mNativeWindow( nativeWindow ),
790 mPlatformAbstraction( NULL ),
791 mEventHandler( NULL ),
792 mCallbackManager( NULL ),
793 mNotificationOnIdleInstalled( false ),
794 mNotificationTrigger( NULL ),
795 mGestureManager( NULL ),
796 mDaliFeedbackPlugin(),
797 mFeedbackController( NULL ),
800 mDragAndDropDetector(),
801 mDeferredRotationObserver( NULL ),
802 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
803 mPerformanceInterface( NULL ),
806 mTriggerEventFactory(),
807 mObjectProfiler( NULL ),
809 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
810 mUseRemoteSurface( false )
812 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
813 gThreadLocalAdaptor = this;
818 void Adaptor::SetViewMode( ViewMode viewMode )
820 mSurface->SetViewMode( viewMode );
821 mCore->SetViewMode( viewMode );
824 ViewMode Adaptor::GetViewMode() const
826 return mCore->GetViewMode();
829 void Adaptor::SetStereoBase( float stereoBase )
831 mCore->SetStereoBase( stereoBase );
834 float Adaptor::GetStereoBase() const
836 return mCore->GetStereoBase();
839 void Adaptor::SetRootLayoutDirection( std::string locale )
841 Dali::Stage stage = Dali::Stage::GetCurrent();
843 stage.GetRootLayer().SetProperty( DevelActor::Property::LAYOUT_DIRECTION,
844 static_cast< DevelActor::LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
847 } // namespace Adaptor
849 } // namespace Internal