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