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