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