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/update-render-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 <feedback/feedback-controller.h>
44 #include <feedback/feedback-plugin-proxy.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_RETAINS_MESH_DATA;
114 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
115 // files automatically.
117 if( mEnvironmentOptions->PerformanceServerRequired() )
119 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
122 mCallbackManager = CallbackManager::New();
124 PositionSize size = mSurface->GetPositionSize();
126 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
128 if( mEnvironmentOptions->GetGlesCallTime() > 0 )
130 mGLES = new GlProxyImplementation( *mEnvironmentOptions );
134 mGLES = new GlImplementation();
137 mEglFactory = new EglFactory();
139 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
141 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
143 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
144 if( 0u < timeInterval )
146 mObjectProfiler = new ObjectProfiler( timeInterval );
149 mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
151 mVSyncMonitor = new VSyncMonitor;
153 mUpdateRenderController = new UpdateRenderController( *this, *mEnvironmentOptions );
155 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
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 mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
206 delete mVSyncMonitor;
207 delete mEventHandler;
208 delete mObjectProfiler;
212 // Delete feedback controller before feedback plugin & style monitor dependencies
213 delete mFeedbackController;
214 delete mDaliFeedbackPlugin;
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 // Start the update & render threads
268 mUpdateRenderController->Start();
272 ProcessCoreEvents(); // Ensure any startup messages are processed.
274 if ( !mFeedbackController )
276 // Start sound & haptic feedback
277 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
280 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
286 // Dali::Internal::Adaptor::Adaptor::Pause
287 void Adaptor::Pause()
289 // Only pause the adaptor if we're actually running.
290 if( RUNNING == mState )
292 // Inform observers that we are about to be paused.
293 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
298 // Reset the event handler when adaptor paused
301 mEventHandler->Reset();
304 mUpdateRenderController->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 )
316 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
317 // If there were events pending, mCore->Resume() will call
318 // RenderController->RequestUpdate()
319 // UpdateRenderController->RequestUpdate()
320 // UpdateRenderSynchronization->RequestUpdate()
321 // and we should have reset the frame timers before allowing Core->Update() to be called.
322 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
324 mUpdateRenderController->ResumeFrameTime();
326 mUpdateRenderController->Resume();
330 // Reset the event handler when adaptor resumed
333 mEventHandler->Reset();
336 // Inform observers that we have resumed.
337 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
342 ProcessCoreEvents(); // Ensure any outstanding messages are processed
348 if( RUNNING == mState ||
350 PAUSED_WHILE_HIDDEN == mState )
352 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
357 mUpdateRenderController->Stop();
360 // Delete the TTS player
361 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
365 mTtsPlayers[i].Reset();
369 delete mEventHandler;
370 mEventHandler = NULL;
372 delete mNotificationTrigger;
373 mNotificationTrigger = NULL;
375 mCallbackManager->Stop();
381 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
383 mEventHandler->FeedTouchPoint( point, timeStamp );
386 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
388 mEventHandler->FeedWheelEvent( wheelEvent );
391 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
393 mEventHandler->FeedKeyEvent( keyEvent );
396 bool Adaptor::MoveResize( const PositionSize& positionSize )
398 PositionSize old = mSurface->GetPositionSize();
400 // just resize the surface. The driver should automatically resize the egl Surface (untested)
401 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
402 // is resized. Implementations typically use hooks into the OS and native window
403 // system to perform this resizing on demand, transparently to the client.
404 mSurface->MoveResize( positionSize );
406 if(old.width != positionSize.width || old.height != positionSize.height)
408 SurfaceSizeChanged(positionSize);
414 void Adaptor::SurfaceResized( const PositionSize& positionSize )
416 PositionSize old = mSurface->GetPositionSize();
418 // Called by an application, when it has resized a window outside of Dali.
419 // The EGL driver automatically detects X Window resize calls, and resizes
420 // the EGL surface for us.
421 mSurface->MoveResize( positionSize );
423 if(old.width != positionSize.width || old.height != positionSize.height)
425 SurfaceSizeChanged(positionSize);
429 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
431 mNativeWindow = nativeWindow;
434 SurfaceSizeChanged(mSurface->GetPositionSize());
436 // flush the event queue to give update and render threads chance
437 // to start processing messages for new camera setup etc as soon as possible
440 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
442 // this method blocks until the render thread has completed the replace.
443 mUpdateRenderController->ReplaceSurface(mSurface);
445 // Inform core, so that texture resources can be reloaded
446 mCore->RecoverFromContextLoss();
448 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
451 RenderSurface& Adaptor::GetSurface() const
456 void Adaptor::ReleaseSurfaceLock()
458 mSurface->ReleaseLock();
461 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
463 if(!mTtsPlayers[mode])
465 // Create the TTS player when it needed, because it can reduce launching time.
466 mTtsPlayers[mode] = TtsPlayer::New(mode);
469 return mTtsPlayers[mode];
472 bool Adaptor::AddIdle( CallbackBase* callback )
474 bool idleAdded(false);
476 // Only add an idle if the Adaptor is actually running
477 if( RUNNING == mState )
479 idleAdded = mCallbackManager->AddIdleCallback( callback );
486 Dali::Adaptor& Adaptor::Get()
488 DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
489 return gThreadLocalAdaptor->mAdaptor;
492 bool Adaptor::IsAvailable()
494 return gThreadLocalAdaptor != NULL;
497 Dali::Integration::Core& Adaptor::GetCore()
502 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
504 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
507 void Adaptor::SetUseHardwareVSync( bool useHardware )
509 mVSyncMonitor->SetUseHardwareVSync( useHardware );
512 EglFactory& Adaptor::GetEGLFactory() const
514 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
518 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
523 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
525 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
529 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
531 return *mPlatformAbstraction;
534 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
539 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
541 return *mNotificationTrigger;
544 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
546 return mTriggerEventFactory;
549 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
551 return mSocketFactory;
554 RenderSurface* Adaptor::GetRenderSurfaceInterface()
559 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
561 return mVSyncMonitor;
564 TraceInterface& Adaptor::GetKernelTraceInterface()
566 return mKernelTracer;
569 TraceInterface& Adaptor::GetSystemTraceInterface()
571 return mSystemTracer;
574 PerformanceInterface* Adaptor::GetPerformanceInterface()
576 return mPerformanceInterface;
579 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
581 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
582 return *mPlatformAbstraction;
585 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
587 mDragAndDropDetector = detector;
591 mEventHandler->SetDragAndDropDetector( detector );
595 void Adaptor::SetRotationObserver( RotationObserver* observer )
599 mEventHandler->SetRotationObserver( observer );
601 else if( mState == READY )
603 // Set once event handler exists
604 mDeferredRotationObserver = observer;
608 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
610 if(mTtsPlayers[mode])
612 mTtsPlayers[mode].Reset();
616 void Adaptor::SetMinimumPinchDistance(float distance)
618 if( mGestureManager )
620 mGestureManager->SetMinimumPinchDistance(distance);
624 Any Adaptor::GetNativeWindowHandle()
626 return mNativeWindow;
629 void Adaptor::AddObserver( LifeCycleObserver& observer )
631 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
633 if ( match == mObservers.end() )
635 mObservers.push_back( &observer );
639 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
641 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
643 if ( match != mObservers.end() )
645 mObservers.erase( match );
649 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
653 mCore->QueueEvent(event);
657 void Adaptor::ProcessCoreEvents()
661 if( mPerformanceInterface )
663 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
666 mCore->ProcessEvents();
668 if( mPerformanceInterface )
670 mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
675 void Adaptor::RequestUpdate()
677 // When Dali applications are partially visible behind the lock-screen,
678 // the indicator must be updated (therefore allow updates in the PAUSED state)
679 if ( PAUSED == mState ||
682 mUpdateRenderController->RequestUpdate();
686 void Adaptor::RequestProcessEventsOnIdle()
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 ) )
692 mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
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
728 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
730 // let the core know the surface size has changed
731 mCore->SurfaceResized(positionSize.width, positionSize.height);
733 mResizedSignal.Emit( mAdaptor );
736 void Adaptor::NotifySceneCreated()
738 GetCore().SceneCreated();
741 void Adaptor::NotifyLanguageChanged()
743 mLanguageChangedSignal.Emit( mAdaptor );
746 void Adaptor::RequestUpdateOnce()
748 if( PAUSED_WHILE_HIDDEN != mState )
750 if( mUpdateRenderController )
752 mUpdateRenderController->RequestUpdateOnce();
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 mUpdateRenderController(NULL),
775 mNativeWindow( nativeWindow ),
777 mPlatformAbstraction( NULL ),
778 mEventHandler( NULL ),
779 mCallbackManager( NULL ),
780 mNotificationOnIdleInstalled( false ),
781 mNotificationTrigger(NULL),
782 mGestureManager(NULL),
783 mDaliFeedbackPlugin(NULL),
784 mFeedbackController(NULL),
786 mDragAndDropDetector(),
787 mDeferredRotationObserver(NULL),
788 mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
789 mPerformanceInterface(NULL),
790 mObjectProfiler(NULL),
791 mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
793 DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
794 gThreadLocalAdaptor = this;
799 void Adaptor::SetViewMode( ViewMode viewMode )
801 mSurface->SetViewMode( viewMode );
802 mCore->SetViewMode( viewMode );
805 ViewMode Adaptor::GetViewMode() const
807 return mCore->GetViewMode();
810 void Adaptor::SetStereoBase( float stereoBase )
812 mCore->SetStereoBase( stereoBase );
815 float Adaptor::GetStereoBase() const
817 return mCore->GetStereoBase();
820 } // namespace Adaptor
822 } // namespace Internal