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/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/thread-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>
56 #include <image-loading.h>
58 using Dali::TextAbstraction::FontClient;
71 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
72 } // unnamed namespace
74 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
76 Dali::Adaptor* adaptor = new Dali::Adaptor;
77 Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
78 adaptor->mImpl = impl;
80 impl->Initialize(configuration);
85 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
87 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( mEnvironmentOptions->GetMultiSamplingLevel() );
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 mThreadController = new ThreadController( *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());
187 // Set max texture size
188 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
190 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
196 // Ensure stop status
199 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
200 gThreadLocalAdaptor = NULL;
202 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
204 (*iter)->OnDestroy();
207 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
208 delete mVSyncMonitor;
209 delete mEventHandler;
210 delete mObjectProfiler;
215 delete mGestureManager;
216 delete mPlatformAbstraction;
217 delete mCallbackManager;
218 delete mPerformanceInterface;
220 // uninstall it on this thread (main actor thread)
221 Dali::Integration::Log::UninstallLogFunction();
223 // Delete environment options if we own it
224 if( mEnvironmentOptionsOwned )
226 delete mEnvironmentOptions;
230 void Adaptor::Start()
232 // it doesn't support restart after stop at this moment
233 // to support restarting, need more testing
234 if( READY != mState )
239 // Start the callback manager
240 mCallbackManager->Start();
242 // create event handler
243 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
245 if( mDeferredRotationObserver != NULL )
247 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
248 mDeferredRotationObserver = NULL;
251 unsigned int dpiHor, dpiVer;
253 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
255 // tell core about the DPI value
256 mCore->SetDpi(dpiHor, dpiVer);
258 // set the DPI value for font rendering
259 FontClient fontClient = FontClient::Get();
260 fontClient.SetDpi( dpiHor, dpiVer );
262 // Tell the core the size of the surface just before we start the render-thread
263 PositionSize size = mSurface->GetPositionSize();
264 mCore->SurfaceResized( size.width, size.height );
266 // Initialize the thread controller
267 mThreadController->Initialize();
271 ProcessCoreEvents(); // Ensure any startup messages are processed.
273 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
279 // Dali::Internal::Adaptor::Adaptor::Pause
280 void Adaptor::Pause()
282 // Only pause the adaptor if we're actually running.
283 if( RUNNING == mState )
285 // Inform observers that we are about to be paused.
286 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
291 // Reset the event handler when adaptor paused
294 mEventHandler->Pause();
297 mThreadController->Pause();
303 // Dali::Internal::Adaptor::Adaptor::Resume
304 void Adaptor::Resume()
306 // Only resume the adaptor if we are in the suspended state.
307 if( PAUSED == mState )
311 // Reset the event handler when adaptor resumed
314 mEventHandler->Resume();
317 // Inform observers that we have resumed.
318 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
323 // Resume core so it processes any requests as well
326 // Do at end to ensure our first update/render after resumption includes the processed messages as well
327 mThreadController->Resume();
333 if( RUNNING == mState ||
335 PAUSED_WHILE_HIDDEN == mState )
337 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
342 mThreadController->Stop();
345 // Delete the TTS player
346 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
350 mTtsPlayers[i].Reset();
354 delete mEventHandler;
355 mEventHandler = NULL;
357 delete mNotificationTrigger;
358 mNotificationTrigger = NULL;
360 mCallbackManager->Stop();
366 void Adaptor::ContextLost()
368 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
371 void Adaptor::ContextRegained()
373 // Inform core, so that texture resources can be reloaded
374 mCore->RecoverFromContextLoss();
376 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
379 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
381 mEventHandler->FeedTouchPoint( point, timeStamp );
384 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
386 mEventHandler->FeedWheelEvent( wheelEvent );
389 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
391 mEventHandler->FeedKeyEvent( keyEvent );
394 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
396 PositionSize positionSize = surface.GetPositionSize();
398 // let the core know the surface size has changed
399 mCore->SurfaceResized( positionSize.width, positionSize.height );
401 mResizedSignal.Emit( mAdaptor );
403 mNativeWindow = nativeWindow;
406 // flush the event queue to give the update-render thread chance
407 // to start processing messages for new camera setup etc as soon as possible
410 // this method blocks until the render thread has completed the replace.
411 mThreadController->ReplaceSurface(mSurface);
414 RenderSurface& Adaptor::GetSurface() const
419 void Adaptor::ReleaseSurfaceLock()
421 mSurface->ReleaseLock();
424 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
426 if(!mTtsPlayers[mode])
428 // Create the TTS player when it needed, because it can reduce launching time.
429 mTtsPlayers[mode] = TtsPlayer::New(mode);
432 return mTtsPlayers[mode];
435 bool Adaptor::AddIdle( CallbackBase* callback )
437 bool idleAdded(false);
439 // Only add an idle if the Adaptor is actually running
440 if( RUNNING == mState )
442 idleAdded = mCallbackManager->AddIdleCallback( callback );
448 void Adaptor::RemoveIdle( CallbackBase* callback )
450 mCallbackManager->RemoveIdleCallback( callback );
453 Dali::Adaptor& Adaptor::Get()
455 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
456 return gThreadLocalAdaptor->mAdaptor;
459 bool Adaptor::IsAvailable()
461 return gThreadLocalAdaptor != NULL;
464 void Adaptor::SceneCreated()
466 mCore->SceneCreated();
469 Dali::Integration::Core& Adaptor::GetCore()
474 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
476 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
479 void Adaptor::SetUseHardwareVSync( bool useHardware )
481 mVSyncMonitor->SetUseHardwareVSync( useHardware );
484 EglFactory& Adaptor::GetEGLFactory() const
486 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
490 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
495 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
497 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
501 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
503 return *mPlatformAbstraction;
506 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
511 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
513 return *mNotificationTrigger;
516 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
518 return mTriggerEventFactory;
521 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
523 return mSocketFactory;
526 RenderSurface* Adaptor::GetRenderSurfaceInterface()
531 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
533 return mVSyncMonitor;
536 TraceInterface& Adaptor::GetKernelTraceInterface()
538 return mKernelTracer;
541 TraceInterface& Adaptor::GetSystemTraceInterface()
543 return mSystemTracer;
546 PerformanceInterface* Adaptor::GetPerformanceInterface()
548 return mPerformanceInterface;
551 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
553 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
554 return *mPlatformAbstraction;
557 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
559 mDragAndDropDetector = detector;
563 mEventHandler->SetDragAndDropDetector( detector );
567 void Adaptor::SetRotationObserver( RotationObserver* observer )
571 mEventHandler->SetRotationObserver( observer );
573 else if( mState == READY )
575 // Set once event handler exists
576 mDeferredRotationObserver = observer;
580 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
582 if(mTtsPlayers[mode])
584 mTtsPlayers[mode].Reset();
588 void Adaptor::SetMinimumPinchDistance(float distance)
590 if( mGestureManager )
592 mGestureManager->SetMinimumPinchDistance(distance);
596 Any Adaptor::GetNativeWindowHandle()
598 return mNativeWindow;
601 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
603 mUseRemoteSurface = useRemoteSurface;
606 void Adaptor::AddObserver( LifeCycleObserver& observer )
608 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
610 if ( match == mObservers.end() )
612 mObservers.push_back( &observer );
616 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
618 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
620 if ( match != mObservers.end() )
622 mObservers.erase( match );
626 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
630 mCore->QueueEvent(event);
634 void Adaptor::ProcessCoreEvents()
638 if( mPerformanceInterface )
640 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
643 mCore->ProcessEvents();
645 if( mPerformanceInterface )
647 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
652 void Adaptor::RequestUpdate()
654 // When Dali applications are partially visible behind the lock-screen,
655 // the indicator must be updated (therefore allow updates in the PAUSED state)
656 if ( PAUSED == mState ||
659 mThreadController->RequestUpdate();
663 void Adaptor::RequestProcessEventsOnIdle()
665 // Only request a notification if the Adaptor is actually running
666 // and we haven't installed the idle notification
667 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
669 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
673 void Adaptor::OnWindowShown()
675 if ( PAUSED_WHILE_HIDDEN == mState )
677 // Adaptor can now be resumed
682 // Force a render task
687 void Adaptor::OnWindowHidden()
689 if ( STOPPED != mState )
693 // Adaptor cannot be resumed until the window is shown
694 mState = PAUSED_WHILE_HIDDEN;
698 // Dali::Internal::Adaptor::Adaptor::OnDamaged
699 void Adaptor::OnDamaged( const DamageArea& area )
701 // This is needed for the case where Dali window is partially obscured
705 void Adaptor::SurfaceResizePrepare( Dali::Adaptor::SurfaceSize surfaceSize )
707 // let the core know the surface size has changed
708 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
710 mResizedSignal.Emit( mAdaptor );
713 void Adaptor::SurfaceResizeComplete( Dali::Adaptor::SurfaceSize surfaceSize )
715 // flush the event queue to give the update-render thread chance
716 // to start processing messages for new camera setup etc as soon as possible
719 // this method blocks until the render thread has completed the resizing.
720 mThreadController->ResizeSurface();
723 void Adaptor::NotifySceneCreated()
725 GetCore().SceneCreated();
727 // Start thread controller after the scene has been created
728 mThreadController->Start();
730 // process after surface is created (registering to remote surface provider if required)
731 SurfaceInitialized();
734 void Adaptor::NotifyLanguageChanged()
736 mLanguageChangedSignal.Emit( mAdaptor );
739 void Adaptor::RequestUpdateOnce()
741 if( PAUSED_WHILE_HIDDEN != mState )
743 if( mThreadController )
745 mThreadController->RequestUpdateOnce();
750 void Adaptor::IndicatorSizeChanged(int height)
752 // let the core know the indicator height is changed
753 mCore->SetTopMargin(height);
756 void Adaptor::ProcessCoreEventsFromIdle()
760 // the idle handle automatically un-installs itself
761 mNotificationOnIdleInstalled = false;
764 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
766 mLanguageChangedSignal(),
770 mThreadController( NULL ),
771 mVSyncMonitor( NULL ),
775 mNativeWindow( nativeWindow ),
777 mPlatformAbstraction( NULL ),
778 mEventHandler( NULL ),
779 mCallbackManager( NULL ),
780 mNotificationOnIdleInstalled( false ),
781 mNotificationTrigger( NULL ),
782 mGestureManager( NULL ),
783 mDaliFeedbackPlugin(),
784 mFeedbackController( NULL ),
787 mDragAndDropDetector(),
788 mDeferredRotationObserver( NULL ),
789 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
790 mPerformanceInterface( NULL ),
793 mTriggerEventFactory(),
794 mObjectProfiler( NULL ),
796 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
797 mUseRemoteSurface( false )
799 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
800 gThreadLocalAdaptor = this;
805 void Adaptor::SetViewMode( ViewMode viewMode )
807 mSurface->SetViewMode( viewMode );
808 mCore->SetViewMode( viewMode );
811 ViewMode Adaptor::GetViewMode() const
813 return mCore->GetViewMode();
816 void Adaptor::SetStereoBase( float stereoBase )
818 mCore->SetStereoBase( stereoBase );
821 float Adaptor::GetStereoBase() const
823 return mCore->GetStereoBase();
826 } // namespace Adaptor
828 } // namespace Internal