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