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 mObjectProfiler = new ObjectProfiler();
146 mNotificationTrigger = new TriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ) );
148 mVSyncMonitor = new VSyncMonitor;
150 mUpdateRenderController = new UpdateRenderController( *this, *mEnvironmentOptions );
152 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
154 // Should be called after Core creation
155 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
157 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
159 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
161 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
163 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
165 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
167 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
169 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
171 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
173 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
175 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
177 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
179 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
181 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
183 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
185 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
191 // Ensure stop status
194 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
195 gThreadLocalAdaptor = NULL;
197 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
199 (*iter)->OnDestroy();
202 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
203 delete mVSyncMonitor;
204 delete mEventHandler;
205 delete mObjectProfiler;
209 // Delete feedback controller before feedback plugin & style monitor dependencies
210 delete mFeedbackController;
211 delete mDaliFeedbackPlugin;
213 delete mGestureManager;
214 delete mPlatformAbstraction;
215 delete mCallbackManager;
216 delete mPerformanceInterface;
218 // uninstall it on this thread (main actor thread)
219 Dali::Integration::Log::UninstallLogFunction();
221 // Delete environment options if we own it
222 if( mEnvironmentOptionsOwned )
224 delete mEnvironmentOptions;
228 void Adaptor::Start()
230 // it doesn't support restart after stop at this moment
231 // to support restarting, need more testing
232 if( READY != mState )
237 // Start the callback manager
238 mCallbackManager->Start();
240 // create event handler
241 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
243 if( mDeferredRotationObserver != NULL )
245 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
246 mDeferredRotationObserver = NULL;
249 unsigned int dpiHor, dpiVer;
251 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
253 // tell core about the DPI value
254 mCore->SetDpi(dpiHor, dpiVer);
256 // set the DPI value for font rendering
257 FontClient fontClient = FontClient::Get();
258 fontClient.SetDpi( dpiHor, dpiVer );
260 // Tell the core the size of the surface just before we start the render-thread
261 PositionSize size = mSurface->GetPositionSize();
262 mCore->SurfaceResized( size.width, size.height );
264 // Start the update & render threads
265 mUpdateRenderController->Start();
269 ProcessCoreEvents(); // Ensure any startup messages are processed.
271 if ( !mFeedbackController )
273 // Start sound & haptic feedback
274 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
277 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
283 // Dali::Internal::Adaptor::Adaptor::Pause
284 void Adaptor::Pause()
286 // Only pause the adaptor if we're actually running.
287 if( RUNNING == mState )
289 // Inform observers that we are about to be paused.
290 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
295 // Reset the event handler when adaptor paused
298 mEventHandler->Reset();
301 mUpdateRenderController->Pause();
307 // Dali::Internal::Adaptor::Adaptor::Resume
308 void Adaptor::Resume()
310 // Only resume the adaptor if we are in the suspended state.
311 if( PAUSED == mState )
313 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
314 // If there were events pending, mCore->Resume() will call
315 // RenderController->RequestUpdate()
316 // UpdateRenderController->RequestUpdate()
317 // UpdateRenderSynchronization->RequestUpdate()
318 // and we should have reset the frame timers before allowing Core->Update() to be called.
319 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
321 mUpdateRenderController->ResumeFrameTime();
323 mUpdateRenderController->Resume();
327 // Reset the event handler when adaptor resumed
330 mEventHandler->Reset();
333 // Inform observers that we have resumed.
334 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
339 ProcessCoreEvents(); // Ensure any outstanding messages are processed
345 if( RUNNING == mState ||
347 PAUSED_WHILE_HIDDEN == mState )
349 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
354 mUpdateRenderController->Stop();
357 // Delete the TTS player
358 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
362 mTtsPlayers[i].Reset();
366 delete mEventHandler;
367 mEventHandler = NULL;
369 delete mNotificationTrigger;
370 mNotificationTrigger = NULL;
372 mCallbackManager->Stop();
378 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
380 mEventHandler->FeedTouchPoint( point, timeStamp );
383 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
385 mEventHandler->FeedWheelEvent( wheelEvent );
388 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
390 mEventHandler->FeedKeyEvent( keyEvent );
393 bool Adaptor::MoveResize( const PositionSize& positionSize )
395 PositionSize old = mSurface->GetPositionSize();
397 // just resize the surface. The driver should automatically resize the egl Surface (untested)
398 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
399 // is resized. Implementations typically use hooks into the OS and native window
400 // system to perform this resizing on demand, transparently to the client.
401 mSurface->MoveResize( positionSize );
403 if(old.width != positionSize.width || old.height != positionSize.height)
405 SurfaceSizeChanged(positionSize);
411 void Adaptor::SurfaceResized( const PositionSize& positionSize )
413 PositionSize old = mSurface->GetPositionSize();
415 // Called by an application, when it has resized a window outside of Dali.
416 // The EGL driver automatically detects X Window resize calls, and resizes
417 // the EGL surface for us.
418 mSurface->MoveResize( positionSize );
420 if(old.width != positionSize.width || old.height != positionSize.height)
422 SurfaceSizeChanged(positionSize);
426 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
428 mNativeWindow = nativeWindow;
431 SurfaceSizeChanged(mSurface->GetPositionSize());
433 // flush the event queue to give update and render threads chance
434 // to start processing messages for new camera setup etc as soon as possible
437 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
439 // this method blocks until the render thread has completed the replace.
440 mUpdateRenderController->ReplaceSurface(mSurface);
442 // Inform core, so that texture resources can be reloaded
443 mCore->RecoverFromContextLoss();
445 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
448 RenderSurface& Adaptor::GetSurface() const
453 void Adaptor::ReleaseSurfaceLock()
455 mSurface->ReleaseLock();
458 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
460 if(!mTtsPlayers[mode])
462 // Create the TTS player when it needed, because it can reduce launching time.
463 mTtsPlayers[mode] = TtsPlayer::New(mode);
466 return mTtsPlayers[mode];
469 bool Adaptor::AddIdle( CallbackBase* callback )
471 bool idleAdded(false);
473 // Only add an idle if the Adaptor is actually running
474 if( RUNNING == mState )
476 idleAdded = mCallbackManager->AddCallback( callback, CallbackManager::IDLE_PRIORITY );
482 bool Adaptor::CallFromMainLoop( CallbackBase* callback )
484 bool callAdded(false);
486 // Only allow the callback if the Adaptor is actually running
487 if ( RUNNING == mState )
489 callAdded = mCallbackManager->AddCallback( callback, CallbackManager::DEFAULT_PRIORITY );
495 Dali::Adaptor& Adaptor::Get()
497 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
498 return gThreadLocalAdaptor->mAdaptor;
501 bool Adaptor::IsAvailable()
503 return gThreadLocalAdaptor != NULL;
506 Dali::Integration::Core& Adaptor::GetCore()
511 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
513 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
516 void Adaptor::SetUseHardwareVSync( bool useHardware )
518 mVSyncMonitor->SetUseHardwareVSync( useHardware );
521 EglFactory& Adaptor::GetEGLFactory() const
523 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
527 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
532 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
534 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
538 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
540 return *mPlatformAbstraction;
543 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
548 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
550 return *mNotificationTrigger;
553 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
555 return mTriggerEventFactory;
558 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
560 return mSocketFactory;
563 RenderSurface* Adaptor::GetRenderSurfaceInterface()
568 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
570 return mVSyncMonitor;
573 TraceInterface& Adaptor::GetKernelTraceInterface()
575 return mKernelTracer;
578 TraceInterface& Adaptor::GetSystemTraceInterface()
580 return mSystemTracer;
583 PerformanceInterface* Adaptor::GetPerformanceInterface()
585 return mPerformanceInterface;
588 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
590 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
591 return *mPlatformAbstraction;
594 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
596 mDragAndDropDetector = detector;
600 mEventHandler->SetDragAndDropDetector( detector );
604 void Adaptor::SetRotationObserver( RotationObserver* observer )
608 mEventHandler->SetRotationObserver( observer );
610 else if( mState == READY )
612 // Set once event handler exists
613 mDeferredRotationObserver = observer;
617 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
619 if(mTtsPlayers[mode])
621 mTtsPlayers[mode].Reset();
625 void Adaptor::SetMinimumPinchDistance(float distance)
627 if( mGestureManager )
629 mGestureManager->SetMinimumPinchDistance(distance);
633 Any Adaptor::GetNativeWindowHandle()
635 return mNativeWindow;
638 void Adaptor::AddObserver( LifeCycleObserver& observer )
640 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
642 if ( match == mObservers.end() )
644 mObservers.push_back( &observer );
648 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
650 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
652 if ( match != mObservers.end() )
654 mObservers.erase( match );
658 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
662 mCore->QueueEvent(event);
666 void Adaptor::ProcessCoreEvents()
670 if( mPerformanceInterface )
672 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
675 mCore->ProcessEvents();
677 if( mPerformanceInterface )
679 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
684 void Adaptor::RequestUpdate()
686 // When Dali applications are partially visible behind the lock-screen,
687 // the indicator must be updated (therefore allow updates in the PAUSED state)
688 if ( PAUSED == mState ||
691 mUpdateRenderController->RequestUpdate();
695 void Adaptor::RequestProcessEventsOnIdle()
697 // Only request a notification if the Adaptor is actually running
698 // and we haven't installed the idle notification
699 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
701 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
705 void Adaptor::OnWindowShown()
707 if ( PAUSED_WHILE_HIDDEN == mState )
709 // Adaptor can now be resumed
714 // Force a render task
719 void Adaptor::OnWindowHidden()
721 if ( STOPPED != mState )
725 // Adaptor cannot be resumed until the window is shown
726 mState = PAUSED_WHILE_HIDDEN;
730 // Dali::Internal::Adaptor::Adaptor::OnDamaged
731 void Adaptor::OnDamaged( const DamageArea& area )
733 // This is needed for the case where Dali window is partially obscured
737 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
739 // let the core know the surface size has changed
740 mCore->SurfaceResized(positionSize.width, positionSize.height);
742 mResizedSignal.Emit( mAdaptor );
745 void Adaptor::NotifySceneCreated()
747 GetCore().SceneCreated();
750 void Adaptor::NotifyLanguageChanged()
752 mLanguageChangedSignal.Emit( mAdaptor );
755 void Adaptor::RequestUpdateOnce()
757 if( PAUSED_WHILE_HIDDEN != mState )
759 if( mUpdateRenderController )
761 mUpdateRenderController->RequestUpdateOnce();
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 mUpdateRenderController(NULL),
784 mNativeWindow( nativeWindow ),
786 mPlatformAbstraction( NULL ),
787 mEventHandler( NULL ),
788 mCallbackManager( NULL ),
789 mNotificationOnIdleInstalled( false ),
790 mNotificationTrigger(NULL),
791 mGestureManager(NULL),
792 mDaliFeedbackPlugin(NULL),
793 mFeedbackController(NULL),
795 mDragAndDropDetector(),
796 mDeferredRotationObserver(NULL),
797 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
798 mPerformanceInterface(NULL),
799 mObjectProfiler(NULL),
800 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
802 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
803 gThreadLocalAdaptor = this;
808 void Adaptor::SetViewMode( ViewMode viewMode )
810 mSurface->SetViewMode( viewMode );
811 mCore->SetViewMode( viewMode );
814 ViewMode Adaptor::GetViewMode() const
816 return mCore->GetViewMode();
819 void Adaptor::SetStereoBase( float stereoBase )
821 mCore->SetStereoBase( stereoBase );
824 float Adaptor::GetStereoBase() const
826 return mCore->GetStereoBase();
829 } // namespace Adaptor
831 } // namespace Internal