nuclear@1: /************************************************************************************ nuclear@1: nuclear@1: Filename : OVR_DeviceHandle.cpp nuclear@1: Content : Implementation of device handle class nuclear@1: Created : February 5, 2013 nuclear@1: Authors : Lee Cooper nuclear@1: nuclear@1: Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. nuclear@1: nuclear@1: Use of this software is subject to the terms of the Oculus license nuclear@1: agreement provided at the time of installation or download, or which nuclear@1: otherwise accompanies this software in either electronic or hard copy form. nuclear@1: nuclear@1: *************************************************************************************/ nuclear@1: nuclear@1: #include "OVR_DeviceHandle.h" nuclear@1: nuclear@1: #include "OVR_DeviceImpl.h" nuclear@1: nuclear@1: namespace OVR { nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** DeviceHandle nuclear@1: nuclear@1: DeviceHandle::DeviceHandle(DeviceCreateDesc* impl) : pImpl(impl) nuclear@1: { nuclear@1: if (pImpl) nuclear@1: pImpl->AddRef(); nuclear@1: } nuclear@1: nuclear@1: DeviceHandle::DeviceHandle(const DeviceHandle& src) : pImpl(src.pImpl) nuclear@1: { nuclear@1: if (pImpl) nuclear@1: pImpl->AddRef(); nuclear@1: } nuclear@1: nuclear@1: DeviceHandle::~DeviceHandle() nuclear@1: { nuclear@1: if (pImpl) nuclear@1: pImpl->Release(); nuclear@1: } nuclear@1: nuclear@1: void DeviceHandle::operator = (const DeviceHandle& src) nuclear@1: { nuclear@1: if (src.pImpl) nuclear@1: src.pImpl->AddRef(); nuclear@1: if (pImpl) nuclear@1: pImpl->Release(); nuclear@1: pImpl = src.pImpl; nuclear@1: } nuclear@1: nuclear@1: DeviceBase* DeviceHandle::GetDevice_AddRef() const nuclear@1: { nuclear@1: if (pImpl && pImpl->pDevice) nuclear@1: { nuclear@1: pImpl->pDevice->AddRef(); nuclear@1: return pImpl->pDevice; nuclear@1: } nuclear@1: return NULL; nuclear@1: } nuclear@1: nuclear@1: // Returns true, if the handle contains the same device ptr nuclear@1: // as specified in the parameter. nuclear@1: bool DeviceHandle::IsDevice(DeviceBase* pdev) const nuclear@1: { nuclear@1: return (pdev && pImpl && pImpl->pDevice) ? nuclear@1: pImpl->pDevice == pdev : false; nuclear@1: } nuclear@1: nuclear@1: DeviceType DeviceHandle::GetType() const nuclear@1: { nuclear@1: return pImpl ? pImpl->Type : Device_None; nuclear@1: } nuclear@1: nuclear@1: bool DeviceHandle::GetDeviceInfo(DeviceInfo* info) const nuclear@1: { nuclear@1: return pImpl ? pImpl->GetDeviceInfo(info) : false; nuclear@1: } nuclear@1: bool DeviceHandle::IsAvailable() const nuclear@1: { nuclear@1: // This isn't "atomically safe", but the function only returns the nuclear@1: // recent state that may change. nuclear@1: return pImpl ? (pImpl->Enumerated && pImpl->pLock->pManager) : false; nuclear@1: } nuclear@1: nuclear@1: bool DeviceHandle::IsCreated() const nuclear@1: { nuclear@1: return pImpl ? (pImpl->pDevice != 0) : false; nuclear@1: } nuclear@1: nuclear@1: DeviceBase* DeviceHandle::CreateDevice() nuclear@1: { nuclear@1: if (!pImpl) nuclear@1: return 0; nuclear@1: nuclear@1: DeviceBase* device = 0; nuclear@1: Ptr manager= 0; nuclear@1: nuclear@1: // Since both manager and device pointers can only be destroyed during a lock, nuclear@1: // hold it while checking for availability. nuclear@1: // AddRef to manager so that it doesn't get released on us. nuclear@1: { nuclear@1: Lock::Locker deviceLockScope(pImpl->GetLock()); nuclear@1: nuclear@1: if (pImpl->pDevice) nuclear@1: { nuclear@1: pImpl->pDevice->AddRef(); nuclear@1: return pImpl->pDevice; nuclear@1: } nuclear@1: manager = pImpl->GetManagerImpl(); nuclear@1: } nuclear@1: nuclear@1: if (manager) nuclear@1: { nuclear@1: if (manager->GetThreadId() != OVR::GetCurrentThreadId()) nuclear@1: { nuclear@1: // Queue up a CreateDevice request. This fills in '&device' with AddRefed value, nuclear@1: // or keep it at null. nuclear@1: manager->GetThreadQueue()->PushCallAndWaitResult( nuclear@1: manager.GetPtr(), &DeviceManagerImpl::CreateDevice_MgrThread, nuclear@1: &device, pImpl, (DeviceBase*)0); nuclear@1: } nuclear@1: else nuclear@1: device = manager->CreateDevice_MgrThread(pImpl, (DeviceBase*)0); nuclear@1: } nuclear@1: return device; nuclear@1: } nuclear@1: nuclear@1: void DeviceHandle::Clear() nuclear@1: { nuclear@1: if (pImpl) nuclear@1: { nuclear@1: pImpl->Release(); nuclear@1: pImpl = 0; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: bool DeviceHandle::enumerateNext(const DeviceEnumerationArgs& args) nuclear@1: { nuclear@1: if (GetType() == Device_None) nuclear@1: return false; nuclear@1: nuclear@1: Ptr managerKeepAlive; nuclear@1: Lock::Locker lockScope(pImpl->GetLock()); nuclear@1: nuclear@1: DeviceCreateDesc* next = pImpl; nuclear@1: // If manager was destroyed, we get removed from the list. nuclear@1: if (!pImpl->pNext) nuclear@1: return false; nuclear@1: nuclear@1: managerKeepAlive = next->GetManagerImpl(); nuclear@1: OVR_ASSERT(managerKeepAlive); nuclear@1: nuclear@1: do { nuclear@1: next = next->pNext; nuclear@1: nuclear@1: if (managerKeepAlive->Devices.IsNull(next)) nuclear@1: { nuclear@1: pImpl->Release(); nuclear@1: pImpl = 0; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: } while(!args.MatchRule(next->Type, next->Enumerated)); nuclear@1: nuclear@1: next->AddRef(); nuclear@1: pImpl->Release(); nuclear@1: pImpl = next; nuclear@1: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: } // namespace OVR nuclear@1: