2 * Copyright (c) 2017 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/public-api/common/stage.h>
24 #include <dali/public-api/actors/layer.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/integration-api/debug.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/integration-api/context-notifier.h>
29 #include <dali/integration-api/profiling.h>
30 #include <dali/integration-api/input-options.h>
31 #include <dali/integration-api/events/touch-event-integ.h>
34 #include <base/thread-controller.h>
35 #include <base/performance-logging/performance-interface-factory.h>
36 #include <base/lifecycle-observer.h>
38 #include <dali/devel-api/text-abstraction/font-client.h>
40 #include <callback-manager.h>
41 #include <render-surface.h>
42 #include <tts-player-impl.h>
43 #include <accessibility-adaptor-impl.h>
44 #include <events/gesture-manager.h>
45 #include <events/event-handler.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>
55 #include <base/display-connection.h>
56 #include <window-impl.h>
58 #include <tizen-logging.h>
59 #include <image-loading.h>
61 #include <locale-utils.h>
63 using Dali::TextAbstraction::FontClient;
76 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
77 } // unnamed namespace
79 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
81 Dali::Adaptor* adaptor = new Dali::Adaptor;
82 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
83 adaptor->mImpl = impl;
85 impl->Initialize(configuration);
90 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
92 Any winId = window.GetNativeHandle();
94 Window& windowImpl = Dali::GetImplementation(window);
95 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
96 windowImpl.SetAdaptor(*adaptor);
100 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
102 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
103 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
104 mEnvironmentOptions->SetLogFunction( logFunction );
105 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
107 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
110 GetDataStoragePath( path );
111 mPlatformAbstraction->SetDataStoragePath( path );
113 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
114 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
116 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
118 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
119 // files automatically.
121 if( mEnvironmentOptions->PerformanceServerRequired() )
123 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
126 mCallbackManager = CallbackManager::New();
128 PositionSize size = mSurface->GetPositionSize();
130 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
132 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
134 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
138 mGLES = new GlImplementation();
141 mEglFactory = new EglFactory( mEnvironmentOptions->GetMultiSamplingLevel() );
143 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
145 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
147 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
148 if( 0u < timeInterval )
150 mObjectProfiler = new ObjectProfiler( timeInterval );
153 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
155 mVSyncMonitor = new VSyncMonitor;
157 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
159 // Should be called after Core creation
160 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
162 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
164 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
166 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
168 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
170 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
172 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
174 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
176 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
178 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
180 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
182 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
184 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
186 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
188 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
190 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
193 // Set max texture size
194 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
196 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
199 SetupSystemInformation();
204 // Ensure stop status
207 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
208 gThreadLocalAdaptor = NULL;
210 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
212 (*iter)->OnDestroy();
215 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
216 delete mVSyncMonitor;
217 delete mEventHandler;
218 delete mObjectProfiler;
223 delete mGestureManager;
224 delete mPlatformAbstraction;
225 delete mCallbackManager;
226 delete mPerformanceInterface;
228 // uninstall it on this thread (main actor thread)
229 Dali::Integration::Log::UninstallLogFunction();
231 // Delete environment options if we own it
232 if( mEnvironmentOptionsOwned )
234 delete mEnvironmentOptions;
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 unsigned int dpiHor, dpiVer;
261 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
263 // tell core about the DPI value
264 mCore->SetDpi(dpiHor, dpiVer);
266 // set the DPI value for font rendering
267 FontClient fontClient = FontClient::Get();
268 fontClient.SetDpi( dpiHor, dpiVer );
270 // Tell the core the size of the surface just before we start the render-thread
271 PositionSize size = mSurface->GetPositionSize();
272 mCore->SurfaceResized( size.width, size.height );
274 // Initialize the thread controller
275 mThreadController->Initialize();
279 ProcessCoreEvents(); // Ensure any startup messages are processed.
281 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
287 // Dali::Internal::Adaptor::Adaptor::Pause
288 void Adaptor::Pause()
290 // Only pause the adaptor if we're actually running.
291 if( RUNNING == mState )
293 // Inform observers that we are about to be paused.
294 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
299 // Reset the event handler when adaptor paused
302 mEventHandler->Pause();
305 mThreadController->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 )
318 // Reset the event handler when adaptor resumed
321 mEventHandler->Resume();
324 // Inform observers that we have resumed.
325 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
330 // trigger processing of events queued up while paused
331 mCore->ProcessEvents();
333 // Do at end to ensure our first update/render after resumption includes the processed messages as well
334 mThreadController->Resume();
340 if( RUNNING == mState ||
342 PAUSED_WHILE_HIDDEN == mState )
344 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
349 mThreadController->Stop();
351 // Delete the TTS player
352 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
356 mTtsPlayers[i].Reset();
360 delete mEventHandler;
361 mEventHandler = NULL;
363 delete mNotificationTrigger;
364 mNotificationTrigger = NULL;
366 mCallbackManager->Stop();
372 void Adaptor::ContextLost()
374 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
377 void Adaptor::ContextRegained()
379 // Inform core, so that texture resources can be reloaded
380 mCore->RecoverFromContextLoss();
382 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
385 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
387 mEventHandler->FeedTouchPoint( point, timeStamp );
390 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
392 mEventHandler->FeedWheelEvent( wheelEvent );
395 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
397 mEventHandler->FeedKeyEvent( keyEvent );
400 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
402 PositionSize positionSize = surface.GetPositionSize();
404 // let the core know the surface size has changed
405 mCore->SurfaceResized( positionSize.width, positionSize.height );
407 mResizedSignal.Emit( mAdaptor );
409 mNativeWindow = nativeWindow;
412 // flush the event queue to give the update-render thread chance
413 // to start processing messages for new camera setup etc as soon as possible
416 // this method blocks until the render thread has completed the replace.
417 mThreadController->ReplaceSurface(mSurface);
420 RenderSurface& Adaptor::GetSurface() const
425 void Adaptor::ReleaseSurfaceLock()
427 mSurface->ReleaseLock();
430 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
432 if(!mTtsPlayers[mode])
434 // Create the TTS player when it needed, because it can reduce launching time.
435 mTtsPlayers[mode] = TtsPlayer::New(mode);
438 return mTtsPlayers[mode];
441 bool Adaptor::AddIdle( CallbackBase* callback, bool forceAdd )
443 bool idleAdded(false);
445 // Only add an idle if the Adaptor is actually running
446 if( RUNNING == mState || forceAdd )
448 idleAdded = mCallbackManager->AddIdleCallback( callback );
454 void Adaptor::RemoveIdle( CallbackBase* callback )
456 mCallbackManager->RemoveIdleCallback( callback );
459 Dali::Adaptor& Adaptor::Get()
461 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
462 return gThreadLocalAdaptor->mAdaptor;
465 bool Adaptor::IsAvailable()
467 return gThreadLocalAdaptor != NULL;
470 void Adaptor::SceneCreated()
472 mCore->SceneCreated();
475 Dali::Integration::Core& Adaptor::GetCore()
480 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
482 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
485 void Adaptor::SetUseHardwareVSync( bool useHardware )
487 mVSyncMonitor->SetUseHardwareVSync( useHardware );
490 EglFactory& Adaptor::GetEGLFactory() const
492 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
496 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
501 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
503 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
507 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
509 return *mPlatformAbstraction;
512 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
517 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
519 return *mNotificationTrigger;
522 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
524 return mTriggerEventFactory;
527 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
529 return mSocketFactory;
532 RenderSurface* Adaptor::GetRenderSurfaceInterface()
537 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
539 return mVSyncMonitor;
542 TraceInterface& Adaptor::GetKernelTraceInterface()
544 return mKernelTracer;
547 TraceInterface& Adaptor::GetSystemTraceInterface()
549 return mSystemTracer;
552 PerformanceInterface* Adaptor::GetPerformanceInterface()
554 return mPerformanceInterface;
557 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
559 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
560 return *mPlatformAbstraction;
563 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
565 mDragAndDropDetector = detector;
569 mEventHandler->SetDragAndDropDetector( detector );
573 void Adaptor::SetRotationObserver( RotationObserver* observer )
577 mEventHandler->SetRotationObserver( observer );
579 else if( mState == READY )
581 // Set once event handler exists
582 mDeferredRotationObserver = observer;
586 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
588 if(mTtsPlayers[mode])
590 mTtsPlayers[mode].Reset();
594 void Adaptor::SetMinimumPinchDistance(float distance)
596 if( mGestureManager )
598 mGestureManager->SetMinimumPinchDistance(distance);
602 Any Adaptor::GetNativeWindowHandle()
604 return mNativeWindow;
607 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
609 mUseRemoteSurface = useRemoteSurface;
612 void Adaptor::AddObserver( LifeCycleObserver& observer )
614 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
616 if ( match == mObservers.end() )
618 mObservers.push_back( &observer );
622 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
624 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
626 if ( match != mObservers.end() )
628 mObservers.erase( match );
632 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
636 mCore->QueueEvent(event);
640 void Adaptor::ProcessCoreEvents()
644 if( mPerformanceInterface )
646 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
649 mCore->ProcessEvents();
651 if( mPerformanceInterface )
653 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
658 void Adaptor::RequestUpdate( bool forceUpdate )
664 mThreadController->RequestUpdate();
668 case PAUSED_WHILE_HIDDEN:
670 // When Dali applications are partially visible behind the lock-screen,
671 // the indicator must be updated (therefore allow updates in the PAUSED state)
674 mThreadController->RequestUpdateOnce();
686 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
688 // Only request a notification if the Adaptor is actually running
689 // and we haven't installed the idle notification
690 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || forceProcess ) )
692 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
696 void Adaptor::OnWindowShown()
698 if ( PAUSED_WHILE_HIDDEN == mState )
700 // Adaptor can now be resumed
705 // Force a render task
710 void Adaptor::OnWindowHidden()
712 if ( STOPPED != mState )
716 // Adaptor cannot be resumed until the window is shown
717 mState = PAUSED_WHILE_HIDDEN;
721 // Dali::Internal::Adaptor::Adaptor::OnDamaged
722 void Adaptor::OnDamaged( const DamageArea& area )
724 // This is needed for the case where Dali window is partially obscured
725 RequestUpdate( false );
728 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
730 // let the core know the surface size has changed
731 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
733 mResizedSignal.Emit( mAdaptor );
736 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
738 // flush the event queue to give the update-render thread chance
739 // to start processing messages for new camera setup etc as soon as possible
742 // this method blocks until the render thread has completed the resizing.
743 mThreadController->ResizeSurface();
746 void Adaptor::NotifySceneCreated()
748 GetCore().SceneCreated();
750 // Start thread controller after the scene has been created
751 mThreadController->Start();
753 // process after surface is created (registering to remote surface provider if required)
754 SurfaceInitialized();
757 void Adaptor::NotifyLanguageChanged()
759 mLanguageChangedSignal.Emit( mAdaptor );
762 void Adaptor::RenderOnce()
767 void Adaptor::RequestUpdateOnce()
769 if( mThreadController )
771 mThreadController->RequestUpdateOnce();
775 void Adaptor::IndicatorSizeChanged(int height)
777 // let the core know the indicator height is changed
778 mCore->SetTopMargin(height);
781 void Adaptor::ProcessCoreEventsFromIdle()
785 // the idle handle automatically un-installs itself
786 mNotificationOnIdleInstalled = false;
789 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
791 mLanguageChangedSignal(),
795 mThreadController( NULL ),
796 mVSyncMonitor( NULL ),
800 mNativeWindow( nativeWindow ),
802 mPlatformAbstraction( NULL ),
803 mEventHandler( NULL ),
804 mCallbackManager( NULL ),
805 mNotificationOnIdleInstalled( false ),
806 mNotificationTrigger( NULL ),
807 mGestureManager( NULL ),
808 mDaliFeedbackPlugin(),
809 mFeedbackController( NULL ),
812 mDragAndDropDetector(),
813 mDeferredRotationObserver( NULL ),
814 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
815 mPerformanceInterface( NULL ),
818 mTriggerEventFactory(),
819 mObjectProfiler( NULL ),
821 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
822 mUseRemoteSurface( false )
824 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
825 gThreadLocalAdaptor = this;
830 void Adaptor::SetViewMode( ViewMode viewMode )
832 mSurface->SetViewMode( viewMode );
833 mCore->SetViewMode( viewMode );
836 ViewMode Adaptor::GetViewMode() const
838 return mCore->GetViewMode();
841 void Adaptor::SetStereoBase( float stereoBase )
843 mCore->SetStereoBase( stereoBase );
846 float Adaptor::GetStereoBase() const
848 return mCore->GetStereoBase();
851 void Adaptor::SetRootLayoutDirection( std::string locale )
853 Dali::Stage stage = Dali::Stage::GetCurrent();
855 stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
856 static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
859 } // namespace Adaptor
861 } // namespace Internal