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 if ( RUNNING == mState )
744 boost::unique_lock<boost::mutex> lock( mIdleInstaller );
746 // check if the idle handle is already installed
747 if( mNotificationOnIdleInstalled )
751 mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
755 void Adaptor::OnWindowShown()
757 if ( PAUSED_WHILE_HIDDEN == mState )
759 // Adaptor can now be resumed
764 // Force a render task
769 void Adaptor::OnWindowHidden()
771 if ( STOPPED != mState )
775 // Adaptor cannot be resumed until the window is shown
776 mState = PAUSED_WHILE_HIDDEN;
780 // Dali::Internal::Adaptor::Adaptor::OnDamaged
781 void Adaptor::OnDamaged( const DamageArea& area )
783 // This is needed for the case where Dali window is partially obscured
787 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
789 // let the core know the surface size has changed
790 mCore->SurfaceResized(positionSize.width, positionSize.height);
792 mResizedSignalV2.Emit( mAdaptor );
795 void Adaptor::NotifyLanguageChanged()
797 mLanguageChangedSignalV2.Emit( mAdaptor );
800 void Adaptor::RequestUpdateOnce()
802 if( PAUSED_WHILE_HIDDEN != mState )
804 if( mUpdateRenderController )
806 mUpdateRenderController->RequestUpdateOnce();
811 void Adaptor::ProcessCoreEventsFromIdle()
815 // the idle handle automatically un-installs itself
816 mNotificationOnIdleInstalled = false;
819 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
823 mUpdateRenderController(NULL),
828 mPlatformAbstraction( NULL ),
829 mEventHandler( NULL ),
830 mCallbackManager( NULL ),
831 mNotificationOnIdleInstalled( false ),
832 mNotificationTrigger(NULL),
833 mGestureManager(NULL),
836 mDaliFeedbackPlugin(NULL),
837 mFeedbackController(NULL),
839 mDragAndDropDetector(),
840 mDeferredRotationObserver(NULL),
841 mBaseLayout(baseLayout),
842 mEnvironmentOptions(),
843 mPerformanceInterface(NULL),
844 mObjectProfiler(NULL)
846 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
847 gThreadLocalAdaptor.reset(this);
852 void Adaptor::SetViewMode( ViewMode viewMode )
854 mSurface->SetViewMode( viewMode );
855 mCore->SetViewMode( viewMode );
858 ViewMode Adaptor::GetViewMode() const
860 return mCore->GetViewMode();
863 void Adaptor::SetStereoBase( float stereoBase )
865 mCore->SetStereoBase( stereoBase );
868 float Adaptor::GetStereoBase() const
870 return mCore->GetStereoBase();
873 } // namespace Adaptor
875 } // namespace Internal