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/thread-controller.h>
32 #if defined(NETWORK_LOGGING_ENABLED)
33 # include <base/performance-logging/performance-interface-factory.h>
35 #include <base/lifecycle-observer.h>
37 #include <dali/devel-api/text-abstraction/font-client.h>
39 #include <callback-manager.h>
40 #include <render-surface.h>
41 #include <tts-player-impl.h>
42 #include <accessibility-adaptor-impl.h>
43 #include <events/gesture-manager.h>
44 #include <events/event-handler.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_DISCARDS_ALL_DATA;
114 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
115 // files automatically.
117 #if defined(NETWORK_LOGGING_ENABLED)
118 if( mEnvironmentOptions->PerformanceServerRequired() )
120 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
124 mCallbackManager = CallbackManager::New();
126 PositionSize size = mSurface->GetPositionSize();
128 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
130 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
132 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
136 mGLES = new GlImplementation();
139 mEglFactory = new EglFactory();
141 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
143 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
145 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
146 if( 0u < timeInterval )
148 mObjectProfiler = new ObjectProfiler( timeInterval );
151 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
153 mVSyncMonitor = new VSyncMonitor;
155 mThreadController = new ThreadController( *this, *mEnvironmentOptions );
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 mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
206 delete mVSyncMonitor;
207 delete mEventHandler;
208 delete mObjectProfiler;
213 delete mGestureManager;
214 delete mPlatformAbstraction;
215 delete mCallbackManager;
216 delete mPerformanceInterface;
218 // uninstall it on this thread (main actor thread)
219 Dali::Integration::Log::UninstallLogFunction();
221 // Delete environment options if we own it
222 if( mEnvironmentOptionsOwned )
224 delete mEnvironmentOptions;
228 void Adaptor::Start()
230 // it doesn't support restart after stop at this moment
231 // to support restarting, need more testing
232 if( READY != mState )
237 // Start the callback manager
238 mCallbackManager->Start();
240 // create event handler
241 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
243 if( mDeferredRotationObserver != NULL )
245 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
246 mDeferredRotationObserver = NULL;
249 unsigned int dpiHor, dpiVer;
251 Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
253 // tell core about the DPI value
254 mCore->SetDpi(dpiHor, dpiVer);
256 // set the DPI value for font rendering
257 FontClient fontClient = FontClient::Get();
258 fontClient.SetDpi( dpiHor, dpiVer );
260 // Tell the core the size of the surface just before we start the render-thread
261 PositionSize size = mSurface->GetPositionSize();
262 mCore->SurfaceResized( size.width, size.height );
264 // Initialize the thread controller
265 mThreadController->Initialize();
269 ProcessCoreEvents(); // Ensure any startup messages are processed.
271 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
277 // Dali::Internal::Adaptor::Adaptor::Pause
278 void Adaptor::Pause()
280 // Only pause the adaptor if we're actually running.
281 if( RUNNING == mState )
283 // Inform observers that we are about to be paused.
284 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
289 // Reset the event handler when adaptor paused
292 mEventHandler->Pause();
295 mThreadController->Pause();
301 // Dali::Internal::Adaptor::Adaptor::Resume
302 void Adaptor::Resume()
304 // Only resume the adaptor if we are in the suspended state.
305 if( PAUSED == mState )
309 // Reset the event handler when adaptor resumed
312 mEventHandler->Resume();
315 // Inform observers that we have resumed.
316 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
321 // Resume core so it processes any requests as well
324 // Do at end to ensure our first update/render after resumption includes the processed messages as well
325 mThreadController->Resume();
331 if( RUNNING == mState ||
333 PAUSED_WHILE_HIDDEN == mState )
335 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
340 mThreadController->Stop();
343 // Delete the TTS player
344 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
348 mTtsPlayers[i].Reset();
352 delete mEventHandler;
353 mEventHandler = NULL;
355 delete mNotificationTrigger;
356 mNotificationTrigger = NULL;
358 mCallbackManager->Stop();
364 void Adaptor::ContextLost()
366 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
369 void Adaptor::ContextRegained()
371 // Inform core, so that texture resources can be reloaded
372 mCore->RecoverFromContextLoss();
374 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
377 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
379 mEventHandler->FeedTouchPoint( point, timeStamp );
382 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
384 mEventHandler->FeedWheelEvent( wheelEvent );
387 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
389 mEventHandler->FeedKeyEvent( keyEvent );
392 bool Adaptor::MoveResize( const PositionSize& positionSize )
394 PositionSize old = mSurface->GetPositionSize();
396 // just resize the surface. The driver should automatically resize the egl Surface (untested)
397 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
398 // is resized. Implementations typically use hooks into the OS and native window
399 // system to perform this resizing on demand, transparently to the client.
400 mSurface->MoveResize( positionSize );
402 if(old.width != positionSize.width || old.height != positionSize.height)
404 SurfaceSizeChanged(positionSize);
410 void Adaptor::SurfaceResized( const PositionSize& positionSize )
412 PositionSize old = mSurface->GetPositionSize();
414 // Called by an application, when it has resized a window outside of Dali.
415 // The EGL driver automatically detects X Window resize calls, and resizes
416 // the EGL surface for us.
417 mSurface->MoveResize( positionSize );
419 if(old.width != positionSize.width || old.height != positionSize.height)
421 SurfaceSizeChanged(positionSize);
425 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
427 mNativeWindow = nativeWindow;
430 SurfaceSizeChanged(mSurface->GetPositionSize());
432 // flush the event queue to give update and render threads chance
433 // to start processing messages for new camera setup etc as soon as possible
436 // this method blocks until the render thread has completed the replace.
437 mThreadController->ReplaceSurface(mSurface);
440 RenderSurface& Adaptor::GetSurface() const
445 void Adaptor::ReleaseSurfaceLock()
447 mSurface->ReleaseLock();
450 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
452 if(!mTtsPlayers[mode])
454 // Create the TTS player when it needed, because it can reduce launching time.
455 mTtsPlayers[mode] = TtsPlayer::New(mode);
458 return mTtsPlayers[mode];
461 bool Adaptor::AddIdle( CallbackBase* callback )
463 bool idleAdded(false);
465 // Only add an idle if the Adaptor is actually running
466 if( RUNNING == mState )
468 idleAdded = mCallbackManager->AddIdleCallback( 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