oculus1
diff libovr/Src/OVR_DeviceImpl.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/OVR_DeviceImpl.cpp Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,790 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_DeviceImpl.h 1.7 +Content : Partial back-end independent implementation of Device interfaces 1.8 +Created : October 10, 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_DeviceImpl.h" 1.20 +#include "Kernel/OVR_Atomic.h" 1.21 +#include "Kernel/OVR_Log.h" 1.22 +#include "Kernel/OVR_System.h" 1.23 + 1.24 +#include "OVR_DeviceImpl.h" 1.25 +#include "OVR_SensorImpl.h" 1.26 +#include "OVR_Profile.h" 1.27 + 1.28 +namespace OVR { 1.29 + 1.30 + 1.31 +//------------------------------------------------------------------------------------- 1.32 +// ***** SharedLock 1.33 + 1.34 +// This is a general purpose globally shared Lock implementation that should probably be 1.35 +// moved to Kernel. 1.36 +// May in theory busy spin-wait if we hit contention on first lock creation, 1.37 +// but this shouldn't matter in practice since Lock* should be cached. 1.38 + 1.39 + 1.40 +enum { LockInitMarker = 0xFFFFFFFF }; 1.41 + 1.42 +Lock* SharedLock::GetLockAddRef() 1.43 +{ 1.44 + int oldUseCount; 1.45 + 1.46 + do { 1.47 + oldUseCount = UseCount; 1.48 + if (oldUseCount == LockInitMarker) 1.49 + continue; 1.50 + 1.51 + if (oldUseCount == 0) 1.52 + { 1.53 + // Initialize marker 1.54 + if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 0, LockInitMarker)) 1.55 + { 1.56 + Construct<Lock>(Buffer); 1.57 + do { } 1.58 + while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 1)); 1.59 + return toLock(); 1.60 + } 1.61 + continue; 1.62 + } 1.63 + 1.64 + } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1)); 1.65 + 1.66 + return toLock(); 1.67 +} 1.68 + 1.69 +void SharedLock::ReleaseLock(Lock* plock) 1.70 +{ 1.71 + OVR_UNUSED(plock); 1.72 + OVR_ASSERT(plock == toLock()); 1.73 + 1.74 + int oldUseCount; 1.75 + 1.76 + do { 1.77 + oldUseCount = UseCount; 1.78 + OVR_ASSERT(oldUseCount != LockInitMarker); 1.79 + 1.80 + if (oldUseCount == 1) 1.81 + { 1.82 + // Initialize marker 1.83 + if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 1, LockInitMarker)) 1.84 + { 1.85 + Destruct<Lock>(toLock()); 1.86 + 1.87 + do { } 1.88 + while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 0)); 1.89 + 1.90 + return; 1.91 + } 1.92 + continue; 1.93 + } 1.94 + 1.95 + } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1)); 1.96 +} 1.97 + 1.98 + 1.99 + 1.100 +//------------------------------------------------------------------------------------- 1.101 +// ***** MessageHandler 1.102 + 1.103 +// Threading notes: 1.104 +// The OnMessage() handler and SetMessageHandler are currently synchronized 1.105 +// through a separately stored shared Lock object to avoid calling the handler 1.106 +// from background thread while it's being removed. 1.107 + 1.108 +static SharedLock MessageHandlerSharedLock; 1.109 + 1.110 + 1.111 +class MessageHandlerImpl 1.112 +{ 1.113 +public: 1.114 + MessageHandlerImpl() 1.115 + : pLock(MessageHandlerSharedLock.GetLockAddRef()) 1.116 + { 1.117 + } 1.118 + ~MessageHandlerImpl() 1.119 + { 1.120 + MessageHandlerSharedLock.ReleaseLock(pLock); 1.121 + pLock = 0; 1.122 + } 1.123 + 1.124 + static MessageHandlerImpl* FromHandler(MessageHandler* handler) 1.125 + { return (MessageHandlerImpl*)&handler->Internal; } 1.126 + static const MessageHandlerImpl* FromHandler(const MessageHandler* handler) 1.127 + { return (const MessageHandlerImpl*)&handler->Internal; } 1.128 + 1.129 + // This lock is held while calling a handler and when we are applied/ 1.130 + // removed from a device. 1.131 + Lock* pLock; 1.132 + // List of device we are applied to. 1.133 + List<MessageHandlerRef> UseList; 1.134 +}; 1.135 + 1.136 + 1.137 +MessageHandlerRef::MessageHandlerRef(DeviceBase* device) 1.138 + : pLock(MessageHandlerSharedLock.GetLockAddRef()), pDevice(device), pHandler(0) 1.139 +{ 1.140 +} 1.141 + 1.142 +MessageHandlerRef::~MessageHandlerRef() 1.143 +{ 1.144 + { 1.145 + Lock::Locker lockScope(pLock); 1.146 + if (pHandler) 1.147 + { 1.148 + pHandler = 0; 1.149 + RemoveNode(); 1.150 + } 1.151 + } 1.152 + MessageHandlerSharedLock.ReleaseLock(pLock); 1.153 + pLock = 0; 1.154 +} 1.155 + 1.156 +void MessageHandlerRef::SetHandler(MessageHandler* handler) 1.157 +{ 1.158 + OVR_ASSERT(!handler || 1.159 + MessageHandlerImpl::FromHandler(handler)->pLock == pLock); 1.160 + Lock::Locker lockScope(pLock); 1.161 + SetHandler_NTS(handler); 1.162 +} 1.163 + 1.164 +void MessageHandlerRef::SetHandler_NTS(MessageHandler* handler) 1.165 +{ 1.166 + if (pHandler != handler) 1.167 + { 1.168 + if (pHandler) 1.169 + RemoveNode(); 1.170 + pHandler = handler; 1.171 + 1.172 + if (handler) 1.173 + { 1.174 + MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(handler); 1.175 + handlerImpl->UseList.PushBack(this); 1.176 + } 1.177 + // TBD: Call notifier on device? 1.178 + } 1.179 +} 1.180 + 1.181 + 1.182 +MessageHandler::MessageHandler() 1.183 +{ 1.184 + OVR_COMPILER_ASSERT(sizeof(Internal) > sizeof(MessageHandlerImpl)); 1.185 + Construct<MessageHandlerImpl>(Internal); 1.186 +} 1.187 + 1.188 +MessageHandler::~MessageHandler() 1.189 +{ 1.190 + MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this); 1.191 + { 1.192 + Lock::Locker lockedScope(handlerImpl->pLock); 1.193 + OVR_ASSERT_LOG(handlerImpl->UseList.IsEmpty(), 1.194 + ("~MessageHandler %p - Handler still active; call RemoveHandlerFromDevices", this)); 1.195 + } 1.196 + 1.197 + Destruct<MessageHandlerImpl>(handlerImpl); 1.198 +} 1.199 + 1.200 +bool MessageHandler::IsHandlerInstalled() const 1.201 +{ 1.202 + const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this); 1.203 + Lock::Locker lockedScope(handlerImpl->pLock); 1.204 + return handlerImpl->UseList.IsEmpty() != true; 1.205 +} 1.206 + 1.207 + 1.208 +void MessageHandler::RemoveHandlerFromDevices() 1.209 +{ 1.210 + MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this); 1.211 + Lock::Locker lockedScope(handlerImpl->pLock); 1.212 + 1.213 + while(!handlerImpl->UseList.IsEmpty()) 1.214 + { 1.215 + MessageHandlerRef* use = handlerImpl->UseList.GetFirst(); 1.216 + use->SetHandler_NTS(0); 1.217 + } 1.218 +} 1.219 + 1.220 +Lock* MessageHandler::GetHandlerLock() const 1.221 +{ 1.222 + const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this); 1.223 + return handlerImpl->pLock; 1.224 +} 1.225 + 1.226 + 1.227 +//------------------------------------------------------------------------------------- 1.228 +// ***** DeviceBase 1.229 + 1.230 + 1.231 +// Delegate relevant implementation to DeviceRectord to avoid re-implementation in 1.232 +// every derived Device. 1.233 +void DeviceBase::AddRef() 1.234 +{ 1.235 + getDeviceCommon()->DeviceAddRef(); 1.236 +} 1.237 +void DeviceBase::Release() 1.238 +{ 1.239 + getDeviceCommon()->DeviceRelease(); 1.240 +} 1.241 +DeviceBase* DeviceBase::GetParent() const 1.242 +{ 1.243 + return getDeviceCommon()->pParent.GetPtr(); 1.244 +} 1.245 +DeviceManager* DeviceBase::GetManager() const 1.246 +{ 1.247 + return getDeviceCommon()->pCreateDesc->GetManagerImpl(); 1.248 +} 1.249 + 1.250 +void DeviceBase::SetMessageHandler(MessageHandler* handler) 1.251 +{ 1.252 + getDeviceCommon()->HandlerRef.SetHandler(handler); 1.253 +} 1.254 +MessageHandler* DeviceBase::GetMessageHandler() const 1.255 +{ 1.256 + return getDeviceCommon()->HandlerRef.GetHandler(); 1.257 +} 1.258 + 1.259 +DeviceType DeviceBase::GetType() const 1.260 +{ 1.261 + return getDeviceCommon()->pCreateDesc->Type; 1.262 +} 1.263 + 1.264 +bool DeviceBase::GetDeviceInfo(DeviceInfo* info) const 1.265 +{ 1.266 + return getDeviceCommon()->pCreateDesc->GetDeviceInfo(info); 1.267 + //info->Name[0] = 0; 1.268 + //return false; 1.269 +} 1.270 + 1.271 +// returns the MessageHandler's lock 1.272 +Lock* DeviceBase::GetHandlerLock() const 1.273 +{ 1.274 + return getDeviceCommon()->HandlerRef.GetLock(); 1.275 +} 1.276 + 1.277 +// Derive DeviceManagerCreateDesc to provide abstract function implementation. 1.278 +class DeviceManagerCreateDesc : public DeviceCreateDesc 1.279 +{ 1.280 +public: 1.281 + DeviceManagerCreateDesc(DeviceFactory* factory) 1.282 + : DeviceCreateDesc(factory, Device_Manager) { } 1.283 + 1.284 + // We don't need there on Manager since it isn't assigned to DeviceHandle. 1.285 + virtual DeviceCreateDesc* Clone() const { return 0; } 1.286 + virtual MatchResult MatchDevice(const DeviceCreateDesc&, 1.287 + DeviceCreateDesc**) const { return Match_None; } 1.288 + virtual DeviceBase* NewDeviceInstance() { return 0; } 1.289 + virtual bool GetDeviceInfo(DeviceInfo*) const { return false; } 1.290 +}; 1.291 + 1.292 +//------------------------------------------------------------------------------------- 1.293 +// ***** DeviceManagerImpl 1.294 + 1.295 +DeviceManagerImpl::DeviceManagerImpl() 1.296 + : DeviceImpl<OVR::DeviceManager>(CreateManagerDesc(), 0) 1.297 + //,DeviceCreateDescList(pCreateDesc ? pCreateDesc->pLock : 0) 1.298 +{ 1.299 + if (pCreateDesc) 1.300 + { 1.301 + pCreateDesc->pLock->pManager = this; 1.302 + } 1.303 +} 1.304 + 1.305 +DeviceManagerImpl::~DeviceManagerImpl() 1.306 +{ 1.307 + // Shutdown must've been called. 1.308 + OVR_ASSERT(!pCreateDesc->pDevice); 1.309 + 1.310 + // Remove all factories 1.311 + while(!Factories.IsEmpty()) 1.312 + { 1.313 + DeviceFactory* factory = Factories.GetFirst(); 1.314 + factory->RemovedFromManager(); 1.315 + factory->RemoveNode(); 1.316 + } 1.317 +} 1.318 + 1.319 +DeviceCreateDesc* DeviceManagerImpl::CreateManagerDesc() 1.320 +{ 1.321 + DeviceCreateDesc* managerDesc = new DeviceManagerCreateDesc(0); 1.322 + if (managerDesc) 1.323 + { 1.324 + managerDesc->pLock = *new DeviceManagerLock; 1.325 + } 1.326 + return managerDesc; 1.327 +} 1.328 + 1.329 +bool DeviceManagerImpl::Initialize(DeviceBase* parent) 1.330 +{ 1.331 + OVR_UNUSED(parent); 1.332 + if (!pCreateDesc || !pCreateDesc->pLock) 1.333 + return false; 1.334 + 1.335 + pProfileManager = *ProfileManager::Create(); 1.336 + 1.337 + return true; 1.338 +} 1.339 + 1.340 +void DeviceManagerImpl::Shutdown() 1.341 +{ 1.342 + // Remove all device descriptors from list while the lock is held. 1.343 + // Some descriptors may survive longer due to handles. 1.344 + while(!Devices.IsEmpty()) 1.345 + { 1.346 + DeviceCreateDesc* devDesc = Devices.GetFirst(); 1.347 + OVR_ASSERT(!devDesc->pDevice); // Manager shouldn't be dying while Device exists. 1.348 + devDesc->Enumerated = false; 1.349 + devDesc->RemoveNode(); 1.350 + devDesc->pNext = devDesc->pPrev = 0; 1.351 + 1.352 + if (devDesc->HandleCount == 0) 1.353 + { 1.354 + delete devDesc; 1.355 + } 1.356 + } 1.357 + Devices.Clear(); 1.358 + 1.359 + // These must've been cleared by caller. 1.360 + OVR_ASSERT(pCreateDesc->pDevice == 0); 1.361 + OVR_ASSERT(pCreateDesc->pLock->pManager == 0); 1.362 + 1.363 + pProfileManager.Clear(); 1.364 +} 1.365 + 1.366 + 1.367 +// Callbacks for DeviceCreation/Release 1.368 +DeviceBase* DeviceManagerImpl::CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent) 1.369 +{ 1.370 + // Calls to DeviceManagerImpl::CreateDevice are enqueued with wait while holding pManager, 1.371 + // so 'this' must remain valid. 1.372 + OVR_ASSERT(createDesc->pLock->pManager); 1.373 + 1.374 + Lock::Locker devicesLock(GetLock()); 1.375 + 1.376 + // If device already exists, just AddRef to it. 1.377 + if (createDesc->pDevice) 1.378 + { 1.379 + createDesc->pDevice->AddRef(); 1.380 + return createDesc->pDevice; 1.381 + } 1.382 + 1.383 + if (!parent) 1.384 + parent = this; 1.385 + 1.386 + DeviceBase* device = createDesc->NewDeviceInstance(); 1.387 + 1.388 + if (device) 1.389 + { 1.390 + if (device->getDeviceCommon()->Initialize(parent)) 1.391 + { 1.392 + createDesc->pDevice = device; 1.393 + } 1.394 + else 1.395 + { 1.396 + // Don't go through Release() to avoid PushCall behaviour, 1.397 + // as it is not needed here. 1.398 + delete device; 1.399 + device = 0; 1.400 + } 1.401 + } 1.402 + 1.403 + return device; 1.404 +} 1.405 + 1.406 +Void DeviceManagerImpl::ReleaseDevice_MgrThread(DeviceBase* device) 1.407 +{ 1.408 + // descKeepAlive will keep ManagerLock object alive as well, 1.409 + // allowing us to exit gracefully. 1.410 + Ptr<DeviceCreateDesc> descKeepAlive; 1.411 + Lock::Locker devicesLock(GetLock()); 1.412 + DeviceCommon* devCommon = device->getDeviceCommon(); 1.413 + 1.414 + while(1) 1.415 + { 1.416 + UInt32 refCount = devCommon->RefCount; 1.417 + 1.418 + if (refCount > 1) 1.419 + { 1.420 + if (devCommon->RefCount.CompareAndSet_NoSync(refCount, refCount-1)) 1.421 + { 1.422 + // We decreented from initial count higher then 1; 1.423 + // nothing else to do. 1.424 + return 0; 1.425 + } 1.426 + } 1.427 + else if (devCommon->RefCount.CompareAndSet_NoSync(1, 0)) 1.428 + { 1.429 + // { 1 -> 0 } decrement succeded. Destroy this device. 1.430 + break; 1.431 + } 1.432 + } 1.433 + 1.434 + // At this point, may be releasing the device manager itself. 1.435 + // This does not matter, however, since shutdown logic is the same 1.436 + // in both cases. DeviceManager::Shutdown with begin shutdown process for 1.437 + // the internal manager thread, which will eventually destroy itself. 1.438 + // TBD: Clean thread shutdown. 1.439 + descKeepAlive = devCommon->pCreateDesc; 1.440 + descKeepAlive->pDevice = 0; 1.441 + devCommon->Shutdown(); 1.442 + delete device; 1.443 + return 0; 1.444 +} 1.445 + 1.446 + 1.447 + 1.448 +Void DeviceManagerImpl::EnumerateAllFactoryDevices() 1.449 +{ 1.450 + // 1. Mark matching devices as NOT enumerated. 1.451 + // 2. Call factory to enumerate all HW devices, adding any device that 1.452 + // was not matched. 1.453 + // 3. Remove non-matching devices. 1.454 + 1.455 + Lock::Locker deviceLock(GetLock()); 1.456 + 1.457 + DeviceCreateDesc* devDesc, *nextdevDesc; 1.458 + 1.459 + // 1. 1.460 + for(devDesc = Devices.GetFirst(); 1.461 + !Devices.IsNull(devDesc); devDesc = devDesc->pNext) 1.462 + { 1.463 + //if (devDesc->pFactory == factory) 1.464 + devDesc->Enumerated = false; 1.465 + } 1.466 + 1.467 + // 2. 1.468 + DeviceFactory* factory = Factories.GetFirst(); 1.469 + while(!Factories.IsNull(factory)) 1.470 + { 1.471 + EnumerateFactoryDevices(factory); 1.472 + factory = factory->pNext; 1.473 + } 1.474 + 1.475 + 1.476 + // 3. 1.477 + for(devDesc = Devices.GetFirst(); 1.478 + !Devices.IsNull(devDesc); devDesc = nextdevDesc) 1.479 + { 1.480 + // In case 'devDesc' gets removed. 1.481 + nextdevDesc = devDesc->pNext; 1.482 + 1.483 + // Note, device might be not enumerated since it is opened and 1.484 + // in use! Do NOT notify 'device removed' in this case (!AB) 1.485 + if (!devDesc->Enumerated) 1.486 + { 1.487 + // This deletes the devDesc for HandleCount == 0 due to Release in DeviceHandle. 1.488 + CallOnDeviceRemoved(devDesc); 1.489 + 1.490 + /* 1.491 + if (devDesc->HandleCount == 0) 1.492 + { 1.493 + // Device must be dead if it ever existed, since it AddRefs to us. 1.494 + // ~DeviceCreateDesc removes its node from list. 1.495 + OVR_ASSERT(!devDesc->pDevice); 1.496 + delete devDesc; 1.497 + } 1.498 + */ 1.499 + } 1.500 + } 1.501 + 1.502 + return 0; 1.503 +} 1.504 + 1.505 +Ptr<DeviceCreateDesc> DeviceManagerImpl::AddDevice_NeedsLock( 1.506 + const DeviceCreateDesc& createDesc) 1.507 +{ 1.508 + // If found, mark as enumerated and we are done. 1.509 + DeviceCreateDesc* descCandidate = 0; 1.510 + 1.511 + for(DeviceCreateDesc* devDesc = Devices.GetFirst(); 1.512 + !Devices.IsNull(devDesc); devDesc = devDesc->pNext) 1.513 + { 1.514 + DeviceCreateDesc::MatchResult mr = devDesc->MatchDevice(createDesc, &descCandidate); 1.515 + if (mr == DeviceCreateDesc::Match_Found) 1.516 + { 1.517 + devDesc->Enumerated = true; 1.518 + if (!devDesc->pDevice) 1.519 + CallOnDeviceAdded(devDesc); 1.520 + return devDesc; 1.521 + } 1.522 + } 1.523 + 1.524 + // Update candidate (this may involve writing fields to HMDDevice createDesc). 1.525 + if (descCandidate) 1.526 + { 1.527 + bool newDevice = false; 1.528 + if (descCandidate->UpdateMatchedCandidate(createDesc, &newDevice)) 1.529 + { 1.530 + descCandidate->Enumerated = true; 1.531 + if (!descCandidate->pDevice || newDevice) 1.532 + CallOnDeviceAdded(descCandidate); 1.533 + return descCandidate; 1.534 + } 1.535 + } 1.536 + 1.537 + // If not found, add new device. 1.538 + // - This stores a new descriptor with 1.539 + // {pDevice = 0, HandleCount = 1, Enumerated = true} 1.540 + DeviceCreateDesc* desc = createDesc.Clone(); 1.541 + desc->pLock = pCreateDesc->pLock; 1.542 + Devices.PushBack(desc); 1.543 + desc->Enumerated = true; 1.544 + 1.545 + CallOnDeviceAdded(desc); 1.546 + 1.547 + return desc; 1.548 +} 1.549 + 1.550 +Ptr<DeviceCreateDesc> DeviceManagerImpl::FindDevice( 1.551 + const String& path, 1.552 + DeviceType deviceType) 1.553 +{ 1.554 + Lock::Locker deviceLock(GetLock()); 1.555 + DeviceCreateDesc* devDesc; 1.556 + 1.557 + for (devDesc = Devices.GetFirst(); 1.558 + !Devices.IsNull(devDesc); devDesc = devDesc->pNext) 1.559 + { 1.560 + if ((deviceType == Device_None || deviceType == devDesc->Type) && 1.561 + devDesc->MatchDevice(path)) 1.562 + return devDesc; 1.563 + } 1.564 + return NULL; 1.565 +} 1.566 + 1.567 +Ptr<DeviceCreateDesc> DeviceManagerImpl::FindHIDDevice(const HIDDeviceDesc& hidDevDesc) 1.568 +{ 1.569 + Lock::Locker deviceLock(GetLock()); 1.570 + DeviceCreateDesc* devDesc; 1.571 + 1.572 + for (devDesc = Devices.GetFirst(); 1.573 + !Devices.IsNull(devDesc); devDesc = devDesc->pNext) 1.574 + { 1.575 + if (devDesc->MatchHIDDevice(hidDevDesc)) 1.576 + return devDesc; 1.577 + } 1.578 + return NULL; 1.579 +} 1.580 + 1.581 +void DeviceManagerImpl::DetectHIDDevice(const HIDDeviceDesc& hidDevDesc) 1.582 +{ 1.583 + Lock::Locker deviceLock(GetLock()); 1.584 + DeviceFactory* factory = Factories.GetFirst(); 1.585 + while(!Factories.IsNull(factory)) 1.586 + { 1.587 + if (factory->DetectHIDDevice(this, hidDevDesc)) 1.588 + break; 1.589 + factory = factory->pNext; 1.590 + } 1.591 + 1.592 +} 1.593 + 1.594 +// Enumerates devices for a particular factory. 1.595 +Void DeviceManagerImpl::EnumerateFactoryDevices(DeviceFactory* factory) 1.596 +{ 1.597 + 1.598 + class FactoryEnumerateVisitor : public DeviceFactory::EnumerateVisitor 1.599 + { 1.600 + DeviceManagerImpl* pManager; 1.601 + DeviceFactory* pFactory; 1.602 + public: 1.603 + FactoryEnumerateVisitor(DeviceManagerImpl* manager, DeviceFactory* factory) 1.604 + : pManager(manager), pFactory(factory) { } 1.605 + 1.606 + virtual void Visit(const DeviceCreateDesc& createDesc) 1.607 + { 1.608 + pManager->AddDevice_NeedsLock(createDesc); 1.609 + } 1.610 + }; 1.611 + 1.612 + FactoryEnumerateVisitor newDeviceVisitor(this, factory); 1.613 + factory->EnumerateDevices(newDeviceVisitor); 1.614 + 1.615 + 1.616 + return 0; 1.617 +} 1.618 + 1.619 + 1.620 +DeviceEnumerator<> DeviceManagerImpl::EnumerateDevicesEx(const DeviceEnumerationArgs& args) 1.621 +{ 1.622 + Lock::Locker deviceLock(GetLock()); 1.623 + 1.624 + if (Devices.IsEmpty()) 1.625 + return DeviceEnumerator<>(); 1.626 + 1.627 + DeviceCreateDesc* firstDeviceDesc = Devices.GetFirst(); 1.628 + DeviceEnumerator<> e = enumeratorFromHandle(DeviceHandle(firstDeviceDesc), args); 1.629 + 1.630 + if (!args.MatchRule(firstDeviceDesc->Type, firstDeviceDesc->Enumerated)) 1.631 + { 1.632 + e.Next(); 1.633 + } 1.634 + 1.635 + return e; 1.636 +} 1.637 + 1.638 +//------------------------------------------------------------------------------------- 1.639 +// ***** DeviceCommon 1.640 + 1.641 +void DeviceCommon::DeviceAddRef() 1.642 +{ 1.643 + RefCount++; 1.644 +} 1.645 + 1.646 +void DeviceCommon::DeviceRelease() 1.647 +{ 1.648 + while(1) 1.649 + { 1.650 + UInt32 refCount = RefCount; 1.651 + OVR_ASSERT(refCount > 0); 1.652 + 1.653 + if (refCount == 1) 1.654 + { 1.655 + DeviceManagerImpl* manager = pCreateDesc->GetManagerImpl(); 1.656 + ThreadCommandQueue* queue = manager->GetThreadQueue(); 1.657 + 1.658 + // Enqueue ReleaseDevice for {1 -> 0} transition with no wait. 1.659 + // We pass our reference ownership into the queue to destroy. 1.660 + // It's in theory possible for another thread to re-steal our device reference, 1.661 + // but that is checked for atomically in DeviceManagerImpl::ReleaseDevice. 1.662 + if (!queue->PushCall(manager, &DeviceManagerImpl::ReleaseDevice_MgrThread, 1.663 + pCreateDesc->pDevice)) 1.664 + { 1.665 + // PushCall shouldn't fail because background thread runs while manager is 1.666 + // alive and we are holding Manager alive through pParent chain. 1.667 + OVR_ASSERT(false); 1.668 + } 1.669 + 1.670 + // Warning! At his point everything, including manager, may be dead. 1.671 + break; 1.672 + } 1.673 + else if (RefCount.CompareAndSet_NoSync(refCount, refCount-1)) 1.674 + { 1.675 + break; 1.676 + } 1.677 + } 1.678 +} 1.679 + 1.680 + 1.681 + 1.682 +//------------------------------------------------------------------------------------- 1.683 +// ***** DeviceCreateDesc 1.684 + 1.685 + 1.686 +void DeviceCreateDesc::AddRef() 1.687 +{ 1.688 + // Technically, HandleCount { 0 -> 1 } transition can only happen during Lock, 1.689 + // but we leave this to caller to worry about (happens during enumeration). 1.690 + HandleCount++; 1.691 +} 1.692 + 1.693 +void DeviceCreateDesc::Release() 1.694 +{ 1.695 + while(1) 1.696 + { 1.697 + UInt32 handleCount = HandleCount; 1.698 + // HandleCount must obviously be >= 1, since we are releasing it. 1.699 + OVR_ASSERT(handleCount > 0); 1.700 + 1.701 + // {1 -> 0} transition may cause us to be destroyed, so require a lock. 1.702 + if (handleCount == 1) 1.703 + { 1.704 + Ptr<DeviceManagerLock> lockKeepAlive; 1.705 + Lock::Locker deviceLockScope(GetLock()); 1.706 + 1.707 + if (!HandleCount.CompareAndSet_NoSync(handleCount, 0)) 1.708 + continue; 1.709 + 1.710 + OVR_ASSERT(pDevice == 0); 1.711 + 1.712 + // Destroy *this if the manager was destroyed already, or Enumerated 1.713 + // is false (device no longer available). 1.714 + if (!GetManagerImpl() || !Enumerated) 1.715 + { 1.716 + lockKeepAlive = pLock; 1.717 + 1.718 + // Remove from manager list (only matters for !Enumerated). 1.719 + if (pNext) 1.720 + { 1.721 + RemoveNode(); 1.722 + pNext = pPrev = 0; 1.723 + } 1.724 + 1.725 + delete this; 1.726 + } 1.727 + 1.728 + // Available DeviceCreateDesc may survive with { HandleCount == 0 }, 1.729 + // in case it might be enumerated again later. 1.730 + break; 1.731 + } 1.732 + else if (HandleCount.CompareAndSet_NoSync(handleCount, handleCount-1)) 1.733 + { 1.734 + break; 1.735 + } 1.736 + } 1.737 +} 1.738 + 1.739 +HMDDevice* HMDDevice::Disconnect(SensorDevice* psensor) 1.740 +{ 1.741 + if (!psensor) 1.742 + return NULL; 1.743 + 1.744 + OVR::DeviceManager* manager = GetManager(); 1.745 + if (manager) 1.746 + { 1.747 + //DeviceManagerImpl* mgrImpl = static_cast<DeviceManagerImpl*>(manager); 1.748 + Ptr<DeviceCreateDesc> desc = getDeviceCommon()->pCreateDesc; 1.749 + if (desc) 1.750 + { 1.751 + class Visitor : public DeviceFactory::EnumerateVisitor 1.752 + { 1.753 + Ptr<DeviceCreateDesc> Desc; 1.754 + public: 1.755 + Visitor(DeviceCreateDesc* desc) : Desc(desc) {} 1.756 + virtual void Visit(const DeviceCreateDesc& createDesc) 1.757 + { 1.758 + Lock::Locker lock(Desc->GetLock()); 1.759 + Desc->UpdateMatchedCandidate(createDesc); 1.760 + } 1.761 + } visitor(desc); 1.762 + //SensorDeviceImpl* sImpl = static_cast<SensorDeviceImpl*>(psensor); 1.763 + 1.764 + SensorDisplayInfoImpl displayInfo; 1.765 + 1.766 + if (psensor->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize)) 1.767 + { 1.768 + displayInfo.Unpack(); 1.769 + 1.770 + // If we got display info, try to match / create HMDDevice as well 1.771 + // so that sensor settings give preference. 1.772 + if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) 1.773 + { 1.774 + SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, visitor); 1.775 + } 1.776 + } 1.777 + } 1.778 + } 1.779 + return this; 1.780 +} 1.781 + 1.782 +bool HMDDevice::IsDisconnected() const 1.783 +{ 1.784 + OVR::HMDInfo info; 1.785 + GetDeviceInfo(&info); 1.786 + // if strlen(info.DisplayDeviceName) == 0 then 1.787 + // this HMD is 'fake' (created using sensor). 1.788 + return (strlen(info.DisplayDeviceName) == 0); 1.789 +} 1.790 + 1.791 + 1.792 +} // namespace OVR 1.793 +