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