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 <render-surface.h>
39 #include <tts-player-impl.h>
40 #include <accessibility-adaptor-impl.h>
41 #include <events/gesture-manager.h>
42 #include <events/event-handler.h>
43 #include <gl/gl-proxy-implementation.h>
44 #include <gl/gl-implementation.h>
45 #include <gl/egl-sync-implementation.h>
46 #include <gl/egl-image-extensions.h>
47 #include <gl/egl-factory.h>
48 #include <imf-manager-impl.h>
49 #include <clipboard-impl.h>
50 #include <vsync-monitor.h>
51 #include <object-profiler.h>
52 #include <base/display-connection.h>
53 #include <window-impl.h>
55 #include <tizen-logging.h>
57 using Dali::TextAbstraction::FontClient;
70 __thread Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
71 } // unnamed namespace
73 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
75 Dali::Adaptor* adaptor = new Dali::Adaptor;
76 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
77 adaptor->mImpl = impl;
79 impl->Initialize(configuration);
84 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
86 Any winId = window.GetNativeHandle();
88 Window& windowImpl = Dali::GetImplementation(window);
89 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
90 windowImpl.SetAdaptor(*adaptor);
94 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
96 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
97 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
98 mEnvironmentOptions->SetLogFunction( logFunction );
99 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
101 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
104 GetDataStoragePath( path );
105 mPlatformAbstraction->SetDataStoragePath( path );
107 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
108 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
110 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
112 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
113 // files automatically.
115 if( mEnvironmentOptions->PerformanceServerRequired() )
117 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
120 mCallbackManager = CallbackManager::New();
122 PositionSize size = mSurface->GetPositionSize();
124 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
126 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
128 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
132 mGLES = new GlImplementation();
135 mEglFactory = new EglFactory();
137 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
139 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
141 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
142 if( 0u < timeInterval )
144 mObjectProfiler = new ObjectProfiler( timeInterval );
147 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
149 mVSyncMonitor = new VSyncMonitor;
151 mUpdateRenderController = new UpdateRenderController( *this, *mEnvironmentOptions );
153 // Should be called after Core creation
154 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
156 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
158 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
160 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
162 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
164 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
166 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
168 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
170 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
172 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
174 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
176 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
178 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
180 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
182 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
184 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
190 // Ensure stop status
193 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
194 gThreadLocalAdaptor = NULL;
196 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
198 (*iter)->OnDestroy();
201 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
202 delete mVSyncMonitor;
203 delete mEventHandler;
204 delete mObjectProfiler;
209 delete mGestureManager;
210 delete mPlatformAbstraction;
211 delete mCallbackManager;
212 delete mPerformanceInterface;
214 // uninstall it on this thread (main actor thread)
215 Dali::Integration::Log::UninstallLogFunction();
217 // Delete environment options if we own it
218 if( mEnvironmentOptionsOwned )
220 delete mEnvironmentOptions;
224 void Adaptor::Start()
226 // it doesn't support restart after stop at this moment
227 // to support restarting, need more testing
228 if( READY != mState )
233 // Start the callback manager
234 mCallbackManager->Start();
236 // create event handler
237 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
239 if( mDeferredRotationObserver != NULL )
241 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
242 mDeferredRotationObserver = NULL;
245 unsigned int dpiHor, dpiVer;
247 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
249 // tell core about the DPI value
250 mCore->SetDpi(dpiHor, dpiVer);
252 // set the DPI value for font rendering
253 FontClient fontClient = FontClient::Get();
254 fontClient.SetDpi( dpiHor, dpiVer );
256 // Tell the core the size of the surface just before we start the render-thread
257 PositionSize size = mSurface->GetPositionSize();
258 mCore->SurfaceResized( size.width, size.height );
260 // Start the update & render threads
261 mUpdateRenderController->Start();
265 ProcessCoreEvents(); // Ensure any startup messages are processed.
267 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
273 // Dali::Internal::Adaptor::Adaptor::Pause
274 void Adaptor::Pause()
276 // Only pause the adaptor if we're actually running.
277 if( RUNNING == mState )
279 // Inform observers that we are about to be paused.
280 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
285 // Reset the event handler when adaptor paused
288 mEventHandler->Reset();
291 mUpdateRenderController->Pause();
297 // Dali::Internal::Adaptor::Adaptor::Resume
298 void Adaptor::Resume()
300 // Only resume the adaptor if we are in the suspended state.
301 if( PAUSED == mState )
303 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
304 // If there were events pending, mCore->Resume() will call
305 // RenderController->RequestUpdate()
306 // UpdateRenderController->RequestUpdate()
307 // UpdateRenderSynchronization->RequestUpdate()
308 // and we should have reset the frame timers before allowing Core->Update() to be called.
309 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
311 mUpdateRenderController->ResumeFrameTime();
313 mUpdateRenderController->Resume();
317 // Reset the event handler when adaptor resumed
320 mEventHandler->Reset();
323 // Inform observers that we have resumed.
324 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
329 ProcessCoreEvents(); // Ensure any outstanding messages are processed
335 if( RUNNING == mState ||
337 PAUSED_WHILE_HIDDEN == mState )
339 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
344 mUpdateRenderController->Stop();
347 // Delete the TTS player
348 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
352 mTtsPlayers[i].Reset();
356 delete mEventHandler;
357 mEventHandler = NULL;
359 delete mNotificationTrigger;
360 mNotificationTrigger = NULL;
362 mCallbackManager->Stop();
368 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
370 mEventHandler->FeedTouchPoint( point, timeStamp );
373 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
375 mEventHandler->FeedWheelEvent( wheelEvent );
378 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
380 mEventHandler->FeedKeyEvent( keyEvent );
383 bool Adaptor::MoveResize( const PositionSize& positionSize )
385 PositionSize old = mSurface->GetPositionSize();
387 // just resize the surface. The driver should automatically resize the egl Surface (untested)
388 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
389 // is resized. Implementations typically use hooks into the OS and native window
390 // system to perform this resizing on demand, transparently to the client.
391 mSurface->MoveResize( positionSize );
393 if(old.width != positionSize.width || old.height != positionSize.height)
395 SurfaceSizeChanged(positionSize);
401 void Adaptor::SurfaceResized( const PositionSize& positionSize )
403 PositionSize old = mSurface->GetPositionSize();
405 // Called by an application, when it has resized a window outside of Dali.
406 // The EGL driver automatically detects X Window resize calls, and resizes
407 // the EGL surface for us.
408 mSurface->MoveResize( positionSize );
410 if(old.width != positionSize.width || old.height != positionSize.height)
412 SurfaceSizeChanged(positionSize);
416 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
418 mNativeWindow = nativeWindow;
421 SurfaceSizeChanged(mSurface->GetPositionSize());
423 // flush the event queue to give update and render threads chance
424 // to start processing messages for new camera setup etc as soon as possible
427 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
429 // this method blocks until the render thread has completed the replace.
430 mUpdateRenderController->ReplaceSurface(mSurface);
432 // Inform core, so that texture resources can be reloaded
433 mCore->RecoverFromContextLoss();
435 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
438 RenderSurface& Adaptor::GetSurface() const
443 void Adaptor::ReleaseSurfaceLock()
445 mSurface->ReleaseLock();
448 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
450 if(!mTtsPlayers[mode])
452 // Create the TTS player when it needed, because it can reduce launching time.
453 mTtsPlayers[mode] = TtsPlayer::New(mode);
456 return mTtsPlayers[mode];
459 bool Adaptor::AddIdle( CallbackBase* callback )
461 bool idleAdded(false);
463 // Only add an idle if the Adaptor is actually running
464 if( RUNNING == mState )
466 idleAdded = mCallbackManager->AddIdleCallback( callback );
473 Dali::Adaptor& Adaptor::Get()
475 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
476 return gThreadLocalAdaptor->mAdaptor;
479 bool Adaptor::IsAvailable()
481 return gThreadLocalAdaptor != NULL;
484 void Adaptor::SceneCreated()
486 mCore->SceneCreated();
489 Dali::Integration::Core& Adaptor::GetCore()
494 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
496 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
499 void Adaptor::SetUseHardwareVSync( bool useHardware )
501 mVSyncMonitor->SetUseHardwareVSync( useHardware );
504 EglFactory& Adaptor::GetEGLFactory() const
506 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
510 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
515 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
517 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
521 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
523 return *mPlatformAbstraction;
526 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
531 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
533 return *mNotificationTrigger;
536 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
538 return mTriggerEventFactory;
541 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
543 return mSocketFactory;
546 RenderSurface* Adaptor::GetRenderSurfaceInterface()
551 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
553 return mVSyncMonitor;
556 TraceInterface& Adaptor::GetKernelTraceInterface()
558 return mKernelTracer;
561 TraceInterface& Adaptor::GetSystemTraceInterface()
563 return mSystemTracer;
566 PerformanceInterface* Adaptor::GetPerformanceInterface()
568 return mPerformanceInterface;
571 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
573 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
574 return *mPlatformAbstraction;
577 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
579 mDragAndDropDetector = detector;
583 mEventHandler->SetDragAndDropDetector( detector );
587 void Adaptor::SetRotationObserver( RotationObserver* observer )
591 mEventHandler->SetRotationObserver( observer );
593 else if( mState == READY )
595 // Set once event handler exists
596 mDeferredRotationObserver = observer;
600 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
602 if(mTtsPlayers[mode])
604 mTtsPlayers[mode].Reset();
608 void Adaptor::SetMinimumPinchDistance(float distance)
610 if( mGestureManager )
612 mGestureManager->SetMinimumPinchDistance(distance);
616 Any Adaptor::GetNativeWindowHandle()
618 return mNativeWindow;
621 void Adaptor::AddObserver( LifeCycleObserver& observer )
623 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
625 if ( match == mObservers.end() )
627 mObservers.push_back( &observer );
631 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
633 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
635 if ( match != mObservers.end() )
637 mObservers.erase( match );
641 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
645 mCore->QueueEvent(event);
649 void Adaptor::ProcessCoreEvents()
653 if( mPerformanceInterface )
655 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
658 mCore->ProcessEvents();
660 if( mPerformanceInterface )
662 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
667 void Adaptor::RequestUpdate()
669 // When Dali applications are partially visible behind the lock-screen,
670 // the indicator must be updated (therefore allow updates in the PAUSED state)
671 if ( PAUSED == mState ||
674 mUpdateRenderController->RequestUpdate();
678 void Adaptor::RequestProcessEventsOnIdle()
680 // Only request a notification if the Adaptor is actually running
681 // and we haven't installed the idle notification
682 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
684 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
688 void Adaptor::OnWindowShown()
690 if ( PAUSED_WHILE_HIDDEN == mState )
692 // Adaptor can now be resumed
697 // Force a render task
702 void Adaptor::OnWindowHidden()
704 if ( STOPPED != mState )
708 // Adaptor cannot be resumed until the window is shown
709 mState = PAUSED_WHILE_HIDDEN;
713 // Dali::Internal::Adaptor::Adaptor::OnDamaged
714 void Adaptor::OnDamaged( const DamageArea& area )
716 // This is needed for the case where Dali window is partially obscured
720 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
722 // let the core know the surface size has changed
723 mCore->SurfaceResized(positionSize.width, positionSize.height);
725 mResizedSignal.Emit( mAdaptor );
728 void Adaptor::NotifySceneCreated()
730 GetCore().SceneCreated();
733 void Adaptor::NotifyLanguageChanged()
735 mLanguageChangedSignal.Emit( mAdaptor );
738 void Adaptor::RequestUpdateOnce()
740 if( PAUSED_WHILE_HIDDEN != mState )
742 if( mUpdateRenderController )
744 mUpdateRenderController->RequestUpdateOnce();
749 void Adaptor::ProcessCoreEventsFromIdle()
753 // the idle handle automatically un-installs itself
754 mNotificationOnIdleInstalled = false;
757 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
759 mLanguageChangedSignal(),
763 mUpdateRenderController(NULL),
767 mNativeWindow( nativeWindow ),
769 mPlatformAbstraction( NULL ),
770 mEventHandler( NULL ),
771 mCallbackManager( NULL ),
772 mNotificationOnIdleInstalled( false ),
773 mNotificationTrigger(NULL),
774 mGestureManager(NULL),
776 mDragAndDropDetector(),
777 mDeferredRotationObserver(NULL),
778 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
779 mPerformanceInterface(NULL),
780 mObjectProfiler(NULL),
781 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
783 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
784 gThreadLocalAdaptor = this;
789 void Adaptor::SetViewMode( ViewMode viewMode )
791 mSurface->SetViewMode( viewMode );
792 mCore->SetViewMode( viewMode );
795 ViewMode Adaptor::GetViewMode() const
797 return mCore->GetViewMode();
800 void Adaptor::SetStereoBase( float stereoBase )
802 mCore->SetStereoBase( stereoBase );
805 float Adaptor::GetStereoBase() const
807 return mCore->GetStereoBase();
810 } // namespace Adaptor
812 } // namespace Internal