2 * Copyright (c) 2014 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 <boost/thread/tss.hpp>
23 #include <dali/public-api/common/dali-common.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/integration-api/core.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/environment-variables.h>
33 #include <base/performance-logging/performance-interface-factory.h>
34 #include <base/lifecycle-observer.h>
36 #include <callback-manager.h>
37 #include <trigger-event.h>
38 #include <render-surface-impl.h>
39 #include <tts-player-impl.h>
40 #include <accessibility-manager-impl.h>
41 #include <timer-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>
56 #include <slp-logging.h>
71 boost::thread_specific_ptr<Adaptor> gThreadLocalAdaptor;
73 unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue )
75 const char* variableParameter = std::getenv(variable);
77 // if the parameter exists convert it to an integer, else return the default value
78 unsigned int intValue = variableParameter ? atoi(variableParameter) : defaultValue;
82 bool GetIntegerEnvironmentVariable( const char* variable, int& intValue )
84 const char* variableParameter = std::getenv(variable);
86 if( !variableParameter )
90 // if the parameter exists convert it to an integer, else return the default value
91 intValue = atoi(variableParameter);
95 bool GetFloatEnvironmentVariable( const char* variable, float& floatValue )
97 const char* variableParameter = std::getenv(variable);
99 if( !variableParameter )
103 // if the parameter exists convert it to an integer, else return the default value
104 floatValue = atof(variableParameter);
108 } // unnamed namespace
110 Dali::Adaptor* Adaptor::New( RenderSurface *surface, const DeviceLayout& baseLayout )
112 DALI_ASSERT_ALWAYS( surface->GetType() != Dali::RenderSurface::NO_SURFACE && "No surface for adaptor" );
114 Dali::Adaptor* adaptor = new Dali::Adaptor;
115 Adaptor* impl = new Adaptor( *adaptor, surface, baseLayout );
116 adaptor->mImpl = impl;
123 void Adaptor::ParseEnvironmentOptions()
125 // get logging options
126 unsigned int logFrameRateFrequency = GetIntegerEnvironmentVariable( DALI_ENV_FPS_TRACKING, 0 );
127 unsigned int logupdateStatusFrequency = GetIntegerEnvironmentVariable( DALI_ENV_UPDATE_STATUS_INTERVAL, 0 );
128 unsigned int logPerformanceLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE, 0 );
129 unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
131 // all threads here (event, update, and render) will send their logs to SLP Platform's LogMessage handler.
132 Dali::Integration::Log::LogFunction logFunction(Dali::SlpPlatform::LogMessage);
134 mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceLevel, logPanGesture );
137 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
139 mEnvironmentOptions.SetPanGesturePredictionMode(predictionMode);
141 int predictionAmount = -1;
142 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_AMOUNT, predictionAmount) )
144 if( predictionAmount < 0 )
146 // do not support times in the past
147 predictionAmount = 0;
149 mEnvironmentOptions.SetPanGesturePredictionAmount(predictionAmount);
152 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_MODE, smoothingMode) )
154 mEnvironmentOptions.SetPanGestureSmoothingMode(smoothingMode);
156 float smoothingAmount = 1.0f;
157 if( GetFloatEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_AMOUNT, smoothingAmount) )
159 smoothingAmount = Clamp(smoothingAmount, 0.0f, 1.0f);
160 mEnvironmentOptions.SetPanGestureSmoothingAmount(smoothingAmount);
163 int minimumDistance(-1);
164 if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_DISTANCE, minimumDistance ))
166 mEnvironmentOptions.SetMinimumPanDistance( minimumDistance );
169 int minimumEvents(-1);
170 if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_EVENTS, minimumEvents ))
172 mEnvironmentOptions.SetMinimumPanEvents( minimumEvents );
176 if ( GetIntegerEnvironmentVariable(DALI_GLES_CALL_TIME, glesCallTime ))
178 mEnvironmentOptions.SetGlesCallTime( glesCallTime );
181 mEnvironmentOptions.InstallLogFunction();
184 void Adaptor::Initialize()
186 ParseEnvironmentOptions();
188 mPlatformAbstraction = new SlpPlatform::SlpPlatformAbstraction;
190 if( mEnvironmentOptions.GetPerformanceLoggingLevel() > 0 )
192 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
195 mCallbackManager = CallbackManager::New();
197 PositionSize size = mSurface->GetPositionSize();
199 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, mEnvironmentOptions);
201 if( mEnvironmentOptions.GetGlesCallTime() > 0 )
203 mGLES = new GlProxyImplementation( mEnvironmentOptions );
207 mGLES = new GlImplementation();
210 mEglFactory = new EglFactory();
212 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
214 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager );
216 mObjectProfiler = new ObjectProfiler();
218 mNotificationTrigger = new TriggerEvent( boost::bind(&Adaptor::ProcessCoreEvents, this) );
220 mVSyncMonitor = new VSyncMonitor;
222 mUpdateRenderController = new UpdateRenderController( *this, mEnvironmentOptions );
224 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
226 // Should be called after Core creation
227 if( mEnvironmentOptions.GetPanGestureLoggingLevel() )
229 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
231 if( mEnvironmentOptions.GetPanGesturePredictionMode() >= 0 )
233 Integration::SetPanGesturePredictionMode(mEnvironmentOptions.GetPanGesturePredictionMode());
235 if( mEnvironmentOptions.GetPanGesturePredictionAmount() >= 0.0f )
237 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions.GetPanGesturePredictionAmount());
239 if( mEnvironmentOptions.GetPanGestureSmoothingMode() >= 0 )
241 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions.GetPanGestureSmoothingMode());
243 if( mEnvironmentOptions.GetPanGestureSmoothingAmount() >= 0.0f )
245 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions.GetPanGestureSmoothingAmount());
251 // Ensure stop status
254 // Release first as we do not want any access to Adaptor as it is being destroyed.
255 gThreadLocalAdaptor.release();
257 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
259 (*iter)->OnDestroy();
262 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
263 delete mVSyncMonitor;
264 delete mEventHandler;
265 delete mObjectProfiler;
269 // Delete feedback controller before feedback plugin & style monitor dependencies
270 delete mFeedbackController;
271 delete mDaliFeedbackPlugin;
273 delete mGestureManager;
274 delete mPlatformAbstraction;
275 delete mCallbackManager;
276 delete mPerformanceInterface;
278 // uninstall it on this thread (main actor thread)
279 Dali::Integration::Log::UninstallLogFunction();
282 void Adaptor::Start()
284 // it doesn't support restart after stop at this moment
285 // to support restarting, need more testing
286 if( READY != mState )
291 // Start the callback manager
292 mCallbackManager->Start();
294 // create event handler
295 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
297 if( mDeferredRotationObserver != NULL )
299 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
300 mDeferredRotationObserver = NULL;
303 // guarantee map the surface before starting render-thread.
306 // NOTE: dpi must be set before starting the render thread
307 // use default or command line settings if not run on device
309 // set the DPI value for font rendering
310 unsigned int dpiHor, dpiVer;
312 mSurface->GetDpi(dpiHor, dpiVer);
314 // tell core about the value
315 mCore->SetDpi(dpiHor, dpiVer);
317 mCore->SetDpi(mHDpi, mVDpi);
320 // Tell the core the size of the surface just before we start the render-thread
321 PositionSize size = mSurface->GetPositionSize();
322 mCore->SurfaceResized( size.width, size.height );
324 // Start the update & render threads
325 mUpdateRenderController->Start();
329 ProcessCoreEvents(); // Ensure any startup messages are processed.
331 if ( !mFeedbackController )
333 // Start sound & haptic feedback
334 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
337 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
343 // Dali::Internal::Adaptor::Adaptor::Pause
344 void Adaptor::Pause()
346 // Only pause the adaptor if we're actually running.
347 if( RUNNING == mState )
349 // Inform observers that we are about to be paused.
350 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
355 // Reset the event handler when adaptor paused
358 mEventHandler->Reset();
361 mUpdateRenderController->Pause();
367 // Dali::Internal::Adaptor::Adaptor::Resume
368 void Adaptor::Resume()
370 // Only resume the adaptor if we are in the suspended state.
371 if( PAUSED == mState )
373 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
374 // If there were events pending, mCore->Resume() will call
375 // RenderController->RequestUpdate()
376 // UpdateRenderController->RequestUpdate()
377 // UpdateRenderSynchronization->RequestUpdate()
378 // and we should have reset the frame timers before allowing Core->Update() to be called.
379 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
381 mUpdateRenderController->ResumeFrameTime();
383 mUpdateRenderController->Resume();
387 // Reset the event handler when adaptor resumed
390 mEventHandler->Reset();
393 // Inform observers that we have resumed.
394 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
399 ProcessCoreEvents(); // Ensure any outstanding messages are processed
405 if( RUNNING == mState ||
407 PAUSED_WHILE_HIDDEN == mState )
409 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
414 mUpdateRenderController->Stop();
417 // Delete the TTS player
418 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
422 mTtsPlayers[i].Reset();
426 delete mEventHandler;
427 mEventHandler = NULL;
429 delete mNotificationTrigger;
430 mNotificationTrigger = NULL;
432 mCallbackManager->Stop();
438 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
440 mEventHandler->FeedTouchPoint( point, timeStamp );
443 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
445 mEventHandler->FeedWheelEvent( wheelEvent );
448 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
450 mEventHandler->FeedKeyEvent( keyEvent );
453 bool Adaptor::MoveResize( const PositionSize& positionSize )
455 PositionSize old = mSurface->GetPositionSize();
457 // just resize the surface. The driver should automatically resize the egl Surface (untested)
458 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
459 // is resized. Implementations typically use hooks into the OS and native window
460 // system to perform this resizing on demand, transparently to the client.
461 mSurface->MoveResize( positionSize );
463 if(old.width != positionSize.width || old.height != positionSize.height)
465 SurfaceSizeChanged(positionSize);
471 void Adaptor::SurfaceResized( const PositionSize& positionSize )
473 PositionSize old = mSurface->GetPositionSize();
475 // Called by an application, when it has resized a window outside of Dali.
476 // The EGL driver automatically detects X Window resize calls, and resizes
477 // the EGL surface for us.
478 mSurface->MoveResize( positionSize );
480 if(old.width != positionSize.width || old.height != positionSize.height)
482 SurfaceSizeChanged(positionSize);
486 void Adaptor::ReplaceSurface( Dali::RenderSurface& surface )
488 // adaptor implementation needs the implementation of
489 RenderSurface* internalSurface = dynamic_cast<Internal::Adaptor::RenderSurface*>( &surface );
490 DALI_ASSERT_ALWAYS( internalSurface && "Incorrect surface" );
492 mSurface = internalSurface;
494 SurfaceSizeChanged( internalSurface->GetPositionSize() );
496 // flush the event queue to give update and render threads chance
497 // to start processing messages for new camera setup etc as soon as possible
500 // this method is synchronous
501 mUpdateRenderController->ReplaceSurface(internalSurface);
504 Dali::RenderSurface& Adaptor::GetSurface() const
509 void Adaptor::ReleaseSurfaceLock()
511 mSurface->ReleaseLock();
514 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
516 if(!mTtsPlayers[mode])
518 // Create the TTS player when it needed, because it can reduce launching time.
519 mTtsPlayers[mode] = TtsPlayer::New(mode);
522 return mTtsPlayers[mode];
525 bool Adaptor::AddIdle(boost::function<void(void)> callBack)
527 bool idleAdded(false);
529 // Only add an idle if the Adaptor is actually running
530 if( RUNNING == mState )
532 idleAdded = mCallbackManager->AddCallback(callBack, CallbackManager::IDLE_PRIORITY);
538 bool Adaptor::CallFromMainLoop(boost::function<void(void)> callBack)
540 bool callAdded(false);
542 // Only allow the callback if the Adaptor is actually running
543 if ( RUNNING == mState )
545 callAdded = mCallbackManager->AddCallback(callBack, CallbackManager::DEFAULT_PRIORITY);
551 Dali::Adaptor& Adaptor::Get()
553 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() != NULL && "Adaptor not instantiated" );
554 return gThreadLocalAdaptor->mAdaptor;
557 bool Adaptor::IsAvailable()
559 return gThreadLocalAdaptor.get() != NULL;
562 Dali::Integration::Core& Adaptor::GetCore()
567 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
569 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
572 void Adaptor::SetUseHardwareVSync( bool useHardware )
574 mVSyncMonitor->SetUseHardwareVSync( useHardware );
577 void Adaptor::SetDpi(size_t hDpi, size_t vDpi)
583 EglFactory& Adaptor::GetEGLFactory() const
585 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
589 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
594 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
596 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
600 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
602 return *mPlatformAbstraction;
605 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
610 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
612 return *mNotificationTrigger;
614 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
616 return mTriggerEventFactory;
618 RenderSurface* Adaptor::GetRenderSurfaceInterface()
622 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
624 return mVSyncMonitor;
627 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
629 return mKernelTracer;
632 PerformanceInterface* Adaptor::GetPerformanceInterface()
634 return mPerformanceInterface;
637 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
639 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
640 return *mPlatformAbstraction;
643 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
645 mDragAndDropDetector = detector;
649 mEventHandler->SetDragAndDropDetector( detector );
653 void Adaptor::SetRotationObserver( RotationObserver* observer )
657 mEventHandler->SetRotationObserver( observer );
659 else if( mState == READY )
661 // Set once event handler exists
662 mDeferredRotationObserver = observer;
666 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
668 if(mTtsPlayers[mode])
670 mTtsPlayers[mode].Reset();
674 void Adaptor::SetMinimumPinchDistance(float distance)
676 if( mGestureManager )
678 mGestureManager->SetMinimumPinchDistance(distance);
682 void Adaptor::AddObserver( LifeCycleObserver& observer )
684 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
686 if ( match == mObservers.end() )
688 mObservers.push_back( &observer );
692 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
694 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
696 if ( match != mObservers.end() )
698 mObservers.erase( match );
702 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
706 mCore->QueueEvent(event);
710 void Adaptor::ProcessCoreEvents()
714 if( mPerformanceInterface )
716 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_START );
719 mCore->ProcessEvents();
721 if( mPerformanceInterface )
723 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_END );
728 void Adaptor::RequestUpdate()
730 // When Dali applications are partially visible behind the lock-screen,
731 // the indicator must be updated (therefore allow updates in the PAUSED state)
732 if ( PAUSED == mState ||
735 mUpdateRenderController->RequestUpdate();
739 void Adaptor::RequestProcessEventsOnIdle()
741 // Only request a notification if the Adaptor is actually running
742 // and we haven't installed the idle notification
743 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
745 mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
749 void Adaptor::OnWindowShown()
751 if ( PAUSED_WHILE_HIDDEN == mState )
753 // Adaptor can now be resumed
758 // Force a render task
763 void Adaptor::OnWindowHidden()
765 if ( STOPPED != mState )
769 // Adaptor cannot be resumed until the window is shown
770 mState = PAUSED_WHILE_HIDDEN;
774 // Dali::Internal::Adaptor::Adaptor::OnDamaged
775 void Adaptor::OnDamaged( const DamageArea& area )
777 // This is needed for the case where Dali window is partially obscured
781 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
783 // let the core know the surface size has changed
784 mCore->SurfaceResized(positionSize.width, positionSize.height);
786 mResizedSignalV2.Emit( mAdaptor );
789 void Adaptor::NotifyLanguageChanged()
791 mLanguageChangedSignalV2.Emit( mAdaptor );
794 void Adaptor::RequestUpdateOnce()
796 if( PAUSED_WHILE_HIDDEN != mState )
798 if( mUpdateRenderController )
800 mUpdateRenderController->RequestUpdateOnce();
805 void Adaptor::ProcessCoreEventsFromIdle()
809 // the idle handle automatically un-installs itself
810 mNotificationOnIdleInstalled = false;
813 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
817 mUpdateRenderController(NULL),
822 mPlatformAbstraction( NULL ),
823 mEventHandler( NULL ),
824 mCallbackManager( NULL ),
825 mNotificationOnIdleInstalled( false ),
826 mNotificationTrigger(NULL),
827 mGestureManager(NULL),
830 mDaliFeedbackPlugin(NULL),
831 mFeedbackController(NULL),
833 mDragAndDropDetector(),
834 mDeferredRotationObserver(NULL),
835 mBaseLayout(baseLayout),
836 mEnvironmentOptions(),
837 mPerformanceInterface(NULL),
838 mObjectProfiler(NULL)
840 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
841 gThreadLocalAdaptor.reset(this);
846 void Adaptor::SetViewMode( ViewMode viewMode )
848 mSurface->SetViewMode( viewMode );
849 mCore->SetViewMode( viewMode );
852 ViewMode Adaptor::GetViewMode() const
854 return mCore->GetViewMode();
857 void Adaptor::SetStereoBase( float stereoBase )
859 mCore->SetStereoBase( stereoBase );
862 float Adaptor::GetStereoBase() const
864 return mCore->GetStereoBase();
867 } // namespace Adaptor
869 } // namespace Internal