Expose custom performance timers
[platform/core/uifw/dali-adaptor.git] / adaptors / common / adaptor-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "adaptor-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <boost/thread/tss.hpp>
23 #include <dali/public-api/common/dali-common.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/integration-api/core.h>
26 #include <dali/integration-api/context-notifier.h>
27 #include <dali/integration-api/profiling.h>
28 #include <dali/integration-api/input-options.h>
29 #include <dali/integration-api/events/touch-event-integ.h>
30
31 // INTERNAL INCLUDES
32 #include <base/update-render-controller.h>
33 #include <base/environment-variables.h>
34 #include <base/performance-logging/performance-interface-factory.h>
35 #include <base/lifecycle-observer.h>
36
37 #include <callback-manager.h>
38 #include <trigger-event.h>
39 #include <window-render-surface.h>
40 #include <render-surface-impl.h>
41 #include <tts-player-impl.h>
42 #include <accessibility-manager-impl.h>
43 #include <timer-impl.h>
44 #include <events/gesture-manager.h>
45 #include <events/event-handler.h>
46 #include <feedback/feedback-controller.h>
47 #include <feedback/feedback-plugin-proxy.h>
48 #include <gl/gl-proxy-implementation.h>
49 #include <gl/gl-implementation.h>
50 #include <gl/egl-sync-implementation.h>
51 #include <gl/egl-image-extensions.h>
52 #include <gl/egl-factory.h>
53 #include <imf-manager-impl.h>
54 #include <clipboard-impl.h>
55 #include <vsync-monitor.h>
56 #include <object-profiler.h>
57
58 #include <slp-logging.h>
59
60
61
62 namespace Dali
63 {
64
65 namespace Internal
66 {
67
68 namespace Adaptor
69 {
70
71 namespace
72 {
73 boost::thread_specific_ptr<Adaptor> gThreadLocalAdaptor;
74
75 unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue )
76 {
77   const char* variableParameter = std::getenv(variable);
78
79   // if the parameter exists convert it to an integer, else return the default value
80   unsigned int intValue = variableParameter ? atoi(variableParameter) : defaultValue;
81   return intValue;
82 }
83
84 bool GetIntegerEnvironmentVariable( const char* variable, int& intValue )
85 {
86   const char* variableParameter = std::getenv(variable);
87
88   if( !variableParameter )
89   {
90     return false;
91   }
92   // if the parameter exists convert it to an integer, else return the default value
93   intValue = atoi(variableParameter);
94   return true;
95 }
96
97 bool GetFloatEnvironmentVariable( const char* variable, float& floatValue )
98 {
99   const char* variableParameter = std::getenv(variable);
100
101   if( !variableParameter )
102   {
103     return false;
104   }
105   // if the parameter exists convert it to an integer, else return the default value
106   floatValue = atof(variableParameter);
107   return true;
108 }
109
110 } // unnamed namespace
111
112 Dali::Adaptor* Adaptor::New( RenderSurface *surface, const DeviceLayout& baseLayout,
113                              Dali::Configuration::ContextLoss configuration )
114 {
115   DALI_ASSERT_ALWAYS( surface->GetType() != Dali::RenderSurface::NO_SURFACE && "No surface for adaptor" );
116
117   Dali::Adaptor* adaptor = new Dali::Adaptor;
118   Adaptor* impl = new Adaptor( *adaptor, surface, baseLayout );
119   adaptor->mImpl = impl;
120
121   impl->Initialize(configuration);
122
123   return adaptor;
124 }
125
126 void Adaptor::ParseEnvironmentOptions()
127 {
128   // get logging options
129   unsigned int logFrameRateFrequency = GetIntegerEnvironmentVariable( DALI_ENV_FPS_TRACKING, 0 );
130   unsigned int logupdateStatusFrequency = GetIntegerEnvironmentVariable( DALI_ENV_UPDATE_STATUS_INTERVAL, 0 );
131   unsigned int logPerformanceLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE, 0 );
132   unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
133
134   // all threads here (event, update, and render) will send their logs to SLP Platform's LogMessage handler.
135   Dali::Integration::Log::LogFunction  logFunction(Dali::SlpPlatform::LogMessage);
136
137   mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceLevel, logPanGesture );
138
139   int predictionMode;
140   if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
141   {
142     mEnvironmentOptions.SetPanGesturePredictionMode(predictionMode);
143   }
144   int predictionAmount = -1;
145   if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_AMOUNT, predictionAmount) )
146   {
147     if( predictionAmount < 0 )
148     {
149       // do not support times in the past
150       predictionAmount = 0;
151     }
152     mEnvironmentOptions.SetPanGesturePredictionAmount(predictionAmount);
153   }
154   int smoothingMode;
155   if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_MODE, smoothingMode) )
156   {
157     mEnvironmentOptions.SetPanGestureSmoothingMode(smoothingMode);
158   }
159   float smoothingAmount = 1.0f;
160   if( GetFloatEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_AMOUNT, smoothingAmount) )
161   {
162     smoothingAmount = Clamp(smoothingAmount, 0.0f, 1.0f);
163     mEnvironmentOptions.SetPanGestureSmoothingAmount(smoothingAmount);
164   }
165
166   int minimumDistance(-1);
167   if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_DISTANCE, minimumDistance ))
168   {
169     mEnvironmentOptions.SetMinimumPanDistance( minimumDistance );
170   }
171
172   int minimumEvents(-1);
173   if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_EVENTS, minimumEvents ))
174   {
175     mEnvironmentOptions.SetMinimumPanEvents( minimumEvents );
176   }
177
178   int glesCallTime(0);
179   if ( GetIntegerEnvironmentVariable(DALI_GLES_CALL_TIME, glesCallTime ))
180   {
181     mEnvironmentOptions.SetGlesCallTime( glesCallTime );
182   }
183
184   mEnvironmentOptions.InstallLogFunction();
185 }
186
187 void Adaptor::Initialize(Dali::Configuration::ContextLoss configuration)
188 {
189   ParseEnvironmentOptions();
190
191   mPlatformAbstraction = new SlpPlatform::SlpPlatformAbstraction;
192
193   ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
194   if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
195   {
196     dataRetentionPolicy = ResourcePolicy::DALI_RETAINS_MESH_DATA;
197   }
198   // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
199   // files automatically.
200
201   if( mEnvironmentOptions.GetPerformanceLoggingLevel() > 0 )
202   {
203     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
204   }
205
206   mCallbackManager = CallbackManager::New();
207
208   PositionSize size = mSurface->GetPositionSize();
209
210   mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, mEnvironmentOptions);
211
212   if( mEnvironmentOptions.GetGlesCallTime() > 0 )
213   {
214     mGLES = new GlProxyImplementation( mEnvironmentOptions );
215   }
216   else
217   {
218     mGLES = new GlImplementation();
219   }
220
221   mEglFactory = new EglFactory();
222
223   EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
224
225   mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
226
227   mObjectProfiler = new ObjectProfiler();
228
229   mNotificationTrigger = new TriggerEvent( boost::bind(&Adaptor::ProcessCoreEvents, this) );
230
231   mVSyncMonitor = new VSyncMonitor;
232
233   mUpdateRenderController = new UpdateRenderController( *this, mEnvironmentOptions );
234
235   mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
236
237   // Should be called after Core creation
238   if( mEnvironmentOptions.GetPanGestureLoggingLevel() )
239   {
240     Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
241   }
242   if( mEnvironmentOptions.GetPanGesturePredictionMode() >= 0 )
243   {
244     Integration::SetPanGesturePredictionMode(mEnvironmentOptions.GetPanGesturePredictionMode());
245   }
246   if( mEnvironmentOptions.GetPanGesturePredictionAmount() >= 0.0f )
247   {
248     Integration::SetPanGesturePredictionAmount(mEnvironmentOptions.GetPanGesturePredictionAmount());
249   }
250   if( mEnvironmentOptions.GetPanGestureSmoothingMode() >= 0 )
251   {
252     Integration::SetPanGestureSmoothingMode(mEnvironmentOptions.GetPanGestureSmoothingMode());
253   }
254   if( mEnvironmentOptions.GetPanGestureSmoothingAmount() >= 0.0f )
255   {
256     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions.GetPanGestureSmoothingAmount());
257   }
258 }
259
260 Adaptor::~Adaptor()
261 {
262   // Ensure stop status
263   Stop();
264
265   // Release first as we do not want any access to Adaptor as it is being destroyed.
266   gThreadLocalAdaptor.release();
267
268   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
269   {
270     (*iter)->OnDestroy();
271   }
272
273   delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
274   delete mVSyncMonitor;
275   delete mEventHandler;
276   delete mObjectProfiler;
277
278   delete mCore;
279   delete mEglFactory;
280   // Delete feedback controller before feedback plugin & style monitor dependencies
281   delete mFeedbackController;
282   delete mDaliFeedbackPlugin;
283   delete mGLES;
284   delete mGestureManager;
285   delete mPlatformAbstraction;
286   delete mCallbackManager;
287   delete mPerformanceInterface;
288
289   // uninstall it on this thread (main actor thread)
290   Dali::Integration::Log::UninstallLogFunction();
291 }
292
293 void Adaptor::Start()
294 {
295   // it doesn't support restart after stop at this moment
296   // to support restarting, need more testing
297   if( READY != mState )
298   {
299     return;
300   }
301
302   // Start the callback manager
303   mCallbackManager->Start();
304
305   // create event handler
306   mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
307
308   if( mDeferredRotationObserver != NULL )
309   {
310     mEventHandler->SetRotationObserver(mDeferredRotationObserver);
311     mDeferredRotationObserver = NULL;
312   }
313
314   // guarantee map the surface before starting render-thread.
315   mSurface->Map();
316
317   // NOTE: dpi must be set before starting the render thread
318   // use default or command line settings if not run on device
319 #ifdef __arm__
320   // set the DPI value for font rendering
321   unsigned int dpiHor, dpiVer;
322   dpiHor = dpiVer = 0;
323   mSurface->GetDpi(dpiHor, dpiVer);
324
325   // tell core about the value
326   mCore->SetDpi(dpiHor, dpiVer);
327 #else
328   mCore->SetDpi(mHDpi, mVDpi);
329 #endif
330
331   // Tell the core the size of the surface just before we start the render-thread
332   PositionSize size = mSurface->GetPositionSize();
333   mCore->SurfaceResized( size.width, size.height );
334
335   // Start the update & render threads
336   mUpdateRenderController->Start();
337
338   mState = RUNNING;
339
340   ProcessCoreEvents(); // Ensure any startup messages are processed.
341
342   if ( !mFeedbackController )
343   {
344     // Start sound & haptic feedback
345     mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
346   }
347
348   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
349   {
350     (*iter)->OnStart();
351   }
352 }
353
354 // Dali::Internal::Adaptor::Adaptor::Pause
355 void Adaptor::Pause()
356 {
357   // Only pause the adaptor if we're actually running.
358   if( RUNNING == mState )
359   {
360     // Inform observers that we are about to be paused.
361     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
362     {
363       (*iter)->OnPause();
364     }
365
366     // Reset the event handler when adaptor paused
367     if( mEventHandler )
368     {
369       mEventHandler->Reset();
370     }
371
372     mUpdateRenderController->Pause();
373     mCore->Suspend();
374     mState = PAUSED;
375   }
376 }
377
378 // Dali::Internal::Adaptor::Adaptor::Resume
379 void Adaptor::Resume()
380 {
381   // Only resume the adaptor if we are in the suspended state.
382   if( PAUSED == mState )
383   {
384     // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
385     // If there were events pending, mCore->Resume() will call
386     //   RenderController->RequestUpdate()
387     //     UpdateRenderController->RequestUpdate()
388     //       UpdateRenderSynchronization->RequestUpdate()
389     // and we should have reset the frame timers before allowing Core->Update() to be called.
390     //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
391
392     mUpdateRenderController->ResumeFrameTime();
393     mCore->Resume();
394     mUpdateRenderController->Resume();
395
396     mState = RUNNING;
397
398     // Reset the event handler when adaptor resumed
399     if( mEventHandler )
400     {
401       mEventHandler->Reset();
402     }
403
404     // Inform observers that we have resumed.
405     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
406     {
407       (*iter)->OnResume();
408     }
409
410     ProcessCoreEvents(); // Ensure any outstanding messages are processed
411   }
412 }
413
414 void Adaptor::Stop()
415 {
416   if( RUNNING == mState ||
417       PAUSED  == mState ||
418       PAUSED_WHILE_HIDDEN == mState )
419   {
420     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
421     {
422       (*iter)->OnStop();
423     }
424
425     mUpdateRenderController->Stop();
426     mCore->Suspend();
427
428     // Delete the TTS player
429     for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
430     {
431       if(mTtsPlayers[i])
432       {
433         mTtsPlayers[i].Reset();
434       }
435     }
436
437     delete mEventHandler;
438     mEventHandler = NULL;
439
440     delete mNotificationTrigger;
441     mNotificationTrigger = NULL;
442
443     mCallbackManager->Stop();
444
445     mState = STOPPED;
446   }
447 }
448
449 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
450 {
451   mEventHandler->FeedTouchPoint( point, timeStamp );
452 }
453
454 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
455 {
456   mEventHandler->FeedWheelEvent( wheelEvent );
457 }
458
459 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
460 {
461   mEventHandler->FeedKeyEvent( keyEvent );
462 }
463
464 bool Adaptor::MoveResize( const PositionSize& positionSize )
465 {
466   PositionSize old = mSurface->GetPositionSize();
467
468   // just resize the surface. The driver should automatically resize the egl Surface (untested)
469   // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
470   // is resized. Implementations typically use hooks into the OS and native window
471   // system to perform this resizing on demand, transparently to the client.
472   mSurface->MoveResize( positionSize );
473
474   if(old.width != positionSize.width || old.height != positionSize.height)
475   {
476     SurfaceSizeChanged(positionSize);
477   }
478
479   return true;
480 }
481
482 void Adaptor::SurfaceResized( const PositionSize& positionSize )
483 {
484   PositionSize old = mSurface->GetPositionSize();
485
486   // Called by an application, when it has resized a window outside of Dali.
487   // The EGL driver automatically detects X Window resize calls, and resizes
488   // the EGL surface for us.
489   mSurface->MoveResize( positionSize );
490
491   if(old.width != positionSize.width || old.height != positionSize.height)
492   {
493     SurfaceSizeChanged(positionSize);
494   }
495 }
496
497 void Adaptor::ReplaceSurface( Dali::RenderSurface& surface )
498 {
499   // adaptor implementation needs the implementation of
500   RenderSurface* internalSurface = dynamic_cast<Internal::Adaptor::RenderSurface*>( &surface );
501   DALI_ASSERT_ALWAYS( internalSurface && "Incorrect surface" );
502
503   ECore::WindowRenderSurface* windowSurface = dynamic_cast<Internal::Adaptor::ECore::WindowRenderSurface*>( &surface);
504   if( windowSurface != NULL )
505   {
506     windowSurface->Map();
507     // @todo Restart event handler with new surface
508   }
509
510   mSurface = internalSurface;
511
512   SurfaceSizeChanged( internalSurface->GetPositionSize() );
513
514   // flush the event queue to give update and render threads chance
515   // to start processing messages for new camera setup etc as soon as possible
516   ProcessCoreEvents();
517
518   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
519
520   // this method blocks until the render thread has completed the replace.
521   mUpdateRenderController->ReplaceSurface(internalSurface);
522
523   // Inform core, so that texture resources can be reloaded
524   mCore->RecoverFromContextLoss();
525
526   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
527 }
528
529 Dali::RenderSurface& Adaptor::GetSurface() const
530 {
531   return *mSurface;
532 }
533
534 void Adaptor::ReleaseSurfaceLock()
535 {
536   mSurface->ReleaseLock();
537 }
538
539 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
540 {
541   if(!mTtsPlayers[mode])
542   {
543     // Create the TTS player when it needed, because it can reduce launching time.
544     mTtsPlayers[mode] = TtsPlayer::New(mode);
545   }
546
547   return mTtsPlayers[mode];
548 }
549
550 bool Adaptor::AddIdle(boost::function<void(void)> callBack)
551 {
552   bool idleAdded(false);
553
554   // Only add an idle if the Adaptor is actually running
555   if( RUNNING == mState )
556   {
557     idleAdded = mCallbackManager->AddCallback(callBack, CallbackManager::IDLE_PRIORITY);
558   }
559
560   return idleAdded;
561 }
562
563 bool Adaptor::CallFromMainLoop(boost::function<void(void)> callBack)
564 {
565   bool callAdded(false);
566
567   // Only allow the callback if the Adaptor is actually running
568   if ( RUNNING == mState )
569   {
570     callAdded = mCallbackManager->AddCallback(callBack, CallbackManager::DEFAULT_PRIORITY);
571   }
572
573   return callAdded;
574 }
575
576 Dali::Adaptor& Adaptor::Get()
577 {
578   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() != NULL && "Adaptor not instantiated" );
579   return gThreadLocalAdaptor->mAdaptor;
580 }
581
582 bool Adaptor::IsAvailable()
583 {
584   return gThreadLocalAdaptor.get() != NULL;
585 }
586
587 Dali::Integration::Core& Adaptor::GetCore()
588 {
589   return *mCore;
590 }
591
592 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
593 {
594   mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
595 }
596
597 void Adaptor::SetUseHardwareVSync( bool useHardware )
598 {
599   mVSyncMonitor->SetUseHardwareVSync( useHardware );
600 }
601
602 void Adaptor::SetDpi(size_t hDpi, size_t vDpi)
603 {
604   mHDpi = hDpi;
605   mVDpi = vDpi;
606 }
607
608 EglFactory& Adaptor::GetEGLFactory() const
609 {
610   DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
611   return *mEglFactory;
612 }
613
614 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
615 {
616   return *mEglFactory;
617 }
618
619 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
620 {
621   DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
622   return *mGLES;
623 }
624
625 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
626 {
627   return *mPlatformAbstraction;
628 }
629
630 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
631 {
632   return *mGLES;
633 }
634
635 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
636 {
637   return *mNotificationTrigger;
638 }
639 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
640 {
641   return mTriggerEventFactory;
642 }
643 RenderSurface* Adaptor::GetRenderSurfaceInterface()
644 {
645   return mSurface;
646 }
647 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
648 {
649   return mVSyncMonitor;
650 }
651
652 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
653 {
654   return mKernelTracer;
655 }
656
657 PerformanceInterface* Adaptor::GetPerformanceInterface()
658 {
659   return mPerformanceInterface;
660 }
661
662 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
663 {
664   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
665   return *mPlatformAbstraction;
666 }
667
668 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
669 {
670   mDragAndDropDetector = detector;
671
672   if ( mEventHandler )
673   {
674     mEventHandler->SetDragAndDropDetector( detector );
675   }
676 }
677
678 void Adaptor::SetRotationObserver( RotationObserver* observer )
679 {
680   if( mEventHandler )
681   {
682     mEventHandler->SetRotationObserver( observer );
683   }
684   else if( mState == READY )
685   {
686     // Set once event handler exists
687     mDeferredRotationObserver = observer;
688   }
689 }
690
691 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
692 {
693   if(mTtsPlayers[mode])
694   {
695     mTtsPlayers[mode].Reset();
696   }
697 }
698
699 void Adaptor::SetMinimumPinchDistance(float distance)
700 {
701   if( mGestureManager )
702   {
703     mGestureManager->SetMinimumPinchDistance(distance);
704   }
705 }
706
707
708 void Adaptor::AddObserver( LifeCycleObserver& observer )
709 {
710   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
711
712   if ( match == mObservers.end() )
713   {
714     mObservers.push_back( &observer );
715   }
716 }
717
718 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
719 {
720   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
721
722   if ( match != mObservers.end() )
723   {
724     mObservers.erase( match );
725   }
726 }
727
728 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
729 {
730   if( mCore )
731   {
732     mCore->QueueEvent(event);
733   }
734 }
735
736 void Adaptor::ProcessCoreEvents()
737 {
738   if( mCore )
739   {
740     if( mPerformanceInterface )
741     {
742       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
743     }
744
745     mCore->ProcessEvents();
746
747     if( mPerformanceInterface )
748     {
749       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
750     }
751   }
752 }
753
754 void Adaptor::RequestUpdate()
755 {
756   // When Dali applications are partially visible behind the lock-screen,
757   // the indicator must be updated (therefore allow updates in the PAUSED state)
758   if ( PAUSED  == mState ||
759        RUNNING == mState )
760   {
761     mUpdateRenderController->RequestUpdate();
762   }
763 }
764
765 void Adaptor::RequestProcessEventsOnIdle()
766 {
767   // Only request a notification if the Adaptor is actually running
768   // and we haven't installed the idle notification
769   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
770   {
771     mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
772   }
773 }
774
775 void Adaptor::OnWindowShown()
776 {
777   if ( PAUSED_WHILE_HIDDEN == mState )
778   {
779     // Adaptor can now be resumed
780     mState = PAUSED;
781
782     Resume();
783
784     // Force a render task
785     RequestUpdateOnce();
786   }
787 }
788
789 void Adaptor::OnWindowHidden()
790 {
791   if ( STOPPED != mState )
792   {
793     Pause();
794
795     // Adaptor cannot be resumed until the window is shown
796     mState = PAUSED_WHILE_HIDDEN;
797   }
798 }
799
800 // Dali::Internal::Adaptor::Adaptor::OnDamaged
801 void Adaptor::OnDamaged( const DamageArea& area )
802 {
803   // This is needed for the case where Dali window is partially obscured
804   RequestUpdate();
805 }
806
807 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
808 {
809   // let the core know the surface size has changed
810   mCore->SurfaceResized(positionSize.width, positionSize.height);
811
812   mResizedSignalV2.Emit( mAdaptor );
813 }
814
815 void Adaptor::NotifyLanguageChanged()
816 {
817   mLanguageChangedSignalV2.Emit( mAdaptor );
818 }
819
820 void Adaptor::RequestUpdateOnce()
821 {
822   if( PAUSED_WHILE_HIDDEN != mState )
823   {
824     if( mUpdateRenderController )
825     {
826       mUpdateRenderController->RequestUpdateOnce();
827     }
828   }
829 }
830
831 void Adaptor::ProcessCoreEventsFromIdle()
832 {
833   ProcessCoreEvents();
834
835   // the idle handle automatically un-installs itself
836   mNotificationOnIdleInstalled = false;
837 }
838
839 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
840 : mResizedSignalV2(),
841   mLanguageChangedSignalV2(),
842   mAdaptor(adaptor),
843   mState(READY),
844   mCore(NULL),
845   mUpdateRenderController(NULL),
846   mVSyncMonitor(NULL),
847   mGLES( NULL ),
848   mEglFactory( NULL ),
849   mSurface( surface ),
850   mPlatformAbstraction( NULL ),
851   mEventHandler( NULL ),
852   mCallbackManager( NULL ),
853   mNotificationOnIdleInstalled( false ),
854   mNotificationTrigger(NULL),
855   mGestureManager(NULL),
856   mHDpi( 0 ),
857   mVDpi( 0 ),
858   mDaliFeedbackPlugin(NULL),
859   mFeedbackController(NULL),
860   mObservers(),
861   mDragAndDropDetector(),
862   mDeferredRotationObserver(NULL),
863   mBaseLayout(baseLayout),
864   mEnvironmentOptions(),
865   mPerformanceInterface(NULL),
866   mObjectProfiler(NULL)
867 {
868   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
869   gThreadLocalAdaptor.reset(this);
870 }
871
872 // Stereoscopy
873
874 void Adaptor::SetViewMode( ViewMode viewMode )
875 {
876   mSurface->SetViewMode( viewMode );
877   mCore->SetViewMode( viewMode );
878 }
879
880 ViewMode Adaptor::GetViewMode() const
881 {
882   return mCore->GetViewMode();
883 }
884
885 void Adaptor::SetStereoBase( float stereoBase )
886 {
887   mCore->SetStereoBase( stereoBase );
888 }
889
890 float Adaptor::GetStereoBase() const
891 {
892   return mCore->GetStereoBase();
893 }
894
895 } // namespace Adaptor
896
897 } // namespace Internal
898
899 } // namespace Dali