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->Pause();
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->Resume();
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::ContextLost()
370 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
373 void Adaptor::ContextRegained()
375 // Inform core, so that texture resources can be reloaded
376 mCore->RecoverFromContextLoss();
378 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
381 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
383 mEventHandler->FeedTouchPoint( point, timeStamp );
386 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
388 mEventHandler->FeedWheelEvent( wheelEvent );
391 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
393 mEventHandler->FeedKeyEvent( keyEvent );
396 bool Adaptor::MoveResize( const PositionSize& positionSize )
398 PositionSize old = mSurface->GetPositionSize();
400 // just resize the surface. The driver should automatically resize the egl Surface (untested)
401 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
402 // is resized. Implementations typically use hooks into the OS and native window
403 // system to perform this resizing on demand, transparently to the client.
404 mSurface->MoveResize( positionSize );
406 if(old.width != positionSize.width || old.height != positionSize.height)
408 SurfaceSizeChanged(positionSize);
414 void Adaptor::SurfaceResized( const PositionSize& positionSize )
416 PositionSize old = mSurface->GetPositionSize();
418 // Called by an application, when it has resized a window outside of Dali.
419 // The EGL driver automatically detects X Window resize calls, and resizes
420 // the EGL surface for us.
421 mSurface->MoveResize( positionSize );
423 if(old.width != positionSize.width || old.height != positionSize.height)
425 SurfaceSizeChanged(positionSize);
429 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
431 mNativeWindow = nativeWindow;
434 SurfaceSizeChanged(mSurface->GetPositionSize());
436 // flush the event queue to give update and render threads chance
437 // to start processing messages for new camera setup etc as soon as possible
440 // this method blocks until the render thread has completed the replace.
441 mUpdateRenderController->ReplaceSurface(mSurface);
444 RenderSurface& Adaptor::GetSurface() const
449 void Adaptor::ReleaseSurfaceLock()
451 mSurface->ReleaseLock();
454 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
456 if(!mTtsPlayers[mode])
458 // Create the TTS player when it needed, because it can reduce launching time.
459 mTtsPlayers[mode] = TtsPlayer::New(mode);
462 return mTtsPlayers[mode];
465 bool Adaptor::AddIdle( CallbackBase* callback )
467 bool idleAdded(false);
469 // Only add an idle if the Adaptor is actually running
470 if( RUNNING == mState )
472 idleAdded = mCallbackManager->AddIdleCallback( callback );
479 Dali::Adaptor& Adaptor::Get()
481 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
482 return gThreadLocalAdaptor->mAdaptor;
485 bool Adaptor::IsAvailable()
487 return gThreadLocalAdaptor != NULL;
490 void Adaptor::SceneCreated()
492 mCore->SceneCreated();
495 Dali::Integration::Core& Adaptor::GetCore()
500 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
502 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
505 void Adaptor::SetUseHardwareVSync( bool useHardware )
507 mVSyncMonitor->SetUseHardwareVSync( useHardware );
510 EglFactory& Adaptor::GetEGLFactory() const
512 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
516 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
521 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
523 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
527 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
529 return *mPlatformAbstraction;
532 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
537 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
539 return *mNotificationTrigger;
542 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
544 return mTriggerEventFactory;
547 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
549 return mSocketFactory;
552 RenderSurface* Adaptor::GetRenderSurfaceInterface()
557 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
559 return mVSyncMonitor;
562 TraceInterface& Adaptor::GetKernelTraceInterface()
564 return mKernelTracer;
567 TraceInterface& Adaptor::GetSystemTraceInterface()
569 return mSystemTracer;
572 PerformanceInterface* Adaptor::GetPerformanceInterface()
574 return mPerformanceInterface;
577 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
579 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
580 return *mPlatformAbstraction;
583 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
585 mDragAndDropDetector = detector;
589 mEventHandler->SetDragAndDropDetector( detector );
593 void Adaptor::SetRotationObserver( RotationObserver* observer )
597 mEventHandler->SetRotationObserver( observer );
599 else if( mState == READY )
601 // Set once event handler exists
602 mDeferredRotationObserver = observer;
606 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
608 if(mTtsPlayers[mode])
610 mTtsPlayers[mode].Reset();
614 void Adaptor::SetMinimumPinchDistance(float distance)
616 if( mGestureManager )
618 mGestureManager->SetMinimumPinchDistance(distance);
622 Any Adaptor::GetNativeWindowHandle()
624 return mNativeWindow;
627 void Adaptor::AddObserver( LifeCycleObserver& observer )
629 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
631 if ( match == mObservers.end() )
633 mObservers.push_back( &observer );
637 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
639 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
641 if ( match != mObservers.end() )
643 mObservers.erase( match );
647 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
651 mCore->QueueEvent(event);
655 void Adaptor::ProcessCoreEvents()
659 if( mPerformanceInterface )
661 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
664 mCore->ProcessEvents();
666 if( mPerformanceInterface )
668 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
673 void Adaptor::RequestUpdate()
675 // When Dali applications are partially visible behind the lock-screen,
676 // the indicator must be updated (therefore allow updates in the PAUSED state)
677 if ( PAUSED == mState ||
680 mUpdateRenderController->RequestUpdate();
684 void Adaptor::RequestProcessEventsOnIdle()
686 // Only request a notification if the Adaptor is actually running
687 // and we haven't installed the idle notification
688 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
690 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
694 void Adaptor::OnWindowShown()
696 if ( PAUSED_WHILE_HIDDEN == mState )
698 // Adaptor can now be resumed
703 // Force a render task
708 void Adaptor::OnWindowHidden()
710 if ( STOPPED != mState )
714 // Adaptor cannot be resumed until the window is shown
715 mState = PAUSED_WHILE_HIDDEN;
719 // Dali::Internal::Adaptor::Adaptor::OnDamaged
720 void Adaptor::OnDamaged( const DamageArea& area )
722 // This is needed for the case where Dali window is partially obscured
726 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
728 // let the core know the surface size has changed
729 mCore->SurfaceResized(positionSize.width, positionSize.height);
731 mResizedSignal.Emit( mAdaptor );
734 void Adaptor::NotifySceneCreated()
736 GetCore().SceneCreated();
739 void Adaptor::NotifyLanguageChanged()
741 mLanguageChangedSignal.Emit( mAdaptor );
744 void Adaptor::RequestUpdateOnce()
746 if( PAUSED_WHILE_HIDDEN != mState )
748 if( mUpdateRenderController )
750 mUpdateRenderController->RequestUpdateOnce();
755 void Adaptor::ProcessCoreEventsFromIdle()
759 // the idle handle automatically un-installs itself
760 mNotificationOnIdleInstalled = false;
763 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
765 mLanguageChangedSignal(),
769 mUpdateRenderController(NULL),
773 mNativeWindow( nativeWindow ),
775 mPlatformAbstraction( NULL ),
776 mEventHandler( NULL ),
777 mCallbackManager( NULL ),
778 mNotificationOnIdleInstalled( false ),
779 mNotificationTrigger(NULL),
780 mGestureManager(NULL),
782 mDragAndDropDetector(),
783 mDeferredRotationObserver(NULL),
784 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
785 mPerformanceInterface(NULL),
786 mObjectProfiler(NULL),
787 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
789 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
790 gThreadLocalAdaptor = this;
795 void Adaptor::SetViewMode( ViewMode viewMode )
797 mSurface->SetViewMode( viewMode );
798 mCore->SetViewMode( viewMode );
801 ViewMode Adaptor::GetViewMode() const
803 return mCore->GetViewMode();
806 void Adaptor::SetStereoBase( float stereoBase )
808 mCore->SetStereoBase( stereoBase );
811 float Adaptor::GetStereoBase() const
813 return mCore->GetStereoBase();
816 } // namespace Adaptor
818 } // namespace Internal