34822505167bab69c3f6793135253def04113d1b
[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 void Adaptor::RenderSync()
513 {
514   mUpdateRenderController->RenderSync();
515 }
516
517 Dali::RenderSurface& Adaptor::GetSurface() const
518 {
519   return *mSurface;
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::DisableVSync()
576 {
577   mUpdateRenderController->DisableVSync();
578 }
579
580 void Adaptor::SetDpi(size_t hDpi, size_t vDpi)
581 {
582   mHDpi = hDpi;
583   mVDpi = vDpi;
584 }
585
586 EglFactory& Adaptor::GetEGLFactory() const
587 {
588   DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
589   return *mEglFactory;
590 }
591
592 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
593 {
594   return *mEglFactory;
595 }
596
597 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
598 {
599   DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
600   return *mGLES;
601 }
602
603 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
604 {
605   return *mPlatformAbstraction;
606 }
607
608 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
609 {
610   return *mGLES;
611 }
612
613 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
614 {
615   return *mNotificationTrigger;
616 }
617 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
618 {
619   return mTriggerEventFactory;
620 }
621 RenderSurface* Adaptor::GetRenderSurfaceInterface()
622 {
623   return mSurface;
624 }
625 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
626 {
627   return mVSyncMonitor;
628 }
629
630 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
631 {
632   return mKernelTracer;
633 }
634
635 PerformanceInterface* Adaptor::GetPerformanceInterface()
636 {
637   return mPerformanceInterface;
638 }
639
640 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
641 {
642   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
643   return *mPlatformAbstraction;
644 }
645
646 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
647 {
648   mDragAndDropDetector = detector;
649
650   if ( mEventHandler )
651   {
652     mEventHandler->SetDragAndDropDetector( detector );
653   }
654 }
655
656 void Adaptor::SetRotationObserver( RotationObserver* observer )
657 {
658   if( mEventHandler )
659   {
660     mEventHandler->SetRotationObserver( observer );
661   }
662   else if( mState == READY )
663   {
664     // Set once event handler exists
665     mDeferredRotationObserver = observer;
666   }
667 }
668
669 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
670 {
671   if(mTtsPlayers[mode])
672   {
673     mTtsPlayers[mode].Reset();
674   }
675 }
676
677 void Adaptor::SetMinimumPinchDistance(float distance)
678 {
679   if( mGestureManager )
680   {
681     mGestureManager->SetMinimumPinchDistance(distance);
682   }
683 }
684
685 void Adaptor::AddObserver( LifeCycleObserver& observer )
686 {
687   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
688
689   if ( match == mObservers.end() )
690   {
691     mObservers.push_back( &observer );
692   }
693 }
694
695 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
696 {
697   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
698
699   if ( match != mObservers.end() )
700   {
701     mObservers.erase( match );
702   }
703 }
704
705 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
706 {
707   if( mCore )
708   {
709     mCore->QueueEvent(event);
710   }
711 }
712
713 void Adaptor::ProcessCoreEvents()
714 {
715   if( mCore )
716   {
717     if( mPerformanceInterface )
718     {
719       mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_START );
720     }
721
722     mCore->ProcessEvents();
723
724     if( mPerformanceInterface )
725     {
726       mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_END );
727     }
728   }
729 }
730
731 void Adaptor::RequestUpdate()
732 {
733   // When Dali applications are partially visible behind the lock-screen,
734   // the indicator must be updated (therefore allow updates in the PAUSED state)
735   if ( PAUSED  == mState ||
736        RUNNING == mState )
737   {
738     mUpdateRenderController->RequestUpdate();
739   }
740 }
741
742 void Adaptor::RequestProcessEventsOnIdle()
743 {
744   // Only request a notification if the Adaptor is actually running
745   if ( RUNNING == mState )
746   {
747     boost::unique_lock<boost::mutex> lock( mIdleInstaller );
748
749     // check if the idle handle is already installed
750     if( mNotificationOnIdleInstalled )
751     {
752       return;
753     }
754     mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
755   }
756 }
757
758 void Adaptor::OnWindowShown()
759 {
760   if ( PAUSED_WHILE_HIDDEN == mState )
761   {
762     // Adaptor can now be resumed
763     mState = PAUSED;
764
765     Resume();
766
767     // Force a render task
768     RequestUpdateOnce();
769   }
770 }
771
772 void Adaptor::OnWindowHidden()
773 {
774   if ( STOPPED != mState )
775   {
776     Pause();
777
778     // Adaptor cannot be resumed until the window is shown
779     mState = PAUSED_WHILE_HIDDEN;
780   }
781 }
782
783 // Dali::Internal::Adaptor::Adaptor::OnDamaged
784 void Adaptor::OnDamaged( const DamageArea& area )
785 {
786   // This is needed for the case where Dali window is partially obscured
787   RequestUpdate();
788 }
789
790 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
791 {
792   // let the core know the surface size has changed
793   mCore->SurfaceResized(positionSize.width, positionSize.height);
794
795   mResizedSignalV2.Emit( mAdaptor );
796 }
797
798 void Adaptor::NotifyLanguageChanged()
799 {
800   mLanguageChangedSignalV2.Emit( mAdaptor );
801 }
802
803 void Adaptor::RequestUpdateOnce()
804 {
805   if( PAUSED_WHILE_HIDDEN != mState )
806   {
807     if( mUpdateRenderController )
808     {
809       mUpdateRenderController->RequestUpdateOnce();
810     }
811   }
812 }
813
814 void Adaptor::ProcessCoreEventsFromIdle()
815 {
816   ProcessCoreEvents();
817
818   // the idle handle automatically un-installs itself
819   mNotificationOnIdleInstalled = false;
820 }
821
822 void Adaptor::RegisterSingleton(const std::type_info& info, BaseHandle singleton)
823 {
824   if(singleton)
825   {
826     mSingletonContainer.insert(SingletonPair(info.name(), singleton));
827   }
828 }
829
830 BaseHandle Adaptor::GetSingleton(const std::type_info& info) const
831 {
832   BaseHandle object = Dali::BaseHandle();
833
834   SingletonConstIter iter = mSingletonContainer.find(info.name());
835   if(iter != mSingletonContainer.end())
836   {
837     object = (*iter).second;
838   }
839
840   return object;
841 }
842
843 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
844 : mAdaptor(adaptor),
845   mState(READY),
846   mCore(NULL),
847   mUpdateRenderController(NULL),
848   mVSyncMonitor(NULL),
849   mGLES( NULL ),
850   mEglFactory( NULL ),
851   mSurface( surface ),
852   mPlatformAbstraction( NULL ),
853   mEventHandler( NULL ),
854   mCallbackManager( NULL ),
855   mNotificationOnIdleInstalled( false ),
856   mNotificationTrigger(NULL),
857   mGestureManager(NULL),
858   mHDpi( 0 ),
859   mVDpi( 0 ),
860   mDaliFeedbackPlugin(NULL),
861   mFeedbackController(NULL),
862   mObservers(),
863   mDragAndDropDetector(),
864   mDeferredRotationObserver(NULL),
865   mBaseLayout(baseLayout),
866   mEnvironmentOptions(),
867   mPerformanceInterface(NULL),
868   mObjectProfiler(NULL)
869 {
870   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
871   gThreadLocalAdaptor.reset(this);
872 }
873
874 // Stereoscopy
875
876 void Adaptor::SetViewMode( ViewMode viewMode )
877 {
878   mSurface->SetViewMode( viewMode );
879   mCore->SetViewMode( viewMode );
880 }
881
882 ViewMode Adaptor::GetViewMode() const
883 {
884   return mCore->GetViewMode();
885 }
886
887 void Adaptor::SetStereoBase( float stereoBase )
888 {
889   mCore->SetStereoBase( stereoBase );
890 }
891
892 float Adaptor::GetStereoBase() const
893 {
894   return mCore->GetStereoBase();
895 }
896
897 } // namespace Adaptor
898
899 } // namespace Internal
900
901 } // namespace Dali