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>
57 #include <tizen-logging.h>
59 using Dali::TextAbstraction::FontClient;
72 __thread Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
73 } // unnamed namespace
75 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration )
77 Dali::Adaptor* adaptor = new Dali::Adaptor;
78 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface );
79 adaptor->mImpl = impl;
81 impl->Initialize(configuration);
87 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
89 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
90 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
91 mEnvironmentOptions.SetLogFunction( logFunction );
92 mEnvironmentOptions.InstallLogFunction(); // install logging for main thread
94 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
97 GetDataStoragePath( path );
98 mPlatformAbstraction->SetDataStoragePath( path );
100 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
101 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
103 dataRetentionPolicy = ResourcePolicy::DALI_RETAINS_MESH_DATA;
105 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
106 // files automatically.
108 if( mEnvironmentOptions.PerformanceServerRequired() )
110 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
113 mCallbackManager = CallbackManager::New();
115 PositionSize size = mSurface->GetPositionSize();
117 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, mEnvironmentOptions);
119 if( mEnvironmentOptions.GetGlesCallTime() > 0 )
121 mGLES = new GlProxyImplementation( mEnvironmentOptions );
125 mGLES = new GlImplementation();
128 mEglFactory = new EglFactory();
130 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
132 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
134 mObjectProfiler = new ObjectProfiler();
136 mNotificationTrigger = new TriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ) );
138 mVSyncMonitor = new VSyncMonitor;
140 mUpdateRenderController = new UpdateRenderController( *this, mEnvironmentOptions );
142 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
144 // Should be called after Core creation
145 if( mEnvironmentOptions.GetPanGestureLoggingLevel() )
147 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
149 if( mEnvironmentOptions.GetPanGesturePredictionMode() >= 0 )
151 Integration::SetPanGesturePredictionMode(mEnvironmentOptions.GetPanGesturePredictionMode());
153 if( mEnvironmentOptions.GetPanGesturePredictionAmount() >= 0 )
155 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions.GetPanGesturePredictionAmount());
157 if( mEnvironmentOptions.GetPanGestureMaximumPredictionAmount() >= 0 )
159 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions.GetPanGestureMaximumPredictionAmount());
161 if( mEnvironmentOptions.GetPanGestureMinimumPredictionAmount() >= 0 )
163 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions.GetPanGestureMinimumPredictionAmount());
165 if( mEnvironmentOptions.GetPanGesturePredictionAmountAdjustment() >= 0 )
167 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions.GetPanGesturePredictionAmountAdjustment());
169 if( mEnvironmentOptions.GetPanGestureSmoothingMode() >= 0 )
171 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions.GetPanGestureSmoothingMode());
173 if( mEnvironmentOptions.GetPanGestureSmoothingAmount() >= 0.0f )
175 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions.GetPanGestureSmoothingAmount());
177 if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
179 SurfaceResized( PositionSize( 0, 0, mEnvironmentOptions.GetWindowWidth(), mEnvironmentOptions.GetWindowHeight() ));
185 // Ensure stop status
188 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
189 gThreadLocalAdaptor = NULL;
191 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
193 (*iter)->OnDestroy();
196 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
197 delete mVSyncMonitor;
198 delete mEventHandler;
199 delete mObjectProfiler;
203 // Delete feedback controller before feedback plugin & style monitor dependencies
204 delete mFeedbackController;
205 delete mDaliFeedbackPlugin;
207 delete mGestureManager;
208 delete mPlatformAbstraction;
209 delete mCallbackManager;
210 delete mPerformanceInterface;
212 // uninstall it on this thread (main actor thread)
213 Dali::Integration::Log::UninstallLogFunction();
216 void Adaptor::Start()
218 // it doesn't support restart after stop at this moment
219 // to support restarting, need more testing
220 if( READY != mState )
225 // Start the callback manager
226 mCallbackManager->Start();
228 // create event handler
229 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
231 if( mDeferredRotationObserver != NULL )
233 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
234 mDeferredRotationObserver = NULL;
237 unsigned int dpiHor, dpiVer;
239 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
241 // tell core about the DPI value
242 mCore->SetDpi(dpiHor, dpiVer);
244 // set the DPI value for font rendering
245 FontClient fontClient = FontClient::Get();
246 fontClient.SetDpi( dpiHor, dpiVer );
248 // Tell the core the size of the surface just before we start the render-thread
249 PositionSize size = mSurface->GetPositionSize();
250 mCore->SurfaceResized( size.width, size.height );
252 // Start the update & render threads
253 mUpdateRenderController->Start();
257 ProcessCoreEvents(); // Ensure any startup messages are processed.
259 if ( !mFeedbackController )
261 // Start sound & haptic feedback
262 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
265 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
271 // Dali::Internal::Adaptor::Adaptor::Pause
272 void Adaptor::Pause()
274 // Only pause the adaptor if we're actually running.
275 if( RUNNING == mState )
277 // Inform observers that we are about to be paused.
278 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
283 // Reset the event handler when adaptor paused
286 mEventHandler->Reset();
289 mUpdateRenderController->Pause();
295 // Dali::Internal::Adaptor::Adaptor::Resume
296 void Adaptor::Resume()
298 // Only resume the adaptor if we are in the suspended state.
299 if( PAUSED == mState )
301 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
302 // If there were events pending, mCore->Resume() will call
303 // RenderController->RequestUpdate()
304 // UpdateRenderController->RequestUpdate()
305 // UpdateRenderSynchronization->RequestUpdate()
306 // and we should have reset the frame timers before allowing Core->Update() to be called.
307 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
309 mUpdateRenderController->ResumeFrameTime();
311 mUpdateRenderController->Resume();
315 // Reset the event handler when adaptor resumed
318 mEventHandler->Reset();
321 // Inform observers that we have resumed.
322 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
327 ProcessCoreEvents(); // Ensure any outstanding messages are processed
333 if( RUNNING == mState ||
335 PAUSED_WHILE_HIDDEN == mState )
337 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
342 mUpdateRenderController->Stop();
345 // Delete the TTS player
346 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
350 mTtsPlayers[i].Reset();
354 delete mEventHandler;
355 mEventHandler = NULL;
357 delete mNotificationTrigger;
358 mNotificationTrigger = NULL;
360 mCallbackManager->Stop();
366 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
368 mEventHandler->FeedTouchPoint( point, timeStamp );
371 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
373 mEventHandler->FeedWheelEvent( wheelEvent );
376 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
378 mEventHandler->FeedKeyEvent( keyEvent );
381 bool Adaptor::MoveResize( const PositionSize& positionSize )
383 PositionSize old = mSurface->GetPositionSize();
385 // just resize the surface. The driver should automatically resize the egl Surface (untested)
386 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
387 // is resized. Implementations typically use hooks into the OS and native window
388 // system to perform this resizing on demand, transparently to the client.
389 mSurface->MoveResize( positionSize );
391 if(old.width != positionSize.width || old.height != positionSize.height)
393 SurfaceSizeChanged(positionSize);
399 void Adaptor::SurfaceResized( const PositionSize& positionSize )
401 PositionSize old = mSurface->GetPositionSize();
403 // Called by an application, when it has resized a window outside of Dali.
404 // The EGL driver automatically detects X Window resize calls, and resizes
405 // the EGL surface for us.
406 mSurface->MoveResize( positionSize );
408 if(old.width != positionSize.width || old.height != positionSize.height)
410 SurfaceSizeChanged(positionSize);
414 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
416 mNativeWindow = nativeWindow;
419 SurfaceSizeChanged(mSurface->GetPositionSize());
421 // flush the event queue to give update and render threads chance
422 // to start processing messages for new camera setup etc as soon as possible
425 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
427 // this method blocks until the render thread has completed the replace.
428 mUpdateRenderController->ReplaceSurface(mSurface);
430 // Inform core, so that texture resources can be reloaded
431 mCore->RecoverFromContextLoss();
433 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
436 RenderSurface& Adaptor::GetSurface() const
441 void Adaptor::ReleaseSurfaceLock()
443 mSurface->ReleaseLock();
446 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
448 if(!mTtsPlayers[mode])
450 // Create the TTS player when it needed, because it can reduce launching time.
451 mTtsPlayers[mode] = TtsPlayer::New(mode);
454 return mTtsPlayers[mode];
457 bool Adaptor::AddIdle( CallbackBase* callback )
459 bool idleAdded(false);
461 // Only add an idle if the Adaptor is actually running
462 if( RUNNING == mState )
464 idleAdded = mCallbackManager->AddCallback( callback, CallbackManager::IDLE_PRIORITY );
470 bool Adaptor::CallFromMainLoop( CallbackBase* callback )
472 bool callAdded(false);
474 // Only allow the callback if the Adaptor is actually running
475 if ( RUNNING == mState )
477 callAdded = mCallbackManager->AddCallback( callback, CallbackManager::DEFAULT_PRIORITY );
483 Dali::Adaptor& Adaptor::Get()
485 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
486 return gThreadLocalAdaptor->mAdaptor;
489 bool Adaptor::IsAvailable()
491 return gThreadLocalAdaptor != NULL;
494 Dali::Integration::Core& Adaptor::GetCore()
499 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
501 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
504 void Adaptor::SetUseHardwareVSync( bool useHardware )
506 mVSyncMonitor->SetUseHardwareVSync( useHardware );
509 EglFactory& Adaptor::GetEGLFactory() const
511 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
515 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
520 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
522 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
526 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
528 return *mPlatformAbstraction;
531 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
536 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
538 return *mNotificationTrigger;
541 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
543 return mTriggerEventFactory;
546 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
548 return mSocketFactory;
551 RenderSurface* Adaptor::GetRenderSurfaceInterface()
556 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
558 return mVSyncMonitor;
561 TraceInterface& Adaptor::GetKernelTraceInterface()
563 return mKernelTracer;
566 TraceInterface& Adaptor::GetSystemTraceInterface()
568 return mSystemTracer;
571 PerformanceInterface* Adaptor::GetPerformanceInterface()
573 return mPerformanceInterface;
576 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
578 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
579 return *mPlatformAbstraction;
582 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
584 mDragAndDropDetector = detector;
588 mEventHandler->SetDragAndDropDetector( detector );
592 void Adaptor::SetRotationObserver( RotationObserver* observer )
596 mEventHandler->SetRotationObserver( observer );
598 else if( mState == READY )
600 // Set once event handler exists
601 mDeferredRotationObserver = observer;
605 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
607 if(mTtsPlayers[mode])
609 mTtsPlayers[mode].Reset();
613 void Adaptor::SetMinimumPinchDistance(float distance)
615 if( mGestureManager )
617 mGestureManager->SetMinimumPinchDistance(distance);
621 Any Adaptor::GetNativeWindowHandle()
623 return mNativeWindow;
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 mUpdateRenderController->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::NotifyLanguageChanged()
735 mLanguageChangedSignal.Emit( mAdaptor );
738 void Adaptor::RequestUpdateOnce()
740 if( PAUSED_WHILE_HIDDEN != mState )
742 if( mUpdateRenderController )
744 mUpdateRenderController->RequestUpdateOnce();
749 void Adaptor::ProcessCoreEventsFromIdle()
753 // the idle handle automatically un-installs itself
754 mNotificationOnIdleInstalled = false;
757 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface)
759 mLanguageChangedSignal(),
763 mUpdateRenderController(NULL),
767 mNativeWindow( nativeWindow ),
769 mPlatformAbstraction( NULL ),
770 mEventHandler( NULL ),
771 mCallbackManager( NULL ),
772 mNotificationOnIdleInstalled( false ),
773 mNotificationTrigger(NULL),
774 mGestureManager(NULL),
775 mDaliFeedbackPlugin(NULL),
776 mFeedbackController(NULL),
778 mDragAndDropDetector(),
779 mDeferredRotationObserver(NULL),
780 mEnvironmentOptions(),
781 mPerformanceInterface(NULL),
782 mObjectProfiler(NULL)
784 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
785 gThreadLocalAdaptor = this;
790 void Adaptor::SetViewMode( ViewMode viewMode )
792 mSurface->SetViewMode( viewMode );
793 mCore->SetViewMode( viewMode );
796 ViewMode Adaptor::GetViewMode() const
798 return mCore->GetViewMode();
801 void Adaptor::SetStereoBase( float stereoBase )
803 mCore->SetStereoBase( stereoBase );
806 float Adaptor::GetStereoBase() const
808 return mCore->GetStereoBase();
811 } // namespace Adaptor
813 } // namespace Internal