2 * Copyright (c) 2015 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 )
308 // Reset the event handler when adaptor resumed
311 mEventHandler->Resume();
314 // Inform observers that we have resumed.
315 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
320 ProcessCoreEvents(); // Ensure any outstanding messages are processed
322 // Ensure our first update includes the processed messages
323 mThreadController->Resume();
329 if( RUNNING == mState ||
331 PAUSED_WHILE_HIDDEN == mState )
333 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
338 mThreadController->Stop();
341 // Delete the TTS player
342 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
346 mTtsPlayers[i].Reset();
350 delete mEventHandler;
351 mEventHandler = NULL;
353 delete mNotificationTrigger;
354 mNotificationTrigger = NULL;
356 mCallbackManager->Stop();
362 void Adaptor::ContextLost()
364 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
367 void Adaptor::ContextRegained()
369 // Inform core, so that texture resources can be reloaded
370 mCore->RecoverFromContextLoss();
372 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
375 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
377 mEventHandler->FeedTouchPoint( point, timeStamp );
380 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
382 mEventHandler->FeedWheelEvent( wheelEvent );
385 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
387 mEventHandler->FeedKeyEvent( keyEvent );
390 bool Adaptor::MoveResize( const PositionSize& positionSize )
392 PositionSize old = mSurface->GetPositionSize();
394 // just resize the surface. The driver should automatically resize the egl Surface (untested)
395 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
396 // is resized. Implementations typically use hooks into the OS and native window
397 // system to perform this resizing on demand, transparently to the client.
398 mSurface->MoveResize( positionSize );
400 if(old.width != positionSize.width || old.height != positionSize.height)
402 SurfaceSizeChanged(positionSize);
408 void Adaptor::SurfaceResized( const PositionSize& positionSize )
410 PositionSize old = mSurface->GetPositionSize();
412 // Called by an application, when it has resized a window outside of Dali.
413 // The EGL driver automatically detects X Window resize calls, and resizes
414 // the EGL surface for us.
415 mSurface->MoveResize( positionSize );
417 if(old.width != positionSize.width || old.height != positionSize.height)
419 SurfaceSizeChanged(positionSize);
423 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
425 mNativeWindow = nativeWindow;
428 SurfaceSizeChanged(mSurface->GetPositionSize());
430 // flush the event queue to give update and render threads chance
431 // to start processing messages for new camera setup etc as soon as possible
434 // this method blocks until the render thread has completed the replace.
435 mThreadController->ReplaceSurface(mSurface);
438 RenderSurface& Adaptor::GetSurface() const
443 void Adaptor::ReleaseSurfaceLock()
445 mSurface->ReleaseLock();
448 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
450 if(!mTtsPlayers[mode])
452 // Create the TTS player when it needed, because it can reduce launching time.
453 mTtsPlayers[mode] = TtsPlayer::New(mode);
456 return mTtsPlayers[mode];
459 bool Adaptor::AddIdle( CallbackBase* callback )
461 bool idleAdded(false);
463 // Only add an idle if the Adaptor is actually running
464 if( RUNNING == mState )
466 idleAdded = mCallbackManager->AddIdleCallback( 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::AddObserver( LifeCycleObserver& observer )
623 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
625 if ( match == mObservers.end() )
627 mObservers.push_back( &observer );
631 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
633 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
635 if ( match != mObservers.end() )
637 mObservers.erase( match );
641 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
645 mCore->QueueEvent(event);
649 void Adaptor::ProcessCoreEvents()
653 if( mPerformanceInterface )
655 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
658 mCore->ProcessEvents();
660 if( mPerformanceInterface )
662 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
667 void Adaptor::RequestUpdate()
669 // When Dali applications are partially visible behind the lock-screen,
670 // the indicator must be updated (therefore allow updates in the PAUSED state)
671 if ( PAUSED == mState ||
674 mThreadController->RequestUpdate();
678 void Adaptor::RequestProcessEventsOnIdle()
680 // Only request a notification if the Adaptor is actually running
681 // and we haven't installed the idle notification
682 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
684 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
688 void Adaptor::OnWindowShown()
690 if ( PAUSED_WHILE_HIDDEN == mState )
692 // Adaptor can now be resumed
697 // Force a render task
702 void Adaptor::OnWindowHidden()
704 if ( STOPPED != mState )
708 // Adaptor cannot be resumed until the window is shown
709 mState = PAUSED_WHILE_HIDDEN;
713 // Dali::Internal::Adaptor::Adaptor::OnDamaged
714 void Adaptor::OnDamaged( const DamageArea& area )
716 // This is needed for the case where Dali window is partially obscured
720 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
722 // let the core know the surface size has changed
723 mCore->SurfaceResized(positionSize.width, positionSize.height);
725 mResizedSignal.Emit( mAdaptor );
728 void Adaptor::NotifySceneCreated()
730 GetCore().SceneCreated();
732 // Start thread controller after the scene has been created
733 mThreadController->Start();
736 void Adaptor::NotifyLanguageChanged()
738 mLanguageChangedSignal.Emit( mAdaptor );
741 void Adaptor::RequestUpdateOnce()
743 if( PAUSED_WHILE_HIDDEN != mState )
745 if( mThreadController )
747 mThreadController->RequestUpdateOnce();
752 void Adaptor::ProcessCoreEventsFromIdle()
756 // the idle handle automatically un-installs itself
757 mNotificationOnIdleInstalled = false;
760 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
762 mLanguageChangedSignal(),
766 mThreadController(NULL),
770 mNativeWindow( nativeWindow ),
772 mPlatformAbstraction( NULL ),
773 mEventHandler( NULL ),
774 mCallbackManager( NULL ),
775 mNotificationOnIdleInstalled( false ),
776 mNotificationTrigger(NULL),
777 mGestureManager(NULL),
779 mDragAndDropDetector(),
780 mDeferredRotationObserver(NULL),
781 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
782 mPerformanceInterface(NULL),
783 mObjectProfiler(NULL),
784 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
786 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
787 gThreadLocalAdaptor = this;
792 void Adaptor::SetViewMode( ViewMode viewMode )
794 mSurface->SetViewMode( viewMode );
795 mCore->SetViewMode( viewMode );
798 ViewMode Adaptor::GetViewMode() const
800 return mCore->GetViewMode();
803 void Adaptor::SetStereoBase( float stereoBase )
805 mCore->SetStereoBase( stereoBase );
808 float Adaptor::GetStereoBase() const
810 return mCore->GetStereoBase();
813 } // namespace Adaptor
815 } // namespace Internal