2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "adaptor-impl.h"
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>
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>
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>
58 #include <slp-logging.h>
73 boost::thread_specific_ptr<Adaptor> gThreadLocalAdaptor;
75 unsigned int GetIntegerEnvironmentVariable( const char* variable, unsigned int defaultValue )
77 const char* variableParameter = std::getenv(variable);
79 // if the parameter exists convert it to an integer, else return the default value
80 unsigned int intValue = variableParameter ? atoi(variableParameter) : defaultValue;
84 bool GetIntegerEnvironmentVariable( const char* variable, int& intValue )
86 const char* variableParameter = std::getenv(variable);
88 if( !variableParameter )
92 // if the parameter exists convert it to an integer, else return the default value
93 intValue = atoi(variableParameter);
97 bool GetFloatEnvironmentVariable( const char* variable, float& floatValue )
99 const char* variableParameter = std::getenv(variable);
101 if( !variableParameter )
105 // if the parameter exists convert it to an integer, else return the default value
106 floatValue = atof(variableParameter);
110 } // unnamed namespace
112 Dali::Adaptor* Adaptor::New( RenderSurface *surface, const DeviceLayout& baseLayout,
113 Dali::Configuration::ContextLoss configuration )
115 DALI_ASSERT_ALWAYS( surface->GetType() != Dali::RenderSurface::NO_SURFACE && "No surface for adaptor" );
117 Dali::Adaptor* adaptor = new Dali::Adaptor;
118 Adaptor* impl = new Adaptor( *adaptor, surface, baseLayout );
119 adaptor->mImpl = impl;
121 impl->Initialize(configuration);
126 void Adaptor::ParseEnvironmentOptions()
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 logPerformanceLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE, 0 );
132 unsigned int logPanGesture = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );
134 // all threads here (event, update, and render) will send their logs to SLP Platform's LogMessage handler.
135 Dali::Integration::Log::LogFunction logFunction(Dali::SlpPlatform::LogMessage);
137 mEnvironmentOptions.SetLogOptions( logFunction, logFrameRateFrequency, logupdateStatusFrequency, logPerformanceLevel, logPanGesture );
140 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
142 mEnvironmentOptions.SetPanGesturePredictionMode(predictionMode);
144 int predictionAmount = -1;
145 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_AMOUNT, predictionAmount) )
147 if( predictionAmount < 0 )
149 // do not support times in the past
150 predictionAmount = 0;
152 mEnvironmentOptions.SetPanGesturePredictionAmount(predictionAmount);
155 if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_MODE, smoothingMode) )
157 mEnvironmentOptions.SetPanGestureSmoothingMode(smoothingMode);
159 float smoothingAmount = 1.0f;
160 if( GetFloatEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_AMOUNT, smoothingAmount) )
162 smoothingAmount = Clamp(smoothingAmount, 0.0f, 1.0f);
163 mEnvironmentOptions.SetPanGestureSmoothingAmount(smoothingAmount);
166 int minimumDistance(-1);
167 if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_DISTANCE, minimumDistance ))
169 mEnvironmentOptions.SetMinimumPanDistance( minimumDistance );
172 int minimumEvents(-1);
173 if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_EVENTS, minimumEvents ))
175 mEnvironmentOptions.SetMinimumPanEvents( minimumEvents );
179 if ( GetIntegerEnvironmentVariable(DALI_GLES_CALL_TIME, glesCallTime ))
181 mEnvironmentOptions.SetGlesCallTime( glesCallTime );
184 mEnvironmentOptions.InstallLogFunction();
187 void Adaptor::Initialize(Dali::Configuration::ContextLoss configuration)
189 ParseEnvironmentOptions();
191 mPlatformAbstraction = new SlpPlatform::SlpPlatformAbstraction;
193 ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
194 if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
196 dataRetentionPolicy = ResourcePolicy::DALI_RETAINS_MESH_DATA;
198 // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
199 // files automatically.
201 if( mEnvironmentOptions.GetPerformanceLoggingLevel() > 0 )
203 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, mEnvironmentOptions );
206 mCallbackManager = CallbackManager::New();
208 PositionSize size = mSurface->GetPositionSize();
210 mGestureManager = new GestureManager(*this, Vector2(size.width, size.height), mCallbackManager, mEnvironmentOptions);
212 if( mEnvironmentOptions.GetGlesCallTime() > 0 )
214 mGLES = new GlProxyImplementation( mEnvironmentOptions );
218 mGLES = new GlImplementation();
221 mEglFactory = new EglFactory();
223 EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
225 mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
227 mObjectProfiler = new ObjectProfiler();
229 mNotificationTrigger = new TriggerEvent( boost::bind(&Adaptor::ProcessCoreEvents, this) );
231 mVSyncMonitor = new VSyncMonitor;
233 mUpdateRenderController = new UpdateRenderController( *this, mEnvironmentOptions );
235 mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
237 // Should be called after Core creation
238 if( mEnvironmentOptions.GetPanGestureLoggingLevel() )
240 Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
242 if( mEnvironmentOptions.GetPanGesturePredictionMode() >= 0 )
244 Integration::SetPanGesturePredictionMode(mEnvironmentOptions.GetPanGesturePredictionMode());
246 if( mEnvironmentOptions.GetPanGesturePredictionAmount() >= 0.0f )
248 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions.GetPanGesturePredictionAmount());
250 if( mEnvironmentOptions.GetPanGestureSmoothingMode() >= 0 )
252 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions.GetPanGestureSmoothingMode());
254 if( mEnvironmentOptions.GetPanGestureSmoothingAmount() >= 0.0f )
256 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions.GetPanGestureSmoothingAmount());
262 // Ensure stop status
265 // Release first as we do not want any access to Adaptor as it is being destroyed.
266 gThreadLocalAdaptor.release();
268 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
270 (*iter)->OnDestroy();
273 delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
274 delete mVSyncMonitor;
275 delete mEventHandler;
276 delete mObjectProfiler;
280 // Delete feedback controller before feedback plugin & style monitor dependencies
281 delete mFeedbackController;
282 delete mDaliFeedbackPlugin;
284 delete mGestureManager;
285 delete mPlatformAbstraction;
286 delete mCallbackManager;
287 delete mPerformanceInterface;
289 // uninstall it on this thread (main actor thread)
290 Dali::Integration::Log::UninstallLogFunction();
293 void Adaptor::Start()
295 // it doesn't support restart after stop at this moment
296 // to support restarting, need more testing
297 if( READY != mState )
302 // Start the callback manager
303 mCallbackManager->Start();
305 // create event handler
306 mEventHandler = new EventHandler( mSurface, *this, *mGestureManager, *this, mDragAndDropDetector );
308 if( mDeferredRotationObserver != NULL )
310 mEventHandler->SetRotationObserver(mDeferredRotationObserver);
311 mDeferredRotationObserver = NULL;
314 // guarantee map the surface before starting render-thread.
317 // NOTE: dpi must be set before starting the render thread
318 // use default or command line settings if not run on device
320 // set the DPI value for font rendering
321 unsigned int dpiHor, dpiVer;
323 mSurface->GetDpi(dpiHor, dpiVer);
325 // tell core about the value
326 mCore->SetDpi(dpiHor, dpiVer);
328 mCore->SetDpi(mHDpi, mVDpi);
331 // Tell the core the size of the surface just before we start the render-thread
332 PositionSize size = mSurface->GetPositionSize();
333 mCore->SurfaceResized( size.width, size.height );
335 // Start the update & render threads
336 mUpdateRenderController->Start();
340 ProcessCoreEvents(); // Ensure any startup messages are processed.
342 if ( !mFeedbackController )
344 // Start sound & haptic feedback
345 mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
348 for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
354 // Dali::Internal::Adaptor::Adaptor::Pause
355 void Adaptor::Pause()
357 // Only pause the adaptor if we're actually running.
358 if( RUNNING == mState )
360 // Inform observers that we are about to be paused.
361 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
366 // Reset the event handler when adaptor paused
369 mEventHandler->Reset();
372 mUpdateRenderController->Pause();
378 // Dali::Internal::Adaptor::Adaptor::Resume
379 void Adaptor::Resume()
381 // Only resume the adaptor if we are in the suspended state.
382 if( PAUSED == mState )
384 // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
385 // If there were events pending, mCore->Resume() will call
386 // RenderController->RequestUpdate()
387 // UpdateRenderController->RequestUpdate()
388 // UpdateRenderSynchronization->RequestUpdate()
389 // and we should have reset the frame timers before allowing Core->Update() to be called.
390 //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
392 mUpdateRenderController->ResumeFrameTime();
394 mUpdateRenderController->Resume();
398 // Reset the event handler when adaptor resumed
401 mEventHandler->Reset();
404 // Inform observers that we have resumed.
405 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
410 ProcessCoreEvents(); // Ensure any outstanding messages are processed
416 if( RUNNING == mState ||
418 PAUSED_WHILE_HIDDEN == mState )
420 for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
425 mUpdateRenderController->Stop();
428 // Delete the TTS player
429 for(int i =0; i < Dali::TtsPlayer::MODE_NUM; i++)
433 mTtsPlayers[i].Reset();
437 delete mEventHandler;
438 mEventHandler = NULL;
440 delete mNotificationTrigger;
441 mNotificationTrigger = NULL;
443 mCallbackManager->Stop();
449 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
451 mEventHandler->FeedTouchPoint( point, timeStamp );
454 void Adaptor::FeedWheelEvent( MouseWheelEvent& wheelEvent )
456 mEventHandler->FeedWheelEvent( wheelEvent );
459 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
461 mEventHandler->FeedKeyEvent( keyEvent );
464 bool Adaptor::MoveResize( const PositionSize& positionSize )
466 PositionSize old = mSurface->GetPositionSize();
468 // just resize the surface. The driver should automatically resize the egl Surface (untested)
469 // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
470 // is resized. Implementations typically use hooks into the OS and native window
471 // system to perform this resizing on demand, transparently to the client.
472 mSurface->MoveResize( positionSize );
474 if(old.width != positionSize.width || old.height != positionSize.height)
476 SurfaceSizeChanged(positionSize);
482 void Adaptor::SurfaceResized( const PositionSize& positionSize )
484 PositionSize old = mSurface->GetPositionSize();
486 // Called by an application, when it has resized a window outside of Dali.
487 // The EGL driver automatically detects X Window resize calls, and resizes
488 // the EGL surface for us.
489 mSurface->MoveResize( positionSize );
491 if(old.width != positionSize.width || old.height != positionSize.height)
493 SurfaceSizeChanged(positionSize);
497 void Adaptor::ReplaceSurface( Dali::RenderSurface& surface )
499 // adaptor implementation needs the implementation of
500 RenderSurface* internalSurface = dynamic_cast<Internal::Adaptor::RenderSurface*>( &surface );
501 DALI_ASSERT_ALWAYS( internalSurface && "Incorrect surface" );
503 ECore::WindowRenderSurface* windowSurface = dynamic_cast<Internal::Adaptor::ECore::WindowRenderSurface*>( &surface);
504 if( windowSurface != NULL )
506 windowSurface->Map();
507 // @todo Restart event handler with new surface
510 mSurface = internalSurface;
512 SurfaceSizeChanged( internalSurface->GetPositionSize() );
514 // flush the event queue to give update and render threads chance
515 // to start processing messages for new camera setup etc as soon as possible
518 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
520 // this method blocks until the render thread has completed the replace.
521 mUpdateRenderController->ReplaceSurface(internalSurface);
523 // Inform core, so that texture resources can be reloaded
524 mCore->RecoverFromContextLoss();
526 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
529 Dali::RenderSurface& Adaptor::GetSurface() const
534 void Adaptor::ReleaseSurfaceLock()
536 mSurface->ReleaseLock();
539 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
541 if(!mTtsPlayers[mode])
543 // Create the TTS player when it needed, because it can reduce launching time.
544 mTtsPlayers[mode] = TtsPlayer::New(mode);
547 return mTtsPlayers[mode];
550 bool Adaptor::AddIdle(boost::function<void(void)> callBack)
552 bool idleAdded(false);
554 // Only add an idle if the Adaptor is actually running
555 if( RUNNING == mState )
557 idleAdded = mCallbackManager->AddCallback(callBack, CallbackManager::IDLE_PRIORITY);
563 bool Adaptor::CallFromMainLoop(boost::function<void(void)> callBack)
565 bool callAdded(false);
567 // Only allow the callback if the Adaptor is actually running
568 if ( RUNNING == mState )
570 callAdded = mCallbackManager->AddCallback(callBack, CallbackManager::DEFAULT_PRIORITY);
576 Dali::Adaptor& Adaptor::Get()
578 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() != NULL && "Adaptor not instantiated" );
579 return gThreadLocalAdaptor->mAdaptor;
582 bool Adaptor::IsAvailable()
584 return gThreadLocalAdaptor.get() != NULL;
587 Dali::Integration::Core& Adaptor::GetCore()
592 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
594 mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
597 void Adaptor::SetUseHardwareVSync( bool useHardware )
599 mVSyncMonitor->SetUseHardwareVSync( useHardware );
602 void Adaptor::SetDpi(size_t hDpi, size_t vDpi)
608 EglFactory& Adaptor::GetEGLFactory() const
610 DALI_ASSERT_DEBUG( mEglFactory && "EGL Factory not created" );
614 EglFactoryInterface& Adaptor::GetEGLFactoryInterface() const
619 Integration::GlAbstraction& Adaptor::GetGlAbstraction() const
621 DALI_ASSERT_DEBUG( mGLES && "GLImplementation not created" );
625 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
627 return *mPlatformAbstraction;
630 Dali::Integration::GlAbstraction& Adaptor::GetGlesInterface()
635 TriggerEventInterface& Adaptor::GetTriggerEventInterface()
637 return *mNotificationTrigger;
639 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
641 return mTriggerEventFactory;
643 RenderSurface* Adaptor::GetRenderSurfaceInterface()
647 VSyncMonitorInterface* Adaptor::GetVSyncMonitorInterface()
649 return mVSyncMonitor;
652 KernelTraceInterface& Adaptor::GetKernelTraceInterface()
654 return mKernelTracer;
657 PerformanceInterface* Adaptor::GetPerformanceInterface()
659 return mPerformanceInterface;
662 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
664 DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
665 return *mPlatformAbstraction;
668 void Adaptor::SetDragAndDropDetector( DragAndDropDetectorPtr detector )
670 mDragAndDropDetector = detector;
674 mEventHandler->SetDragAndDropDetector( detector );
678 void Adaptor::SetRotationObserver( RotationObserver* observer )
682 mEventHandler->SetRotationObserver( observer );
684 else if( mState == READY )
686 // Set once event handler exists
687 mDeferredRotationObserver = observer;
691 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
693 if(mTtsPlayers[mode])
695 mTtsPlayers[mode].Reset();
699 void Adaptor::SetMinimumPinchDistance(float distance)
701 if( mGestureManager )
703 mGestureManager->SetMinimumPinchDistance(distance);
708 void Adaptor::AddObserver( LifeCycleObserver& observer )
710 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
712 if ( match == mObservers.end() )
714 mObservers.push_back( &observer );
718 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
720 ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
722 if ( match != mObservers.end() )
724 mObservers.erase( match );
728 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
732 mCore->QueueEvent(event);
736 void Adaptor::ProcessCoreEvents()
740 if( mPerformanceInterface )
742 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_START );
745 mCore->ProcessEvents();
747 if( mPerformanceInterface )
749 mPerformanceInterface->AddMarker( PerformanceMarker::PROCESS_EVENTS_END );
754 void Adaptor::RequestUpdate()
756 // When Dali applications are partially visible behind the lock-screen,
757 // the indicator must be updated (therefore allow updates in the PAUSED state)
758 if ( PAUSED == mState ||
761 mUpdateRenderController->RequestUpdate();
765 void Adaptor::RequestProcessEventsOnIdle()
767 // Only request a notification if the Adaptor is actually running
768 // and we haven't installed the idle notification
769 if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState ) )
771 mNotificationOnIdleInstalled = AddIdle( boost::bind( &Adaptor::ProcessCoreEventsFromIdle, this ) );
775 void Adaptor::OnWindowShown()
777 if ( PAUSED_WHILE_HIDDEN == mState )
779 // Adaptor can now be resumed
784 // Force a render task
789 void Adaptor::OnWindowHidden()
791 if ( STOPPED != mState )
795 // Adaptor cannot be resumed until the window is shown
796 mState = PAUSED_WHILE_HIDDEN;
800 // Dali::Internal::Adaptor::Adaptor::OnDamaged
801 void Adaptor::OnDamaged( const DamageArea& area )
803 // This is needed for the case where Dali window is partially obscured
807 void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
809 // let the core know the surface size has changed
810 mCore->SurfaceResized(positionSize.width, positionSize.height);
812 mResizedSignalV2.Emit( mAdaptor );
815 void Adaptor::NotifyLanguageChanged()
817 mLanguageChangedSignalV2.Emit( mAdaptor );
820 void Adaptor::RequestUpdateOnce()
822 if( PAUSED_WHILE_HIDDEN != mState )
824 if( mUpdateRenderController )
826 mUpdateRenderController->RequestUpdateOnce();
831 void Adaptor::ProcessCoreEventsFromIdle()
835 // the idle handle automatically un-installs itself
836 mNotificationOnIdleInstalled = false;
839 Adaptor::Adaptor(Dali::Adaptor& adaptor, RenderSurface* surface, const DeviceLayout& baseLayout)
840 : mResizedSignalV2(),
841 mLanguageChangedSignalV2(),
845 mUpdateRenderController(NULL),
850 mPlatformAbstraction( NULL ),
851 mEventHandler( NULL ),
852 mCallbackManager( NULL ),
853 mNotificationOnIdleInstalled( false ),
854 mNotificationTrigger(NULL),
855 mGestureManager(NULL),
858 mDaliFeedbackPlugin(NULL),
859 mFeedbackController(NULL),
861 mDragAndDropDetector(),
862 mDeferredRotationObserver(NULL),
863 mBaseLayout(baseLayout),
864 mEnvironmentOptions(),
865 mPerformanceInterface(NULL),
866 mObjectProfiler(NULL)
868 DALI_ASSERT_ALWAYS( gThreadLocalAdaptor.get() == NULL && "Cannot create more than one Adaptor per thread" );
869 gThreadLocalAdaptor.reset(this);
874 void Adaptor::SetViewMode( ViewMode viewMode )
876 mSurface->SetViewMode( viewMode );
877 mCore->SetViewMode( viewMode );
880 ViewMode Adaptor::GetViewMode() const
882 return mCore->GetViewMode();
885 void Adaptor::SetStereoBase( float stereoBase )
887 mCore->SetStereoBase( stereoBase );
890 float Adaptor::GetStereoBase() const
892 return mCore->GetStereoBase();
895 } // namespace Adaptor
897 } // namespace Internal