2 * Copyright (c) 2016 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/integration-api/debug.h>
24 #include <dali/integration-api/core.h>
25 #include <dali/integration-api/context-notifier.h>
26 #include <dali/integration-api/profiling.h>
27 #include <dali/integration-api/input-options.h>
28 #include <dali/integration-api/events/touch-event-integ.h>
31 #include <base/thread-controller.h>
32 # include <base/performance-logging/performance-interface-factory.h>
33 #include <base/lifecycle-observer.h>
35 #include <dali/devel-api/text-abstraction/font-client.h>
37 #include <callback-manager.h>
38 #include <render-surface.h>
39 #include <tts-player-impl.h>
40 #include <accessibility-adaptor-impl.h>
41 #include <events/gesture-manager.h>
42 #include <events/event-handler.h>
43 #include <gl/gl-proxy-implementation.h>
44 #include <gl/gl-implementation.h>
45 #include <gl/egl-sync-implementation.h>
46 #include <gl/egl-image-extensions.h>
47 #include <gl/egl-factory.h>
48 #include <imf-manager-impl.h>
49 #include <clipboard-impl.h>
50 #include <vsync-monitor.h>
51 #include <object-profiler.h>
52 #include <base/display-connection.h>
53 #include <window-impl.h>
55 #include <tizen-logging.h>
57 using Dali::TextAbstraction::FontClient;
70 __thread Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
71 } // unnamed namespace
73 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
75 Dali::Adaptor* adaptor = new Dali::Adaptor;
76 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
77 adaptor->mImpl = impl;
79 impl->Initialize(configuration);
84 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
86 Any winId = window.GetNativeHandle();
88 Window& windowImpl = Dali::GetImplementation(window);
89 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
90 windowImpl.SetAdaptor(*adaptor);
94 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
96 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
97 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
98 mEnvironmentOptions->SetLogFunction( logFunction );
99 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
101 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
104 GetDataStoragePath( path );
105 mPlatformAbstraction->SetDataStoragePath( path );
107 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
108 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
110 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
112 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
113 // files automatically.
115 if( mEnvironmentOptions->PerformanceServerRequired() )
117 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
120 mCallbackManager = CallbackManager::New();
122 PositionSize size = mSurface->GetPositionSize();
124 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
126 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
128 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
132 mGLES = new GlImplementation();
135 mEglFactory = new EglFactory();
137 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
139 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
141 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
142 if( 0u < timeInterval )
144 mObjectProfiler = new ObjectProfiler( timeInterval );
147 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
149 mVSyncMonitor = new VSyncMonitor;
151 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
153 // Should be called after Core creation
154 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
156 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
158 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
160 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
162 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
164 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
166 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
168 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
170 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
172 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
174 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
176 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
178 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
180 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
182 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
184 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
190 // Ensure stop status
193 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
194 gThreadLocalAdaptor = NULL;
196 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
198 (*iter)->OnDestroy();
201 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
202 delete mVSyncMonitor;
203 delete mEventHandler;
204 delete mObjectProfiler;
209 delete mGestureManager;
210 delete mPlatformAbstraction;
211 delete mCallbackManager;
212 delete mPerformanceInterface;
214 // uninstall it on this thread (main actor thread)
215 Dali::Integration::Log::UninstallLogFunction();
217 // Delete environment options if we own it
218 if( mEnvironmentOptionsOwned )
220 delete mEnvironmentOptions;
224 void Adaptor::Start()
226 // it doesn't support restart after stop at this moment
227 // to support restarting, need more testing
228 if( READY != mState )
233 // Start the callback manager
234 mCallbackManager->Start();
236 // create event handler
237 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
239 if( mDeferredRotationObserver != NULL )
241 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
242 mDeferredRotationObserver = NULL;
245 unsigned int dpiHor, dpiVer;
247 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
249 // tell core about the DPI value
250 mCore->SetDpi(dpiHor, dpiVer);
252 // set the DPI value for font rendering
253 FontClient fontClient = FontClient::Get();
254 fontClient.SetDpi( dpiHor, dpiVer );
256 // Tell the core the size of the surface just before we start the render-thread
257 PositionSize size = mSurface->GetPositionSize();
258 mCore->SurfaceResized( size.width, size.height );
260 // Initialize the thread controller
261 mThreadController->Initialize();
265 ProcessCoreEvents(); // Ensure any startup messages are processed.
267 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
273 // Dali::Internal::Adaptor::Adaptor::Pause
274 void Adaptor::Pause()
276 // Only pause the adaptor if we're actually running.
277 if( RUNNING == mState )
279 // Inform observers that we are about to be paused.
280 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
285 // Reset the event handler when adaptor paused
288 mEventHandler->Pause();
291 mThreadController->Pause();
297 // Dali::Internal::Adaptor::Adaptor::Resume
298 void Adaptor::Resume()
300 // Only resume the adaptor if we are in the suspended state.
301 if( PAUSED == mState )
305 // Reset the event handler when adaptor resumed
308 mEventHandler->Resume();
311 // Inform observers that we have resumed.
312 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
317 // Resume core so it processes any requests as well
320 // Do at end to ensure our first update/render after resumption includes the processed messages as well
321 mThreadController->Resume();
327 if( RUNNING == mState ||
329 PAUSED_WHILE_HIDDEN == mState )
331 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
336 mThreadController->Stop();
339 // Delete the TTS player
340 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
344 mTtsPlayers[i].Reset();
348 delete mEventHandler;
349 mEventHandler = NULL;
351 delete mNotificationTrigger;
352 mNotificationTrigger = NULL;
354 mCallbackManager->Stop();
360 void Adaptor::ContextLost()
362 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
365 void Adaptor::ContextRegained()
367 // Inform core, so that texture resources can be reloaded
368 mCore->RecoverFromContextLoss();
370 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
373 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
375 mEventHandler->FeedTouchPoint( point, timeStamp );
378 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
380 mEventHandler->FeedWheelEvent( wheelEvent );
383 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
385 mEventHandler->FeedKeyEvent( keyEvent );
388 bool Adaptor::MoveResize( const PositionSize& positionSize )
390 PositionSize old = mSurface->GetPositionSize();
392 // just resize the surface. The driver should automatically resize the egl Surface (untested)
393 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
394 // is resized. Implementations typically use hooks into the OS and native window
395 // system to perform this resizing on demand, transparently to the client.
396 mSurface->MoveResize( positionSize );
398 if(old.width != positionSize.width || old.height != positionSize.height)
400 SurfaceSizeChanged(positionSize);
406 void Adaptor::SurfaceResized( const PositionSize& positionSize )
408 PositionSize old = mSurface->GetPositionSize();
410 // Called by an application, when it has resized a window outside of Dali.
411 // The EGL driver automatically detects X Window resize calls, and resizes
412 // the EGL surface for us.
413 mSurface->MoveResize( positionSize );
415 if(old.width != positionSize.width || old.height != positionSize.height)
417 SurfaceSizeChanged(positionSize);
421 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
423 mNativeWindow = nativeWindow;
426 // flush the event queue to give update and render threads chance
427 // to start processing messages for new camera setup etc as soon as possible
430 // this method blocks until the render thread has completed the replace.
431 mThreadController->ReplaceSurface(mSurface);
434 RenderSurface& Adaptor::GetSurface() const
439 void Adaptor::ReleaseSurfaceLock()
441 mSurface->ReleaseLock();
444 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
446 if(!mTtsPlayers[mode])
448 // Create the TTS player when it needed, because it can reduce launching time.
449 mTtsPlayers[mode] = TtsPlayer::New(mode);
452 return mTtsPlayers[mode];
455 bool Adaptor::AddIdle( CallbackBase* callback )
457 bool idleAdded(false);
459 // Only add an idle if the Adaptor is actually running
460 if( RUNNING == mState )
462 idleAdded = mCallbackManager->AddIdleCallback( callback );
468 void Adaptor::RemoveIdle( CallbackBase* callback )
470 mCallbackManager->RemoveIdleCallback( callback );
473 Dali::Adaptor& Adaptor::Get()
475 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
476 return gThreadLocalAdaptor->mAdaptor;
479 bool Adaptor::IsAvailable()
481 return gThreadLocalAdaptor != NULL;
484 void Adaptor::SceneCreated()
486 mCore->SceneCreated();
489 Dali::Integration::Core& Adaptor::GetCore()
494 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
496 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
499 void Adaptor::SetUseHardwareVSync( bool useHardware )
501 mVSyncMonitor->SetUseHardwareVSync( useHardware );
504 EglFactory& Adaptor::GetEGLFactory() const
506 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
510 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
515 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
517 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
521 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
523 return *mPlatformAbstraction;
526 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
531 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
533 return *mNotificationTrigger;
536 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
538 return mTriggerEventFactory;
541 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
543 return mSocketFactory;
546 RenderSurface* Adaptor::GetRenderSurfaceInterface()
551 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
553 return mVSyncMonitor;
556 TraceInterface& Adaptor::GetKernelTraceInterface()
558 return mKernelTracer;
561 TraceInterface& Adaptor::GetSystemTraceInterface()
563 return mSystemTracer;
566 PerformanceInterface* Adaptor::GetPerformanceInterface()
568 return mPerformanceInterface;
571 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
573 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
574 return *mPlatformAbstraction;
577 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
579 mDragAndDropDetector = detector;
583 mEventHandler->SetDragAndDropDetector( detector );
587 void Adaptor::SetRotationObserver( RotationObserver* observer )
591 mEventHandler->SetRotationObserver( observer );
593 else if( mState == READY )
595 // Set once event handler exists
596 mDeferredRotationObserver = observer;
600 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
602 if(mTtsPlayers[mode])
604 mTtsPlayers[mode].Reset();
608 void Adaptor::SetMinimumPinchDistance(float distance)
610 if( mGestureManager )
612 mGestureManager->SetMinimumPinchDistance(distance);
616 Any Adaptor::GetNativeWindowHandle()
618 return mNativeWindow;
621 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
623 mUseRemoteSurface = useRemoteSurface;
626 void Adaptor::AddObserver( LifeCycleObserver& observer )
628 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
630 if ( match == mObservers.end() )
632 mObservers.push_back( &observer );
636 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
638 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
640 if ( match != mObservers.end() )
642 mObservers.erase( match );
646 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
650 mCore->QueueEvent(event);
654 void Adaptor::ProcessCoreEvents()
658 if( mPerformanceInterface )
660 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
663 mCore->ProcessEvents();
665 if( mPerformanceInterface )
667 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
672 void Adaptor::RequestUpdate()
674 // When Dali applications are partially visible behind the lock-screen,
675 // the indicator must be updated (therefore allow updates in the PAUSED state)
676 if ( PAUSED == mState ||
679 mThreadController->RequestUpdate();
683 void Adaptor::RequestProcessEventsOnIdle()
685 // Only request a notification if the Adaptor is actually running
686 // and we haven't installed the idle notification
687 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
689 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
693 void Adaptor::OnWindowShown()
695 if ( PAUSED_WHILE_HIDDEN == mState )
697 // Adaptor can now be resumed
702 // Force a render task
707 void Adaptor::OnWindowHidden()
709 if ( STOPPED != mState )
713 // Adaptor cannot be resumed until the window is shown
714 mState = PAUSED_WHILE_HIDDEN;
718 // Dali::Internal::Adaptor::Adaptor::OnDamaged
719 void Adaptor::OnDamaged( const DamageArea& area )
721 // This is needed for the case where Dali window is partially obscured
725 void Adaptor::SurfaceSizeChanged( const PositionSize& positionSize )
727 // let the core know the surface size has changed
728 mCore->SurfaceResized(positionSize.width, positionSize.height);
730 mResizedSignal.Emit( mAdaptor );
733 void Adaptor::NotifySceneCreated()
735 GetCore().SceneCreated();
737 // Start thread controller after the scene has been created
738 mThreadController->Start();
740 // process after surface is created (registering to remote surface provider if required)
741 SurfaceInitialized();
744 void Adaptor::NotifyLanguageChanged()
746 mLanguageChangedSignal.Emit( mAdaptor );
749 void Adaptor::RequestUpdateOnce()
751 if( PAUSED_WHILE_HIDDEN != mState )
753 if( mThreadController )
755 mThreadController->RequestUpdateOnce();
760 void Adaptor::IndicatorSizeChanged(int height)
762 // let the core know the indicator height is changed
763 mCore->SetTopMargin(height);
766 void Adaptor::ProcessCoreEventsFromIdle()
770 // the idle handle automatically un-installs itself
771 mNotificationOnIdleInstalled = false;
774 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
776 mLanguageChangedSignal(),
780 mThreadController( NULL ),
781 mVSyncMonitor( NULL ),
785 mNativeWindow( nativeWindow ),
787 mPlatformAbstraction( NULL ),
788 mEventHandler( NULL ),
789 mCallbackManager( NULL ),
790 mNotificationOnIdleInstalled( false ),
791 mNotificationTrigger( NULL ),
792 mGestureManager( NULL ),
793 mDaliFeedbackPlugin(),
794 mFeedbackController( NULL ),
797 mDragAndDropDetector(),
798 mDeferredRotationObserver( NULL ),
799 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
800 mPerformanceInterface( NULL ),
803 mTriggerEventFactory(),
804 mObjectProfiler( NULL ),
806 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
807 mUseRemoteSurface( false )
809 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
810 gThreadLocalAdaptor = this;
815 void Adaptor::SetViewMode( ViewMode viewMode )
817 mSurface->SetViewMode( viewMode );
818 mCore->SetViewMode( viewMode );
821 ViewMode Adaptor::GetViewMode() const
823 return mCore->GetViewMode();
826 void Adaptor::SetStereoBase( float stereoBase )
828 mCore->SetStereoBase( stereoBase );
831 float Adaptor::GetStereoBase() const
833 return mCore->GetStereoBase();
836 } // namespace Adaptor
838 } // namespace Internal