2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include "adaptor-impl.h"
21 #include <boost/thread/tss.hpp>
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/profiling.h>
26 #include <dali/integration-api/events/touch-event-integ.h>
29 #include <base/update-render-controller.h>
30 #include <base/environment-variables.h>
31 #include <base/performance-logging/performance-interface-factory.h>
32 #include <base/lifecycle-observer.h>
34 #include <internal/common/callback-manager.h>
35 #include <internal/common/trigger-event.h>
36 #include <internal/common/render-surface-impl.h>
37 #include <internal/common/tts-player-impl.h>
38 #include <internal/common/accessibility-manager-impl.h>
39 #include <internal/common/timer-impl.h>
40 #include <internal/common/events/gesture-manager.h>
41 #include <internal/common/events/event-handler.h>
42 #include <internal/common/feedback/feedback-controller.h>
43 #include <internal/common/feedback/feedback-plugin-proxy.h>
44 #include <internal/common/gl/gl-implementation.h>
45 #include <internal/common/gl/egl-sync-implementation.h>
46 #include <internal/common/gl/egl-image-extensions.h>
47 #include <internal/common/gl/egl-factory.h>
48 #include <internal/common/imf-manager-impl.h>
49 #include <internal/common/clipboard-impl.h>
50 #include <internal/common/vsync-monitor.h>
52 #include <slp-logging.h>
67 boost::thread_specific_ptr<Adaptor> gThreadLocalAdaptor;
69 unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue )
71 const char* variableParameter = std::getenv(variable);
73 // if the parameter exists convert it to an integer, else return the default value
74 unsigned int intValue = variableParameter ? atoi(variableParameter) : defaultValue;
78 } // unnamed namespace
80 Dali::Adaptor* Adaptor::New( RenderSurface *surface, const DeviceLayout& baseLayout )
82 DALI_ASSERT_ALWAYS( surface->GetType() != Dali::RenderSurface::NO_SURFACE && "No surface for adaptor" );
84 Dali::Adaptor* adaptor = new Dali::Adaptor;
85 Adaptor* impl = new Adaptor( *adaptor, surface, baseLayout );
86 adaptor->mImpl = impl;
93 void Adaptor::ParseLogOptions()
95 // get logging options
96 unsigned int logFrameRateFrequency = GetIntegerEnvironmentVariable( DALI_ENV_FPS_TRACKING, 0 );
97 unsigned int logupdateStatusFrequency = GetIntegerEnvironmentVariable( DALI_ENV_UPDATE_STATUS_INTERVAL, 0 );
98 unsigned int logPerformanceLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE, 0 );
99 unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
101 Dali::Integration::Log::LogFunction logFunction(Dali::SlpPlatform::LogMessage);
103 mLogOptions.SetOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceLevel, logPanGesture );
105 // all threads here (event, update, and render) will send their logs to SLP Platform's LogMessage handler.
106 // Dali::Integration::Log::LogFunction logFunction(Dali::SlpPlatform::LogMessage);
108 mLogOptions.InstallLogFunction();
111 void Adaptor::Initialize()
115 mPlatformAbstraction = new SlpPlatform::SlpPlatformAbstraction;
117 if( mLogOptions.GetPerformanceLoggingLevel() > 0 )
119 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mLogOptions );
122 mCallbackManager = CallbackManager::New();
124 PositionSize size = mSurface->GetPositionSize();
126 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager);
128 mGLES = new GlImplementation;
130 mEglFactory = new EglFactory();
132 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
134 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager );
136 mNotificationTrigger = new TriggerEvent( boost::bind(&Adaptor::ProcessCoreEvents, this) );
138 mVSyncMonitor = new VSyncMonitor;
140 mUpdateRenderController = new UpdateRenderController( *this, mLogOptions );
142 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
144 // Should be called after Core creation
145 if( mLogOptions.GetPanGestureLoggingLevel() )
147 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
153 // Ensure stop status
156 // Release first as we do not want any access to Adaptor as it is being destroyed.
157 gThreadLocalAdaptor.release();
159 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
161 (*iter)->OnDestroy();
164 if (mUpdateRenderController)
166 delete mUpdateRenderController;
167 mUpdateRenderController = NULL;
172 delete mVSyncMonitor;
173 mVSyncMonitor = NULL;
178 delete mEventHandler;
179 mEventHandler = NULL;
188 // Delete EGL factory after Core, otherwise we may have a crash from GL resource destructors
195 // Delete feedback controller before feedback plugin & style monitor dependencies
196 delete mFeedbackController;
198 if (mDaliFeedbackPlugin)
200 delete mDaliFeedbackPlugin;
201 mDaliFeedbackPlugin = NULL;
212 delete mGestureManager;
213 mGestureManager = NULL;
216 if (mPlatformAbstraction)
218 delete mPlatformAbstraction;
219 mPlatformAbstraction = NULL;
222 if (mCallbackManager)
224 delete mCallbackManager;
225 mCallbackManager = NULL;
228 if( mPerformanceInterface )
230 delete mPerformanceInterface;
231 mPerformanceInterface = NULL;
234 // uninstall it on this thread (main actor thread)
235 Dali::Integration::Log::UninstallLogFunction();
238 void Adaptor::Start()
240 // it doesn't support restart after stop at this moment
241 // to support restarting, need more testing
242 if( READY != mState )
247 // Start the callback manager
248 mCallbackManager->Start();
250 // create event handler
251 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
253 if( mDeferredRotationObserver != NULL )
255 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
256 mDeferredRotationObserver = NULL;
259 // guarantee map the surface before starting render-thread.
262 // NOTE: dpi must be set before starting the render thread
263 // use default or command line settings if not run on device
265 // set the DPI value for font rendering
266 unsigned int dpiHor, dpiVer;
268 mSurface->GetDpi(dpiHor, dpiVer);
270 // tell core about the value
271 mCore->SetDpi(dpiHor, dpiVer);
273 mCore->SetDpi(mHDpi, mVDpi);
276 // Tell the core the size of the surface just before we start the render-thread
277 PositionSize size = mSurface->GetPositionSize();
278 mCore->SurfaceResized( size.width, size.height );
280 // Start the update & render threads
281 mUpdateRenderController->Start();
285 ProcessCoreEvents(); // Ensure any startup messages are processed.
287 if ( !mFeedbackController )
289 // Start sound & haptic feedback
290 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
293 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
299 // Dali::Internal::Adaptor::Adaptor::Pause
300 void Adaptor::Pause()
302 // Only pause the adaptor if we're actually running.
303 if( RUNNING == mState )
305 // Inform observers that we are about to be paused.
306 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
311 // Reset the event handler when adaptor paused
314 mEventHandler->Reset();
317 mUpdateRenderController->Pause();
323 // Dali::Internal::Adaptor::Adaptor::Resume
324 void Adaptor::Resume()
326 // Only resume the adaptor if we are in the suspended state.
327 if( PAUSED == mState )
330 mUpdateRenderController->Resume();
333 // Reset the event handler when adaptor resumed
336 mEventHandler->Reset();
339 // Inform observers that we have resumed.
340 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
345 ProcessCoreEvents(); // Ensure any outstanding messages are processed
351 if( RUNNING == mState ||
353 PAUSED_WHILE_HIDDEN == mState )
355 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
360 mUpdateRenderController->Stop();
363 // Delete the TTS player
364 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
368 mTtsPlayers[i].Reset();
372 delete mEventHandler;
373 mEventHandler = NULL;
375 delete mNotificationTrigger;
376 mNotificationTrigger = NULL;
378 mCallbackManager->Stop();
384 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
386 mEventHandler->FeedTouchPoint( point, timeStamp );
389 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
391 mEventHandler->FeedWheelEvent( wheelEvent );
394 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
396 mEventHandler->FeedKeyEvent( keyEvent );
399 bool Adaptor::MoveResize( const PositionSize& positionSize )
401 PositionSize old = mSurface->GetPositionSize();
403 // just resize the surface. The driver should automatically resize the egl Surface (untested)
404 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
405 // is resized. Implementations typically use hooks into the OS and native window
406 // system to perform this resizing on demand, transparently to the client.
407 mSurface->MoveResize( positionSize );
409 if(old.width != positionSize.width || old.height != positionSize.height)
411 SurfaceSizeChanged(positionSize);
417 void Adaptor::SurfaceResized( const PositionSize& positionSize )
419 PositionSize old = mSurface->GetPositionSize();
421 // Called by an application, when it has resized a window outside of Dali.
422 // The EGL driver automatically detects X Window resize calls, and resizes
423 // the EGL surface for us.
424 mSurface->MoveResize( positionSize );
426 if(old.width != positionSize.width || old.height != positionSize.height)
428 SurfaceSizeChanged(positionSize);
432 void Adaptor::ReplaceSurface( Dali::RenderSurface& surface )
434 // adaptor implementation needs the implementation of
435 RenderSurface* internalSurface = dynamic_cast<Internal::Adaptor::RenderSurface*>( &surface );
436 DALI_ASSERT_ALWAYS( internalSurface && "Incorrect surface" );
438 mSurface = internalSurface;
440 SurfaceSizeChanged( internalSurface->GetPositionSize() );
442 // flush the event queue to give update and render threads chance
443 // to start processing messages for new camera setup etc as soon as possible
446 // this method is synchronous
447 mUpdateRenderController->ReplaceSurface(internalSurface);
450 void Adaptor::RenderSync()
452 mUpdateRenderController->RenderSync();
455 Dali::RenderSurface& Adaptor::GetSurface() const
460 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
462 if(!mTtsPlayers[mode])
464 // Create the TTS player when it needed, because it can reduce launching time.
465 mTtsPlayers[mode] = TtsPlayer::New(mode);
468 return mTtsPlayers[mode];
471 bool Adaptor::AddIdle(boost::function<void(void)> callBack)
473 bool idleAdded(false);
475 // Only add an idle if the Adaptor is actually running
476 if( RUNNING == mState )
478 idleAdded = mCallbackManager->AddCallback(callBack, CallbackManager::IDLE_PRIORITY);
484 bool Adaptor::CallFromMainLoop(boost::function<void(void)> callBack)
486 bool callAdded(false);
488 // Only allow the callback if the Adaptor is actually running
489 if ( RUNNING == mState )
491 callAdded = mCallbackManager->AddCallback(callBack, CallbackManager::DEFAULT_PRIORITY);
497 Dali::Adaptor& Adaptor::Get()
499 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() != NULL && "Adaptor not instantiated" );
500 return gThreadLocalAdaptor->mAdaptor;
503 bool Adaptor::IsAvailable()
505 return gThreadLocalAdaptor.get() != NULL;
508 Dali::Integration::Core& Adaptor::GetCore()
513 void Adaptor::DisableVSync()
515 mUpdateRenderController->DisableVSync();
518 void Adaptor::SetDpi(size_t hDpi, size_t vDpi)
524 EglFactory& Adaptor::GetEGLFactory() const
526 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
530 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
535 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
537 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
541 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
543 return *mPlatformAbstraction;
546 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
551 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
553 return *mNotificationTrigger;
555 RenderSurface* Adaptor::GetRenderSurfaceInterface()
559 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
561 return mVSyncMonitor;
564 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
566 return mKernelTracer;
569 PerformanceInterface* Adaptor::GetPerformanceInterface()
571 return mPerformanceInterface;
574 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
576 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
577 return *mPlatformAbstraction;
580 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
582 mDragAndDropDetector = detector;
586 mEventHandler->SetDragAndDropDetector( detector );
590 void Adaptor::SetRotationObserver( RotationObserver* observer )
594 mEventHandler->SetRotationObserver( observer );
596 else if( mState == READY )
598 // Set once event handler exists
599 mDeferredRotationObserver = observer;
603 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
605 if(mTtsPlayers[mode])
607 mTtsPlayers[mode].Reset();
611 void Adaptor::AddObserver( LifeCycleObserver& observer )
613 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
615 if ( match == mObservers.end() )
617 mObservers.push_back( &observer );
621 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
623 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
625 if ( match != mObservers.end() )
627 mObservers.erase( match );
631 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
635 mCore->QueueEvent(event);
639 void Adaptor::ProcessCoreEvents()
643 if( mPerformanceInterface )
645 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_START );
648 mCore->ProcessEvents();
650 if( mPerformanceInterface )
652 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_END );
658 void Adaptor::RequestUpdate()
660 // When Dali applications are partially visible behind the lock-screen,
661 // the indicator must be updated (therefore allow updates in the PAUSED state)
662 if ( PAUSED == mState ||
665 mUpdateRenderController->RequestUpdate();
669 void Adaptor::RequestProcessEventsOnIdle()
671 // Only request a notification if the Adaptor is actually running
672 if ( RUNNING == mState )
674 boost::unique_lock<boost::mutex> lock( mIdleInstaller );
676 // check if the idle handle is already installed
677 if( mNotificationOnIdleInstalled )
681 mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
685 void Adaptor::OnWindowShown()
687 if ( PAUSED_WHILE_HIDDEN == mState )
689 // Adaptor can now be resumed
694 // Force a render task
699 void Adaptor::OnWindowHidden()
701 if ( STOPPED != mState )
705 // Adaptor cannot be resumed until the window is shown
706 mState = PAUSED_WHILE_HIDDEN;
710 // Dali::Internal::Adaptor::Adaptor::OnDamaged
711 void Adaptor::OnDamaged( const DamageArea& area )
713 // This is needed for the case where Dali window is partially obscured
717 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
719 // let the core know the surface size has changed
720 mCore->SurfaceResized(positionSize.width, positionSize.height);
722 mResizedSignalV2.Emit( mAdaptor );
725 void Adaptor::NotifyLanguageChanged()
727 mLanguageChangedSignalV2.Emit( mAdaptor );
730 void Adaptor::RequestUpdateOnce()
732 if( PAUSED_WHILE_HIDDEN != mState )
734 if( mUpdateRenderController )
736 mUpdateRenderController->RequestUpdateOnce();
741 void Adaptor::ProcessCoreEventsFromIdle()
745 // the idle handle automatically un-installs itself
746 mNotificationOnIdleInstalled = false;
749 void Adaptor::RegisterSingleton(const std::type_info& info, BaseHandle singleton)
753 mSingletonContainer.insert(SingletonPair(info.name(), singleton));
757 BaseHandle Adaptor::GetSingleton(const std::type_info& info) const
759 BaseHandle object = Dali::BaseHandle();
761 SingletonConstIter iter = mSingletonContainer.find(info.name());
762 if(iter != mSingletonContainer.end())
764 object = (*iter).second;
770 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
774 mUpdateRenderController(NULL),
779 mPlatformAbstraction( NULL ),
780 mEventHandler( NULL ),
781 mCallbackManager( NULL ),
782 mNotificationOnIdleInstalled( false ),
783 mNotificationTrigger(NULL),
784 mGestureManager(NULL),
787 mDaliFeedbackPlugin(NULL),
788 mFeedbackController(NULL),
790 mDragAndDropDetector(),
791 mDeferredRotationObserver(NULL),
792 mBaseLayout(baseLayout),
794 mPerformanceInterface(NULL)
796 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
797 gThreadLocalAdaptor.reset(this);
800 } // namespace Adaptor
802 } // namespace Internal