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/public-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, const DeviceLayout& baseLayout,
76 Dali::Configuration::ContextLoss configuration )
78 Dali::Adaptor* adaptor = new Dali::Adaptor;
79 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, baseLayout );
80 adaptor->mImpl = impl;
82 impl->Initialize(configuration);
88 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
90 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
91 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
92 mEnvironmentOptions.SetLogFunction( logFunction );
93 mEnvironmentOptions.InstallLogFunction(); // install logging for main thread
95 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
98 GetDataStoragePath( path );
99 mPlatformAbstraction->SetDataStoragePath( path );
101 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
102 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
104 dataRetentionPolicy = ResourcePolicy::DALI_RETAINS_MESH_DATA;
106 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
107 // files automatically.
109 if( mEnvironmentOptions.PerformanceServerRequired() )
111 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
114 mCallbackManager = CallbackManager::New();
116 PositionSize size = mSurface->GetPositionSize();
118 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, mEnvironmentOptions);
120 if( mEnvironmentOptions.GetGlesCallTime() > 0 )
122 mGLES = new GlProxyImplementation( mEnvironmentOptions );
126 mGLES = new GlImplementation();
129 mEglFactory = new EglFactory();
131 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
133 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
135 mObjectProfiler = new ObjectProfiler();
137 mNotificationTrigger = new TriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ) );
139 mVSyncMonitor = new VSyncMonitor;
141 mUpdateRenderController = new UpdateRenderController( *this, mEnvironmentOptions );
143 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
145 // Should be called after Core creation
146 if( mEnvironmentOptions.GetPanGestureLoggingLevel() )
148 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
150 if( mEnvironmentOptions.GetPanGesturePredictionMode() >= 0 )
152 Integration::SetPanGesturePredictionMode(mEnvironmentOptions.GetPanGesturePredictionMode());
154 if( mEnvironmentOptions.GetPanGesturePredictionAmount() >= 0 )
156 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions.GetPanGesturePredictionAmount());
158 if( mEnvironmentOptions.GetPanGestureMaximumPredictionAmount() >= 0 )
160 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions.GetPanGestureMaximumPredictionAmount());
162 if( mEnvironmentOptions.GetPanGestureMinimumPredictionAmount() >= 0 )
164 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions.GetPanGestureMinimumPredictionAmount());
166 if( mEnvironmentOptions.GetPanGesturePredictionAmountAdjustment() >= 0 )
168 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions.GetPanGesturePredictionAmountAdjustment());
170 if( mEnvironmentOptions.GetPanGestureSmoothingMode() >= 0 )
172 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions.GetPanGestureSmoothingMode());
174 if( mEnvironmentOptions.GetPanGestureSmoothingAmount() >= 0.0f )
176 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions.GetPanGestureSmoothingAmount());
178 if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
180 SurfaceResized( PositionSize( 0, 0, mEnvironmentOptions.GetWindowWidth(), mEnvironmentOptions.GetWindowHeight() ));
186 // Ensure stop status
189 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
190 gThreadLocalAdaptor = NULL;
192 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
194 (*iter)->OnDestroy();
197 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
198 delete mVSyncMonitor;
199 delete mEventHandler;
200 delete mObjectProfiler;
204 // Delete feedback controller before feedback plugin & style monitor dependencies
205 delete mFeedbackController;
206 delete mDaliFeedbackPlugin;
208 delete mGestureManager;
209 delete mPlatformAbstraction;
210 delete mCallbackManager;
211 delete mPerformanceInterface;
213 // uninstall it on this thread (main actor thread)
214 Dali::Integration::Log::UninstallLogFunction();
217 void Adaptor::Start()
219 // it doesn't support restart after stop at this moment
220 // to support restarting, need more testing
221 if( READY != mState )
226 // Start the callback manager
227 mCallbackManager->Start();
229 // create event handler
230 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
232 if( mDeferredRotationObserver != NULL )
234 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
235 mDeferredRotationObserver = NULL;
238 unsigned int dpiHor, dpiVer;
240 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
242 // tell core about the DPI value
243 mCore->SetDpi(dpiHor, dpiVer);
245 // set the DPI value for font rendering
246 FontClient fontClient = FontClient::Get();
247 fontClient.SetDpi( dpiHor, dpiVer );
249 // Tell the core the size of the surface just before we start the render-thread
250 PositionSize size = mSurface->GetPositionSize();
251 mCore->SurfaceResized( size.width, size.height );
253 // Start the update & render threads
254 mUpdateRenderController->Start();
258 ProcessCoreEvents(); // Ensure any startup messages are processed.
260 if ( !mFeedbackController )
262 // Start sound & haptic feedback
263 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
266 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
272 // Dali::Internal::Adaptor::Adaptor::Pause
273 void Adaptor::Pause()
275 // Only pause the adaptor if we're actually running.
276 if( RUNNING == mState )
278 // Inform observers that we are about to be paused.
279 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
284 // Reset the event handler when adaptor paused
287 mEventHandler->Reset();
290 mUpdateRenderController->Pause();
296 // Dali::Internal::Adaptor::Adaptor::Resume
297 void Adaptor::Resume()
299 // Only resume the adaptor if we are in the suspended state.
300 if( PAUSED == mState )
302 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
303 // If there were events pending, mCore->Resume() will call
304 // RenderController->RequestUpdate()
305 // UpdateRenderController->RequestUpdate()
306 // UpdateRenderSynchronization->RequestUpdate()
307 // and we should have reset the frame timers before allowing Core->Update() to be called.
308 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
310 mUpdateRenderController->ResumeFrameTime();
312 mUpdateRenderController->Resume();
316 // Reset the event handler when adaptor resumed
319 mEventHandler->Reset();
322 // Inform observers that we have resumed.
323 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
328 ProcessCoreEvents(); // Ensure any outstanding messages are processed
334 if( RUNNING == mState ||
336 PAUSED_WHILE_HIDDEN == mState )
338 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
343 mUpdateRenderController->Stop();
346 // Delete the TTS player
347 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
351 mTtsPlayers[i].Reset();
355 delete mEventHandler;
356 mEventHandler = NULL;
358 delete mNotificationTrigger;
359 mNotificationTrigger = NULL;
361 mCallbackManager->Stop();
367 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
369 mEventHandler->FeedTouchPoint( point, timeStamp );
372 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
374 mEventHandler->FeedWheelEvent( wheelEvent );
377 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
379 mEventHandler->FeedKeyEvent( keyEvent );
382 bool Adaptor::MoveResize( const PositionSize& positionSize )
384 PositionSize old = mSurface->GetPositionSize();
386 // just resize the surface. The driver should automatically resize the egl Surface (untested)
387 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
388 // is resized. Implementations typically use hooks into the OS and native window
389 // system to perform this resizing on demand, transparently to the client.
390 mSurface->MoveResize( positionSize );
392 if(old.width != positionSize.width || old.height != positionSize.height)
394 SurfaceSizeChanged(positionSize);
400 void Adaptor::SurfaceResized( const PositionSize& positionSize )
402 PositionSize old = mSurface->GetPositionSize();
404 // Called by an application, when it has resized a window outside of Dali.
405 // The EGL driver automatically detects X Window resize calls, and resizes
406 // the EGL surface for us.
407 mSurface->MoveResize( positionSize );
409 if(old.width != positionSize.width || old.height != positionSize.height)
411 SurfaceSizeChanged(positionSize);
415 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
417 mNativeWindow = nativeWindow;
420 SurfaceSizeChanged(mSurface->GetPositionSize());
422 // flush the event queue to give update and render threads chance
423 // to start processing messages for new camera setup etc as soon as possible
426 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
428 // this method blocks until the render thread has completed the replace.
429 mUpdateRenderController->ReplaceSurface(mSurface);
431 // Inform core, so that texture resources can be reloaded
432 mCore->RecoverFromContextLoss();
434 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
437 RenderSurface& Adaptor::GetSurface() const
442 void Adaptor::ReleaseSurfaceLock()
444 mSurface->ReleaseLock();
447 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
449 if(!mTtsPlayers[mode])
451 // Create the TTS player when it needed, because it can reduce launching time.
452 mTtsPlayers[mode] = TtsPlayer::New(mode);
455 return mTtsPlayers[mode];
458 bool Adaptor::AddIdle( CallbackBase* callback )
460 bool idleAdded(false);
462 // Only add an idle if the Adaptor is actually running
463 if( RUNNING == mState )
465 idleAdded = mCallbackManager->AddCallback( callback, CallbackManager::IDLE_PRIORITY );
471 bool Adaptor::CallFromMainLoop( CallbackBase* callback )
473 bool callAdded(false);
475 // Only allow the callback if the Adaptor is actually running
476 if ( RUNNING == mState )
478 callAdded = mCallbackManager->AddCallback( callback, CallbackManager::DEFAULT_PRIORITY );
484 Dali::Adaptor& Adaptor::Get()
486 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
487 return gThreadLocalAdaptor->mAdaptor;
490 bool Adaptor::IsAvailable()
492 return gThreadLocalAdaptor != NULL;
495 Dali::Integration::Core& Adaptor::GetCore()
500 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
502 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
505 void Adaptor::SetUseHardwareVSync( bool useHardware )
507 mVSyncMonitor->SetUseHardwareVSync( useHardware );
510 EglFactory& Adaptor::GetEGLFactory() const
512 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
516 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
521 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
523 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
527 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
529 return *mPlatformAbstraction;
532 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
537 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
539 return *mNotificationTrigger;
542 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
544 return mTriggerEventFactory;
547 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
549 return mSocketFactory;
552 RenderSurface* Adaptor::GetRenderSurfaceInterface()
557 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
559 return mVSyncMonitor;
562 TraceInterface& Adaptor::GetKernelTraceInterface()
564 return mKernelTracer;
567 TraceInterface& Adaptor::GetSystemTraceInterface()
569 return mSystemTracer;
572 PerformanceInterface* Adaptor::GetPerformanceInterface()
574 return mPerformanceInterface;
577 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
579 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
580 return *mPlatformAbstraction;
583 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
585 mDragAndDropDetector = detector;
589 mEventHandler->SetDragAndDropDetector( detector );
593 void Adaptor::SetRotationObserver( RotationObserver* observer )
597 mEventHandler->SetRotationObserver( observer );
599 else if( mState == READY )
601 // Set once event handler exists
602 mDeferredRotationObserver = observer;
606 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
608 if(mTtsPlayers[mode])
610 mTtsPlayers[mode].Reset();
614 void Adaptor::SetMinimumPinchDistance(float distance)
616 if( mGestureManager )
618 mGestureManager->SetMinimumPinchDistance(distance);
622 Any Adaptor::GetNativeWindowHandle()
624 return mNativeWindow;
627 void Adaptor::AddObserver( LifeCycleObserver& observer )
629 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
631 if ( match == mObservers.end() )
633 mObservers.push_back( &observer );
637 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
639 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
641 if ( match != mObservers.end() )
643 mObservers.erase( match );
647 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
651 mCore->QueueEvent(event);
655 void Adaptor::ProcessCoreEvents()
659 if( mPerformanceInterface )
661 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
664 mCore->ProcessEvents();
666 if( mPerformanceInterface )
668 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
673 void Adaptor::RequestUpdate()
675 // When Dali applications are partially visible behind the lock-screen,
676 // the indicator must be updated (therefore allow updates in the PAUSED state)
677 if ( PAUSED == mState ||
680 mUpdateRenderController->RequestUpdate();
684 void Adaptor::RequestProcessEventsOnIdle()
686 // Only request a notification if the Adaptor is actually running
687 // and we haven't installed the idle notification
688 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
690 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
694 void Adaptor::OnWindowShown()
696 if ( PAUSED_WHILE_HIDDEN == mState )
698 // Adaptor can now be resumed
703 // Force a render task
708 void Adaptor::OnWindowHidden()
710 if ( STOPPED != mState )
714 // Adaptor cannot be resumed until the window is shown
715 mState = PAUSED_WHILE_HIDDEN;
719 // Dali::Internal::Adaptor::Adaptor::OnDamaged
720 void Adaptor::OnDamaged( const DamageArea& area )
722 // This is needed for the case where Dali window is partially obscured
726 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
728 // let the core know the surface size has changed
729 mCore->SurfaceResized(positionSize.width, positionSize.height);
731 mResizedSignal.Emit( mAdaptor );
734 void Adaptor::NotifyLanguageChanged()
736 mLanguageChangedSignal.Emit( mAdaptor );
739 void Adaptor::RequestUpdateOnce()
741 if( PAUSED_WHILE_HIDDEN != mState )
743 if( mUpdateRenderController )
745 mUpdateRenderController->RequestUpdateOnce();
750 void Adaptor::ProcessCoreEventsFromIdle()
754 // the idle handle automatically un-installs itself
755 mNotificationOnIdleInstalled = false;
758 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
760 mLanguageChangedSignal(),
764 mUpdateRenderController(NULL),
768 mNativeWindow( nativeWindow ),
770 mPlatformAbstraction( NULL ),
771 mEventHandler( NULL ),
772 mCallbackManager( NULL ),
773 mNotificationOnIdleInstalled( false ),
774 mNotificationTrigger(NULL),
775 mGestureManager(NULL),
776 mDaliFeedbackPlugin(NULL),
777 mFeedbackController(NULL),
779 mDragAndDropDetector(),
780 mDeferredRotationObserver(NULL),
781 mBaseLayout(baseLayout),
782 mEnvironmentOptions(),
783 mPerformanceInterface(NULL),
784 mObjectProfiler(NULL)
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