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