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