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/update-render-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 <trigger-event.h>
39 #include <render-surface.h>
40 #include <tts-player-impl.h>
41 #include <accessibility-manager-impl.h>
42 #include <events/gesture-manager.h>
43 #include <events/event-handler.h>
44 #include <feedback/feedback-controller.h>
45 #include <feedback/feedback-plugin-proxy.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>
60 using Dali::TextAbstraction::FontClient;
73 __thread Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
74 } // unnamed namespace
76 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
78 Dali::Adaptor* adaptor = new Dali::Adaptor;
79 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
80 adaptor->mImpl = impl;
82 impl->Initialize(configuration);
87 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
89 Any winId = window.GetNativeHandle();
91 Window& windowImpl = Dali::GetImplementation(window);
92 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
93 windowImpl.SetAdaptor(*adaptor);
97 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
99 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
100 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
101 mEnvironmentOptions->SetLogFunction( logFunction );
102 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
104 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
107 GetDataStoragePath( path );
108 mPlatformAbstraction->SetDataStoragePath( path );
110 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
111 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
113 dataRetentionPolicy = ResourcePolicy::DALI_RETAINS_MESH_DATA;
115 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
116 // files automatically.
118 if( mEnvironmentOptions->PerformanceServerRequired() )
120 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
123 mCallbackManager = CallbackManager::New();
125 PositionSize size = mSurface->GetPositionSize();
127 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
129 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
131 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
135 mGLES = new GlImplementation();
138 mEglFactory = new EglFactory();
140 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
142 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
144 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
145 if( 0u < timeInterval )
147 mObjectProfiler = new ObjectProfiler( timeInterval );
150 mNotificationTrigger = new TriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ) );
152 mVSyncMonitor = new VSyncMonitor;
154 mUpdateRenderController = new UpdateRenderController( *this, *mEnvironmentOptions );
156 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
158 // Should be called after Core creation
159 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
161 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
163 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
165 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
167 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
169 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
171 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
173 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
175 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
177 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
179 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
181 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
183 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
185 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
187 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
189 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
195 // Ensure stop status
198 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
199 gThreadLocalAdaptor = NULL;
201 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
203 (*iter)->OnDestroy();
206 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
207 delete mVSyncMonitor;
208 delete mEventHandler;
209 delete mObjectProfiler;
213 // Delete feedback controller before feedback plugin & style monitor dependencies
214 delete mFeedbackController;
215 delete mDaliFeedbackPlugin;
217 delete mGestureManager;
218 delete mPlatformAbstraction;
219 delete mCallbackManager;
220 delete mPerformanceInterface;
222 // uninstall it on this thread (main actor thread)
223 Dali::Integration::Log::UninstallLogFunction();
225 // Delete environment options if we own it
226 if( mEnvironmentOptionsOwned )
228 delete mEnvironmentOptions;
232 void Adaptor::Start()
234 // it doesn't support restart after stop at this moment
235 // to support restarting, need more testing
236 if( READY != mState )
241 // Start the callback manager
242 mCallbackManager->Start();
244 // create event handler
245 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
247 if( mDeferredRotationObserver != NULL )
249 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
250 mDeferredRotationObserver = NULL;
253 unsigned int dpiHor, dpiVer;
255 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
257 // tell core about the DPI value
258 mCore->SetDpi(dpiHor, dpiVer);
260 // set the DPI value for font rendering
261 FontClient fontClient = FontClient::Get();
262 fontClient.SetDpi( dpiHor, dpiVer );
264 // Tell the core the size of the surface just before we start the render-thread
265 PositionSize size = mSurface->GetPositionSize();
266 mCore->SurfaceResized( size.width, size.height );
268 // Start the update & render threads
269 mUpdateRenderController->Start();
273 ProcessCoreEvents(); // Ensure any startup messages are processed.
275 if ( !mFeedbackController )
277 // Start sound & haptic feedback
278 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
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->Reset();
305 mUpdateRenderController->Pause();
311 // Dali::Internal::Adaptor::Adaptor::Resume
312 void Adaptor::Resume()
314 // Only resume the adaptor if we are in the suspended state.
315 if( PAUSED == mState )
317 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
318 // If there were events pending, mCore->Resume() will call
319 // RenderController->RequestUpdate()
320 // UpdateRenderController->RequestUpdate()
321 // UpdateRenderSynchronization->RequestUpdate()
322 // and we should have reset the frame timers before allowing Core->Update() to be called.
323 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
325 mUpdateRenderController->ResumeFrameTime();
327 mUpdateRenderController->Resume();
331 // Reset the event handler when adaptor resumed
334 mEventHandler->Reset();
337 // Inform observers that we have resumed.
338 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
343 ProcessCoreEvents(); // Ensure any outstanding messages are processed
349 if( RUNNING == mState ||
351 PAUSED_WHILE_HIDDEN == mState )
353 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
358 mUpdateRenderController->Stop();
361 // Delete the TTS player
362 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
366 mTtsPlayers[i].Reset();
370 delete mEventHandler;
371 mEventHandler = NULL;
373 delete mNotificationTrigger;
374 mNotificationTrigger = NULL;
376 mCallbackManager->Stop();
382 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
384 mEventHandler->FeedTouchPoint( point, timeStamp );
387 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
389 mEventHandler->FeedWheelEvent( wheelEvent );
392 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
394 mEventHandler->FeedKeyEvent( keyEvent );
397 bool Adaptor::MoveResize( const PositionSize& positionSize )
399 PositionSize old = mSurface->GetPositionSize();
401 // just resize the surface. The driver should automatically resize the egl Surface (untested)
402 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
403 // is resized. Implementations typically use hooks into the OS and native window
404 // system to perform this resizing on demand, transparently to the client.
405 mSurface->MoveResize( positionSize );
407 if(old.width != positionSize.width || old.height != positionSize.height)
409 SurfaceSizeChanged(positionSize);
415 void Adaptor::SurfaceResized( const PositionSize& positionSize )
417 PositionSize old = mSurface->GetPositionSize();
419 // Called by an application, when it has resized a window outside of Dali.
420 // The EGL driver automatically detects X Window resize calls, and resizes
421 // the EGL surface for us.
422 mSurface->MoveResize( positionSize );
424 if(old.width != positionSize.width || old.height != positionSize.height)
426 SurfaceSizeChanged(positionSize);
430 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
432 mNativeWindow = nativeWindow;
435 SurfaceSizeChanged(mSurface->GetPositionSize());
437 // flush the event queue to give update and render threads chance
438 // to start processing messages for new camera setup etc as soon as possible
441 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
443 // this method blocks until the render thread has completed the replace.
444 mUpdateRenderController->ReplaceSurface(mSurface);
446 // Inform core, so that texture resources can be reloaded
447 mCore->RecoverFromContextLoss();
449 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
452 RenderSurface& Adaptor::GetSurface() const
457 void Adaptor::ReleaseSurfaceLock()
459 mSurface->ReleaseLock();
462 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
464 if(!mTtsPlayers[mode])
466 // Create the TTS player when it needed, because it can reduce launching time.
467 mTtsPlayers[mode] = TtsPlayer::New(mode);
470 return mTtsPlayers[mode];
473 bool Adaptor::AddIdle( CallbackBase* callback )
475 bool idleAdded(false);
477 // Only add an idle if the Adaptor is actually running
478 if( RUNNING == mState )
480 idleAdded = mCallbackManager->AddCallback( callback, CallbackManager::IDLE_PRIORITY );
486 bool Adaptor::CallFromMainLoop( CallbackBase* callback )
488 bool callAdded(false);
490 // Only allow the callback if the Adaptor is actually running
491 if ( RUNNING == mState )
493 callAdded = mCallbackManager->AddCallback( callback, CallbackManager::DEFAULT_PRIORITY );
499 Dali::Adaptor& Adaptor::Get()
501 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
502 return gThreadLocalAdaptor->mAdaptor;
505 bool Adaptor::IsAvailable()
507 return gThreadLocalAdaptor != NULL;
510 Dali::Integration::Core& Adaptor::GetCore()
515 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
517 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
520 void Adaptor::SetUseHardwareVSync( bool useHardware )
522 mVSyncMonitor->SetUseHardwareVSync( useHardware );
525 EglFactory& Adaptor::GetEGLFactory() const
527 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
531 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
536 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
538 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
542 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
544 return *mPlatformAbstraction;
547 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
552 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
554 return *mNotificationTrigger;
557 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
559 return mTriggerEventFactory;
562 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
564 return mSocketFactory;
567 RenderSurface* Adaptor::GetRenderSurfaceInterface()
572 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
574 return mVSyncMonitor;
577 TraceInterface& Adaptor::GetKernelTraceInterface()
579 return mKernelTracer;
582 TraceInterface& Adaptor::GetSystemTraceInterface()
584 return mSystemTracer;
587 PerformanceInterface* Adaptor::GetPerformanceInterface()
589 return mPerformanceInterface;
592 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
594 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
595 return *mPlatformAbstraction;
598 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
600 mDragAndDropDetector = detector;
604 mEventHandler->SetDragAndDropDetector( detector );
608 void Adaptor::SetRotationObserver( RotationObserver* observer )
612 mEventHandler->SetRotationObserver( observer );
614 else if( mState == READY )
616 // Set once event handler exists
617 mDeferredRotationObserver = observer;
621 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
623 if(mTtsPlayers[mode])
625 mTtsPlayers[mode].Reset();
629 void Adaptor::SetMinimumPinchDistance(float distance)
631 if( mGestureManager )
633 mGestureManager->SetMinimumPinchDistance(distance);
637 Any Adaptor::GetNativeWindowHandle()
639 return mNativeWindow;
642 void Adaptor::AddObserver( LifeCycleObserver& observer )
644 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
646 if ( match == mObservers.end() )
648 mObservers.push_back( &observer );
652 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
654 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
656 if ( match != mObservers.end() )
658 mObservers.erase( match );
662 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
666 mCore->QueueEvent(event);
670 void Adaptor::ProcessCoreEvents()
674 if( mPerformanceInterface )
676 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
679 mCore->ProcessEvents();
681 if( mPerformanceInterface )
683 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
688 void Adaptor::RequestUpdate()
690 // When Dali applications are partially visible behind the lock-screen,
691 // the indicator must be updated (therefore allow updates in the PAUSED state)
692 if ( PAUSED == mState ||
695 mUpdateRenderController->RequestUpdate();
699 void Adaptor::RequestProcessEventsOnIdle()
701 // Only request a notification if the Adaptor is actually running
702 // and we haven't installed the idle notification
703 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
705 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
709 void Adaptor::OnWindowShown()
711 if ( PAUSED_WHILE_HIDDEN == mState )
713 // Adaptor can now be resumed
718 // Force a render task
723 void Adaptor::OnWindowHidden()
725 if ( STOPPED != mState )
729 // Adaptor cannot be resumed until the window is shown
730 mState = PAUSED_WHILE_HIDDEN;
734 // Dali::Internal::Adaptor::Adaptor::OnDamaged
735 void Adaptor::OnDamaged( const DamageArea& area )
737 // This is needed for the case where Dali window is partially obscured
741 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
743 // let the core know the surface size has changed
744 mCore->SurfaceResized(positionSize.width, positionSize.height);
746 mResizedSignal.Emit( mAdaptor );
749 void Adaptor::NotifySceneCreated()
751 GetCore().SceneCreated();
754 void Adaptor::NotifyLanguageChanged()
756 mLanguageChangedSignal.Emit( mAdaptor );
759 void Adaptor::RequestUpdateOnce()
761 if( PAUSED_WHILE_HIDDEN != mState )
763 if( mUpdateRenderController )
765 mUpdateRenderController->RequestUpdateOnce();
770 void Adaptor::ProcessCoreEventsFromIdle()
774 // the idle handle automatically un-installs itself
775 mNotificationOnIdleInstalled = false;
778 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
780 mLanguageChangedSignal(),
784 mUpdateRenderController(NULL),
788 mNativeWindow( nativeWindow ),
790 mPlatformAbstraction( NULL ),
791 mEventHandler( NULL ),
792 mCallbackManager( NULL ),
793 mNotificationOnIdleInstalled( false ),
794 mNotificationTrigger(NULL),
795 mGestureManager(NULL),
796 mDaliFeedbackPlugin(NULL),
797 mFeedbackController(NULL),
799 mDragAndDropDetector(),
800 mDeferredRotationObserver(NULL),
801 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
802 mPerformanceInterface(NULL),
803 mObjectProfiler(NULL),
804 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
806 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
807 gThreadLocalAdaptor = this;
812 void Adaptor::SetViewMode( ViewMode viewMode )
814 mSurface->SetViewMode( viewMode );
815 mCore->SetViewMode( viewMode );
818 ViewMode Adaptor::GetViewMode() const
820 return mCore->GetViewMode();
823 void Adaptor::SetStereoBase( float stereoBase )
825 mCore->SetStereoBase( stereoBase );
828 float Adaptor::GetStereoBase() const
830 return mCore->GetStereoBase();
833 } // namespace Adaptor
835 } // namespace Internal