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 GetBooleanEnvironmentVariable( const char* variable, bool& boolValue )
97 const char* variableParameter = std::getenv(variable);
99 boolValue = variableParameter ? true : false;
103 bool GetFloatEnvironmentVariable( const char* variable, float& floatValue )
105 const char* variableParameter = std::getenv(variable);
107 if( !variableParameter )
111 // if the parameter exists convert it to an integer, else return the default value
112 floatValue = atof(variableParameter);
116 } // unnamed namespace
118 Dali::Adaptor* Adaptor::New( RenderSurface *surface, const DeviceLayout& baseLayout )
120 DALI_ASSERT_ALWAYS( surface->GetType() != Dali::RenderSurface::NO_SURFACE && "No surface for adaptor" );
122 Dali::Adaptor* adaptor = new Dali::Adaptor;
123 Adaptor* impl = new Adaptor( *adaptor, surface, baseLayout );
124 adaptor->mImpl = impl;
131 void Adaptor::ParseEnvironmentOptions()
133 // get logging options
134 unsigned int logFrameRateFrequency = GetIntegerEnvironmentVariable( DALI_ENV_FPS_TRACKING, 0 );
135 unsigned int logupdateStatusFrequency = GetIntegerEnvironmentVariable( DALI_ENV_UPDATE_STATUS_INTERVAL, 0 );
136 unsigned int logPerformanceLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE, 0 );
137 unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
139 // all threads here (event, update, and render) will send their logs to SLP Platform's LogMessage handler.
140 Dali::Integration::Log::LogFunction logFunction(Dali::SlpPlatform::LogMessage);
142 mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceLevel, logPanGesture );
145 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
147 mEnvironmentOptions.SetPanGesturePredictionMode(predictionMode);
149 int predictionAmount = -1;
150 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_AMOUNT, predictionAmount) )
152 if( predictionAmount < 0 )
154 // do not support times in the past
155 predictionAmount = 0;
157 mEnvironmentOptions.SetPanGesturePredictionAmount(predictionAmount);
160 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_MODE, smoothingMode) )
162 mEnvironmentOptions.SetPanGestureSmoothingMode(smoothingMode);
164 float smoothingAmount = 1.0f;
165 if( GetFloatEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_AMOUNT, smoothingAmount) )
167 smoothingAmount = Clamp(smoothingAmount, 0.0f, 1.0f);
168 mEnvironmentOptions.SetPanGestureSmoothingAmount(smoothingAmount);
171 int minimumDistance(-1);
172 if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_DISTANCE, minimumDistance ))
174 mEnvironmentOptions.SetMinimumPanDistance( minimumDistance );
177 int minimumEvents(-1);
178 if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_EVENTS, minimumEvents ))
180 mEnvironmentOptions.SetMinimumPanEvents( minimumEvents );
184 if ( GetIntegerEnvironmentVariable(DALI_GLES_CALL_TIME, glesCallTime ))
186 mEnvironmentOptions.SetGlesCallTime( glesCallTime );
189 mEnvironmentOptions.InstallLogFunction();
192 void Adaptor::Initialize()
194 ParseEnvironmentOptions();
196 mPlatformAbstraction = new SlpPlatform::SlpPlatformAbstraction;
198 if( mEnvironmentOptions.GetPerformanceLoggingLevel() > 0 )
200 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
203 mCallbackManager = CallbackManager::New();
205 PositionSize size = mSurface->GetPositionSize();
207 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, mEnvironmentOptions);
209 if( mEnvironmentOptions.GetGlesCallTime() > 0 )
211 mGLES = new GlProxyImplementation( mEnvironmentOptions );
215 mGLES = new GlImplementation();
218 mEglFactory = new EglFactory();
220 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
222 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager );
224 mObjectProfiler = new ObjectProfiler();
226 mNotificationTrigger = new TriggerEvent( boost::bind(&Adaptor::ProcessCoreEvents, this) );
228 mVSyncMonitor = new VSyncMonitor;
230 mUpdateRenderController = new UpdateRenderController( *this, mEnvironmentOptions );
232 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
234 // Should be called after Core creation
235 if( mEnvironmentOptions.GetPanGestureLoggingLevel() )
237 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
239 if( mEnvironmentOptions.GetPanGesturePredictionMode() >= 0 )
241 Integration::SetPanGesturePredictionMode(mEnvironmentOptions.GetPanGesturePredictionMode());
243 if( mEnvironmentOptions.GetPanGesturePredictionAmount() >= 0.0f )
245 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions.GetPanGesturePredictionAmount());
247 if( mEnvironmentOptions.GetPanGestureSmoothingMode() >= 0 )
249 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions.GetPanGestureSmoothingMode());
251 if( mEnvironmentOptions.GetPanGestureSmoothingAmount() >= 0.0f )
253 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions.GetPanGestureSmoothingAmount());
259 // Ensure stop status
262 // Release first as we do not want any access to Adaptor as it is being destroyed.
263 gThreadLocalAdaptor.release();
265 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
267 (*iter)->OnDestroy();
270 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
271 delete mVSyncMonitor;
272 delete mEventHandler;
273 delete mObjectProfiler;
277 // Delete feedback controller before feedback plugin & style monitor dependencies
278 delete mFeedbackController;
279 delete mDaliFeedbackPlugin;
281 delete mGestureManager;
282 delete mPlatformAbstraction;
283 delete mCallbackManager;
284 delete mPerformanceInterface;
286 // uninstall it on this thread (main actor thread)
287 Dali::Integration::Log::UninstallLogFunction();
290 void Adaptor::Start()
292 // it doesn't support restart after stop at this moment
293 // to support restarting, need more testing
294 if( READY != mState )
299 // Start the callback manager
300 mCallbackManager->Start();
302 // create event handler
303 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
305 if( mDeferredRotationObserver != NULL )
307 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
308 mDeferredRotationObserver = NULL;
311 // guarantee map the surface before starting render-thread.
314 // NOTE: dpi must be set before starting the render thread
315 // use default or command line settings if not run on device
317 // set the DPI value for font rendering
318 unsigned int dpiHor, dpiVer;
320 mSurface->GetDpi(dpiHor, dpiVer);
322 // tell core about the value
323 mCore->SetDpi(dpiHor, dpiVer);
325 mCore->SetDpi(mHDpi, mVDpi);
328 // Tell the core the size of the surface just before we start the render-thread
329 PositionSize size = mSurface->GetPositionSize();
330 mCore->SurfaceResized( size.width, size.height );
332 // Start the update & render threads
333 mUpdateRenderController->Start();
337 ProcessCoreEvents(); // Ensure any startup messages are processed.
339 if ( !mFeedbackController )
341 // Start sound & haptic feedback
342 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
345 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
351 // Dali::Internal::Adaptor::Adaptor::Pause
352 void Adaptor::Pause()
354 // Only pause the adaptor if we're actually running.
355 if( RUNNING == mState )
357 // Inform observers that we are about to be paused.
358 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
363 // Reset the event handler when adaptor paused
366 mEventHandler->Reset();
369 mUpdateRenderController->Pause();
375 // Dali::Internal::Adaptor::Adaptor::Resume
376 void Adaptor::Resume()
378 // Only resume the adaptor if we are in the suspended state.
379 if( PAUSED == mState )
381 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
382 // If there were events pending, mCore->Resume() will call
383 // RenderController->RequestUpdate()
384 // UpdateRenderController->RequestUpdate()
385 // UpdateRenderSynchronization->RequestUpdate()
386 // and we should have reset the frame timers before allowing Core->Update() to be called.
387 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
389 mUpdateRenderController->ResumeFrameTime();
391 mUpdateRenderController->Resume();
395 // Reset the event handler when adaptor resumed
398 mEventHandler->Reset();
401 // Inform observers that we have resumed.
402 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
407 ProcessCoreEvents(); // Ensure any outstanding messages are processed
413 if( RUNNING == mState ||
415 PAUSED_WHILE_HIDDEN == mState )
417 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
422 mUpdateRenderController->Stop();
425 // Delete the TTS player
426 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
430 mTtsPlayers[i].Reset();
434 delete mEventHandler;
435 mEventHandler = NULL;
437 delete mNotificationTrigger;
438 mNotificationTrigger = NULL;
440 mCallbackManager->Stop();
446 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
448 mEventHandler->FeedTouchPoint( point, timeStamp );
451 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
453 mEventHandler->FeedWheelEvent( wheelEvent );
456 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
458 mEventHandler->FeedKeyEvent( keyEvent );
461 bool Adaptor::MoveResize( const PositionSize& positionSize )
463 PositionSize old = mSurface->GetPositionSize();
465 // just resize the surface. The driver should automatically resize the egl Surface (untested)
466 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
467 // is resized. Implementations typically use hooks into the OS and native window
468 // system to perform this resizing on demand, transparently to the client.
469 mSurface->MoveResize( positionSize );
471 if(old.width != positionSize.width || old.height != positionSize.height)
473 SurfaceSizeChanged(positionSize);
479 void Adaptor::SurfaceResized( const PositionSize& positionSize )
481 PositionSize old = mSurface->GetPositionSize();
483 // Called by an application, when it has resized a window outside of Dali.
484 // The EGL driver automatically detects X Window resize calls, and resizes
485 // the EGL surface for us.
486 mSurface->MoveResize( positionSize );
488 if(old.width != positionSize.width || old.height != positionSize.height)
490 SurfaceSizeChanged(positionSize);
494 void Adaptor::ReplaceSurface( Dali::RenderSurface& surface )
496 // adaptor implementation needs the implementation of
497 RenderSurface* internalSurface = dynamic_cast<Internal::Adaptor::RenderSurface*>( &surface );
498 DALI_ASSERT_ALWAYS( internalSurface && "Incorrect surface" );
500 mSurface = internalSurface;
502 SurfaceSizeChanged( internalSurface->GetPositionSize() );
504 // flush the event queue to give update and render threads chance
505 // to start processing messages for new camera setup etc as soon as possible
508 // this method is synchronous
509 mUpdateRenderController->ReplaceSurface(internalSurface);
512 Dali::RenderSurface& Adaptor::GetSurface() const
517 void Adaptor::ReleaseSurfaceLock()
519 mSurface->ReleaseLock();
522 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
524 if(!mTtsPlayers[mode])
526 // Create the TTS player when it needed, because it can reduce launching time.
527 mTtsPlayers[mode] = TtsPlayer::New(mode);
530 return mTtsPlayers[mode];
533 bool Adaptor::AddIdle(boost::function<void(void)> callBack)
535 bool idleAdded(false);
537 // Only add an idle if the Adaptor is actually running
538 if( RUNNING == mState )
540 idleAdded = mCallbackManager->AddCallback(callBack, CallbackManager::IDLE_PRIORITY);
546 bool Adaptor::CallFromMainLoop(boost::function<void(void)> callBack)
548 bool callAdded(false);
550 // Only allow the callback if the Adaptor is actually running
551 if ( RUNNING == mState )
553 callAdded = mCallbackManager->AddCallback(callBack, CallbackManager::DEFAULT_PRIORITY);
559 Dali::Adaptor& Adaptor::Get()
561 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() != NULL && "Adaptor not instantiated" );
562 return gThreadLocalAdaptor->mAdaptor;
565 bool Adaptor::IsAvailable()
567 return gThreadLocalAdaptor.get() != NULL;
570 Dali::Integration::Core& Adaptor::GetCore()
575 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
577 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
580 void Adaptor::SetUseHardwareVSync( bool useHardware )
582 mVSyncMonitor->SetUseHardwareVSync( useHardware );
585 void Adaptor::SetDpi(size_t hDpi, size_t vDpi)
591 EglFactory& Adaptor::GetEGLFactory() const
593 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
597 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
602 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
604 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
608 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
610 return *mPlatformAbstraction;
613 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
618 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
620 return *mNotificationTrigger;
622 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
624 return mTriggerEventFactory;
626 RenderSurface* Adaptor::GetRenderSurfaceInterface()
630 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
632 return mVSyncMonitor;
635 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
637 return mKernelTracer;
640 PerformanceInterface* Adaptor::GetPerformanceInterface()
642 return mPerformanceInterface;
645 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
647 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
648 return *mPlatformAbstraction;
651 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
653 mDragAndDropDetector = detector;
657 mEventHandler->SetDragAndDropDetector( detector );
661 void Adaptor::SetRotationObserver( RotationObserver* observer )
665 mEventHandler->SetRotationObserver( observer );
667 else if( mState == READY )
669 // Set once event handler exists
670 mDeferredRotationObserver = observer;
674 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
676 if(mTtsPlayers[mode])
678 mTtsPlayers[mode].Reset();
682 void Adaptor::SetMinimumPinchDistance(float distance)
684 if( mGestureManager )
686 mGestureManager->SetMinimumPinchDistance(distance);
690 void Adaptor::AddObserver( LifeCycleObserver& observer )
692 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
694 if ( match == mObservers.end() )
696 mObservers.push_back( &observer );
700 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
702 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
704 if ( match != mObservers.end() )
706 mObservers.erase( match );
710 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
714 mCore->QueueEvent(event);
718 void Adaptor::ProcessCoreEvents()
722 if( mPerformanceInterface )
724 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_START );
727 mCore->ProcessEvents();
729 if( mPerformanceInterface )
731 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_END );
736 void Adaptor::RequestUpdate()
738 // When Dali applications are partially visible behind the lock-screen,
739 // the indicator must be updated (therefore allow updates in the PAUSED state)
740 if ( PAUSED == mState ||
743 mUpdateRenderController->RequestUpdate();
747 void Adaptor::RequestProcessEventsOnIdle()
749 // Only request a notification if the Adaptor is actually running
750 if ( RUNNING == mState )
752 boost::unique_lock<boost::mutex> lock( mIdleInstaller );
754 // check if the idle handle is already installed
755 if( mNotificationOnIdleInstalled )
759 mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
763 void Adaptor::OnWindowShown()
765 if ( PAUSED_WHILE_HIDDEN == mState )
767 // Adaptor can now be resumed
772 // Force a render task
777 void Adaptor::OnWindowHidden()
779 if ( STOPPED != mState )
783 // Adaptor cannot be resumed until the window is shown
784 mState = PAUSED_WHILE_HIDDEN;
788 // Dali::Internal::Adaptor::Adaptor::OnDamaged
789 void Adaptor::OnDamaged( const DamageArea& area )
791 // This is needed for the case where Dali window is partially obscured
795 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
797 // let the core know the surface size has changed
798 mCore->SurfaceResized(positionSize.width, positionSize.height);
800 mResizedSignalV2.Emit( mAdaptor );
803 void Adaptor::NotifyLanguageChanged()
805 mLanguageChangedSignalV2.Emit( mAdaptor );
808 void Adaptor::RequestUpdateOnce()
810 if( PAUSED_WHILE_HIDDEN != mState )
812 if( mUpdateRenderController )
814 mUpdateRenderController->RequestUpdateOnce();
819 void Adaptor::ProcessCoreEventsFromIdle()
823 // the idle handle automatically un-installs itself
824 mNotificationOnIdleInstalled = false;
827 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
831 mUpdateRenderController(NULL),
836 mPlatformAbstraction( NULL ),
837 mEventHandler( NULL ),
838 mCallbackManager( NULL ),
839 mNotificationOnIdleInstalled( false ),
840 mNotificationTrigger(NULL),
841 mGestureManager(NULL),
844 mDaliFeedbackPlugin(NULL),
845 mFeedbackController(NULL),
847 mDragAndDropDetector(),
848 mDeferredRotationObserver(NULL),
849 mBaseLayout(baseLayout),
850 mEnvironmentOptions(),
851 mPerformanceInterface(NULL),
852 mObjectProfiler(NULL)
854 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
855 gThreadLocalAdaptor.reset(this);
860 void Adaptor::SetViewMode( ViewMode viewMode )
862 mSurface->SetViewMode( viewMode );
863 mCore->SetViewMode( viewMode );
866 ViewMode Adaptor::GetViewMode() const
868 return mCore->GetViewMode();
871 void Adaptor::SetStereoBase( float stereoBase )
873 mCore->SetStereoBase( stereoBase );
876 float Adaptor::GetStereoBase() const
878 return mCore->GetStereoBase();
881 } // namespace Adaptor
883 } // namespace Internal