oculus1
diff libovr/Src/win32/OVR_Win32_HMDDevice.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_HMDDevice.cpp Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,498 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_Win32_HMDDevice.cpp 1.7 +Content : Win32 Interface to HMD - detects HMD display 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_HMDDevice.h" 1.20 + 1.21 +#include "OVR_Win32_DeviceManager.h" 1.22 + 1.23 +#include <tchar.h> 1.24 + 1.25 +namespace OVR { namespace Win32 { 1.26 + 1.27 +//------------------------------------------------------------------------------------- 1.28 + 1.29 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, 1.30 + const String& deviceId, const String& displayDeviceName) 1.31 + : DeviceCreateDesc(factory, Device_HMD), 1.32 + DeviceId(deviceId), DisplayDeviceName(displayDeviceName), 1.33 + DesktopX(0), DesktopY(0), Contents(0), 1.34 + HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0) 1.35 +{ 1.36 +} 1.37 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other) 1.38 + : DeviceCreateDesc(other.pFactory, Device_HMD), 1.39 + DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName), 1.40 + DesktopX(other.DesktopX), DesktopY(other.DesktopY), Contents(other.Contents), 1.41 + HResolution(other.HResolution), VResolution(other.VResolution), 1.42 + HScreenSize(other.HScreenSize), VScreenSize(other.VScreenSize) 1.43 +{ 1.44 +} 1.45 + 1.46 +HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other, 1.47 + DeviceCreateDesc** pcandidate) const 1.48 +{ 1.49 + if ((other.Type != Device_HMD) || (other.pFactory != pFactory)) 1.50 + return Match_None; 1.51 + 1.52 + // There are several reasons we can come in here: 1.53 + // a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc 1.54 + // - Require exact device DeviceId/DeviceName match 1.55 + // b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc 1.56 + // - This DeviceId is empty; becomes candidate 1.57 + // c) Matching this HMD Monitor created desc to SensorDisplayInfo desc 1.58 + // - This other.DeviceId is empty; becomes candidate 1.59 + 1.60 + const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other; 1.61 + 1.62 + if ((DeviceId == s2.DeviceId) && 1.63 + (DisplayDeviceName == s2.DisplayDeviceName)) 1.64 + { 1.65 + // Non-null DeviceId may match while size is different if screen size was overwritten 1.66 + // by SensorDisplayInfo in prior iteration. 1.67 + if (!DeviceId.IsEmpty() || 1.68 + ((HScreenSize == s2.HScreenSize) && 1.69 + (VScreenSize == s2.VScreenSize)) ) 1.70 + { 1.71 + *pcandidate = 0; 1.72 + return Match_Found; 1.73 + } 1.74 + } 1.75 + 1.76 + 1.77 + // DisplayInfo takes precedence, although we try to match it first. 1.78 + if ((HResolution == s2.HResolution) && 1.79 + (VResolution == s2.VResolution) && 1.80 + (HScreenSize == s2.HScreenSize) && 1.81 + (VScreenSize == s2.VScreenSize)) 1.82 + { 1.83 + if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty()) 1.84 + { 1.85 + *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); 1.86 + return Match_Candidate; 1.87 + } 1.88 + 1.89 + *pcandidate = 0; 1.90 + return Match_Found; 1.91 + } 1.92 + 1.93 + // SensorDisplayInfo may override resolution settings, so store as candidate. 1.94 + if (s2.DeviceId.IsEmpty()) 1.95 + { 1.96 + *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); 1.97 + return Match_Candidate; 1.98 + } 1.99 + // OTHER HMD Monitor desc may initialize DeviceName/Id 1.100 + else if (DeviceId.IsEmpty()) 1.101 + { 1.102 + *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); 1.103 + return Match_Candidate; 1.104 + } 1.105 + 1.106 + return Match_None; 1.107 +} 1.108 + 1.109 + 1.110 +bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, 1.111 + bool* newDeviceFlag) 1.112 +{ 1.113 + // This candidate was the the "best fit" to apply sensor DisplayInfo to. 1.114 + OVR_ASSERT(other.Type == Device_HMD); 1.115 + 1.116 + const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other; 1.117 + 1.118 + // Force screen size on resolution from SensorDisplayInfo. 1.119 + // We do this because USB detection is more reliable as compared to HDMI EDID, 1.120 + // which may be corrupted by splitter reporting wrong monitor 1.121 + if (s2.DeviceId.IsEmpty()) 1.122 + { 1.123 + HScreenSize = s2.HScreenSize; 1.124 + VScreenSize = s2.VScreenSize; 1.125 + Contents |= Contents_Screen; 1.126 + 1.127 + if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion) 1.128 + { 1.129 + memcpy(DistortionK, s2.DistortionK, sizeof(float)*4); 1.130 + Contents |= Contents_Distortion; 1.131 + } 1.132 + DeviceId = s2.DeviceId; 1.133 + DisplayDeviceName = s2.DisplayDeviceName; 1.134 + DesktopX = s2.DesktopX; 1.135 + DesktopY = s2.DesktopY; 1.136 + if (newDeviceFlag) *newDeviceFlag = true; 1.137 + } 1.138 + else if (DeviceId.IsEmpty()) 1.139 + { 1.140 + DeviceId = s2.DeviceId; 1.141 + DisplayDeviceName = s2.DisplayDeviceName; 1.142 + DesktopX = s2.DesktopX; 1.143 + DesktopY = s2.DesktopY; 1.144 + 1.145 + // ScreenSize and Resolution are NOT assigned here, since they may have 1.146 + // come from a sensor DisplayInfo (which has precedence over HDMI). 1.147 + 1.148 + if (newDeviceFlag) *newDeviceFlag = true; 1.149 + } 1.150 + else 1.151 + { 1.152 + if (newDeviceFlag) *newDeviceFlag = false; 1.153 + } 1.154 + 1.155 + return true; 1.156 +} 1.157 + 1.158 +bool HMDDeviceCreateDesc::MatchDevice(const String& path) 1.159 +{ 1.160 + return DeviceId.CompareNoCase(path) == 0; 1.161 +} 1.162 + 1.163 +//------------------------------------------------------------------------------------- 1.164 + 1.165 + 1.166 +const wchar_t* FormatDisplayStateFlags(wchar_t* buff, int length, DWORD flags) 1.167 +{ 1.168 + buff[0] = 0; 1.169 + if (flags & DISPLAY_DEVICE_ACTIVE) 1.170 + wcscat_s(buff, length, L"Active "); 1.171 + if (flags & DISPLAY_DEVICE_MIRRORING_DRIVER) 1.172 + wcscat_s(buff, length, L"Mirroring_Driver "); 1.173 + if (flags & DISPLAY_DEVICE_MODESPRUNED) 1.174 + wcscat_s(buff, length, L"ModesPruned "); 1.175 + if (flags & DISPLAY_DEVICE_PRIMARY_DEVICE) 1.176 + wcscat_s(buff, length, L"Primary "); 1.177 + if (flags & DISPLAY_DEVICE_REMOVABLE) 1.178 + wcscat_s(buff, length, L"Removable "); 1.179 + if (flags & DISPLAY_DEVICE_VGA_COMPATIBLE) 1.180 + wcscat_s(buff, length, L"VGA_Compatible "); 1.181 + return buff; 1.182 +} 1.183 + 1.184 + 1.185 +//------------------------------------------------------------------------------------- 1.186 +// Callback for monitor enumeration to store all the monitor handles 1.187 + 1.188 +// Used to capture all the active monitor handles 1.189 +struct MonitorSet 1.190 +{ 1.191 + enum { MaxMonitors = 8 }; 1.192 + HMONITOR Monitors[MaxMonitors]; 1.193 + int MonitorCount; 1.194 +}; 1.195 + 1.196 +BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) 1.197 +{ 1.198 + MonitorSet* monitorSet = (MonitorSet*)dwData; 1.199 + if (monitorSet->MonitorCount > MonitorSet::MaxMonitors) 1.200 + return FALSE; 1.201 + 1.202 + monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor; 1.203 + monitorSet->MonitorCount++; 1.204 + return TRUE; 1.205 +}; 1.206 + 1.207 +//------------------------------------------------------------------------------------- 1.208 +// ***** HMDDeviceFactory 1.209 + 1.210 +HMDDeviceFactory HMDDeviceFactory::Instance; 1.211 + 1.212 +void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) 1.213 +{ 1.214 + MonitorSet monitors; 1.215 + monitors.MonitorCount = 0; 1.216 + // Get all the monitor handles 1.217 + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors); 1.218 + 1.219 + bool foundHMD = false; 1.220 + 1.221 + // DeviceManager* manager = getManager(); 1.222 + DISPLAY_DEVICE dd, ddm; 1.223 + UINT i, j; 1.224 + 1.225 + for (i = 0; 1.226 + (ZeroMemory(&dd, sizeof(dd)), dd.cb = sizeof(dd), 1.227 + EnumDisplayDevices(0, i, &dd, 0)) != 0; i++) 1.228 + { 1.229 + 1.230 + /* 1.231 + wchar_t buff[500], flagsBuff[200]; 1.232 + 1.233 + swprintf_s(buff, 500, L"\nDEV: \"%s\" \"%s\" 0x%08x=%s\n \"%s\" \"%s\"\n", 1.234 + dd.DeviceName, dd.DeviceString, 1.235 + dd.StateFlags, FormatDisplayStateFlags(flagsBuff, 200, dd.StateFlags), 1.236 + dd.DeviceID, dd.DeviceKey); 1.237 + ::OutputDebugString(buff); 1.238 + */ 1.239 + 1.240 + for (j = 0; 1.241 + (ZeroMemory(&ddm, sizeof(ddm)), ddm.cb = sizeof(ddm), 1.242 + EnumDisplayDevices(dd.DeviceName, j, &ddm, 0)) != 0; j++) 1.243 + { 1.244 + /* 1.245 + wchar_t mbuff[500]; 1.246 + swprintf_s(mbuff, 500, L"MON: \"%s\" \"%s\" 0x%08x=%s\n \"%s\" \"%s\"\n", 1.247 + ddm.DeviceName, ddm.DeviceString, 1.248 + ddm.StateFlags, FormatDisplayStateFlags(flagsBuff, 200, ddm.StateFlags), 1.249 + ddm.DeviceID, ddm.DeviceKey); 1.250 + ::OutputDebugString(mbuff); 1.251 + */ 1.252 + 1.253 + // Our monitor hardware has string "RTD2205" in it 1.254 + // Nate's device "CVT0003" 1.255 + if (wcsstr(ddm.DeviceID, L"RTD2205") || 1.256 + wcsstr(ddm.DeviceID, L"CVT0003") || 1.257 + wcsstr(ddm.DeviceID, L"MST0030") || 1.258 + wcsstr(ddm.DeviceID, L"OVR00") ) // Part of Oculus EDID. 1.259 + { 1.260 + String deviceId(ddm.DeviceID); 1.261 + String displayDeviceName(ddm.DeviceName); 1.262 + 1.263 + // The default monitor coordinates 1.264 + int mx = 0; 1.265 + int my = 0; 1.266 + int mwidth = 1280; 1.267 + int mheight = 800; 1.268 + 1.269 + // Find the matching MONITORINFOEX for this device so we can get the 1.270 + // screen coordinates 1.271 + MONITORINFOEX info; 1.272 + for (int m=0; m < monitors.MonitorCount; m++) 1.273 + { 1.274 + info.cbSize = sizeof(MONITORINFOEX); 1.275 + GetMonitorInfo(monitors.Monitors[m], &info); 1.276 + if (_tcsstr(ddm.DeviceName, info.szDevice) == ddm.DeviceName) 1.277 + { // If the device name starts with the monitor name 1.278 + // then we found the matching DISPLAY_DEVICE and MONITORINFO 1.279 + // so we can gather the monitor coordinates 1.280 + mx = info.rcMonitor.left; 1.281 + my = info.rcMonitor.top; 1.282 + //mwidth = info.rcMonitor.right - info.rcMonitor.left; 1.283 + //mheight = info.rcMonitor.bottom - info.rcMonitor.top; 1.284 + break; 1.285 + } 1.286 + } 1.287 + 1.288 + HMDDeviceCreateDesc hmdCreateDesc(this, deviceId, displayDeviceName); 1.289 + 1.290 + if (wcsstr(ddm.DeviceID, L"OVR0002")) 1.291 + { 1.292 + hmdCreateDesc.SetScreenParameters(mx, my, 1920, 1080, 0.12096f, 0.06804f); 1.293 + } 1.294 + else 1.295 + { 1.296 + if (hmdCreateDesc.Is7Inch()) 1.297 + { 1.298 + // Physical dimension of SLA screen. 1.299 + hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.14976f, 0.0936f); 1.300 + } 1.301 + else 1.302 + { 1.303 + hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.12096f, 0.0756f); 1.304 + } 1.305 + } 1.306 + 1.307 + 1.308 + OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %s - %s\n", 1.309 + deviceId.ToCStr(), displayDeviceName.ToCStr())); 1.310 + 1.311 + // Notify caller about detected device. This will call EnumerateAddDevice 1.312 + // if the this is the first time device was detected. 1.313 + visitor.Visit(hmdCreateDesc); 1.314 + foundHMD = true; 1.315 + break; 1.316 + } 1.317 + } 1.318 + } 1.319 + 1.320 + // Real HMD device is not found; however, we still may have a 'fake' HMD 1.321 + // device created via SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo. 1.322 + // Need to find it and set 'Enumerated' to true to avoid Removal notification. 1.323 + if (!foundHMD) 1.324 + { 1.325 + Ptr<DeviceCreateDesc> hmdDevDesc = getManager()->FindDevice("", Device_HMD); 1.326 + if (hmdDevDesc) 1.327 + hmdDevDesc->Enumerated = true; 1.328 + } 1.329 +} 1.330 + 1.331 +DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance() 1.332 +{ 1.333 + return new HMDDevice(this); 1.334 +} 1.335 + 1.336 +bool HMDDeviceCreateDesc::Is7Inch() const 1.337 +{ 1.338 + return (strstr(DeviceId.ToCStr(), "OVR0001") != 0) || (Contents & Contents_7Inch); 1.339 +} 1.340 + 1.341 +Profile* HMDDeviceCreateDesc::GetProfileAddRef() const 1.342 +{ 1.343 + // Create device may override profile name, so get it from there is possible. 1.344 + ProfileManager* profileManager = GetManagerImpl()->GetProfileManager(); 1.345 + ProfileType profileType = GetProfileType(); 1.346 + const char * profileName = pDevice ? 1.347 + ((HMDDevice*)pDevice)->GetProfileName() : 1.348 + profileManager->GetDefaultProfileName(profileType); 1.349 + 1.350 + return profileName ? 1.351 + profileManager->LoadProfile(profileType, profileName) : 1.352 + profileManager->GetDeviceDefaultProfile(profileType); 1.353 +} 1.354 + 1.355 + 1.356 +bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const 1.357 +{ 1.358 + if ((info->InfoClassType != Device_HMD) && 1.359 + (info->InfoClassType != Device_None)) 1.360 + return false; 1.361 + 1.362 + bool is7Inch = Is7Inch(); 1.363 + 1.364 + OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, 1.365 + is7Inch ? "Oculus Rift DK1" : 1.366 + ((HResolution >= 1920) ? "Oculus Rift DK HD" : "Oculus Rift DK1-Prototype") ); 1.367 + OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, "Oculus VR"); 1.368 + info->Type = Device_HMD; 1.369 + info->Version = 0; 1.370 + 1.371 + // Display detection. 1.372 + if (info->InfoClassType == Device_HMD) 1.373 + { 1.374 + HMDInfo* hmdInfo = static_cast<HMDInfo*>(info); 1.375 + 1.376 + hmdInfo->DesktopX = DesktopX; 1.377 + hmdInfo->DesktopY = DesktopY; 1.378 + hmdInfo->HResolution = HResolution; 1.379 + hmdInfo->VResolution = VResolution; 1.380 + hmdInfo->HScreenSize = HScreenSize; 1.381 + hmdInfo->VScreenSize = VScreenSize; 1.382 + hmdInfo->VScreenCenter = VScreenSize * 0.5f; 1.383 + hmdInfo->InterpupillaryDistance = 0.064f; // Default IPD; should be configurable. 1.384 + hmdInfo->LensSeparationDistance = 0.0635f; 1.385 + 1.386 + // Obtain IPD from profile. 1.387 + Ptr<Profile> profile = *GetProfileAddRef(); 1.388 + 1.389 + if (profile) 1.390 + { 1.391 + hmdInfo->InterpupillaryDistance = profile->GetIPD(); 1.392 + // TBD: Switch on EyeCup type. 1.393 + } 1.394 + 1.395 + if (Contents & Contents_Distortion) 1.396 + { 1.397 + memcpy(hmdInfo->DistortionK, DistortionK, sizeof(float)*4); 1.398 + } 1.399 + else 1.400 + { 1.401 + if (is7Inch) 1.402 + { 1.403 + // 7" screen. 1.404 + hmdInfo->DistortionK[0] = 1.0f; 1.405 + hmdInfo->DistortionK[1] = 0.22f; 1.406 + hmdInfo->DistortionK[2] = 0.24f; 1.407 + hmdInfo->EyeToScreenDistance = 0.041f; 1.408 + } 1.409 + else 1.410 + { 1.411 + hmdInfo->DistortionK[0] = 1.0f; 1.412 + hmdInfo->DistortionK[1] = 0.18f; 1.413 + hmdInfo->DistortionK[2] = 0.115f; 1.414 + 1.415 + if (HResolution == 1920) 1.416 + hmdInfo->EyeToScreenDistance = 0.040f; 1.417 + else 1.418 + hmdInfo->EyeToScreenDistance = 0.0387f; 1.419 + } 1.420 + 1.421 + hmdInfo->ChromaAbCorrection[0] = 0.996f; 1.422 + hmdInfo->ChromaAbCorrection[1] = -0.004f; 1.423 + hmdInfo->ChromaAbCorrection[2] = 1.014f; 1.424 + hmdInfo->ChromaAbCorrection[3] = 0.0f; 1.425 + } 1.426 + 1.427 + OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName), 1.428 + DisplayDeviceName.ToCStr()); 1.429 + } 1.430 + 1.431 + return true; 1.432 +} 1.433 + 1.434 +//------------------------------------------------------------------------------------- 1.435 +// ***** HMDDevice 1.436 + 1.437 +HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc) 1.438 + : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0) 1.439 +{ 1.440 +} 1.441 +HMDDevice::~HMDDevice() 1.442 +{ 1.443 +} 1.444 + 1.445 +bool HMDDevice::Initialize(DeviceBase* parent) 1.446 +{ 1.447 + pParent = parent; 1.448 + 1.449 + // Initialize user profile to default for device. 1.450 + ProfileManager* profileManager = GetManager()->GetProfileManager(); 1.451 + ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType()); 1.452 + 1.453 + return true; 1.454 +} 1.455 +void HMDDevice::Shutdown() 1.456 +{ 1.457 + ProfileName.Clear(); 1.458 + pCachedProfile.Clear(); 1.459 + pParent.Clear(); 1.460 +} 1.461 + 1.462 +Profile* HMDDevice::GetProfile() const 1.463 +{ 1.464 + if (!pCachedProfile) 1.465 + pCachedProfile = *getDesc()->GetProfileAddRef(); 1.466 + return pCachedProfile.GetPtr(); 1.467 +} 1.468 + 1.469 +const char* HMDDevice::GetProfileName() const 1.470 +{ 1.471 + return ProfileName.ToCStr(); 1.472 +} 1.473 + 1.474 +bool HMDDevice::SetProfileName(const char* name) 1.475 +{ 1.476 + pCachedProfile.Clear(); 1.477 + if (!name) 1.478 + { 1.479 + ProfileName.Clear(); 1.480 + return 0; 1.481 + } 1.482 + if (GetManager()->GetProfileManager()->HasProfile(getDesc()->GetProfileType(), name)) 1.483 + { 1.484 + ProfileName = name; 1.485 + return true; 1.486 + } 1.487 + return false; 1.488 +} 1.489 + 1.490 +OVR::SensorDevice* HMDDevice::GetSensor() 1.491 +{ 1.492 + // Just return first sensor found since we have no way to match it yet. 1.493 + OVR::SensorDevice* sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice(); 1.494 + if (sensor) 1.495 + sensor->SetCoordinateFrame(SensorDevice::Coord_HMD); 1.496 + return sensor; 1.497 +} 1.498 + 1.499 +}} // namespace OVR::Win32 1.500 + 1.501 +