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();
281 ProcessCoreEvents(); // Ensure any startup messages are processed.
283 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
289 // Dali::Internal::Adaptor::Adaptor::Pause
290 void Adaptor::Pause()
292 // Only pause the adaptor if we're actually running.
293 if( RUNNING == mState )
295 // Inform observers that we are about to be paused.
296 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
301 // Reset the event handler when adaptor paused
304 mEventHandler->Pause();
307 mThreadController->Pause();
311 // Process remained events and rendering in the update thread
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 // Resume core so it processes any requests as well
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();
358 // Delete the TTS player
359 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
363 mTtsPlayers[i].Reset();
367 delete mEventHandler;
368 mEventHandler = NULL;
370 delete mNotificationTrigger;
371 mNotificationTrigger = NULL;
373 mCallbackManager->Stop();
379 void Adaptor::ContextLost()
381 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
384 void Adaptor::ContextRegained()
386 // Inform core, so that texture resources can be reloaded
387 mCore->RecoverFromContextLoss();
389 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
392 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
394 mEventHandler->FeedTouchPoint( point, timeStamp );
397 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
399 mEventHandler->FeedWheelEvent( wheelEvent );
402 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
404 mEventHandler->FeedKeyEvent( keyEvent );
407 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
409 PositionSize positionSize = surface.GetPositionSize();
411 // let the core know the surface size has changed
412 mCore->SurfaceResized( positionSize.width, positionSize.height );
414 mResizedSignal.Emit( mAdaptor );
416 mNativeWindow = nativeWindow;
419 // flush the event queue to give the update-render thread chance
420 // to start processing messages for new camera setup etc as soon as possible
423 // this method blocks until the render thread has completed the replace.
424 mThreadController->ReplaceSurface(mSurface);
427 RenderSurface& Adaptor::GetSurface() const
432 void Adaptor::ReleaseSurfaceLock()
434 mSurface->ReleaseLock();
437 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
439 if(!mTtsPlayers[mode])
441 // Create the TTS player when it needed, because it can reduce launching time.
442 mTtsPlayers[mode] = TtsPlayer::New(mode);
445 return mTtsPlayers[mode];
448 bool Adaptor::AddIdle( CallbackBase* callback )
450 bool idleAdded(false);
452 // Only add an idle if the Adaptor is actually running
453 if( RUNNING == mState )
455 idleAdded = mCallbackManager->AddIdleCallback( callback );
461 void Adaptor::RemoveIdle( CallbackBase* callback )
463 mCallbackManager->RemoveIdleCallback( callback );
466 Dali::Adaptor& Adaptor::Get()
468 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
469 return gThreadLocalAdaptor->mAdaptor;
472 bool Adaptor::IsAvailable()
474 return gThreadLocalAdaptor != NULL;
477 void Adaptor::SceneCreated()
479 mCore->SceneCreated();
482 Dali::Integration::Core& Adaptor::GetCore()
487 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
489 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
492 void Adaptor::SetUseHardwareVSync( bool useHardware )
494 mVSyncMonitor->SetUseHardwareVSync( useHardware );
497 EglFactory& Adaptor::GetEGLFactory() const
499 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
503 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
508 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
510 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
514 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
516 return *mPlatformAbstraction;
519 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
524 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
526 return *mNotificationTrigger;
529 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
531 return mTriggerEventFactory;
534 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
536 return mSocketFactory;
539 RenderSurface* Adaptor::GetRenderSurfaceInterface()
544 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
546 return mVSyncMonitor;
549 TraceInterface& Adaptor::GetKernelTraceInterface()
551 return mKernelTracer;
554 TraceInterface& Adaptor::GetSystemTraceInterface()
556 return mSystemTracer;
559 PerformanceInterface* Adaptor::GetPerformanceInterface()
561 return mPerformanceInterface;
564 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
566 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
567 return *mPlatformAbstraction;
570 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
572 mDragAndDropDetector = detector;
576 mEventHandler->SetDragAndDropDetector( detector );
580 void Adaptor::SetRotationObserver( RotationObserver* observer )
584 mEventHandler->SetRotationObserver( observer );
586 else if( mState == READY )
588 // Set once event handler exists
589 mDeferredRotationObserver = observer;
593 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
595 if(mTtsPlayers[mode])
597 mTtsPlayers[mode].Reset();
601 void Adaptor::SetMinimumPinchDistance(float distance)
603 if( mGestureManager )
605 mGestureManager->SetMinimumPinchDistance(distance);
609 Any Adaptor::GetNativeWindowHandle()
611 return mNativeWindow;
614 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
616 mUseRemoteSurface = useRemoteSurface;
619 void Adaptor::AddObserver( LifeCycleObserver& observer )
621 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
623 if ( match == mObservers.end() )
625 mObservers.push_back( &observer );
629 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
631 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
633 if ( match != mObservers.end() )
635 mObservers.erase( match );
639 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
643 mCore->QueueEvent(event);
647 void Adaptor::ProcessCoreEvents()
651 if( mPerformanceInterface )
653 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
656 mCore->ProcessEvents();
658 if( mPerformanceInterface )
660 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
665 void Adaptor::RequestUpdate()
667 // When Dali applications are partially visible behind the lock-screen,
668 // the indicator must be updated (therefore allow updates in the PAUSED state)
669 if ( PAUSED == mState ||
672 mThreadController->RequestUpdate();
676 void Adaptor::RequestProcessEventsOnIdle()
678 // Only request a notification if the Adaptor is actually running
679 // and we haven't installed the idle notification
680 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
682 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
686 void Adaptor::OnWindowShown()
688 if ( PAUSED_WHILE_HIDDEN == mState )
690 // Adaptor can now be resumed
695 // Force a render task
700 void Adaptor::OnWindowHidden()
702 if ( STOPPED != mState )
706 // Adaptor cannot be resumed until the window is shown
707 mState = PAUSED_WHILE_HIDDEN;
711 // Dali::Internal::Adaptor::Adaptor::OnDamaged
712 void Adaptor::OnDamaged( const DamageArea& area )
714 // This is needed for the case where Dali window is partially obscured
718 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
720 // let the core know the surface size has changed
721 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
723 mResizedSignal.Emit( mAdaptor );
726 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
728 // flush the event queue to give the update-render thread chance
729 // to start processing messages for new camera setup etc as soon as possible
732 // this method blocks until the render thread has completed the resizing.
733 mThreadController->ResizeSurface();
736 void Adaptor::NotifySceneCreated()
738 GetCore().SceneCreated();
740 // Start thread controller after the scene has been created
741 mThreadController->Start();
743 // process after surface is created (registering to remote surface provider if required)
744 SurfaceInitialized();
747 void Adaptor::NotifyLanguageChanged()
749 mLanguageChangedSignal.Emit( mAdaptor );
752 void Adaptor::RenderOnce()
757 void Adaptor::RequestUpdateOnce()
759 if( PAUSED_WHILE_HIDDEN != mState )
761 if( mThreadController )
763 mThreadController->RequestUpdateOnce();
768 void Adaptor::IndicatorSizeChanged(int height)
770 // let the core know the indicator height is changed
771 mCore->SetTopMargin(height);
774 void Adaptor::ProcessCoreEventsFromIdle()
778 // the idle handle automatically un-installs itself
779 mNotificationOnIdleInstalled = false;
782 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
784 mLanguageChangedSignal(),
788 mThreadController( NULL ),
789 mVSyncMonitor( NULL ),
793 mNativeWindow( nativeWindow ),
795 mPlatformAbstraction( NULL ),
796 mEventHandler( NULL ),
797 mCallbackManager( NULL ),
798 mNotificationOnIdleInstalled( false ),
799 mNotificationTrigger( NULL ),
800 mGestureManager( NULL ),
801 mDaliFeedbackPlugin(),
802 mFeedbackController( NULL ),
805 mDragAndDropDetector(),
806 mDeferredRotationObserver( NULL ),
807 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
808 mPerformanceInterface( NULL ),
811 mTriggerEventFactory(),
812 mObjectProfiler( NULL ),
815 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
816 mUseRemoteSurface( false )
818 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
819 gThreadLocalAdaptor = this;
824 void Adaptor::SetViewMode( ViewMode viewMode )
826 mSurface->SetViewMode( viewMode );
827 mCore->SetViewMode( viewMode );
830 ViewMode Adaptor::GetViewMode() const
832 return mCore->GetViewMode();
835 void Adaptor::SetStereoBase( float stereoBase )
837 mCore->SetStereoBase( stereoBase );
840 float Adaptor::GetStereoBase() const
842 return mCore->GetStereoBase();
845 void Adaptor::SetRootLayoutDirection( std::string locale )
847 Dali::Stage stage = Dali::Stage::GetCurrent();
849 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
850 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
853 void Adaptor::SetWindow( Dali::Window window )
858 Dali::Window Adaptor::GetWindow()
863 } // namespace Adaptor
865 } // namespace Internal