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