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 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();
89 Window& windowImpl = Dali::GetImplementation(window);
90 Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
91 windowImpl.SetAdaptor(*adaptor);
95 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
97 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
98 Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
99 mEnvironmentOptions->SetLogFunction( logFunction );
100 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
102 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
105 GetDataStoragePath( path );
106 mPlatformAbstraction->SetDataStoragePath( path );
108 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
109 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
111 dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
113 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
114 // files automatically.
116 if( mEnvironmentOptions->PerformanceServerRequired() )
118 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
121 mCallbackManager = CallbackManager::New();
123 PositionSize size = mSurface->GetPositionSize();
125 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
127 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
129 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
133 mGLES = new GlImplementation();
136 mEglFactory = new EglFactory( mEnvironmentOptions->GetMultiSamplingLevel() );
138 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
140 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
142 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
143 if( 0u < timeInterval )
145 mObjectProfiler = new ObjectProfiler( timeInterval );
148 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
150 mVSyncMonitor = new VSyncMonitor;
152 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
154 // Should be called after Core creation
155 if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
157 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
159 if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
161 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
163 if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
165 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
167 if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
169 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
171 if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
173 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
175 if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
177 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
179 if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
181 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
183 if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
185 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
188 // Set max texture size
189 if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
191 Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
197 // Ensure stop status
200 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
201 gThreadLocalAdaptor = NULL;
203 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
205 (*iter)->OnDestroy();
208 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
209 delete mVSyncMonitor;
210 delete mEventHandler;
211 delete mObjectProfiler;
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 // Initialize the thread controller
268 mThreadController->Initialize();
272 ProcessCoreEvents(); // Ensure any startup messages are processed.
274 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
280 // Dali::Internal::Adaptor::Adaptor::Pause
281 void Adaptor::Pause()
283 // Only pause the adaptor if we're actually running.
284 if( RUNNING == mState )
286 // Inform observers that we are about to be paused.
287 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
292 // Reset the event handler when adaptor paused
295 mEventHandler->Pause();
298 mThreadController->Pause();
304 // Dali::Internal::Adaptor::Adaptor::Resume
305 void Adaptor::Resume()
307 // Only resume the adaptor if we are in the suspended state.
308 if( PAUSED == mState )
312 // Reset the event handler when adaptor resumed
315 mEventHandler->Resume();
318 // Inform observers that we have resumed.
319 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
324 // Resume core so it processes any requests as well
327 // Do at end to ensure our first update/render after resumption includes the processed messages as well
328 mThreadController->Resume();
334 if( RUNNING == mState ||
336 PAUSED_WHILE_HIDDEN == mState )
338 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
343 mThreadController->Stop();
346 // Delete the TTS player
347 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
351 mTtsPlayers[i].Reset();
355 delete mEventHandler;
356 mEventHandler = NULL;
358 delete mNotificationTrigger;
359 mNotificationTrigger = NULL;
361 mCallbackManager->Stop();
367 void Adaptor::ContextLost()
369 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
372 void Adaptor::ContextRegained()
374 // Inform core, so that texture resources can be reloaded
375 mCore->RecoverFromContextLoss();
377 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
380 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
382 mEventHandler->FeedTouchPoint( point, timeStamp );
385 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
387 mEventHandler->FeedWheelEvent( wheelEvent );
390 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
392 mEventHandler->FeedKeyEvent( keyEvent );
395 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
397 PositionSize positionSize = surface.GetPositionSize();
399 // let the core know the surface size has changed
400 mCore->SurfaceResized( positionSize.width, positionSize.height );
402 mResizedSignal.Emit( mAdaptor );
404 mNativeWindow = nativeWindow;
407 // flush the event queue to give the update-render thread chance
408 // to start processing messages for new camera setup etc as soon as possible
411 // this method blocks until the render thread has completed the replace.
412 mThreadController->ReplaceSurface(mSurface);
415 RenderSurface& Adaptor::GetSurface() const
420 void Adaptor::ReleaseSurfaceLock()
422 mSurface->ReleaseLock();
425 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
427 if(!mTtsPlayers[mode])
429 // Create the TTS player when it needed, because it can reduce launching time.
430 mTtsPlayers[mode] = TtsPlayer::New(mode);
433 return mTtsPlayers[mode];
436 bool Adaptor::AddIdle( CallbackBase* callback )
438 bool idleAdded(false);
440 // Only add an idle if the Adaptor is actually running
441 if( RUNNING == mState )
443 idleAdded = mCallbackManager->AddIdleCallback( callback );
449 void Adaptor::RemoveIdle( CallbackBase* callback )
451 mCallbackManager->RemoveIdleCallback( callback );
454 Dali::Adaptor& Adaptor::Get()
456 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
457 return gThreadLocalAdaptor->mAdaptor;
460 bool Adaptor::IsAvailable()
462 return gThreadLocalAdaptor != NULL;
465 void Adaptor::SceneCreated()
467 mCore->SceneCreated();
470 Dali::Integration::Core& Adaptor::GetCore()
475 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
477 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
480 void Adaptor::SetUseHardwareVSync( bool useHardware )
482 mVSyncMonitor->SetUseHardwareVSync( useHardware );
485 EglFactory& Adaptor::GetEGLFactory() const
487 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
491 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
496 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
498 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
502 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
504 return *mPlatformAbstraction;
507 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
512 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
514 return *mNotificationTrigger;
517 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
519 return mTriggerEventFactory;
522 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
524 return mSocketFactory;
527 RenderSurface* Adaptor::GetRenderSurfaceInterface()
532 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
534 return mVSyncMonitor;
537 TraceInterface& Adaptor::GetKernelTraceInterface()
539 return mKernelTracer;
542 TraceInterface& Adaptor::GetSystemTraceInterface()
544 return mSystemTracer;
547 PerformanceInterface* Adaptor::GetPerformanceInterface()
549 return mPerformanceInterface;
552 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
554 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
555 return *mPlatformAbstraction;
558 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
560 mDragAndDropDetector = detector;
564 mEventHandler->SetDragAndDropDetector( detector );
568 void Adaptor::SetRotationObserver( RotationObserver* observer )
572 mEventHandler->SetRotationObserver( observer );
574 else if( mState == READY )
576 // Set once event handler exists
577 mDeferredRotationObserver = observer;
581 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
583 if(mTtsPlayers[mode])
585 mTtsPlayers[mode].Reset();
589 void Adaptor::SetMinimumPinchDistance(float distance)
591 if( mGestureManager )
593 mGestureManager->SetMinimumPinchDistance(distance);
597 Any Adaptor::GetNativeWindowHandle()
599 return mNativeWindow;
602 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
604 mUseRemoteSurface = useRemoteSurface;
607 void Adaptor::AddObserver( LifeCycleObserver& observer )
609 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
611 if ( match == mObservers.end() )
613 mObservers.push_back( &observer );
617 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
619 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
621 if ( match != mObservers.end() )
623 mObservers.erase( match );
627 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
631 mCore->QueueEvent(event);
635 void Adaptor::ProcessCoreEvents()
639 if( mPerformanceInterface )
641 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
644 mCore->ProcessEvents();
646 if( mPerformanceInterface )
648 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
653 void Adaptor::RequestUpdate()
655 // When Dali applications are partially visible behind the lock-screen,
656 // the indicator must be updated (therefore allow updates in the PAUSED state)
657 if ( PAUSED == mState ||
660 mThreadController->RequestUpdate();
664 void Adaptor::RequestProcessEventsOnIdle()
666 // Only request a notification if the Adaptor is actually running
667 // and we haven't installed the idle notification
668 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
670 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
674 void Adaptor::OnWindowShown()
676 if ( PAUSED_WHILE_HIDDEN == mState )
678 // Adaptor can now be resumed
683 // Force a render task
688 void Adaptor::OnWindowHidden()
690 if ( STOPPED != mState )
694 // Adaptor cannot be resumed until the window is shown
695 mState = PAUSED_WHILE_HIDDEN;
699 // Dali::Internal::Adaptor::Adaptor::OnDamaged
700 void Adaptor::OnDamaged( const DamageArea& area )
702 // This is needed for the case where Dali window is partially obscured
706 void Adaptor::SurfaceResizePrepare( Dali::Adaptor::SurfaceSize surfaceSize )
708 // let the core know the surface size has changed
709 mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
711 mResizedSignal.Emit( mAdaptor );
714 void Adaptor::SurfaceResizeComplete( Dali::Adaptor::SurfaceSize surfaceSize )
716 // flush the event queue to give the update-render thread chance
717 // to start processing messages for new camera setup etc as soon as possible
720 // this method blocks until the render thread has completed the resizing.
721 mThreadController->ResizeSurface();
724 void Adaptor::NotifySceneCreated()
726 GetCore().SceneCreated();
728 // Start thread controller after the scene has been created
729 mThreadController->Start();
731 // process after surface is created (registering to remote surface provider if required)
732 SurfaceInitialized();
735 void Adaptor::NotifyLanguageChanged()
737 mLanguageChangedSignal.Emit( mAdaptor );
740 void Adaptor::RequestUpdateOnce()
742 if( PAUSED_WHILE_HIDDEN != mState )
744 if( mThreadController )
746 mThreadController->RequestUpdateOnce();
751 void Adaptor::IndicatorSizeChanged(int height)
753 // let the core know the indicator height is changed
754 mCore->SetTopMargin(height);
757 void Adaptor::ProcessCoreEventsFromIdle()
761 // the idle handle automatically un-installs itself
762 mNotificationOnIdleInstalled = false;
765 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
767 mLanguageChangedSignal(),
771 mThreadController( NULL ),
772 mVSyncMonitor( NULL ),
776 mNativeWindow( nativeWindow ),
778 mPlatformAbstraction( NULL ),
779 mEventHandler( NULL ),
780 mCallbackManager( NULL ),
781 mNotificationOnIdleInstalled( false ),
782 mNotificationTrigger( NULL ),
783 mGestureManager( NULL ),
784 mDaliFeedbackPlugin(),
785 mFeedbackController( NULL ),
788 mDragAndDropDetector(),
789 mDeferredRotationObserver( NULL ),
790 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
791 mPerformanceInterface( NULL ),
794 mTriggerEventFactory(),
795 mObjectProfiler( NULL ),
797 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
798 mUseRemoteSurface( false )
800 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
801 gThreadLocalAdaptor = this;
806 void Adaptor::SetViewMode( ViewMode viewMode )
808 mSurface->SetViewMode( viewMode );
809 mCore->SetViewMode( viewMode );
812 ViewMode Adaptor::GetViewMode() const
814 return mCore->GetViewMode();
817 void Adaptor::SetStereoBase( float stereoBase )
819 mCore->SetStereoBase( stereoBase );
822 float Adaptor::GetStereoBase() const
824 return mCore->GetStereoBase();
827 } // namespace Adaptor
829 } // namespace Internal