Merge "Actor's Transformation API Cleanup" 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 <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
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, 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 RenderSurface* Adaptor::GetRenderSurfaceInterface()
706 {
707   return mSurface;
708 }
709 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
710 {
711   return mVSyncMonitor;
712 }
713
714 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
715 {
716   return mKernelTracer;
717 }
718
719 PerformanceInterface* Adaptor::GetPerformanceInterface()
720 {
721   return mPerformanceInterface;
722 }
723
724 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
725 {
726   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
727   return *mPlatformAbstraction;
728 }
729
730 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
731 {
732   mDragAndDropDetector = detector;
733
734   if ( mEventHandler )
735   {
736     mEventHandler->SetDragAndDropDetector( detector );
737   }
738 }
739
740 void Adaptor::SetRotationObserver( RotationObserver* observer )
741 {
742   if( mEventHandler )
743   {
744     mEventHandler->SetRotationObserver( observer );
745   }
746   else if( mState == READY )
747   {
748     // Set once event handler exists
749     mDeferredRotationObserver = observer;
750   }
751 }
752
753 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
754 {
755   if(mTtsPlayers[mode])
756   {
757     mTtsPlayers[mode].Reset();
758   }
759 }
760
761 void Adaptor::SetMinimumPinchDistance(float distance)
762 {
763   if( mGestureManager )
764   {
765     mGestureManager->SetMinimumPinchDistance(distance);
766   }
767 }
768
769
770 void Adaptor::AddObserver( LifeCycleObserver& observer )
771 {
772   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
773
774   if ( match == mObservers.end() )
775   {
776     mObservers.push_back( &observer );
777   }
778 }
779
780 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
781 {
782   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
783
784   if ( match != mObservers.end() )
785   {
786     mObservers.erase( match );
787   }
788 }
789
790 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
791 {
792   if( mCore )
793   {
794     mCore->QueueEvent(event);
795   }
796 }
797
798 void Adaptor::ProcessCoreEvents()
799 {
800   if( mCore )
801   {
802     if( mPerformanceInterface )
803     {
804       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
805     }
806
807     mCore->ProcessEvents();
808
809     if( mPerformanceInterface )
810     {
811       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
812     }
813   }
814 }
815
816 void Adaptor::RequestUpdate()
817 {
818   // When Dali applications are partially visible behind the lock-screen,
819   // the indicator must be updated (therefore allow updates in the PAUSED state)
820   if ( PAUSED  == mState ||
821        RUNNING == mState )
822   {
823     mUpdateRenderController->RequestUpdate();
824   }
825 }
826
827 void Adaptor::RequestProcessEventsOnIdle()
828 {
829   // Only request a notification if the Adaptor is actually running
830   // and we haven't installed the idle notification
831   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
832   {
833     mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
834   }
835 }
836
837 void Adaptor::OnWindowShown()
838 {
839   if ( PAUSED_WHILE_HIDDEN == mState )
840   {
841     // Adaptor can now be resumed
842     mState = PAUSED;
843
844     Resume();
845
846     // Force a render task
847     RequestUpdateOnce();
848   }
849 }
850
851 void Adaptor::OnWindowHidden()
852 {
853   if ( STOPPED != mState )
854   {
855     Pause();
856
857     // Adaptor cannot be resumed until the window is shown
858     mState = PAUSED_WHILE_HIDDEN;
859   }
860 }
861
862 // Dali::Internal::Adaptor::Adaptor::OnDamaged
863 void Adaptor::OnDamaged( const DamageArea& area )
864 {
865   // This is needed for the case where Dali window is partially obscured
866   RequestUpdate();
867 }
868
869 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
870 {
871   // let the core know the surface size has changed
872   mCore->SurfaceResized(positionSize.width, positionSize.height);
873
874   mResizedSignal.Emit( mAdaptor );
875 }
876
877 void Adaptor::NotifyLanguageChanged()
878 {
879   mLanguageChangedSignal.Emit( mAdaptor );
880 }
881
882 void Adaptor::RequestUpdateOnce()
883 {
884   if( PAUSED_WHILE_HIDDEN != mState )
885   {
886     if( mUpdateRenderController )
887     {
888       mUpdateRenderController->RequestUpdateOnce();
889     }
890   }
891 }
892
893 void Adaptor::ProcessCoreEventsFromIdle()
894 {
895   ProcessCoreEvents();
896
897   // the idle handle automatically un-installs itself
898   mNotificationOnIdleInstalled = false;
899 }
900
901 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
902 : mResizedSignal(),
903   mLanguageChangedSignal(),
904   mAdaptor(adaptor),
905   mState(READY),
906   mCore(NULL),
907   mUpdateRenderController(NULL),
908   mVSyncMonitor(NULL),
909   mGLES( NULL ),
910   mEglFactory( NULL ),
911   mSurface( surface ),
912   mPlatformAbstraction( NULL ),
913   mEventHandler( NULL ),
914   mCallbackManager( NULL ),
915   mNotificationOnIdleInstalled( false ),
916   mNotificationTrigger(NULL),
917   mGestureManager(NULL),
918   mHDpi( 0 ),
919   mVDpi( 0 ),
920   mDaliFeedbackPlugin(NULL),
921   mFeedbackController(NULL),
922   mObservers(),
923   mDragAndDropDetector(),
924   mDeferredRotationObserver(NULL),
925   mBaseLayout(baseLayout),
926   mEnvironmentOptions(),
927   mPerformanceInterface(NULL),
928   mObjectProfiler(NULL)
929 {
930   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
931   gThreadLocalAdaptor.reset(this);
932 }
933
934 // Stereoscopy
935
936 void Adaptor::SetViewMode( ViewMode viewMode )
937 {
938   mSurface->SetViewMode( viewMode );
939   mCore->SetViewMode( viewMode );
940 }
941
942 ViewMode Adaptor::GetViewMode() const
943 {
944   return mCore->GetViewMode();
945 }
946
947 void Adaptor::SetStereoBase( float stereoBase )
948 {
949   mCore->SetStereoBase( stereoBase );
950 }
951
952 float Adaptor::GetStereoBase() const
953 {
954   return mCore->GetStereoBase();
955 }
956
957 } // namespace Adaptor
958
959 } // namespace Internal
960
961 } // namespace Dali