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