oculus1
diff libovr/Src/osx/OVR_OSX_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/osx/OVR_OSX_HMDDevice.cpp Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,400 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : OVR_OSX_HMDDevice.cpp 1.7 +Content : OSX 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_OSX_HMDDevice.h" 1.20 +#include <CoreGraphics/CGDirectDisplay.h> 1.21 +#include <CoreGraphics/CGDisplayConfiguration.h> 1.22 +#include <CoreFoundation/CoreFoundation.h> 1.23 +#include <CoreFoundation/CFString.h> 1.24 +#include <IOKit/graphics/IOGraphicsLib.h> 1.25 + 1.26 +namespace OVR { namespace OSX { 1.27 + 1.28 +//------------------------------------------------------------------------------------- 1.29 + 1.30 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, 1.31 + UInt32 vend, UInt32 prod, const String& displayDeviceName, long dispId) 1.32 + : DeviceCreateDesc(factory, Device_HMD), 1.33 + DisplayDeviceName(displayDeviceName), 1.34 + DesktopX(0), DesktopY(0), Contents(0), 1.35 + HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0), 1.36 + DisplayId(dispId) 1.37 +{ 1.38 + /* //?????????? 1.39 + char idstring[9]; 1.40 + idstring[0] = 'A'-1+((vend>>10) & 31); 1.41 + idstring[1] = 'A'-1+((vend>>5) & 31); 1.42 + idstring[2] = 'A'-1+((vend>>0) & 31); 1.43 + snprintf(idstring+3, 5, "%04d", prod); 1.44 + DeviceId = idstring;*/ 1.45 + DeviceId = DisplayDeviceName; 1.46 +} 1.47 + 1.48 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other) 1.49 + : DeviceCreateDesc(other.pFactory, Device_HMD), 1.50 + DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName), 1.51 + DesktopX(other.DesktopX), DesktopY(other.DesktopY), Contents(other.Contents), 1.52 + HResolution(other.HResolution), VResolution(other.VResolution), 1.53 + HScreenSize(other.HScreenSize), VScreenSize(other.VScreenSize), 1.54 + DisplayId(other.DisplayId) 1.55 +{ 1.56 +} 1.57 + 1.58 +HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other, 1.59 + DeviceCreateDesc** pcandidate) const 1.60 +{ 1.61 + if ((other.Type != Device_HMD) || (other.pFactory != pFactory)) 1.62 + return Match_None; 1.63 + 1.64 + // There are several reasons we can come in here: 1.65 + // a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc 1.66 + // - Require exact device DeviceId/DeviceName match 1.67 + // b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc 1.68 + // - This DeviceId is empty; becomes candidate 1.69 + // c) Matching this HMD Monitor created desc to SensorDisplayInfo desc 1.70 + // - This other.DeviceId is empty; becomes candidate 1.71 + 1.72 + const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other; 1.73 + 1.74 + if ((DeviceId == s2.DeviceId) && 1.75 + (DisplayId == s2.DisplayId)) 1.76 + { 1.77 + // Non-null DeviceId may match while size is different if screen size was overwritten 1.78 + // by SensorDisplayInfo in prior iteration. 1.79 + if (!DeviceId.IsEmpty() || 1.80 + ((HScreenSize == s2.HScreenSize) && 1.81 + (VScreenSize == s2.VScreenSize)) ) 1.82 + { 1.83 + *pcandidate = 0; 1.84 + return Match_Found; 1.85 + } 1.86 + } 1.87 + 1.88 + 1.89 + // DisplayInfo takes precedence, although we try to match it first. 1.90 + if ((HResolution == s2.HResolution) && 1.91 + (VResolution == s2.VResolution) && 1.92 + (HScreenSize == s2.HScreenSize) && 1.93 + (VScreenSize == s2.VScreenSize)) 1.94 + { 1.95 + if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty()) 1.96 + { 1.97 + *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); 1.98 + return Match_Candidate; 1.99 + } 1.100 + 1.101 + *pcandidate = 0; 1.102 + return Match_Found; 1.103 + } 1.104 + 1.105 + // SensorDisplayInfo may override resolution settings, so store as candidiate. 1.106 + if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0) 1.107 + { 1.108 + *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); 1.109 + return Match_Candidate; 1.110 + } 1.111 + // OTHER HMD Monitor desc may initialize DeviceName/Id 1.112 + else if (DeviceId.IsEmpty() && DisplayId == 0) 1.113 + { 1.114 + *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); 1.115 + return Match_Candidate; 1.116 + } 1.117 + 1.118 + return Match_None; 1.119 +} 1.120 + 1.121 + 1.122 +bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, bool* newDeviceFlag) 1.123 +{ 1.124 + // This candidate was the the "best fit" to apply sensor DisplayInfo to. 1.125 + OVR_ASSERT(other.Type == Device_HMD); 1.126 + 1.127 + const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other; 1.128 + 1.129 + // Force screen size on resolution from SensorDisplayInfo. 1.130 + // We do this because USB detection is more reliable as compared to HDMI EDID, 1.131 + // which may be corrupted by splitter reporting wrong monitor 1.132 + if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0) 1.133 + { 1.134 + // disconnected HMD: replace old descriptor by the 'fake' one. 1.135 + HScreenSize = s2.HScreenSize; 1.136 + VScreenSize = s2.VScreenSize; 1.137 + Contents |= Contents_Screen; 1.138 + 1.139 + if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion) 1.140 + { 1.141 + memcpy(DistortionK, s2.DistortionK, sizeof(float)*4); 1.142 + Contents |= Contents_Distortion; 1.143 + } 1.144 + DeviceId = s2.DeviceId; 1.145 + DisplayId = s2.DisplayId; 1.146 + DisplayDeviceName = s2.DisplayDeviceName; 1.147 + if (newDeviceFlag) *newDeviceFlag = true; 1.148 + } 1.149 + else if (DeviceId.IsEmpty()) 1.150 + { 1.151 + // This branch is executed when 'fake' HMD descriptor is being replaced by 1.152 + // the real one. 1.153 + DeviceId = s2.DeviceId; 1.154 + DisplayId = s2.DisplayId; 1.155 + DisplayDeviceName = s2.DisplayDeviceName; 1.156 + if (newDeviceFlag) *newDeviceFlag = true; 1.157 + } 1.158 + else 1.159 + { 1.160 + if (newDeviceFlag) *newDeviceFlag = false; 1.161 + } 1.162 + 1.163 + return true; 1.164 +} 1.165 + 1.166 + 1.167 +//------------------------------------------------------------------------------------- 1.168 + 1.169 + 1.170 +//------------------------------------------------------------------------------------- 1.171 +// ***** HMDDeviceFactory 1.172 + 1.173 +HMDDeviceFactory HMDDeviceFactory::Instance; 1.174 + 1.175 +void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) 1.176 +{ 1.177 + CGDirectDisplayID Displays[32]; 1.178 + uint32_t NDisplays = 0; 1.179 + CGGetOnlineDisplayList(32, Displays, &NDisplays); 1.180 + 1.181 + for (int i = 0; i < NDisplays; i++) 1.182 + { 1.183 + io_service_t port = CGDisplayIOServicePort(Displays[i]); 1.184 + CFDictionaryRef DispInfo = IODisplayCreateInfoDictionary(port, kIODisplayMatchingInfo); 1.185 + 1.186 + uint32_t vendor = CGDisplayVendorNumber(Displays[i]); 1.187 + uint32_t product = CGDisplayModelNumber(Displays[i]); 1.188 + unsigned mwidth = (unsigned)CGDisplayPixelsWide(Displays[i]); 1.189 + unsigned mheight = (unsigned)CGDisplayPixelsHigh(Displays[i]); 1.190 + CGRect desktop = CGDisplayBounds(Displays[i]); 1.191 + 1.192 + if (vendor == 16082 && product == 1) 1.193 + { 1.194 + char idstring[9]; 1.195 + idstring[0] = 'A'-1+((vendor>>10) & 31); 1.196 + idstring[1] = 'A'-1+((vendor>>5) & 31); 1.197 + idstring[2] = 'A'-1+((vendor>>0) & 31); 1.198 + snprintf(idstring+3, 5, "%04d", product); 1.199 + 1.200 + HMDDeviceCreateDesc hmdCreateDesc(this, vendor, product, idstring, Displays[i]); 1.201 + 1.202 + if (product == 2) 1.203 + { 1.204 + hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y, 1.205 + mwidth, mheight, 0.12096f, 0.06804f); 1.206 + } 1.207 + else 1.208 + { 1.209 + if (hmdCreateDesc.Is7Inch()) 1.210 + { 1.211 + // Physical dimension of SLA screen. 1.212 + hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y, 1.213 + mwidth, mheight, 0.14976f, 0.0936f); 1.214 + } 1.215 + else 1.216 + { 1.217 + hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y, 1.218 + mwidth, mheight, 0.12096f, 0.0756f); 1.219 + } 1.220 + } 1.221 + 1.222 + OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %x:%x\n", vendor, product)); 1.223 + 1.224 + // Notify caller about detected device. This will call EnumerateAddDevice 1.225 + // if the this is the first time device was detected. 1.226 + visitor.Visit(hmdCreateDesc); 1.227 + } 1.228 + CFRelease(DispInfo); 1.229 + } 1.230 +} 1.231 + 1.232 +DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance() 1.233 +{ 1.234 + return new HMDDevice(this); 1.235 +} 1.236 + 1.237 +bool HMDDeviceCreateDesc::Is7Inch() const 1.238 +{ 1.239 + return (strstr(DeviceId.ToCStr(), "OVR0001") != 0) || (Contents & Contents_7Inch); 1.240 +} 1.241 + 1.242 +Profile* HMDDeviceCreateDesc::GetProfileAddRef() const 1.243 +{ 1.244 + // Create device may override profile name, so get it from there is possible. 1.245 + ProfileManager* profileManager = GetManagerImpl()->GetProfileManager(); 1.246 + ProfileType profileType = GetProfileType(); 1.247 + const char * profileName = pDevice ? 1.248 + ((HMDDevice*)pDevice)->GetProfileName() : 1.249 + profileManager->GetDefaultProfileName(profileType); 1.250 + 1.251 + return profileName ? 1.252 + profileManager->LoadProfile(profileType, profileName) : 1.253 + profileManager->GetDeviceDefaultProfile(profileType); 1.254 +} 1.255 + 1.256 +bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const 1.257 +{ 1.258 + if ((info->InfoClassType != Device_HMD) && 1.259 + (info->InfoClassType != Device_None)) 1.260 + return false; 1.261 + 1.262 + bool is7Inch = Is7Inch(); 1.263 + 1.264 + OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, 1.265 + is7Inch ? "Oculus Rift DK1" : 1.266 + ((HResolution >= 1920) ? "Oculus Rift DK HD" : "Oculus Rift DK1-Prototype") ); 1.267 + OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, "Oculus VR"); 1.268 + info->Type = Device_HMD; 1.269 + info->Version = 0; 1.270 + 1.271 + // Display detection. 1.272 + if (info->InfoClassType == Device_HMD) 1.273 + { 1.274 + HMDInfo* hmdInfo = static_cast<HMDInfo*>(info); 1.275 + 1.276 + hmdInfo->DesktopX = DesktopX; 1.277 + hmdInfo->DesktopY = DesktopY; 1.278 + hmdInfo->HResolution = HResolution; 1.279 + hmdInfo->VResolution = VResolution; 1.280 + hmdInfo->HScreenSize = HScreenSize; 1.281 + hmdInfo->VScreenSize = VScreenSize; 1.282 + hmdInfo->VScreenCenter = VScreenSize * 0.5f; 1.283 + hmdInfo->InterpupillaryDistance = 0.064f; // Default IPD; should be configurable. 1.284 + hmdInfo->LensSeparationDistance = 0.0635f; 1.285 + 1.286 + // Obtain IPD from profile. 1.287 + Ptr<Profile> profile = *GetProfileAddRef(); 1.288 + 1.289 + if (profile) 1.290 + { 1.291 + hmdInfo->InterpupillaryDistance = profile->GetIPD(); 1.292 + // TBD: Switch on EyeCup type. 1.293 + } 1.294 + 1.295 + if (Contents & Contents_Distortion) 1.296 + { 1.297 + memcpy(hmdInfo->DistortionK, DistortionK, sizeof(float)*4); 1.298 + } 1.299 + else 1.300 + { 1.301 + if (is7Inch) 1.302 + { 1.303 + // 7" screen. 1.304 + hmdInfo->DistortionK[0] = 1.0f; 1.305 + hmdInfo->DistortionK[1] = 0.22f; 1.306 + hmdInfo->DistortionK[2] = 0.24f; 1.307 + hmdInfo->EyeToScreenDistance = 0.041f; 1.308 + } 1.309 + else 1.310 + { 1.311 + hmdInfo->DistortionK[0] = 1.0f; 1.312 + hmdInfo->DistortionK[1] = 0.18f; 1.313 + hmdInfo->DistortionK[2] = 0.115f; 1.314 + 1.315 + if (HResolution == 1920) 1.316 + hmdInfo->EyeToScreenDistance = 0.040f; 1.317 + else 1.318 + hmdInfo->EyeToScreenDistance = 0.0387f; 1.319 + } 1.320 + 1.321 + hmdInfo->ChromaAbCorrection[0] = 0.996f; 1.322 + hmdInfo->ChromaAbCorrection[1] = -0.004f; 1.323 + hmdInfo->ChromaAbCorrection[2] = 1.014f; 1.324 + hmdInfo->ChromaAbCorrection[3] = 0.0f; 1.325 + } 1.326 + 1.327 + OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName), 1.328 + DisplayDeviceName.ToCStr()); 1.329 + hmdInfo->DisplayId = DisplayId; 1.330 + } 1.331 + 1.332 + return true; 1.333 +} 1.334 + 1.335 +//------------------------------------------------------------------------------------- 1.336 +// ***** HMDDevice 1.337 + 1.338 +HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc) 1.339 + : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0) 1.340 +{ 1.341 +} 1.342 +HMDDevice::~HMDDevice() 1.343 +{ 1.344 +} 1.345 + 1.346 +bool HMDDevice::Initialize(DeviceBase* parent) 1.347 +{ 1.348 + pParent = parent; 1.349 + 1.350 + // Initialize user profile to default for device. 1.351 + ProfileManager* profileManager = GetManager()->GetProfileManager(); 1.352 + ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType()); 1.353 + 1.354 + return true; 1.355 +} 1.356 +void HMDDevice::Shutdown() 1.357 +{ 1.358 + ProfileName.Clear(); 1.359 + pCachedProfile.Clear(); 1.360 + pParent.Clear(); 1.361 +} 1.362 + 1.363 +Profile* HMDDevice::GetProfile() const 1.364 +{ 1.365 + if (!pCachedProfile) 1.366 + pCachedProfile = *getDesc()->GetProfileAddRef(); 1.367 + return pCachedProfile.GetPtr(); 1.368 +} 1.369 + 1.370 +const char* HMDDevice::GetProfileName() const 1.371 +{ 1.372 + return ProfileName.ToCStr(); 1.373 +} 1.374 + 1.375 +bool HMDDevice::SetProfileName(const char* name) 1.376 +{ 1.377 + pCachedProfile.Clear(); 1.378 + if (!name) 1.379 + { 1.380 + ProfileName.Clear(); 1.381 + return 0; 1.382 + } 1.383 + if (GetManager()->GetProfileManager()->HasProfile(getDesc()->GetProfileType(), name)) 1.384 + { 1.385 + ProfileName = name; 1.386 + return true; 1.387 + } 1.388 + return false; 1.389 +} 1.390 + 1.391 +OVR::SensorDevice* HMDDevice::GetSensor() 1.392 +{ 1.393 + // Just return first sensor found since we have no way to match it yet. 1.394 + OVR::SensorDevice* sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice(); 1.395 + if (sensor) 1.396 + sensor->SetCoordinateFrame(SensorDevice::Coord_HMD); 1.397 + return sensor; 1.398 +} 1.399 + 1.400 + 1.401 +}} // namespace OVR::OSX 1.402 + 1.403 +