2 * Copyright (c) 2016 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>
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 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());
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 mThreadController; // 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 // Initialize the thread controller
261 mThreadController->Initialize();
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 mThreadController->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 )
305 // Reset the event handler when adaptor resumed
308 mEventHandler->Resume();
311 // Inform observers that we have resumed.
312 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
317 // Resume core so it processes any requests as well
320 // Do at end to ensure our first update/render after resumption includes the processed messages as well
321 mThreadController->Resume();
327 if( RUNNING == mState ||
329 PAUSED_WHILE_HIDDEN == mState )
331 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
336 mThreadController->Stop();
339 // Delete the TTS player
340 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
344 mTtsPlayers[i].Reset();
348 delete mEventHandler;
349 mEventHandler = NULL;
351 delete mNotificationTrigger;
352 mNotificationTrigger = NULL;
354 mCallbackManager->Stop();
360 void Adaptor::ContextLost()
362 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
365 void Adaptor::ContextRegained()
367 // Inform core, so that texture resources can be reloaded
368 mCore->RecoverFromContextLoss();
370 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
373 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
375 mEventHandler->FeedTouchPoint( point, timeStamp );
378 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
380 mEventHandler->FeedWheelEvent( wheelEvent );
383 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
385 mEventHandler->FeedKeyEvent( keyEvent );
388 bool Adaptor::MoveResize( const PositionSize& positionSize )
390 PositionSize old = mSurface->GetPositionSize();
392 // just resize the surface. The driver should automatically resize the egl Surface (untested)
393 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
394 // is resized. Implementations typically use hooks into the OS and native window
395 // system to perform this resizing on demand, transparently to the client.
396 mSurface->MoveResize( positionSize );
398 if(old.width != positionSize.width || old.height != positionSize.height)
400 SurfaceSizeChanged(positionSize);
406 void Adaptor::SurfaceResized( const PositionSize& positionSize )
408 PositionSize old = mSurface->GetPositionSize();
410 // Called by an application, when it has resized a window outside of Dali.
411 // The EGL driver automatically detects X Window resize calls, and resizes
412 // the EGL surface for us.
413 mSurface->MoveResize( positionSize );
415 if(old.width != positionSize.width || old.height != positionSize.height)
417 SurfaceSizeChanged(positionSize);
421 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
423 mNativeWindow = nativeWindow;
426 SurfaceSizeChanged(mSurface->GetPositionSize());
428 // flush the event queue to give update and render threads chance
429 // to start processing messages for new camera setup etc as soon as possible
432 // this method blocks until the render thread has completed the replace.
433 mThreadController->ReplaceSurface(mSurface);
436 RenderSurface& Adaptor::GetSurface() const
441 void Adaptor::ReleaseSurfaceLock()
443 mSurface->ReleaseLock();
446 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
448 if(!mTtsPlayers[mode])
450 // Create the TTS player when it needed, because it can reduce launching time.
451 mTtsPlayers[mode] = TtsPlayer::New(mode);
454 return mTtsPlayers[mode];
457 bool Adaptor::AddIdle( CallbackBase* callback )
459 bool idleAdded(false);
461 // Only add an idle if the Adaptor is actually running
462 if( RUNNING == mState )
464 idleAdded = mCallbackManager->AddIdleCallback( callback );
470 void Adaptor::RemoveIdle( CallbackBase* callback )
472 mCallbackManager->RemoveIdleCallback( callback );
475 Dali::Adaptor& Adaptor::Get()
477 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
478 return gThreadLocalAdaptor->mAdaptor;
481 bool Adaptor::IsAvailable()
483 return gThreadLocalAdaptor != NULL;
486 void Adaptor::SceneCreated()
488 mCore->SceneCreated();
491 Dali::Integration::Core& Adaptor::GetCore()
496 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
498 mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
501 void Adaptor::SetUseHardwareVSync( bool useHardware )
503 mVSyncMonitor->SetUseHardwareVSync( useHardware );
506 EglFactory& Adaptor::GetEGLFactory() const
508 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
512 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
517 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
519 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
523 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
525 return *mPlatformAbstraction;
528 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
533 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
535 return *mNotificationTrigger;
538 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
540 return mTriggerEventFactory;
543 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
545 return mSocketFactory;
548 RenderSurface* Adaptor::GetRenderSurfaceInterface()
553 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
555 return mVSyncMonitor;
558 TraceInterface& Adaptor::GetKernelTraceInterface()
560 return mKernelTracer;
563 TraceInterface& Adaptor::GetSystemTraceInterface()
565 return mSystemTracer;
568 PerformanceInterface* Adaptor::GetPerformanceInterface()
570 return mPerformanceInterface;
573 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
575 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
576 return *mPlatformAbstraction;
579 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
581 mDragAndDropDetector = detector;
585 mEventHandler->SetDragAndDropDetector( detector );
589 void Adaptor::SetRotationObserver( RotationObserver* observer )
593 mEventHandler->SetRotationObserver( observer );
595 else if( mState == READY )
597 // Set once event handler exists
598 mDeferredRotationObserver = observer;
602 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
604 if(mTtsPlayers[mode])
606 mTtsPlayers[mode].Reset();
610 void Adaptor::SetMinimumPinchDistance(float distance)
612 if( mGestureManager )
614 mGestureManager->SetMinimumPinchDistance(distance);
618 Any Adaptor::GetNativeWindowHandle()
620 return mNativeWindow;
623 void Adaptor::AddObserver( LifeCycleObserver& observer )
625 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
627 if ( match == mObservers.end() )
629 mObservers.push_back( &observer );
633 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
635 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
637 if ( match != mObservers.end() )
639 mObservers.erase( match );
643 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
647 mCore->QueueEvent(event);
651 void Adaptor::ProcessCoreEvents()
655 if( mPerformanceInterface )
657 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
660 mCore->ProcessEvents();
662 if( mPerformanceInterface )
664 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
669 void Adaptor::RequestUpdate()
671 // When Dali applications are partially visible behind the lock-screen,
672 // the indicator must be updated (therefore allow updates in the PAUSED state)
673 if ( PAUSED == mState ||
676 mThreadController->RequestUpdate();
680 void Adaptor::RequestProcessEventsOnIdle()
682 // Only request a notification if the Adaptor is actually running
683 // and we haven't installed the idle notification
684 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
686 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
690 void Adaptor::OnWindowShown()
692 if ( PAUSED_WHILE_HIDDEN == mState )
694 // Adaptor can now be resumed
699 // Force a render task
704 void Adaptor::OnWindowHidden()
706 if ( STOPPED != mState )
710 // Adaptor cannot be resumed until the window is shown
711 mState = PAUSED_WHILE_HIDDEN;
715 // Dali::Internal::Adaptor::Adaptor::OnDamaged
716 void Adaptor::OnDamaged( const DamageArea& area )
718 // This is needed for the case where Dali window is partially obscured
722 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
724 // let the core know the surface size has changed
725 mCore->SurfaceResized(positionSize.width, positionSize.height);
727 mResizedSignal.Emit( mAdaptor );
730 void Adaptor::NotifySceneCreated()
732 GetCore().SceneCreated();
734 // Start thread controller after the scene has been created
735 mThreadController->Start();
738 void Adaptor::NotifyLanguageChanged()
740 mLanguageChangedSignal.Emit( mAdaptor );
743 void Adaptor::RequestUpdateOnce()
745 if( PAUSED_WHILE_HIDDEN != mState )
747 if( mThreadController )
749 mThreadController->RequestUpdateOnce();
754 void Adaptor::ProcessCoreEventsFromIdle()
758 // the idle handle automatically un-installs itself
759 mNotificationOnIdleInstalled = false;
762 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
764 mLanguageChangedSignal(),
768 mThreadController( NULL ),
769 mVSyncMonitor( NULL ),
773 mNativeWindow( nativeWindow ),
775 mPlatformAbstraction( NULL ),
776 mEventHandler( NULL ),
777 mCallbackManager( NULL ),
778 mNotificationOnIdleInstalled( false ),
779 mNotificationTrigger( NULL ),
780 mGestureManager( NULL ),
781 mDaliFeedbackPlugin(),
782 mFeedbackController( NULL ),
785 mDragAndDropDetector(),
786 mDeferredRotationObserver( NULL ),
787 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
788 mPerformanceInterface( NULL ),
791 mTriggerEventFactory(),
792 mObjectProfiler( NULL ),
794 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
796 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
797 gThreadLocalAdaptor = this;
802 void Adaptor::SetViewMode( ViewMode viewMode )
804 mSurface->SetViewMode( viewMode );
805 mCore->SetViewMode( viewMode );
808 ViewMode Adaptor::GetViewMode() const
810 return mCore->GetViewMode();
813 void Adaptor::SetStereoBase( float stereoBase )
815 mCore->SetStereoBase( stereoBase );
818 float Adaptor::GetStereoBase() const
820 return mCore->GetStereoBase();
823 } // namespace Adaptor
825 } // namespace Internal