oculus1
diff libovr/Src/win32/OVR_Win32_DeviceManager.cpp @ 1:e2f9e4603129
added LibOVR and started a simple vr wrapper.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Sep 2013 16:14:59 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libovr/Src/win32/OVR_Win32_DeviceManager.cpp Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,423 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_Win32_DeviceManager.cpp 1.7 +Content : Win32 implementation of DeviceManager. 1.8 +Created : September 21, 2012 1.9 +Authors : Michael Antonov 1.10 + 1.11 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 1.12 + 1.13 +Use of this software is subject to the terms of the Oculus license 1.14 +agreement provided at the time of installation or download, or which 1.15 +otherwise accompanies this software in either electronic or hard copy form. 1.16 + 1.17 +*************************************************************************************/ 1.18 + 1.19 +#include "OVR_Win32_DeviceManager.h" 1.20 + 1.21 +// Sensor & HMD Factories 1.22 +#include "OVR_SensorImpl.h" 1.23 +#include "OVR_LatencyTestImpl.h" 1.24 +#include "OVR_Win32_HMDDevice.h" 1.25 +#include "OVR_Win32_DeviceStatus.h" 1.26 +#include "OVR_Win32_HIDDevice.h" 1.27 + 1.28 +#include "Kernel/OVR_Timer.h" 1.29 +#include "Kernel/OVR_Std.h" 1.30 +#include "Kernel/OVR_Log.h" 1.31 + 1.32 +DWORD Debug_WaitedObjectCount = 0; 1.33 + 1.34 +namespace OVR { namespace Win32 { 1.35 + 1.36 + 1.37 +//------------------------------------------------------------------------------------- 1.38 +// **** Win32::DeviceManager 1.39 + 1.40 +DeviceManager::DeviceManager() 1.41 +{ 1.42 + HidDeviceManager = *HIDDeviceManager::CreateInternal(this); 1.43 +} 1.44 + 1.45 +DeviceManager::~DeviceManager() 1.46 +{ 1.47 + // make sure Shutdown was called. 1.48 + OVR_ASSERT(!pThread); 1.49 +} 1.50 + 1.51 +bool DeviceManager::Initialize(DeviceBase*) 1.52 +{ 1.53 + if (!DeviceManagerImpl::Initialize(0)) 1.54 + return false; 1.55 + 1.56 + pThread = *new DeviceManagerThread(this); 1.57 + if (!pThread || !pThread->Start()) 1.58 + return false; 1.59 + 1.60 + pCreateDesc->pDevice = this; 1.61 + LogText("OVR::DeviceManager - initialized.\n"); 1.62 + return true; 1.63 +} 1.64 + 1.65 +void DeviceManager::Shutdown() 1.66 +{ 1.67 + LogText("OVR::DeviceManager - shutting down.\n"); 1.68 + 1.69 + // Set Manager shutdown marker variable; this prevents 1.70 + // any existing DeviceHandle objects from accessing device. 1.71 + pCreateDesc->pLock->pManager = 0; 1.72 + 1.73 + // Push for thread shutdown *WITH NO WAIT*. 1.74 + // This will have the following effect: 1.75 + // - Exit command will get enqueued, which will be executed later on the thread itself. 1.76 + // - Beyond this point, this DeviceManager object may be deleted by our caller. 1.77 + // - Other commands, such as CreateDevice, may execute before ExitCommand, but they will 1.78 + // fail gracefully due to pLock->pManager == 0. Future commands can't be enqued 1.79 + // after pManager is null. 1.80 + // - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last 1.81 + // reference to the thread object. 1.82 + pThread->PushExitCommand(false); 1.83 + pThread->DetachDeviceManager(); 1.84 + pThread.Clear(); 1.85 + 1.86 + DeviceManagerImpl::Shutdown(); 1.87 +} 1.88 + 1.89 +ThreadCommandQueue* DeviceManager::GetThreadQueue() 1.90 +{ 1.91 + return pThread; 1.92 +} 1.93 + 1.94 +bool DeviceManager::GetDeviceInfo(DeviceInfo* info) const 1.95 +{ 1.96 + if ((info->InfoClassType != Device_Manager) && 1.97 + (info->InfoClassType != Device_None)) 1.98 + return false; 1.99 + 1.100 + info->Type = Device_Manager; 1.101 + info->Version = 0; 1.102 + OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, "DeviceManager"); 1.103 + OVR_strcpy(info->Manufacturer,DeviceInfo::MaxNameLength, "Oculus VR, Inc."); 1.104 + return true; 1.105 +} 1.106 + 1.107 +DeviceEnumerator<> DeviceManager::EnumerateDevicesEx(const DeviceEnumerationArgs& args) 1.108 +{ 1.109 + // TBD: Can this be avoided in the future, once proper device notification is in place? 1.110 + if (GetThreadId() != OVR::GetCurrentThreadId()) 1.111 + { 1.112 + pThread->PushCall((DeviceManagerImpl*)this, 1.113 + &DeviceManager::EnumerateAllFactoryDevices, true); 1.114 + } 1.115 + else 1.116 + DeviceManager::EnumerateAllFactoryDevices(); 1.117 + 1.118 + return DeviceManagerImpl::EnumerateDevicesEx(args); 1.119 +} 1.120 + 1.121 +ThreadId DeviceManager::GetThreadId() const 1.122 +{ 1.123 + return pThread->GetThreadId(); 1.124 +} 1.125 + 1.126 +bool DeviceManager::GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const 1.127 +{ 1.128 + if (GetHIDDeviceManager()) 1.129 + return static_cast<HIDDeviceManager*>(GetHIDDeviceManager())->GetHIDDeviceDesc(path, pdevDesc); 1.130 + return false; 1.131 +} 1.132 + 1.133 + 1.134 +//------------------------------------------------------------------------------------- 1.135 +// ***** DeviceManager Thread 1.136 + 1.137 +DeviceManagerThread::DeviceManagerThread(DeviceManager* pdevMgr) 1.138 + : Thread(ThreadStackSize), hCommandEvent(0), pDeviceMgr(pdevMgr) 1.139 +{ 1.140 + // Create a non-signaled manual-reset event. 1.141 + hCommandEvent = ::CreateEvent(0, TRUE, FALSE, 0); 1.142 + if (!hCommandEvent) 1.143 + return; 1.144 + 1.145 + // Must add event before starting. 1.146 + AddOverlappedEvent(0, hCommandEvent); 1.147 + 1.148 + // Create device messages object. 1.149 + pStatusObject = *new DeviceStatus(this); 1.150 +} 1.151 + 1.152 +DeviceManagerThread::~DeviceManagerThread() 1.153 +{ 1.154 + // Remove overlapped event [0], after thread service exit. 1.155 + if (hCommandEvent) 1.156 + { 1.157 + RemoveOverlappedEvent(0, hCommandEvent); 1.158 + ::CloseHandle(hCommandEvent); 1.159 + hCommandEvent = 0; 1.160 + } 1.161 +} 1.162 + 1.163 +int DeviceManagerThread::Run() 1.164 +{ 1.165 + ThreadCommand::PopBuffer command; 1.166 + 1.167 + SetThreadName("OVR::DeviceManagerThread"); 1.168 + LogText("OVR::DeviceManagerThread - running (ThreadId=0x%X).\n", GetThreadId()); 1.169 + 1.170 + if (!pStatusObject->Initialize()) 1.171 + { 1.172 + LogText("OVR::DeviceManagerThread - failed to initialize MessageObject.\n"); 1.173 + } 1.174 + 1.175 + while(!IsExiting()) 1.176 + { 1.177 + // PopCommand will reset event on empty queue. 1.178 + if (PopCommand(&command)) 1.179 + { 1.180 + command.Execute(); 1.181 + } 1.182 + else 1.183 + { 1.184 + DWORD eventIndex = 0; 1.185 + do { 1.186 + UPInt numberOfWaitHandles = WaitHandles.GetSize(); 1.187 + Debug_WaitedObjectCount = (DWORD)numberOfWaitHandles; 1.188 + 1.189 + DWORD waitMs = INFINITE; 1.190 + 1.191 + // If devices have time-dependent logic registered, get the longest wait 1.192 + // allowed based on current ticks. 1.193 + if (!TicksNotifiers.IsEmpty()) 1.194 + { 1.195 + UInt64 ticksMks = Timer::GetTicks(); 1.196 + DWORD waitAllowed; 1.197 + 1.198 + for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++) 1.199 + { 1.200 + waitAllowed = (DWORD)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs); 1.201 + if (waitAllowed < waitMs) 1.202 + waitMs = waitAllowed; 1.203 + } 1.204 + } 1.205 + 1.206 + // Wait for event signals or window messages. 1.207 + eventIndex = MsgWaitForMultipleObjects((DWORD)numberOfWaitHandles, &WaitHandles[0], FALSE, waitMs, QS_ALLINPUT); 1.208 + 1.209 + if (eventIndex != WAIT_FAILED) 1.210 + { 1.211 + if (eventIndex == WAIT_TIMEOUT) 1.212 + continue; 1.213 + 1.214 + // TBD: Does this ever apply? 1.215 + OVR_ASSERT(eventIndex < WAIT_ABANDONED_0); 1.216 + 1.217 + if (eventIndex == WAIT_OBJECT_0) 1.218 + { 1.219 + // Handle [0] services commands. 1.220 + break; 1.221 + } 1.222 + else if (eventIndex == WAIT_OBJECT_0 + numberOfWaitHandles) 1.223 + { 1.224 + // Handle Windows messages. 1.225 + pStatusObject->ProcessMessages(); 1.226 + } 1.227 + else 1.228 + { 1.229 + // Notify waiting device that its event is signaled. 1.230 + unsigned i = eventIndex - WAIT_OBJECT_0; 1.231 + OVR_ASSERT(i < numberOfWaitHandles); 1.232 + if (WaitNotifiers[i]) 1.233 + WaitNotifiers[i]->OnOverlappedEvent(WaitHandles[i]); 1.234 + } 1.235 + } 1.236 + 1.237 + } while(eventIndex != WAIT_FAILED); 1.238 + 1.239 + } 1.240 + } 1.241 + 1.242 + pStatusObject->ShutDown(); 1.243 + 1.244 + LogText("OVR::DeviceManagerThread - exiting (ThreadId=0x%X).\n", GetThreadId()); 1.245 + return 0; 1.246 +} 1.247 + 1.248 +bool DeviceManagerThread::AddOverlappedEvent(Notifier* notify, HANDLE hevent) 1.249 +{ 1.250 + WaitNotifiers.PushBack(notify); 1.251 + WaitHandles.PushBack(hevent); 1.252 + 1.253 + OVR_ASSERT(WaitNotifiers.GetSize() <= MAXIMUM_WAIT_OBJECTS); 1.254 + return true; 1.255 +} 1.256 + 1.257 +bool DeviceManagerThread::RemoveOverlappedEvent(Notifier* notify, HANDLE hevent) 1.258 +{ 1.259 + // [0] is reserved for thread commands with notify of null, but we still 1.260 + // can use this function to remove it. 1.261 + for (UPInt i = 0; i < WaitNotifiers.GetSize(); i++) 1.262 + { 1.263 + if ((WaitNotifiers[i] == notify) && (WaitHandles[i] == hevent)) 1.264 + { 1.265 + WaitNotifiers.RemoveAt(i); 1.266 + WaitHandles.RemoveAt(i); 1.267 + return true; 1.268 + } 1.269 + } 1.270 + return false; 1.271 +} 1.272 + 1.273 +bool DeviceManagerThread::AddTicksNotifier(Notifier* notify) 1.274 +{ 1.275 + TicksNotifiers.PushBack(notify); 1.276 + return true; 1.277 +} 1.278 + 1.279 +bool DeviceManagerThread::RemoveTicksNotifier(Notifier* notify) 1.280 +{ 1.281 + for (UPInt i = 0; i < TicksNotifiers.GetSize(); i++) 1.282 + { 1.283 + if (TicksNotifiers[i] == notify) 1.284 + { 1.285 + TicksNotifiers.RemoveAt(i); 1.286 + return true; 1.287 + } 1.288 + } 1.289 + return false; 1.290 +} 1.291 + 1.292 +bool DeviceManagerThread::AddMessageNotifier(Notifier* notify) 1.293 +{ 1.294 + MessageNotifiers.PushBack(notify); 1.295 + return true; 1.296 +} 1.297 + 1.298 +bool DeviceManagerThread::RemoveMessageNotifier(Notifier* notify) 1.299 +{ 1.300 + for (UPInt i = 0; i < MessageNotifiers.GetSize(); i++) 1.301 + { 1.302 + if (MessageNotifiers[i] == notify) 1.303 + { 1.304 + MessageNotifiers.RemoveAt(i); 1.305 + return true; 1.306 + } 1.307 + } 1.308 + return false; 1.309 +} 1.310 + 1.311 +bool DeviceManagerThread::OnMessage(MessageType type, const String& devicePath) 1.312 +{ 1.313 + Notifier::DeviceMessageType notifierMessageType = Notifier::DeviceMessage_DeviceAdded; 1.314 + if (type == DeviceAdded) 1.315 + { 1.316 + } 1.317 + else if (type == DeviceRemoved) 1.318 + { 1.319 + notifierMessageType = Notifier::DeviceMessage_DeviceRemoved; 1.320 + } 1.321 + else 1.322 + { 1.323 + OVR_ASSERT(false); 1.324 + } 1.325 + 1.326 + bool error = false; 1.327 + bool deviceFound = false; 1.328 + for (UPInt i = 0; i < MessageNotifiers.GetSize(); i++) 1.329 + { 1.330 + if (MessageNotifiers[i] && 1.331 + MessageNotifiers[i]->OnDeviceMessage(notifierMessageType, devicePath, &error)) 1.332 + { 1.333 + // The notifier belonged to a device with the specified device name so we're done. 1.334 + deviceFound = true; 1.335 + break; 1.336 + } 1.337 + } 1.338 + if (type == DeviceAdded && !deviceFound) 1.339 + { 1.340 + Lock::Locker devMgrLock(&DevMgrLock); 1.341 + // a new device was connected. Go through all device factories and 1.342 + // try to detect the device using HIDDeviceDesc. 1.343 + HIDDeviceDesc devDesc; 1.344 + if (pDeviceMgr->GetHIDDeviceDesc(devicePath, &devDesc)) 1.345 + { 1.346 + Lock::Locker deviceLock(pDeviceMgr->GetLock()); 1.347 + DeviceFactory* factory = pDeviceMgr->Factories.GetFirst(); 1.348 + while(!pDeviceMgr->Factories.IsNull(factory)) 1.349 + { 1.350 + if (factory->DetectHIDDevice(pDeviceMgr, devDesc)) 1.351 + { 1.352 + deviceFound = true; 1.353 + break; 1.354 + } 1.355 + factory = factory->pNext; 1.356 + } 1.357 + } 1.358 + } 1.359 + 1.360 + if (!deviceFound && strstr(devicePath.ToCStr(), "#OVR00")) 1.361 + { 1.362 + Ptr<DeviceManager> pmgr; 1.363 + { 1.364 + Lock::Locker devMgrLock(&DevMgrLock); 1.365 + pmgr = pDeviceMgr; 1.366 + } 1.367 + // HMD plugged/unplugged 1.368 + // This is not a final solution to enumerate HMD devices and get 1.369 + // a first available handle. This won't work with multiple rifts. 1.370 + // @TODO (!AB) 1.371 + pmgr->EnumerateDevices<HMDDevice>(); 1.372 + } 1.373 + 1.374 + return !error; 1.375 +} 1.376 + 1.377 +void DeviceManagerThread::DetachDeviceManager() 1.378 +{ 1.379 + Lock::Locker devMgrLock(&DevMgrLock); 1.380 + pDeviceMgr = NULL; 1.381 +} 1.382 + 1.383 +} // namespace Win32 1.384 + 1.385 + 1.386 +//------------------------------------------------------------------------------------- 1.387 +// ***** Creation 1.388 + 1.389 + 1.390 +// Creates a new DeviceManager and initializes OVR. 1.391 +DeviceManager* DeviceManager::Create() 1.392 +{ 1.393 + 1.394 + if (!System::IsInitialized()) 1.395 + { 1.396 + // Use custom message, since Log is not yet installed. 1.397 + OVR_DEBUG_STATEMENT(Log::GetDefaultLog()-> 1.398 + LogMessage(Log_Debug, "DeviceManager::Create failed - OVR::System not initialized"); ); 1.399 + return 0; 1.400 + } 1.401 + 1.402 + Ptr<Win32::DeviceManager> manager = *new Win32::DeviceManager; 1.403 + 1.404 + if (manager) 1.405 + { 1.406 + if (manager->Initialize(0)) 1.407 + { 1.408 + manager->AddFactory(&SensorDeviceFactory::Instance); 1.409 + manager->AddFactory(&LatencyTestDeviceFactory::Instance); 1.410 + manager->AddFactory(&Win32::HMDDeviceFactory::Instance); 1.411 + 1.412 + manager->AddRef(); 1.413 + } 1.414 + else 1.415 + { 1.416 + manager.Clear(); 1.417 + } 1.418 + 1.419 + } 1.420 + 1.421 + return manager.GetPtr(); 1.422 +} 1.423 + 1.424 + 1.425 +} // namespace OVR 1.426 +