Added pre-render callback to Adaptor
[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 void Adaptor::SetPreRenderCallback( CallbackBase* callback )
506 {
507   mThreadController->SetPreRenderCallback( callback );
508 }
509
510 Dali::Adaptor& Adaptor::Get()
511 {
512   DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
513   return gThreadLocalAdaptor->mAdaptor;
514 }
515
516 bool Adaptor::IsAvailable()
517 {
518   return gThreadLocalAdaptor != NULL;
519 }
520
521 void Adaptor::SceneCreated()
522 {
523   mCore->SceneCreated();
524 }
525
526 Dali::Integration::Core& Adaptor::GetCore()
527 {
528   return *mCore;
529 }
530
531 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
532 {
533   mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
534 }
535
536 void Adaptor::SetUseHardwareVSync( bool useHardware )
537 {
538   mVSyncMonitor->SetUseHardwareVSync( useHardware );
539 }
540
541 EglFactory& Adaptor::GetEGLFactory() const
542 {
543   DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
544   return *mEglFactory;
545 }
546
547 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
548 {
549   return *mEglFactory;
550 }
551
552 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
553 {
554   DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
555   return *mGLES;
556 }
557
558 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
559 {
560   return *mPlatformAbstraction;
561 }
562
563 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
564 {
565   return *mGLES;
566 }
567
568 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
569 {
570   return *mNotificationTrigger;
571 }
572
573 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
574 {
575   return mTriggerEventFactory;
576 }
577
578 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
579 {
580   return mSocketFactory;
581 }
582
583 RenderSurface* Adaptor::GetRenderSurfaceInterface()
584 {
585   return mSurface;
586 }
587
588 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
589 {
590   return mVSyncMonitor;
591 }
592
593 TraceInterface& Adaptor::GetKernelTraceInterface()
594 {
595   return mKernelTracer;
596 }
597
598 TraceInterface& Adaptor::GetSystemTraceInterface()
599 {
600   return mSystemTracer;
601 }
602
603 PerformanceInterface* Adaptor::GetPerformanceInterface()
604 {
605   return mPerformanceInterface;
606 }
607
608 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
609 {
610   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
611   return *mPlatformAbstraction;
612 }
613
614 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
615 {
616   mDragAndDropDetector = detector;
617
618   if ( mEventHandler )
619   {
620     mEventHandler->SetDragAndDropDetector( detector );
621   }
622 }
623
624 void Adaptor::SetRotationObserver( RotationObserver* observer )
625 {
626   if( mEventHandler )
627   {
628     mEventHandler->SetRotationObserver( observer );
629   }
630   else if( mState == READY )
631   {
632     // Set once event handler exists
633     mDeferredRotationObserver = observer;
634   }
635 }
636
637 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
638 {
639   if(mTtsPlayers[mode])
640   {
641     mTtsPlayers[mode].Reset();
642   }
643 }
644
645 void Adaptor::SetMinimumPinchDistance(float distance)
646 {
647   if( mGestureManager )
648   {
649     mGestureManager->SetMinimumPinchDistance(distance);
650   }
651 }
652
653 Any Adaptor::GetNativeWindowHandle()
654 {
655   return mNativeWindow;
656 }
657
658 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
659 {
660   mUseRemoteSurface = useRemoteSurface;
661 }
662
663 void Adaptor::AddObserver( LifeCycleObserver& observer )
664 {
665   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
666
667   if ( match == mObservers.end() )
668   {
669     mObservers.push_back( &observer );
670   }
671 }
672
673 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
674 {
675   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
676
677   if ( match != mObservers.end() )
678   {
679     mObservers.erase( match );
680   }
681 }
682
683 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
684 {
685   if( mCore )
686   {
687     mCore->QueueEvent(event);
688   }
689 }
690
691 void Adaptor::ProcessCoreEvents()
692 {
693   if( mCore )
694   {
695     if( mPerformanceInterface )
696     {
697       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
698     }
699
700     mCore->ProcessEvents();
701
702     if( mPerformanceInterface )
703     {
704       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
705     }
706   }
707 }
708
709 void Adaptor::RequestUpdate( bool forceUpdate )
710 {
711   switch( mState )
712   {
713     case RUNNING:
714     {
715       mThreadController->RequestUpdate();
716       break;
717     }
718     case PAUSED:
719     case PAUSED_WHILE_HIDDEN:
720     {
721       // When Dali applications are partially visible behind the lock-screen,
722       // the indicator must be updated (therefore allow updates in the PAUSED state)
723       if( forceUpdate )
724       {
725         mThreadController->RequestUpdateOnce();
726       }
727       break;
728     }
729     default:
730     {
731       // Do nothing
732       break;
733     }
734   }
735 }
736
737 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
738 {
739   // Only request a notification if the Adaptor is actually running
740   // and we haven't installed the idle notification
741   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
742   {
743     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
744   }
745 }
746
747 void Adaptor::OnWindowShown()
748 {
749   if ( PAUSED_WHILE_HIDDEN == mState )
750   {
751     // Adaptor can now be resumed
752     mState = PAUSED;
753
754     Resume();
755
756     // Force a render task
757     RequestUpdateOnce();
758   }
759 }
760
761 void Adaptor::OnWindowHidden()
762 {
763   if ( RUNNING == mState )
764   {
765     Pause();
766
767     // Adaptor cannot be resumed until the window is shown
768     mState = PAUSED_WHILE_HIDDEN;
769   }
770 }
771
772 // Dali::Internal::Adaptor::Adaptor::OnDamaged
773 void Adaptor::OnDamaged( const DamageArea& area )
774 {
775   // This is needed for the case where Dali window is partially obscured
776   RequestUpdate( false );
777 }
778
779 void Adaptor::SurfaceResizePrepare( SurfaceSize surfaceSize )
780 {
781   // let the core know the surface size has changed
782   mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
783
784   mResizedSignal.Emit( mAdaptor );
785 }
786
787 void Adaptor::SurfaceResizeComplete( SurfaceSize surfaceSize )
788 {
789   // flush the event queue to give the update-render thread chance
790   // to start processing messages for new camera setup etc as soon as possible
791   ProcessCoreEvents();
792
793   mThreadController->ResizeSurface();
794 }
795
796 void Adaptor::NotifySceneCreated()
797 {
798   GetCore().SceneCreated();
799
800   // Start thread controller after the scene has been created
801   mThreadController->Start();
802
803   // process after surface is created (registering to remote surface provider if required)
804   SurfaceInitialized();
805
806   mState = RUNNING;
807 }
808
809 void Adaptor::NotifyLanguageChanged()
810 {
811   mLanguageChangedSignal.Emit( mAdaptor );
812 }
813
814 void Adaptor::RenderOnce()
815 {
816   RequestUpdateOnce();
817 }
818
819 const LogFactoryInterface& Adaptor::GetLogFactory()
820 {
821   return *mEnvironmentOptions;
822 }
823
824 void Adaptor::RequestUpdateOnce()
825 {
826   if( mThreadController )
827   {
828     mThreadController->RequestUpdateOnce();
829   }
830 }
831
832 void Adaptor::IndicatorSizeChanged(int height)
833 {
834   // let the core know the indicator height is changed
835   mCore->SetTopMargin(height);
836 }
837
838 bool Adaptor::ProcessCoreEventsFromIdle()
839 {
840   ProcessCoreEvents();
841
842   // the idle handle automatically un-installs itself
843   mNotificationOnIdleInstalled = false;
844
845   return false;
846 }
847
848 Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
849 : mResizedSignal(),
850   mLanguageChangedSignal(),
851   mAdaptor( adaptor ),
852   mState( READY ),
853   mCore( NULL ),
854   mThreadController( NULL ),
855   mVSyncMonitor( NULL ),
856   mGLES( NULL ),
857   mGlSync( NULL ),
858   mEglFactory( NULL ),
859   mNativeWindow( nativeWindow ),
860   mSurface( surface ),
861   mPlatformAbstraction( NULL ),
862   mEventHandler( NULL ),
863   mCallbackManager( NULL ),
864   mNotificationOnIdleInstalled( false ),
865   mNotificationTrigger( NULL ),
866   mGestureManager( NULL ),
867   mDaliFeedbackPlugin(),
868   mFeedbackController( NULL ),
869   mTtsPlayers(),
870   mObservers(),
871   mDragAndDropDetector(),
872   mDeferredRotationObserver( NULL ),
873   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
874   mPerformanceInterface( NULL ),
875   mKernelTracer(),
876   mSystemTracer(),
877   mTriggerEventFactory(),
878   mObjectProfiler( NULL ),
879   mSocketFactory(),
880   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
881   mUseRemoteSurface( false )
882 {
883   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
884   gThreadLocalAdaptor = this;
885 }
886
887 // Stereoscopy
888
889 void Adaptor::SetViewMode( ViewMode viewMode )
890 {
891   mSurface->SetViewMode( viewMode );
892   mCore->SetViewMode( viewMode );
893 }
894
895 ViewMode Adaptor::GetViewMode() const
896 {
897   return mCore->GetViewMode();
898 }
899
900 void Adaptor::SetStereoBase( float stereoBase )
901 {
902   mCore->SetStereoBase( stereoBase );
903 }
904
905 float Adaptor::GetStereoBase() const
906 {
907   return mCore->GetStereoBase();
908 }
909
910 void Adaptor::SetRootLayoutDirection( std::string locale )
911 {
912   Dali::Stage stage = Dali::Stage::GetCurrent();
913
914   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
915                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
916 }
917
918 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
919 {
920   bool idleAdded( false );
921
922   // Only add an idle if the Adaptor is actually running
923   if( RUNNING == mState || READY == mState || forceAdd )
924   {
925     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
926   }
927
928   return idleAdded;
929 }
930
931 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
932 {
933   mCallbackManager->RemoveIdleEntererCallback( callback );
934 }
935
936 } // namespace Adaptor
937
938 } // namespace Internal
939
940 } // namespace Dali