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