b660e43fdd3e6fc1a73793659e2f018d12d23d42
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / adaptor-impl.cpp
1 /*
2  * Copyright (c) 2018 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 <dali/internal/adaptor/common/adaptor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/common/stage.h>
23 #include <dali/public-api/actors/layer.h>
24 #include <dali/devel-api/actors/actor-devel.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/context-notifier.h>
28 #include <dali/integration-api/profiling.h>
29 #include <dali/integration-api/input-options.h>
30 #include <dali/integration-api/events/touch-event-integ.h>
31
32 // INTERNAL INCLUDES
33 #include <dali/public-api/dali-adaptor-common.h>
34 #include <dali/internal/system/common/thread-controller.h>
35 #include <dali/internal/system/common/performance-interface-factory.h>
36 #include <dali/internal/adaptor/common/lifecycle-observer.h>
37
38 #include <dali/devel-api/text-abstraction/font-client.h>
39
40 #include <dali/internal/system/common/callback-manager.h>
41 #include <dali/internal/accessibility/common/tts-player-impl.h>
42 #include <dali/internal/accessibility/common/accessibility-adaptor-impl.h>
43 #include <dali/internal/input/common/gesture-manager.h>
44 #include <dali/internal/window-system/common/event-handler.h>
45 #include <dali/internal/graphics/gles20/gl-proxy-implementation.h>
46 #include <dali/internal/graphics/gles20/gl-implementation.h>
47 #include <dali/internal/graphics/gles20/egl-sync-implementation.h>
48 #include <dali/internal/graphics/common/egl-image-extensions.h>
49 #include <dali/internal/graphics/gles20/egl-factory.h>
50 #include <dali/internal/clipboard/common/clipboard-impl.h>
51 #include <dali/internal/graphics/common/vsync-monitor.h>
52 #include <dali/internal/system/common/object-profiler.h>
53 #include <dali/internal/window-system/common/display-connection.h>
54 #include <dali/internal/window-system/common/window-impl.h>
55 #include <dali/internal/window-system/common/window-render-surface.h>
56
57 #include <dali/internal/system/common/logging.h>
58 #include <dali/devel-api/adaptor-framework/image-loading.h>
59
60 #include <dali/internal/system/common/locale-utils.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 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
76 } // unnamed namespace
77
78 Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
79 {
80   Dali::Adaptor* adaptor = new Dali::Adaptor;
81   Adaptor* impl = new Adaptor( nativeWindow, *adaptor, surface, environmentOptions );
82   adaptor->mImpl = impl;
83
84   impl->Initialize(configuration);
85
86   return adaptor;
87 }
88
89 Dali::Adaptor* Adaptor::New( Dali::Window window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
90 {
91   Any winId = window.GetNativeHandle();
92
93   Window& windowImpl = Dali::GetImplementation(window);
94   Dali::Adaptor* adaptor = New( winId, windowImpl.GetSurface(), configuration, environmentOptions );
95   windowImpl.SetAdaptor(*adaptor);
96   return adaptor;
97 }
98
99 void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
100 {
101   // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
102   Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
103   mEnvironmentOptions->SetLogFunction( logFunction );
104   mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
105
106   mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
107
108   std::string path;
109   GetDataStoragePath( path );
110   mPlatformAbstraction->SetDataStoragePath( path );
111
112   ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
113   if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
114   {
115     dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
116   }
117   // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
118   // files automatically.
119
120   if( mEnvironmentOptions->PerformanceServerRequired() )
121   {
122     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
123   }
124
125   mEnvironmentOptions->CreateTraceManager( mPerformanceInterface );
126   mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
127
128   mCallbackManager = CallbackManager::New();
129
130   PositionSize size = mSurface->GetPositionSize();
131
132   mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, *mEnvironmentOptions);
133
134   if( mEnvironmentOptions->GetGlesCallTime() > 0 )
135   {
136     mGLES = new GlProxyImplementation( *mEnvironmentOptions );
137   }
138   else
139   {
140     mGLES = new GlImplementation();
141   }
142
143   const Integration::DepthBufferAvailable depthBufferAvailable = static_cast< Integration::DepthBufferAvailable >( mEnvironmentOptions->DepthBufferRequired() );
144   const Integration::StencilBufferAvailable stencilBufferAvailable = static_cast< Integration::StencilBufferAvailable >( mEnvironmentOptions->StencilBufferRequired() );
145
146   mEglFactory = new EglFactory( mEnvironmentOptions->GetMultiSamplingLevel(), depthBufferAvailable, stencilBufferAvailable );
147
148   EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
149
150   mCore = Integration::Core::New( *this,
151                                   *mPlatformAbstraction,
152                                   *mGLES,
153                                   *eglSyncImpl,
154                                   *mGestureManager,
155                                   dataRetentionPolicy ,
156                                   ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
157                                   depthBufferAvailable,
158                                   stencilBufferAvailable );
159
160   const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
161   if( 0u < timeInterval )
162   {
163     mObjectProfiler = new ObjectProfiler( timeInterval );
164   }
165
166   mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
167
168   mVSyncMonitor = new VSyncMonitor;
169
170   mThreadController = new ThreadController( *this, *mEnvironmentOptions );
171
172   // Should be called after Core creation
173   if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
174   {
175     Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
176   }
177   if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
178   {
179     Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
180   }
181   if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
182   {
183     Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
184   }
185   if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
186   {
187     Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
188   }
189   if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
190   {
191     Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
192   }
193   if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
194   {
195     Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
196   }
197   if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
198   {
199     Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
200   }
201   if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
202   {
203     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
204   }
205   if( mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0 )
206   {
207     Integration::SetPanGestureUseActualTimes( mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false );
208   }
209   if( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0 )
210   {
211     Integration::SetPanGestureInterpolationTimeRange( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() );
212   }
213   if( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0 )
214   {
215     Integration::SetPanGestureScalarOnlyPredictionEnabled( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false  );
216   }
217   if( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0 )
218   {
219     Integration::SetPanGestureTwoPointPredictionEnabled( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false  );
220   }
221   if( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0 )
222   {
223     Integration::SetPanGestureTwoPointInterpolatePastTime( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() );
224   }
225   if( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f )
226   {
227     Integration::SetPanGestureTwoPointVelocityBias( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() );
228   }
229   if( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f )
230   {
231     Integration::SetPanGestureTwoPointAccelerationBias( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() );
232   }
233   if( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0 )
234   {
235     Integration::SetPanGestureMultitapSmoothingRange( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() );
236   }
237
238   // Set max texture size
239   if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
240   {
241     Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
242   }
243
244   SetupSystemInformation();
245 }
246
247 Adaptor::~Adaptor()
248 {
249   // Ensure stop status
250   Stop();
251
252   // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
253   gThreadLocalAdaptor = NULL;
254
255   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
256   {
257     (*iter)->OnDestroy();
258   }
259
260   delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
261   delete mVSyncMonitor;
262   delete mEventHandler;
263   delete mObjectProfiler;
264
265   delete mCore;
266   delete mEglFactory;
267   delete mGLES;
268   delete mGestureManager;
269   delete mPlatformAbstraction;
270   delete mCallbackManager;
271   delete mPerformanceInterface;
272
273   // uninstall it on this thread (main actor thread)
274   Dali::Integration::Log::UninstallLogFunction();
275
276   // Delete environment options if we own it
277   if( mEnvironmentOptionsOwned )
278   {
279     delete mEnvironmentOptions;
280   }
281 }
282
283 void Adaptor::Start()
284 {
285   // it doesn't support restart after stop at this moment
286   // to support restarting, need more testing
287   if( READY != mState )
288   {
289     return;
290   }
291
292   // Start the callback manager
293   mCallbackManager->Start();
294
295   // create event handler
296   mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
297
298   if( mDeferredRotationObserver != NULL )
299   {
300     mEventHandler->SetRotationObserver(mDeferredRotationObserver);
301     mDeferredRotationObserver = NULL;
302   }
303
304   unsigned int dpiHor, dpiVer;
305   dpiHor = dpiVer = 0;
306   mSurface->GetDpi( dpiHor, dpiVer );
307
308   // tell core about the DPI value
309   mCore->SetDpi(dpiHor, dpiVer);
310
311   // set the DPI value for font rendering
312   FontClient fontClient = FontClient::Get();
313   fontClient.SetDpi( dpiHor, dpiVer );
314
315   // Tell the core the size of the surface just before we start the render-thread
316   PositionSize size = mSurface->GetPositionSize();
317   mCore->SurfaceResized( size.width, size.height );
318
319   // Initialize the thread controller
320   mThreadController->Initialize();
321
322   ProcessCoreEvents(); // Ensure any startup messages are processed.
323
324   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
325   {
326     (*iter)->OnStart();
327   }
328 }
329
330 // Dali::Internal::Adaptor::Adaptor::Pause
331 void Adaptor::Pause()
332 {
333   // Only pause the adaptor if we're actually running.
334   if( RUNNING == mState )
335   {
336     // Inform observers that we are about to be paused.
337     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
338     {
339       (*iter)->OnPause();
340     }
341
342     // Reset the event handler when adaptor paused
343     if( mEventHandler )
344     {
345       mEventHandler->Pause();
346     }
347
348     mThreadController->Pause();
349     mState = PAUSED;
350
351     // Ensure any messages queued during pause callbacks are processed by doing another update.
352     RequestUpdateOnce();
353   }
354 }
355
356 // Dali::Internal::Adaptor::Adaptor::Resume
357 void Adaptor::Resume()
358 {
359   // Only resume the adaptor if we are in the suspended state.
360   if( PAUSED == mState )
361   {
362     mState = RUNNING;
363
364     // Reset the event handler when adaptor resumed
365     if( mEventHandler )
366     {
367       mEventHandler->Resume();
368     }
369
370     // Inform observers that we have resumed.
371     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
372     {
373       (*iter)->OnResume();
374     }
375
376     // trigger processing of events queued up while paused
377     mCore->ProcessEvents();
378
379     // Do at end to ensure our first update/render after resumption includes the processed messages as well
380     mThreadController->Resume();
381   }
382 }
383
384 void Adaptor::Stop()
385 {
386   if( RUNNING == mState ||
387       PAUSED  == mState ||
388       PAUSED_WHILE_HIDDEN == mState )
389   {
390     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
391     {
392       (*iter)->OnStop();
393     }
394
395     mThreadController->Stop();
396
397     // Delete the TTS player
398     for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
399     {
400       if(mTtsPlayers[i])
401       {
402         mTtsPlayers[i].Reset();
403       }
404     }
405
406     delete mEventHandler;
407     mEventHandler = NULL;
408
409     delete mNotificationTrigger;
410     mNotificationTrigger = NULL;
411
412     mCallbackManager->Stop();
413
414     mState = STOPPED;
415   }
416 }
417
418 void Adaptor::ContextLost()
419 {
420   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
421 }
422
423 void Adaptor::ContextRegained()
424 {
425   // Inform core, so that texture resources can be reloaded
426   mCore->RecoverFromContextLoss();
427
428   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
429 }
430
431 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
432 {
433   mEventHandler->FeedTouchPoint( point, timeStamp );
434 }
435
436 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
437 {
438   mEventHandler->FeedWheelEvent( wheelEvent );
439 }
440
441 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
442 {
443   mEventHandler->FeedKeyEvent( keyEvent );
444 }
445
446 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
447 {
448   PositionSize positionSize = surface.GetPositionSize();
449
450   // let the core know the surface size has changed
451   mCore->SurfaceResized( positionSize.width, positionSize.height );
452
453   mResizedSignal.Emit( mAdaptor );
454
455   mNativeWindow = nativeWindow;
456   mSurface = &surface;
457
458   // flush the event queue to give the update-render thread chance
459   // to start processing messages for new camera setup etc as soon as possible
460   ProcessCoreEvents();
461
462   // this method blocks until the render thread has completed the replace.
463   mThreadController->ReplaceSurface(mSurface);
464 }
465
466 RenderSurface& Adaptor::GetSurface() const
467 {
468   return *mSurface;
469 }
470
471 void Adaptor::ReleaseSurfaceLock()
472 {
473   mSurface->ReleaseLock();
474 }
475
476 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
477 {
478   if(!mTtsPlayers[mode])
479   {
480     // Create the TTS player when it needed, because it can reduce launching time.
481     mTtsPlayers[mode] = TtsPlayer::New(mode);
482   }
483
484   return mTtsPlayers[mode];
485 }
486
487 bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue, bool forceAdd )
488 {
489   bool idleAdded(false);
490
491   // Only add an idle if the Adaptor is actually running
492   if( RUNNING == mState || READY == mState || forceAdd )
493   {
494     idleAdded = mCallbackManager->AddIdleCallback( callback, hasReturnValue );
495   }
496
497   return idleAdded;
498 }
499
500 void Adaptor::RemoveIdle( CallbackBase* callback )
501 {
502   mCallbackManager->RemoveIdleCallback( callback );
503 }
504
505 Dali::Adaptor& Adaptor::Get()
506 {
507   DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
508   return gThreadLocalAdaptor->mAdaptor;
509 }
510
511 bool Adaptor::IsAvailable()
512 {
513   return gThreadLocalAdaptor != NULL;
514 }
515
516 void Adaptor::SceneCreated()
517 {
518   mCore->SceneCreated();
519 }
520
521 Dali::Integration::Core& Adaptor::GetCore()
522 {
523   return *mCore;
524 }
525
526 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
527 {
528   mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
529 }
530
531 void Adaptor::SetUseHardwareVSync( bool useHardware )
532 {
533   mVSyncMonitor->SetUseHardwareVSync( useHardware );
534 }
535
536 EglFactory& Adaptor::GetEGLFactory() const
537 {
538   DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
539   return *mEglFactory;
540 }
541
542 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
543 {
544   return *mEglFactory;
545 }
546
547 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
548 {
549   DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
550   return *mGLES;
551 }
552
553 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
554 {
555   return *mPlatformAbstraction;
556 }
557
558 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
559 {
560   return *mGLES;
561 }
562
563 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
564 {
565   return *mNotificationTrigger;
566 }
567
568 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
569 {
570   return mTriggerEventFactory;
571 }
572
573 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
574 {
575   return mSocketFactory;
576 }
577
578 RenderSurface* Adaptor::GetRenderSurfaceInterface()
579 {
580   return mSurface;
581 }
582
583 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
584 {
585   return mVSyncMonitor;
586 }
587
588 TraceInterface& Adaptor::GetKernelTraceInterface()
589 {
590   return mKernelTracer;
591 }
592
593 TraceInterface& Adaptor::GetSystemTraceInterface()
594 {
595   return mSystemTracer;
596 }
597
598 PerformanceInterface* Adaptor::GetPerformanceInterface()
599 {
600   return mPerformanceInterface;
601 }
602
603 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
604 {
605   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
606   return *mPlatformAbstraction;
607 }
608
609 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
610 {
611   mDragAndDropDetector = detector;
612
613   if ( mEventHandler )
614   {
615     mEventHandler->SetDragAndDropDetector( detector );
616   }
617 }
618
619 void Adaptor::SetRotationObserver( RotationObserver* observer )
620 {
621   if( mEventHandler )
622   {
623     mEventHandler->SetRotationObserver( observer );
624   }
625   else if( mState == READY )
626   {
627     // Set once event handler exists
628     mDeferredRotationObserver = observer;
629   }
630 }
631
632 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
633 {
634   if(mTtsPlayers[mode])
635   {
636     mTtsPlayers[mode].Reset();
637   }
638 }
639
640 void Adaptor::SetMinimumPinchDistance(float distance)
641 {
642   if( mGestureManager )
643   {
644     mGestureManager->SetMinimumPinchDistance(distance);
645   }
646 }
647
648 Any Adaptor::GetNativeWindowHandle()
649 {
650   return mNativeWindow;
651 }
652
653 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
654 {
655   mUseRemoteSurface = useRemoteSurface;
656 }
657
658 void Adaptor::AddObserver( LifeCycleObserver& observer )
659 {
660   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
661
662   if ( match == mObservers.end() )
663   {
664     mObservers.push_back( &observer );
665   }
666 }
667
668 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
669 {
670   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
671
672   if ( match != mObservers.end() )
673   {
674     mObservers.erase( match );
675   }
676 }
677
678 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
679 {
680   if( mCore )
681   {
682     mCore->QueueEvent(event);
683   }
684 }
685
686 void Adaptor::ProcessCoreEvents()
687 {
688   if( mCore )
689   {
690     if( mPerformanceInterface )
691     {
692       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
693     }
694
695     mCore->ProcessEvents();
696
697     if( mPerformanceInterface )
698     {
699       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
700     }
701   }
702 }
703
704 void Adaptor::RequestUpdate( bool forceUpdate )
705 {
706   switch( mState )
707   {
708     case RUNNING:
709     {
710       mThreadController->RequestUpdate();
711       break;
712     }
713     case PAUSED:
714     case PAUSED_WHILE_HIDDEN:
715     {
716       // When Dali applications are partially visible behind the lock-screen,
717       // the indicator must be updated (therefore allow updates in the PAUSED state)
718       if( forceUpdate )
719       {
720         mThreadController->RequestUpdateOnce();
721       }
722       break;
723     }
724     default:
725     {
726       // Do nothing
727       break;
728     }
729   }
730 }
731
732 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
733 {
734   // Only request a notification if the Adaptor is actually running
735   // and we haven't installed the idle notification
736   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
737   {
738     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
739   }
740 }
741
742 void Adaptor::OnWindowShown()
743 {
744   if ( PAUSED_WHILE_HIDDEN == mState )
745   {
746     // Adaptor can now be resumed
747     mState = PAUSED;
748
749     Resume();
750
751     // Force a render task
752     RequestUpdateOnce();
753   }
754 }
755
756 void Adaptor::OnWindowHidden()
757 {
758   if ( RUNNING == mState )
759   {
760     Pause();
761
762     // Adaptor cannot be resumed until the window is shown
763     mState = PAUSED_WHILE_HIDDEN;
764   }
765 }
766
767 // Dali::Internal::Adaptor::Adaptor::OnDamaged
768 void Adaptor::OnDamaged( const DamageArea& area )
769 {
770   // This is needed for the case where Dali window is partially obscured
771   RequestUpdate( false );
772 }
773
774 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
775 {
776   // let the core know the surface size has changed
777   mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
778
779   mResizedSignal.Emit( mAdaptor );
780 }
781
782 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
783 {
784   // flush the event queue to give the update-render thread chance
785   // to start processing messages for new camera setup etc as soon as possible
786   ProcessCoreEvents();
787
788   mThreadController->ResizeSurface();
789 }
790
791 void Adaptor::NotifySceneCreated()
792 {
793   GetCore().SceneCreated();
794
795   // Start thread controller after the scene has been created
796   mThreadController->Start();
797
798   // process after surface is created (registering to remote surface provider if required)
799   SurfaceInitialized();
800
801   mState = RUNNING;
802 }
803
804 void Adaptor::NotifyLanguageChanged()
805 {
806   mLanguageChangedSignal.Emit( mAdaptor );
807 }
808
809 void Adaptor::RenderOnce()
810 {
811   RequestUpdateOnce();
812 }
813
814 const LogFactoryInterface& Adaptor::GetLogFactory()
815 {
816   return *mEnvironmentOptions;
817 }
818
819 void Adaptor::RequestUpdateOnce()
820 {
821   if( mThreadController )
822   {
823     mThreadController->RequestUpdateOnce();
824   }
825 }
826
827 void Adaptor::IndicatorSizeChanged(int height)
828 {
829   // let the core know the indicator height is changed
830   mCore->SetTopMargin(height);
831 }
832
833 bool Adaptor::ProcessCoreEventsFromIdle()
834 {
835   ProcessCoreEvents();
836
837   // the idle handle automatically un-installs itself
838   mNotificationOnIdleInstalled = false;
839
840   return false;
841 }
842
843 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
844 : mResizedSignal(),
845   mLanguageChangedSignal(),
846   mAdaptor( adaptor ),
847   mState( READY ),
848   mCore( NULL ),
849   mThreadController( NULL ),
850   mVSyncMonitor( NULL ),
851   mGLES( NULL ),
852   mGlSync( NULL ),
853   mEglFactory( NULL ),
854   mNativeWindow( nativeWindow ),
855   mSurface( surface ),
856   mPlatformAbstraction( NULL ),
857   mEventHandler( NULL ),
858   mCallbackManager( NULL ),
859   mNotificationOnIdleInstalled( false ),
860   mNotificationTrigger( NULL ),
861   mGestureManager( NULL ),
862   mDaliFeedbackPlugin(),
863   mFeedbackController( NULL ),
864   mTtsPlayers(),
865   mObservers(),
866   mDragAndDropDetector(),
867   mDeferredRotationObserver( NULL ),
868   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
869   mPerformanceInterface( NULL ),
870   mKernelTracer(),
871   mSystemTracer(),
872   mTriggerEventFactory(),
873   mObjectProfiler( NULL ),
874   mSocketFactory(),
875   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
876   mUseRemoteSurface( false )
877 {
878   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
879   gThreadLocalAdaptor = this;
880 }
881
882 // Stereoscopy
883
884 void Adaptor::SetViewMode( ViewMode viewMode )
885 {
886   mSurface->SetViewMode( viewMode );
887   mCore->SetViewMode( viewMode );
888 }
889
890 ViewMode Adaptor::GetViewMode() const
891 {
892   return mCore->GetViewMode();
893 }
894
895 void Adaptor::SetStereoBase( float stereoBase )
896 {
897   mCore->SetStereoBase( stereoBase );
898 }
899
900 float Adaptor::GetStereoBase() const
901 {
902   return mCore->GetStereoBase();
903 }
904
905 void Adaptor::SetRootLayoutDirection( std::string locale )
906 {
907   Dali::Stage stage = Dali::Stage::GetCurrent();
908
909   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
910                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
911 }
912
913 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
914 {
915   bool idleAdded( false );
916
917   // Only add an idle if the Adaptor is actually running
918   if( RUNNING == mState || READY == mState || forceAdd )
919   {
920     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
921   }
922
923   return idleAdded;
924 }
925
926 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
927 {
928   mCallbackManager->RemoveIdleEntererCallback( callback );
929 }
930
931 } // namespace Adaptor
932
933 } // namespace Internal
934
935 } // namespace Dali