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();
309 // Process remained events and rendering in the update thread
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 // Resume core so it processes any requests as well
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();
356 // Delete the TTS player
357 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
361 mTtsPlayers[i].Reset();
365 delete mEventHandler;
366 mEventHandler = NULL;
368 delete mNotificationTrigger;
369 mNotificationTrigger = NULL;
371 mCallbackManager->Stop();
377 void Adaptor::ContextLost()
379 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
382 void Adaptor::ContextRegained()
384 // Inform core, so that texture resources can be reloaded
385 mCore->RecoverFromContextLoss();
387 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
390 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
392 mEventHandler->FeedTouchPoint( point, timeStamp );
395 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
397 mEventHandler->FeedWheelEvent( wheelEvent );
400 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
402 mEventHandler->FeedKeyEvent( keyEvent );
405 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
407 PositionSize positionSize = surface.GetPositionSize();
409 // let the core know the surface size has changed
410 mCore->SurfaceResized( positionSize.width, positionSize.height );
412 mResizedSignal.Emit( mAdaptor );
414 mNativeWindow = nativeWindow;
417 // flush the event queue to give the update-render thread chance
418 // to start processing messages for new camera setup etc as soon as possible
421 // this method blocks until the render thread has completed the replace.
422 mThreadController->ReplaceSurface(mSurface);
425 RenderSurface& Adaptor::GetSurface() const
430 void Adaptor::ReleaseSurfaceLock()
432 mSurface->ReleaseLock();
435 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
437 if(!mTtsPlayers[mode])
439 // Create the TTS player when it needed, because it can reduce launching time.
440 mTtsPlayers[mode] = TtsPlayer::New(mode);
443 return mTtsPlayers[mode];
446 bool Adaptor::AddIdle( CallbackBase* callback )
448 bool idleAdded(false);
450 // Only add an idle if the Adaptor is actually running
451 if( RUNNING == mState )
453 idleAdded = mCallbackManager->AddIdleCallback( callback );
459 void Adaptor::RemoveIdle( CallbackBase* callback )
461 mCallbackManager->RemoveIdleCallback( callback );
464 Dali::Adaptor& Adaptor::Get()
466 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
467 return gThreadLocalAdaptor->mAdaptor;
470 bool Adaptor::IsAvailable()
472 return gThreadLocalAdaptor != NULL;
475 void Adaptor::SceneCreated()
477 mCore->SceneCreated();
480 Dali::Integration::Core& Adaptor::GetCore()
485 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
487 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
490 void Adaptor::SetUseHardwareVSync( bool useHardware )
492 mVSyncMonitor->SetUseHardwareVSync( useHardware );
495 EglFactory& Adaptor::GetEGLFactory() const
497 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
501 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
506 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
508 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
512 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
514 return *mPlatformAbstraction;
517 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
522 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
524 return *mNotificationTrigger;
527 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
529 return mTriggerEventFactory;
532 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
534 return mSocketFactory;
537 RenderSurface* Adaptor::GetRenderSurfaceInterface()
542 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
544 return mVSyncMonitor;
547 TraceInterface& Adaptor::GetKernelTraceInterface()
549 return mKernelTracer;
552 TraceInterface& Adaptor::GetSystemTraceInterface()
554 return mSystemTracer;
557 PerformanceInterface* Adaptor::GetPerformanceInterface()
559 return mPerformanceInterface;
562 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
564 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
565 return *mPlatformAbstraction;
568 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
570 mDragAndDropDetector = detector;
574 mEventHandler->SetDragAndDropDetector( detector );
578 void Adaptor::SetRotationObserver( RotationObserver* observer )
582 mEventHandler->SetRotationObserver( observer );
584 else if( mState == READY )
586 // Set once event handler exists
587 mDeferredRotationObserver = observer;
591 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
593 if(mTtsPlayers[mode])
595 mTtsPlayers[mode].Reset();
599 void Adaptor::SetMinimumPinchDistance(float distance)
601 if( mGestureManager )
603 mGestureManager->SetMinimumPinchDistance(distance);
607 Any Adaptor::GetNativeWindowHandle()
609 return mNativeWindow;
612 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
614 mUseRemoteSurface = useRemoteSurface;
617 void Adaptor::AddObserver( LifeCycleObserver& observer )
619 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
621 if ( match == mObservers.end() )
623 mObservers.push_back( &observer );
627 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
629 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
631 if ( match != mObservers.end() )
633 mObservers.erase( match );
637 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
641 mCore->QueueEvent(event);
645 void Adaptor::ProcessCoreEvents()
649 if( mPerformanceInterface )
651 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
654 mCore->ProcessEvents();
656 if( mPerformanceInterface )
658 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
663 void Adaptor::RequestUpdate()
665 // When Dali applications are partially visible behind the lock-screen,
666 // the indicator must be updated (therefore allow updates in the PAUSED state)
667 if ( PAUSED == mState ||
670 mThreadController->RequestUpdate();
674 void Adaptor::RequestProcessEventsOnIdle()
676 // Only request a notification if the Adaptor is actually running
677 // and we haven't installed the idle notification
678 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
680 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
684 void Adaptor::OnWindowShown()
686 if ( PAUSED_WHILE_HIDDEN == mState )
688 // Adaptor can now be resumed
693 // Force a render task
698 void Adaptor::OnWindowHidden()
700 if ( STOPPED != mState )
704 // Adaptor cannot be resumed until the window is shown
705 mState = PAUSED_WHILE_HIDDEN;
709 // Dali::Internal::Adaptor::Adaptor::OnDamaged
710 void Adaptor::OnDamaged( const DamageArea& area )
712 // This is needed for the case where Dali window is partially obscured
716 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
718 // let the core know the surface size has changed
719 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
721 mResizedSignal.Emit( mAdaptor );
724 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
726 // flush the event queue to give the update-render thread chance
727 // to start processing messages for new camera setup etc as soon as possible
730 // this method blocks until the render thread has completed the resizing.
731 mThreadController->ResizeSurface();
734 void Adaptor::NotifySceneCreated()
736 GetCore().SceneCreated();
738 // Start thread controller after the scene has been created
739 mThreadController->Start();
741 // process after surface is created (registering to remote surface provider if required)
742 SurfaceInitialized();
745 void Adaptor::NotifyLanguageChanged()
747 mLanguageChangedSignal.Emit( mAdaptor );
750 void Adaptor::RenderOnce()
755 void Adaptor::RequestUpdateOnce()
757 if( PAUSED_WHILE_HIDDEN != mState )
759 if( mThreadController )
761 mThreadController->RequestUpdateOnce();
766 void Adaptor::IndicatorSizeChanged(int height)
768 // let the core know the indicator height is changed
769 mCore->SetTopMargin(height);
772 void Adaptor::ProcessCoreEventsFromIdle()
776 // the idle handle automatically un-installs itself
777 mNotificationOnIdleInstalled = false;
780 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
782 mLanguageChangedSignal(),
786 mThreadController( NULL ),
787 mVSyncMonitor( NULL ),
791 mNativeWindow( nativeWindow ),
793 mPlatformAbstraction( NULL ),
794 mEventHandler( NULL ),
795 mCallbackManager( NULL ),
796 mNotificationOnIdleInstalled( false ),
797 mNotificationTrigger( NULL ),
798 mGestureManager( NULL ),
799 mDaliFeedbackPlugin(),
800 mFeedbackController( NULL ),
803 mDragAndDropDetector(),
804 mDeferredRotationObserver( NULL ),
805 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
806 mPerformanceInterface( NULL ),
809 mTriggerEventFactory(),
810 mObjectProfiler( NULL ),
812 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
813 mUseRemoteSurface( false )
815 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
816 gThreadLocalAdaptor = this;
821 void Adaptor::SetViewMode( ViewMode viewMode )
823 mSurface->SetViewMode( viewMode );
824 mCore->SetViewMode( viewMode );
827 ViewMode Adaptor::GetViewMode() const
829 return mCore->GetViewMode();
832 void Adaptor::SetStereoBase( float stereoBase )
834 mCore->SetStereoBase( stereoBase );
837 float Adaptor::GetStereoBase() const
839 return mCore->GetStereoBase();
842 void Adaptor::SetRootLayoutDirection( std::string locale )
844 Dali::Stage stage = Dali::Stage::GetCurrent();
846 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
847 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
850 } // namespace Adaptor
852 } // namespace Internal