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 <feedback/feedback-controller.h>
44 #include <feedback/feedback-plugin-proxy.h>
45 #include <gl/gl-proxy-implementation.h>
46 #include <gl/gl-implementation.h>
47 #include <gl/egl-sync-implementation.h>
48 #include <gl/egl-image-extensions.h>
49 #include <gl/egl-factory.h>
50 #include <imf-manager-impl.h>
51 #include <clipboard-impl.h>
52 #include <vsync-monitor.h>
53 #include <object-profiler.h>
54 #include <base/display-connection.h>
55 #include <window-impl.h>
57 #include <tizen-logging.h>
59 using Dali::TextAbstraction::FontClient;
72 __thread Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
73 } // unnamed namespace
75 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
77 Dali::Adaptor* adaptor = new Dali::Adaptor;
78 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
79 adaptor->mImpl = impl;
81 impl->Initialize(configuration);
86 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
88 Any winId = window.GetNativeHandle();
90 Window& windowImpl = Dali::GetImplementation(window);
91 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
92 windowImpl.SetAdaptor(*adaptor);
96 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
98 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
99 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
100 mEnvironmentOptions->SetLogFunction( logFunction );
101 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
103 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
106 GetDataStoragePath( path );
107 mPlatformAbstraction->SetDataStoragePath( path );
109 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
110 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
112 dataRetentionPolicy = ResourcePolicy::DALI_RETAINS_MESH_DATA;
114 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
115 // files automatically.
117 if( mEnvironmentOptions->PerformanceServerRequired() )
119 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
122 mCallbackManager = CallbackManager::New();
124 PositionSize size = mSurface->GetPositionSize();
126 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
128 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
130 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
134 mGLES = new GlImplementation();
137 mEglFactory = new EglFactory();
139 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
141 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
143 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
144 if( 0u < timeInterval )
146 mObjectProfiler = new ObjectProfiler( timeInterval );
149 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
151 mVSyncMonitor = new VSyncMonitor;
153 mUpdateRenderController = new UpdateRenderController( *this, *mEnvironmentOptions );
155 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
157 // Should be called after Core creation
158 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
160 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
162 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
164 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
166 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
168 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
170 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
172 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
174 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
176 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
178 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
180 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
182 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
184 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
186 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
188 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
194 // Ensure stop status
197 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
198 gThreadLocalAdaptor = NULL;
200 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
202 (*iter)->OnDestroy();
205 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
206 delete mVSyncMonitor;
207 delete mEventHandler;
208 delete mObjectProfiler;
212 // Delete feedback controller before feedback plugin & style monitor dependencies
213 delete mFeedbackController;
214 delete mDaliFeedbackPlugin;
216 delete mGestureManager;
217 delete mPlatformAbstraction;
218 delete mCallbackManager;
219 delete mPerformanceInterface;
221 // uninstall it on this thread (main actor thread)
222 Dali::Integration::Log::UninstallLogFunction();
224 // Delete environment options if we own it
225 if( mEnvironmentOptionsOwned )
227 delete mEnvironmentOptions;
231 void Adaptor::Start()
233 // it doesn't support restart after stop at this moment
234 // to support restarting, need more testing
235 if( READY != mState )
240 // Start the callback manager
241 mCallbackManager->Start();
243 // create event handler
244 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
246 if( mDeferredRotationObserver != NULL )
248 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
249 mDeferredRotationObserver = NULL;
252 unsigned int dpiHor, dpiVer;
254 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
256 // tell core about the DPI value
257 mCore->SetDpi(dpiHor, dpiVer);
259 // set the DPI value for font rendering
260 FontClient fontClient = FontClient::Get();
261 fontClient.SetDpi( dpiHor, dpiVer );
263 // Tell the core the size of the surface just before we start the render-thread
264 PositionSize size = mSurface->GetPositionSize();
265 mCore->SurfaceResized( size.width, size.height );
267 // Start the update & render threads
268 mUpdateRenderController->Start();
272 ProcessCoreEvents(); // Ensure any startup messages are processed.
274 if ( !mFeedbackController )
276 // Start sound & haptic feedback
277 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
280 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
286 // Dali::Internal::Adaptor::Adaptor::Pause
287 void Adaptor::Pause()
289 // Only pause the adaptor if we're actually running.
290 if( RUNNING == mState )
292 // Inform observers that we are about to be paused.
293 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
298 // Reset the event handler when adaptor paused
301 mEventHandler->Reset();
304 mUpdateRenderController->Pause();
310 // Dali::Internal::Adaptor::Adaptor::Resume
311 void Adaptor::Resume()
313 // Only resume the adaptor if we are in the suspended state.
314 if( PAUSED == mState )
316 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
317 // If there were events pending, mCore->Resume() will call
318 // RenderController->RequestUpdate()
319 // UpdateRenderController->RequestUpdate()
320 // UpdateRenderSynchronization->RequestUpdate()
321 // and we should have reset the frame timers before allowing Core->Update() to be called.
322 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
324 mUpdateRenderController->ResumeFrameTime();
326 mUpdateRenderController->Resume();
330 // Reset the event handler when adaptor resumed
333 mEventHandler->Reset();
336 // Inform observers that we have resumed.
337 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
342 ProcessCoreEvents(); // Ensure any outstanding messages are processed
348 if( RUNNING == mState ||
350 PAUSED_WHILE_HIDDEN == mState )
352 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
357 mUpdateRenderController->Stop();
360 // Delete the TTS player
361 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
365 mTtsPlayers[i].Reset();
369 delete mEventHandler;
370 mEventHandler = NULL;
372 delete mNotificationTrigger;
373 mNotificationTrigger = NULL;
375 mCallbackManager->Stop();
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 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
442 // this method blocks until the render thread has completed the replace.
443 mUpdateRenderController->ReplaceSurface(mSurface);
445 // Inform core, so that texture resources can be reloaded
446 mCore->RecoverFromContextLoss();
448 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
451 RenderSurface& Adaptor::GetSurface() const
456 void Adaptor::ReleaseSurfaceLock()
458 mSurface->ReleaseLock();
461 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
463 if(!mTtsPlayers[mode])
465 // Create the TTS player when it needed, because it can reduce launching time.
466 mTtsPlayers[mode] = TtsPlayer::New(mode);
469 return mTtsPlayers[mode];
472 bool Adaptor::AddIdle( CallbackBase* callback )
474 bool idleAdded(false);
476 // Only add an idle if the Adaptor is actually running
477 if( RUNNING == mState )
479 idleAdded = mCallbackManager->AddIdleCallback( callback );
486 Dali::Adaptor& Adaptor::Get()
488 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
489 return gThreadLocalAdaptor->mAdaptor;
492 bool Adaptor::IsAvailable()
494 return gThreadLocalAdaptor != NULL;
497 void Adaptor::SceneCreated()
499 mCore->SceneCreated();
502 Dali::Integration::Core& Adaptor::GetCore()
507 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
509 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
512 void Adaptor::SetUseHardwareVSync( bool useHardware )
514 mVSyncMonitor->SetUseHardwareVSync( useHardware );
517 EglFactory& Adaptor::GetEGLFactory() const
519 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
523 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
528 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
530 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
534 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
536 return *mPlatformAbstraction;
539 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
544 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
546 return *mNotificationTrigger;
549 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
551 return mTriggerEventFactory;
554 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
556 return mSocketFactory;
559 RenderSurface* Adaptor::GetRenderSurfaceInterface()
564 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
566 return mVSyncMonitor;
569 TraceInterface& Adaptor::GetKernelTraceInterface()
571 return mKernelTracer;
574 TraceInterface& Adaptor::GetSystemTraceInterface()
576 return mSystemTracer;
579 PerformanceInterface* Adaptor::GetPerformanceInterface()
581 return mPerformanceInterface;
584 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
586 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
587 return *mPlatformAbstraction;
590 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
592 mDragAndDropDetector = detector;
596 mEventHandler->SetDragAndDropDetector( detector );
600 void Adaptor::SetRotationObserver( RotationObserver* observer )
604 mEventHandler->SetRotationObserver( observer );
606 else if( mState == READY )
608 // Set once event handler exists
609 mDeferredRotationObserver = observer;
613 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
615 if(mTtsPlayers[mode])
617 mTtsPlayers[mode].Reset();
621 void Adaptor::SetMinimumPinchDistance(float distance)
623 if( mGestureManager )
625 mGestureManager->SetMinimumPinchDistance(distance);
629 Any Adaptor::GetNativeWindowHandle()
631 return mNativeWindow;
634 void Adaptor::AddObserver( LifeCycleObserver& observer )
636 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
638 if ( match == mObservers.end() )
640 mObservers.push_back( &observer );
644 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
646 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
648 if ( match != mObservers.end() )
650 mObservers.erase( match );
654 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
658 mCore->QueueEvent(event);
662 void Adaptor::ProcessCoreEvents()
666 if( mPerformanceInterface )
668 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
671 mCore->ProcessEvents();
673 if( mPerformanceInterface )
675 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
680 void Adaptor::RequestUpdate()
682 // When Dali applications are partially visible behind the lock-screen,
683 // the indicator must be updated (therefore allow updates in the PAUSED state)
684 if ( PAUSED == mState ||
687 mUpdateRenderController->RequestUpdate();
691 void Adaptor::RequestProcessEventsOnIdle()
693 // Only request a notification if the Adaptor is actually running
694 // and we haven't installed the idle notification
695 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
697 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
701 void Adaptor::OnWindowShown()
703 if ( PAUSED_WHILE_HIDDEN == mState )
705 // Adaptor can now be resumed
710 // Force a render task
715 void Adaptor::OnWindowHidden()
717 if ( STOPPED != mState )
721 // Adaptor cannot be resumed until the window is shown
722 mState = PAUSED_WHILE_HIDDEN;
726 // Dali::Internal::Adaptor::Adaptor::OnDamaged
727 void Adaptor::OnDamaged( const DamageArea& area )
729 // This is needed for the case where Dali window is partially obscured
733 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
735 // let the core know the surface size has changed
736 mCore->SurfaceResized(positionSize.width, positionSize.height);
738 mResizedSignal.Emit( mAdaptor );
741 void Adaptor::NotifySceneCreated()
743 GetCore().SceneCreated();
746 void Adaptor::NotifyLanguageChanged()
748 mLanguageChangedSignal.Emit( mAdaptor );
751 void Adaptor::RequestUpdateOnce()
753 if( PAUSED_WHILE_HIDDEN != mState )
755 if( mUpdateRenderController )
757 mUpdateRenderController->RequestUpdateOnce();
762 void Adaptor::ProcessCoreEventsFromIdle()
766 // the idle handle automatically un-installs itself
767 mNotificationOnIdleInstalled = false;
770 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
772 mLanguageChangedSignal(),
776 mUpdateRenderController(NULL),
780 mNativeWindow( nativeWindow ),
782 mPlatformAbstraction( NULL ),
783 mEventHandler( NULL ),
784 mCallbackManager( NULL ),
785 mNotificationOnIdleInstalled( false ),
786 mNotificationTrigger(NULL),
787 mGestureManager(NULL),
788 mDaliFeedbackPlugin(NULL),
789 mFeedbackController(NULL),
791 mDragAndDropDetector(),
792 mDeferredRotationObserver(NULL),
793 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
794 mPerformanceInterface(NULL),
795 mObjectProfiler(NULL),
796 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
798 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
799 gThreadLocalAdaptor = this;
804 void Adaptor::SetViewMode( ViewMode viewMode )
806 mSurface->SetViewMode( viewMode );
807 mCore->SetViewMode( viewMode );
810 ViewMode Adaptor::GetViewMode() const
812 return mCore->GetViewMode();
815 void Adaptor::SetStereoBase( float stereoBase )
817 mCore->SetStereoBase( stereoBase );
820 float Adaptor::GetStereoBase() const
822 return mCore->GetStereoBase();
825 } // namespace Adaptor
827 } // namespace Internal