Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[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 <render-surface.h>
42 #include <tts-player-impl.h>
43 #include <accessibility-manager-impl.h>
44 #include <timer-impl.h>
45 #include <events/gesture-manager.h>
46 #include <events/event-handler.h>
47 #include <feedback/feedback-controller.h>
48 #include <feedback/feedback-plugin-proxy.h>
49 #include <gl/gl-proxy-implementation.h>
50 #include <gl/gl-implementation.h>
51 #include <gl/egl-sync-implementation.h>
52 #include <gl/egl-image-extensions.h>
53 #include <gl/egl-factory.h>
54 #include <imf-manager-impl.h>
55 #include <clipboard-impl.h>
56 #include <vsync-monitor.h>
57 #include <object-profiler.h>
58 #include <base/display-connection.h>
59
60 #include <tizen-logging.h>
61
62 using Dali::TextAbstraction::FontClient;
63
64 namespace Dali
65 {
66
67 namespace Internal
68 {
69
70 namespace Adaptor
71 {
72
73 namespace
74 {
75 boost::thread_specific_ptr<Adaptor> gThreadLocalAdaptor;
76
77 unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue )
78 {
79   const char* variableParameter = std::getenv(variable);
80
81   // if the parameter exists convert it to an integer, else return the default value
82   unsigned int intValue = variableParameter ? atoi(variableParameter) : defaultValue;
83   return intValue;
84 }
85
86 bool GetIntegerEnvironmentVariable( const char* variable, int& intValue )
87 {
88   const char* variableParameter = std::getenv(variable);
89
90   if( !variableParameter )
91   {
92     return false;
93   }
94   // if the parameter exists convert it to an integer, else return the default value
95   intValue = atoi(variableParameter);
96   return true;
97 }
98
99 bool GetFloatEnvironmentVariable( const char* variable, float& floatValue )
100 {
101   const char* variableParameter = std::getenv(variable);
102
103   if( !variableParameter )
104   {
105     return false;
106   }
107   // if the parameter exists convert it to an integer, else return the default value
108   floatValue = atof(variableParameter);
109   return true;
110 }
111
112 } // unnamed namespace
113
114 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, const DeviceLayout& baseLayout,
115                              Dali::Configuration::ContextLoss configuration )
116 {
117   Dali::Adaptor* adaptor = new Dali::Adaptor;
118   Adaptor* impl = new Adaptor( nativeWindow, *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   unsigned int dpiHor, dpiVer;
376   dpiHor = dpiVer = 0;
377   Dali::DisplayConnection::GetDpi(dpiHor, dpiVer);
378
379   // tell core about the DPI value
380   mCore->SetDpi(dpiHor, dpiVer);
381
382   // set the DPI value for font rendering
383   FontClient fontClient = FontClient::Get();
384   fontClient.SetDpi( dpiHor, dpiVer );
385
386   // Tell the core the size of the surface just before we start the render-thread
387   PositionSize size = mSurface->GetPositionSize();
388   mCore->SurfaceResized( size.width, size.height );
389
390   // Start the update & render threads
391   mUpdateRenderController->Start();
392
393   mState = RUNNING;
394
395   ProcessCoreEvents(); // Ensure any startup messages are processed.
396
397   if ( !mFeedbackController )
398   {
399     // Start sound & haptic feedback
400     mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
401   }
402
403   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
404   {
405     (*iter)->OnStart();
406   }
407 }
408
409 // Dali::Internal::Adaptor::Adaptor::Pause
410 void Adaptor::Pause()
411 {
412   // Only pause the adaptor if we're actually running.
413   if( RUNNING == mState )
414   {
415     // Inform observers that we are about to be paused.
416     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
417     {
418       (*iter)->OnPause();
419     }
420
421     // Reset the event handler when adaptor paused
422     if( mEventHandler )
423     {
424       mEventHandler->Reset();
425     }
426
427     mUpdateRenderController->Pause();
428     mCore->Suspend();
429     mState = PAUSED;
430   }
431 }
432
433 // Dali::Internal::Adaptor::Adaptor::Resume
434 void Adaptor::Resume()
435 {
436   // Only resume the adaptor if we are in the suspended state.
437   if( PAUSED == mState )
438   {
439     // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
440     // If there were events pending, mCore->Resume() will call
441     //   RenderController->RequestUpdate()
442     //     UpdateRenderController->RequestUpdate()
443     //       UpdateRenderSynchronization->RequestUpdate()
444     // and we should have reset the frame timers before allowing Core->Update() to be called.
445     //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
446
447     mUpdateRenderController->ResumeFrameTime();
448     mCore->Resume();
449     mUpdateRenderController->Resume();
450
451     mState = RUNNING;
452
453     // Reset the event handler when adaptor resumed
454     if( mEventHandler )
455     {
456       mEventHandler->Reset();
457     }
458
459     // Inform observers that we have resumed.
460     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
461     {
462       (*iter)->OnResume();
463     }
464
465     ProcessCoreEvents(); // Ensure any outstanding messages are processed
466   }
467 }
468
469 void Adaptor::Stop()
470 {
471   if( RUNNING == mState ||
472       PAUSED  == mState ||
473       PAUSED_WHILE_HIDDEN == mState )
474   {
475     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
476     {
477       (*iter)->OnStop();
478     }
479
480     mUpdateRenderController->Stop();
481     mCore->Suspend();
482
483     // Delete the TTS player
484     for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
485     {
486       if(mTtsPlayers[i])
487       {
488         mTtsPlayers[i].Reset();
489       }
490     }
491
492     delete mEventHandler;
493     mEventHandler = NULL;
494
495     delete mNotificationTrigger;
496     mNotificationTrigger = NULL;
497
498     mCallbackManager->Stop();
499
500     mState = STOPPED;
501   }
502 }
503
504 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
505 {
506   mEventHandler->FeedTouchPoint( point, timeStamp );
507 }
508
509 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
510 {
511   mEventHandler->FeedWheelEvent( wheelEvent );
512 }
513
514 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
515 {
516   mEventHandler->FeedKeyEvent( keyEvent );
517 }
518
519 bool Adaptor::MoveResize( const PositionSize& positionSize )
520 {
521   PositionSize old = mSurface->GetPositionSize();
522
523   // just resize the surface. The driver should automatically resize the egl Surface (untested)
524   // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
525   // is resized. Implementations typically use hooks into the OS and native window
526   // system to perform this resizing on demand, transparently to the client.
527   mSurface->MoveResize( positionSize );
528
529   if(old.width != positionSize.width || old.height != positionSize.height)
530   {
531     SurfaceSizeChanged(positionSize);
532   }
533
534   return true;
535 }
536
537 void Adaptor::SurfaceResized( const PositionSize& positionSize )
538 {
539   PositionSize old = mSurface->GetPositionSize();
540
541   // Called by an application, when it has resized a window outside of Dali.
542   // The EGL driver automatically detects X Window resize calls, and resizes
543   // the EGL surface for us.
544   mSurface->MoveResize( positionSize );
545
546   if(old.width != positionSize.width || old.height != positionSize.height)
547   {
548     SurfaceSizeChanged(positionSize);
549   }
550 }
551
552 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
553 {
554   mNativeWindow = nativeWindow;
555   mSurface = &surface;
556
557   SurfaceSizeChanged(mSurface->GetPositionSize());
558
559   // flush the event queue to give update and render threads chance
560   // to start processing messages for new camera setup etc as soon as possible
561   ProcessCoreEvents();
562
563   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
564
565   // this method blocks until the render thread has completed the replace.
566   mUpdateRenderController->ReplaceSurface(mSurface);
567
568   // Inform core, so that texture resources can be reloaded
569   mCore->RecoverFromContextLoss();
570
571   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
572 }
573
574 RenderSurface& Adaptor::GetSurface() const
575 {
576   return *mSurface;
577 }
578
579 void Adaptor::ReleaseSurfaceLock()
580 {
581   mSurface->ReleaseLock();
582 }
583
584 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
585 {
586   if(!mTtsPlayers[mode])
587   {
588     // Create the TTS player when it needed, because it can reduce launching time.
589     mTtsPlayers[mode] = TtsPlayer::New(mode);
590   }
591
592   return mTtsPlayers[mode];
593 }
594
595 bool Adaptor::AddIdle( CallbackBase* callback )
596 {
597   bool idleAdded(false);
598
599   // Only add an idle if the Adaptor is actually running
600   if( RUNNING == mState )
601   {
602     idleAdded = mCallbackManager->AddCallback( callback, CallbackManager::IDLE_PRIORITY );
603   }
604
605   return idleAdded;
606 }
607
608 bool Adaptor::CallFromMainLoop( CallbackBase* callback )
609 {
610   bool callAdded(false);
611
612   // Only allow the callback if the Adaptor is actually running
613   if ( RUNNING == mState )
614   {
615     callAdded = mCallbackManager->AddCallback( callback, CallbackManager::DEFAULT_PRIORITY );
616   }
617
618   return callAdded;
619 }
620
621 Dali::Adaptor& Adaptor::Get()
622 {
623   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() != NULL && "Adaptor not instantiated" );
624   return gThreadLocalAdaptor->mAdaptor;
625 }
626
627 bool Adaptor::IsAvailable()
628 {
629   return gThreadLocalAdaptor.get() != NULL;
630 }
631
632 Dali::Integration::Core& Adaptor::GetCore()
633 {
634   return *mCore;
635 }
636
637 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
638 {
639   mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
640 }
641
642 void Adaptor::SetUseHardwareVSync( bool useHardware )
643 {
644   mVSyncMonitor->SetUseHardwareVSync( useHardware );
645 }
646
647 EglFactory& Adaptor::GetEGLFactory() const
648 {
649   DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
650   return *mEglFactory;
651 }
652
653 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
654 {
655   return *mEglFactory;
656 }
657
658 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
659 {
660   DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
661   return *mGLES;
662 }
663
664 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
665 {
666   return *mPlatformAbstraction;
667 }
668
669 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
670 {
671   return *mGLES;
672 }
673
674 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
675 {
676   return *mNotificationTrigger;
677 }
678
679 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
680 {
681   return mTriggerEventFactory;
682 }
683
684 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
685 {
686   return mSocketFactory;
687 }
688
689 RenderSurface* Adaptor::GetRenderSurfaceInterface()
690 {
691   return mSurface;
692 }
693
694 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
695 {
696   return mVSyncMonitor;
697 }
698
699 TraceInterface& Adaptor::GetKernelTraceInterface()
700 {
701   return mKernelTracer;
702 }
703
704 TraceInterface& Adaptor::GetSystemTraceInterface()
705 {
706   return mSystemTracer;
707 }
708
709 PerformanceInterface* Adaptor::GetPerformanceInterface()
710 {
711   return mPerformanceInterface;
712 }
713
714 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
715 {
716   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
717   return *mPlatformAbstraction;
718 }
719
720 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
721 {
722   mDragAndDropDetector = detector;
723
724   if ( mEventHandler )
725   {
726     mEventHandler->SetDragAndDropDetector( detector );
727   }
728 }
729
730 void Adaptor::SetRotationObserver( RotationObserver* observer )
731 {
732   if( mEventHandler )
733   {
734     mEventHandler->SetRotationObserver( observer );
735   }
736   else if( mState == READY )
737   {
738     // Set once event handler exists
739     mDeferredRotationObserver = observer;
740   }
741 }
742
743 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
744 {
745   if(mTtsPlayers[mode])
746   {
747     mTtsPlayers[mode].Reset();
748   }
749 }
750
751 void Adaptor::SetMinimumPinchDistance(float distance)
752 {
753   if( mGestureManager )
754   {
755     mGestureManager->SetMinimumPinchDistance(distance);
756   }
757 }
758
759 Any Adaptor::GetNativeWindowHandle()
760 {
761   return mNativeWindow;
762 }
763
764 void Adaptor::AddObserver( LifeCycleObserver& observer )
765 {
766   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
767
768   if ( match == mObservers.end() )
769   {
770     mObservers.push_back( &observer );
771   }
772 }
773
774 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
775 {
776   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
777
778   if ( match != mObservers.end() )
779   {
780     mObservers.erase( match );
781   }
782 }
783
784 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
785 {
786   if( mCore )
787   {
788     mCore->QueueEvent(event);
789   }
790 }
791
792 void Adaptor::ProcessCoreEvents()
793 {
794   if( mCore )
795   {
796     if( mPerformanceInterface )
797     {
798       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
799     }
800
801     mCore->ProcessEvents();
802
803     if( mPerformanceInterface )
804     {
805       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
806     }
807   }
808 }
809
810 void Adaptor::RequestUpdate()
811 {
812   // When Dali applications are partially visible behind the lock-screen,
813   // the indicator must be updated (therefore allow updates in the PAUSED state)
814   if ( PAUSED  == mState ||
815        RUNNING == mState )
816   {
817     mUpdateRenderController->RequestUpdate();
818   }
819 }
820
821 void Adaptor::RequestProcessEventsOnIdle()
822 {
823   // Only request a notification if the Adaptor is actually running
824   // and we haven't installed the idle notification
825   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
826   {
827     mNotificationOnIdleInstalled = AddIdle( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ) );
828   }
829 }
830
831 void Adaptor::OnWindowShown()
832 {
833   if ( PAUSED_WHILE_HIDDEN == mState )
834   {
835     // Adaptor can now be resumed
836     mState = PAUSED;
837
838     Resume();
839
840     // Force a render task
841     RequestUpdateOnce();
842   }
843 }
844
845 void Adaptor::OnWindowHidden()
846 {
847   if ( STOPPED != mState )
848   {
849     Pause();
850
851     // Adaptor cannot be resumed until the window is shown
852     mState = PAUSED_WHILE_HIDDEN;
853   }
854 }
855
856 // Dali::Internal::Adaptor::Adaptor::OnDamaged
857 void Adaptor::OnDamaged( const DamageArea& area )
858 {
859   // This is needed for the case where Dali window is partially obscured
860   RequestUpdate();
861 }
862
863 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
864 {
865   // let the core know the surface size has changed
866   mCore->SurfaceResized(positionSize.width, positionSize.height);
867
868   mResizedSignal.Emit( mAdaptor );
869 }
870
871 void Adaptor::NotifyLanguageChanged()
872 {
873   mLanguageChangedSignal.Emit( mAdaptor );
874 }
875
876 void Adaptor::RequestUpdateOnce()
877 {
878   if( PAUSED_WHILE_HIDDEN != mState )
879   {
880     if( mUpdateRenderController )
881     {
882       mUpdateRenderController->RequestUpdateOnce();
883     }
884   }
885 }
886
887 void Adaptor::ProcessCoreEventsFromIdle()
888 {
889   ProcessCoreEvents();
890
891   // the idle handle automatically un-installs itself
892   mNotificationOnIdleInstalled = false;
893 }
894
895 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
896 : mResizedSignal(),
897   mLanguageChangedSignal(),
898   mAdaptor(adaptor),
899   mState(READY),
900   mCore(NULL),
901   mUpdateRenderController(NULL),
902   mVSyncMonitor(NULL),
903   mGLES( NULL ),
904   mEglFactory( NULL ),
905   mNativeWindow( nativeWindow ),
906   mSurface( surface ),
907   mPlatformAbstraction( NULL ),
908   mEventHandler( NULL ),
909   mCallbackManager( NULL ),
910   mNotificationOnIdleInstalled( false ),
911   mNotificationTrigger(NULL),
912   mGestureManager(NULL),
913   mDaliFeedbackPlugin(NULL),
914   mFeedbackController(NULL),
915   mObservers(),
916   mDragAndDropDetector(),
917   mDeferredRotationObserver(NULL),
918   mBaseLayout(baseLayout),
919   mEnvironmentOptions(),
920   mPerformanceInterface(NULL),
921   mObjectProfiler(NULL)
922 {
923   DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
924   gThreadLocalAdaptor.reset(this);
925 }
926
927 // Stereoscopy
928
929 void Adaptor::SetViewMode( ViewMode viewMode )
930 {
931   mSurface->SetViewMode( viewMode );
932   mCore->SetViewMode( viewMode );
933 }
934
935 ViewMode Adaptor::GetViewMode() const
936 {
937   return mCore->GetViewMode();
938 }
939
940 void Adaptor::SetStereoBase( float stereoBase )
941 {
942   mCore->SetStereoBase( stereoBase );
943 }
944
945 float Adaptor::GetStereoBase() const
946 {
947   return mCore->GetStereoBase();
948 }
949
950 } // namespace Adaptor
951
952 } // namespace Internal
953
954 } // namespace Dali