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, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
149 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
150 if( 0u < timeInterval )
152 mObjectProfiler = new ObjectProfiler( timeInterval );
155 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
157 mVSyncMonitor = new VSyncMonitor;
159 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
161 // Should be called after Core creation
162 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
164 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
166 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
168 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
170 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
172 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
174 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
176 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
178 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
180 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
182 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
184 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
186 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
188 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
190 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
192 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
195 // Set max texture size
196 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
198 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
201 SetupSystemInformation();
206 // Ensure stop status
209 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
210 gThreadLocalAdaptor = NULL;
212 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
214 (*iter)->OnDestroy();
217 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
218 delete mVSyncMonitor;
219 delete mEventHandler;
220 delete mObjectProfiler;
225 delete mGestureManager;
226 delete mPlatformAbstraction;
227 delete mCallbackManager;
228 delete mPerformanceInterface;
230 // uninstall it on this thread (main actor thread)
231 Dali::Integration::Log::UninstallLogFunction();
233 // Delete environment options if we own it
234 if( mEnvironmentOptionsOwned )
236 delete mEnvironmentOptions;
240 void Adaptor::Start()
242 // it doesn't support restart after stop at this moment
243 // to support restarting, need more testing
244 if( READY != mState )
249 // Start the callback manager
250 mCallbackManager->Start();
252 // create event handler
253 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
255 if( mDeferredRotationObserver != NULL )
257 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
258 mDeferredRotationObserver = NULL;
261 unsigned int dpiHor, dpiVer;
263 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
265 // tell core about the DPI value
266 mCore->SetDpi(dpiHor, dpiVer);
268 // set the DPI value for font rendering
269 FontClient fontClient = FontClient::Get();
270 fontClient.SetDpi( dpiHor, dpiVer );
272 // Tell the core the size of the surface just before we start the render-thread
273 PositionSize size = mSurface->GetPositionSize();
274 mCore->SurfaceResized( size.width, size.height );
276 // Initialize the thread controller
277 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();
308 // Process remained events and rendering in the update thread
313 // Dali::Internal::Adaptor::Adaptor::Resume
314 void Adaptor::Resume()
316 // Only resume the adaptor if we are in the suspended state.
317 if( PAUSED == mState )
321 // Reset the event handler when adaptor resumed
324 mEventHandler->Resume();
327 // Inform observers that we have resumed.
328 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
333 // trigger processing of events queued up while paused
334 mCore->ProcessEvents();
336 // Do at end to ensure our first update/render after resumption includes the processed messages as well
337 mThreadController->Resume();
343 if( RUNNING == mState ||
345 PAUSED_WHILE_HIDDEN == mState )
347 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
352 mThreadController->Stop();
354 // Delete the TTS player
355 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
359 mTtsPlayers[i].Reset();
363 delete mEventHandler;
364 mEventHandler = NULL;
366 delete mNotificationTrigger;
367 mNotificationTrigger = NULL;
369 mCallbackManager->Stop();
375 void Adaptor::ContextLost()
377 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
380 void Adaptor::ContextRegained()
382 // Inform core, so that texture resources can be reloaded
383 mCore->RecoverFromContextLoss();
385 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
388 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
390 mEventHandler->FeedTouchPoint( point, timeStamp );
393 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
395 mEventHandler->FeedWheelEvent( wheelEvent );
398 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
400 mEventHandler->FeedKeyEvent( keyEvent );
403 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
405 PositionSize positionSize = surface.GetPositionSize();
407 // let the core know the surface size has changed
408 mCore->SurfaceResized( positionSize.width, positionSize.height );
410 mResizedSignal.Emit( mAdaptor );
412 mNativeWindow = nativeWindow;
415 // flush the event queue to give the update-render thread chance
416 // to start processing messages for new camera setup etc as soon as possible
419 // this method blocks until the render thread has completed the replace.
420 mThreadController->ReplaceSurface(mSurface);
423 RenderSurface& Adaptor::GetSurface() const
428 void Adaptor::ReleaseSurfaceLock()
430 mSurface->ReleaseLock();
433 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
435 if(!mTtsPlayers[mode])
437 // Create the TTS player when it needed, because it can reduce launching time.
438 mTtsPlayers[mode] = TtsPlayer::New(mode);
441 return mTtsPlayers[mode];
444 bool Adaptor::AddIdle( CallbackBase* callback, bool forceAdd )
446 bool idleAdded(false);
448 // Only add an idle if the Adaptor is actually running
449 if( RUNNING == mState || forceAdd )
451 idleAdded = mCallbackManager->AddIdleCallback( callback );
457 void Adaptor::RemoveIdle( CallbackBase* callback )
459 mCallbackManager->RemoveIdleCallback( callback );
462 Dali::Adaptor& Adaptor::Get()
464 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
465 return gThreadLocalAdaptor->mAdaptor;
468 bool Adaptor::IsAvailable()
470 return gThreadLocalAdaptor != NULL;
473 void Adaptor::SceneCreated()
475 mCore->SceneCreated();
478 Dali::Integration::Core& Adaptor::GetCore()
483 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
485 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
488 void Adaptor::SetUseHardwareVSync( bool useHardware )
490 mVSyncMonitor->SetUseHardwareVSync( useHardware );
493 EglFactory& Adaptor::GetEGLFactory() const
495 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
499 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
504 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
506 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
510 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
512 return *mPlatformAbstraction;
515 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
520 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
522 return *mNotificationTrigger;
525 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
527 return mTriggerEventFactory;
530 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
532 return mSocketFactory;
535 RenderSurface* Adaptor::GetRenderSurfaceInterface()
540 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
542 return mVSyncMonitor;
545 TraceInterface& Adaptor::GetKernelTraceInterface()
547 return mKernelTracer;
550 TraceInterface& Adaptor::GetSystemTraceInterface()
552 return mSystemTracer;
555 PerformanceInterface* Adaptor::GetPerformanceInterface()
557 return mPerformanceInterface;
560 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
562 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
563 return *mPlatformAbstraction;
566 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
568 mDragAndDropDetector = detector;
572 mEventHandler->SetDragAndDropDetector( detector );
576 void Adaptor::SetRotationObserver( RotationObserver* observer )
580 mEventHandler->SetRotationObserver( observer );
582 else if( mState == READY )
584 // Set once event handler exists
585 mDeferredRotationObserver = observer;
589 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
591 if(mTtsPlayers[mode])
593 mTtsPlayers[mode].Reset();
597 void Adaptor::SetMinimumPinchDistance(float distance)
599 if( mGestureManager )
601 mGestureManager->SetMinimumPinchDistance(distance);
605 Any Adaptor::GetNativeWindowHandle()
607 return mNativeWindow;
610 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
612 mUseRemoteSurface = useRemoteSurface;
615 void Adaptor::AddObserver( LifeCycleObserver& observer )
617 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
619 if ( match == mObservers.end() )
621 mObservers.push_back( &observer );
625 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
627 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
629 if ( match != mObservers.end() )
631 mObservers.erase( match );
635 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
639 mCore->QueueEvent(event);
643 void Adaptor::ProcessCoreEvents()
647 if( mPerformanceInterface )
649 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
652 mCore->ProcessEvents();
654 if( mPerformanceInterface )
656 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
661 void Adaptor::RequestUpdate( bool forceUpdate )
667 mThreadController->RequestUpdate();
671 case PAUSED_WHILE_HIDDEN:
673 // When Dali applications are partially visible behind the lock-screen,
674 // the indicator must be updated (therefore allow updates in the PAUSED state)
677 mThreadController->RequestUpdateOnce();
689 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
691 // Only request a notification if the Adaptor is actually running
692 // and we haven't installed the idle notification
693 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || forceProcess ) )
695 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
699 void Adaptor::OnWindowShown()
701 if ( PAUSED_WHILE_HIDDEN == mState )
703 // Adaptor can now be resumed
708 // Force a render task
713 void Adaptor::OnWindowHidden()
715 if ( RUNNING == mState )
719 // Adaptor cannot be resumed until the window is shown
720 mState = PAUSED_WHILE_HIDDEN;
724 // Dali::Internal::Adaptor::Adaptor::OnDamaged
725 void Adaptor::OnDamaged( const DamageArea& area )
727 // This is needed for the case where Dali window is partially obscured
728 RequestUpdate( false );
731 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
733 // let the core know the surface size has changed
734 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
736 mResizedSignal.Emit( mAdaptor );
739 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
741 // flush the event queue to give the update-render thread chance
742 // to start processing messages for new camera setup etc as soon as possible
745 // this method blocks until the render thread has completed the resizing.
746 mThreadController->ResizeSurface();
749 void Adaptor::NotifySceneCreated()
751 GetCore().SceneCreated();
753 // Start thread controller after the scene has been created
754 mThreadController->Start();
756 // process after surface is created (registering to remote surface provider if required)
757 SurfaceInitialized();
762 void Adaptor::NotifyLanguageChanged()
764 mLanguageChangedSignal.Emit( mAdaptor );
767 void Adaptor::RenderOnce()
772 void Adaptor::RequestUpdateOnce()
774 if( mThreadController )
776 mThreadController->RequestUpdateOnce();
780 void Adaptor::IndicatorSizeChanged(int height)
782 // let the core know the indicator height is changed
783 mCore->SetTopMargin(height);
786 void Adaptor::ProcessCoreEventsFromIdle()
790 // the idle handle automatically un-installs itself
791 mNotificationOnIdleInstalled = false;
794 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
796 mLanguageChangedSignal(),
800 mThreadController( NULL ),
801 mVSyncMonitor( NULL ),
805 mNativeWindow( nativeWindow ),
807 mPlatformAbstraction( NULL ),
808 mEventHandler( NULL ),
809 mCallbackManager( NULL ),
810 mNotificationOnIdleInstalled( false ),
811 mNotificationTrigger( NULL ),
812 mGestureManager( NULL ),
813 mDaliFeedbackPlugin(),
814 mFeedbackController( NULL ),
817 mDragAndDropDetector(),
818 mDeferredRotationObserver( NULL ),
819 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
820 mPerformanceInterface( NULL ),
823 mTriggerEventFactory(),
824 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 void Adaptor::SetWindow( Dali::Window window )
870 Dali::Window Adaptor::GetWindow()
875 } // namespace Adaptor
877 } // namespace Internal