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