oculus1
view 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 source
1 /************************************************************************************
3 Filename : OVR_OSX_HMDDevice.cpp
4 Content : OSX Interface to HMD - detects HMD display
5 Created : September 21, 2012
6 Authors : Michael Antonov
8 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
10 Use of this software is subject to the terms of the Oculus license
11 agreement provided at the time of installation or download, or which
12 otherwise accompanies this software in either electronic or hard copy form.
14 *************************************************************************************/
16 #include "OVR_OSX_HMDDevice.h"
17 #include <CoreGraphics/CGDirectDisplay.h>
18 #include <CoreGraphics/CGDisplayConfiguration.h>
19 #include <CoreFoundation/CoreFoundation.h>
20 #include <CoreFoundation/CFString.h>
21 #include <IOKit/graphics/IOGraphicsLib.h>
23 namespace OVR { namespace OSX {
25 //-------------------------------------------------------------------------------------
27 HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory,
28 UInt32 vend, UInt32 prod, const String& displayDeviceName, long dispId)
29 : DeviceCreateDesc(factory, Device_HMD),
30 DisplayDeviceName(displayDeviceName),
31 DesktopX(0), DesktopY(0), Contents(0),
32 HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0),
33 DisplayId(dispId)
34 {
35 /* //??????????
36 char idstring[9];
37 idstring[0] = 'A'-1+((vend>>10) & 31);
38 idstring[1] = 'A'-1+((vend>>5) & 31);
39 idstring[2] = 'A'-1+((vend>>0) & 31);
40 snprintf(idstring+3, 5, "%04d", prod);
41 DeviceId = idstring;*/
42 DeviceId = DisplayDeviceName;
43 }
45 HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other)
46 : DeviceCreateDesc(other.pFactory, Device_HMD),
47 DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName),
48 DesktopX(other.DesktopX), DesktopY(other.DesktopY), Contents(other.Contents),
49 HResolution(other.HResolution), VResolution(other.VResolution),
50 HScreenSize(other.HScreenSize), VScreenSize(other.VScreenSize),
51 DisplayId(other.DisplayId)
52 {
53 }
55 HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other,
56 DeviceCreateDesc** pcandidate) const
57 {
58 if ((other.Type != Device_HMD) || (other.pFactory != pFactory))
59 return Match_None;
61 // There are several reasons we can come in here:
62 // a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc
63 // - Require exact device DeviceId/DeviceName match
64 // b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc
65 // - This DeviceId is empty; becomes candidate
66 // c) Matching this HMD Monitor created desc to SensorDisplayInfo desc
67 // - This other.DeviceId is empty; becomes candidate
69 const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
71 if ((DeviceId == s2.DeviceId) &&
72 (DisplayId == s2.DisplayId))
73 {
74 // Non-null DeviceId may match while size is different if screen size was overwritten
75 // by SensorDisplayInfo in prior iteration.
76 if (!DeviceId.IsEmpty() ||
77 ((HScreenSize == s2.HScreenSize) &&
78 (VScreenSize == s2.VScreenSize)) )
79 {
80 *pcandidate = 0;
81 return Match_Found;
82 }
83 }
86 // DisplayInfo takes precedence, although we try to match it first.
87 if ((HResolution == s2.HResolution) &&
88 (VResolution == s2.VResolution) &&
89 (HScreenSize == s2.HScreenSize) &&
90 (VScreenSize == s2.VScreenSize))
91 {
92 if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty())
93 {
94 *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
95 return Match_Candidate;
96 }
98 *pcandidate = 0;
99 return Match_Found;
100 }
102 // SensorDisplayInfo may override resolution settings, so store as candidiate.
103 if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0)
104 {
105 *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
106 return Match_Candidate;
107 }
108 // OTHER HMD Monitor desc may initialize DeviceName/Id
109 else if (DeviceId.IsEmpty() && DisplayId == 0)
110 {
111 *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
112 return Match_Candidate;
113 }
115 return Match_None;
116 }
119 bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, bool* newDeviceFlag)
120 {
121 // This candidate was the the "best fit" to apply sensor DisplayInfo to.
122 OVR_ASSERT(other.Type == Device_HMD);
124 const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
126 // Force screen size on resolution from SensorDisplayInfo.
127 // We do this because USB detection is more reliable as compared to HDMI EDID,
128 // which may be corrupted by splitter reporting wrong monitor
129 if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0)
130 {
131 // disconnected HMD: replace old descriptor by the 'fake' one.
132 HScreenSize = s2.HScreenSize;
133 VScreenSize = s2.VScreenSize;
134 Contents |= Contents_Screen;
136 if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion)
137 {
138 memcpy(DistortionK, s2.DistortionK, sizeof(float)*4);
139 Contents |= Contents_Distortion;
140 }
141 DeviceId = s2.DeviceId;
142 DisplayId = s2.DisplayId;
143 DisplayDeviceName = s2.DisplayDeviceName;
144 if (newDeviceFlag) *newDeviceFlag = true;
145 }
146 else if (DeviceId.IsEmpty())
147 {
148 // This branch is executed when 'fake' HMD descriptor is being replaced by
149 // the real one.
150 DeviceId = s2.DeviceId;
151 DisplayId = s2.DisplayId;
152 DisplayDeviceName = s2.DisplayDeviceName;
153 if (newDeviceFlag) *newDeviceFlag = true;
154 }
155 else
156 {
157 if (newDeviceFlag) *newDeviceFlag = false;
158 }
160 return true;
161 }
164 //-------------------------------------------------------------------------------------
167 //-------------------------------------------------------------------------------------
168 // ***** HMDDeviceFactory
170 HMDDeviceFactory HMDDeviceFactory::Instance;
172 void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
173 {
174 CGDirectDisplayID Displays[32];
175 uint32_t NDisplays = 0;
176 CGGetOnlineDisplayList(32, Displays, &NDisplays);
178 for (int i = 0; i < NDisplays; i++)
179 {
180 io_service_t port = CGDisplayIOServicePort(Displays[i]);
181 CFDictionaryRef DispInfo = IODisplayCreateInfoDictionary(port, kIODisplayMatchingInfo);
183 uint32_t vendor = CGDisplayVendorNumber(Displays[i]);
184 uint32_t product = CGDisplayModelNumber(Displays[i]);
185 unsigned mwidth = (unsigned)CGDisplayPixelsWide(Displays[i]);
186 unsigned mheight = (unsigned)CGDisplayPixelsHigh(Displays[i]);
187 CGRect desktop = CGDisplayBounds(Displays[i]);
189 if (vendor == 16082 && product == 1)
190 {
191 char idstring[9];
192 idstring[0] = 'A'-1+((vendor>>10) & 31);
193 idstring[1] = 'A'-1+((vendor>>5) & 31);
194 idstring[2] = 'A'-1+((vendor>>0) & 31);
195 snprintf(idstring+3, 5, "%04d", product);
197 HMDDeviceCreateDesc hmdCreateDesc(this, vendor, product, idstring, Displays[i]);
199 if (product == 2)
200 {
201 hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
202 mwidth, mheight, 0.12096f, 0.06804f);
203 }
204 else
205 {
206 if (hmdCreateDesc.Is7Inch())
207 {
208 // Physical dimension of SLA screen.
209 hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
210 mwidth, mheight, 0.14976f, 0.0936f);
211 }
212 else
213 {
214 hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
215 mwidth, mheight, 0.12096f, 0.0756f);
216 }
217 }
219 OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %x:%x\n", vendor, product));
221 // Notify caller about detected device. This will call EnumerateAddDevice
222 // if the this is the first time device was detected.
223 visitor.Visit(hmdCreateDesc);
224 }
225 CFRelease(DispInfo);
226 }
227 }
229 DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance()
230 {
231 return new HMDDevice(this);
232 }
234 bool HMDDeviceCreateDesc::Is7Inch() const
235 {
236 return (strstr(DeviceId.ToCStr(), "OVR0001") != 0) || (Contents & Contents_7Inch);
237 }
239 Profile* HMDDeviceCreateDesc::GetProfileAddRef() const
240 {
241 // Create device may override profile name, so get it from there is possible.
242 ProfileManager* profileManager = GetManagerImpl()->GetProfileManager();
243 ProfileType profileType = GetProfileType();
244 const char * profileName = pDevice ?
245 ((HMDDevice*)pDevice)->GetProfileName() :
246 profileManager->GetDefaultProfileName(profileType);
248 return profileName ?
249 profileManager->LoadProfile(profileType, profileName) :
250 profileManager->GetDeviceDefaultProfile(profileType);
251 }
253 bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
254 {
255 if ((info->InfoClassType != Device_HMD) &&
256 (info->InfoClassType != Device_None))
257 return false;
259 bool is7Inch = Is7Inch();
261 OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength,
262 is7Inch ? "Oculus Rift DK1" :
263 ((HResolution >= 1920) ? "Oculus Rift DK HD" : "Oculus Rift DK1-Prototype") );
264 OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, "Oculus VR");
265 info->Type = Device_HMD;
266 info->Version = 0;
268 // Display detection.
269 if (info->InfoClassType == Device_HMD)
270 {
271 HMDInfo* hmdInfo = static_cast<HMDInfo*>(info);
273 hmdInfo->DesktopX = DesktopX;
274 hmdInfo->DesktopY = DesktopY;
275 hmdInfo->HResolution = HResolution;
276 hmdInfo->VResolution = VResolution;
277 hmdInfo->HScreenSize = HScreenSize;
278 hmdInfo->VScreenSize = VScreenSize;
279 hmdInfo->VScreenCenter = VScreenSize * 0.5f;
280 hmdInfo->InterpupillaryDistance = 0.064f; // Default IPD; should be configurable.
281 hmdInfo->LensSeparationDistance = 0.0635f;
283 // Obtain IPD from profile.
284 Ptr<Profile> profile = *GetProfileAddRef();
286 if (profile)
287 {
288 hmdInfo->InterpupillaryDistance = profile->GetIPD();
289 // TBD: Switch on EyeCup type.
290 }
292 if (Contents & Contents_Distortion)
293 {
294 memcpy(hmdInfo->DistortionK, DistortionK, sizeof(float)*4);
295 }
296 else
297 {
298 if (is7Inch)
299 {
300 // 7" screen.
301 hmdInfo->DistortionK[0] = 1.0f;
302 hmdInfo->DistortionK[1] = 0.22f;
303 hmdInfo->DistortionK[2] = 0.24f;
304 hmdInfo->EyeToScreenDistance = 0.041f;
305 }
306 else
307 {
308 hmdInfo->DistortionK[0] = 1.0f;
309 hmdInfo->DistortionK[1] = 0.18f;
310 hmdInfo->DistortionK[2] = 0.115f;
312 if (HResolution == 1920)
313 hmdInfo->EyeToScreenDistance = 0.040f;
314 else
315 hmdInfo->EyeToScreenDistance = 0.0387f;
316 }
318 hmdInfo->ChromaAbCorrection[0] = 0.996f;
319 hmdInfo->ChromaAbCorrection[1] = -0.004f;
320 hmdInfo->ChromaAbCorrection[2] = 1.014f;
321 hmdInfo->ChromaAbCorrection[3] = 0.0f;
322 }
324 OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName),
325 DisplayDeviceName.ToCStr());
326 hmdInfo->DisplayId = DisplayId;
327 }
329 return true;
330 }
332 //-------------------------------------------------------------------------------------
333 // ***** HMDDevice
335 HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc)
336 : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0)
337 {
338 }
339 HMDDevice::~HMDDevice()
340 {
341 }
343 bool HMDDevice::Initialize(DeviceBase* parent)
344 {
345 pParent = parent;
347 // Initialize user profile to default for device.
348 ProfileManager* profileManager = GetManager()->GetProfileManager();
349 ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType());
351 return true;
352 }
353 void HMDDevice::Shutdown()
354 {
355 ProfileName.Clear();
356 pCachedProfile.Clear();
357 pParent.Clear();
358 }
360 Profile* HMDDevice::GetProfile() const
361 {
362 if (!pCachedProfile)
363 pCachedProfile = *getDesc()->GetProfileAddRef();
364 return pCachedProfile.GetPtr();
365 }
367 const char* HMDDevice::GetProfileName() const
368 {
369 return ProfileName.ToCStr();
370 }
372 bool HMDDevice::SetProfileName(const char* name)
373 {
374 pCachedProfile.Clear();
375 if (!name)
376 {
377 ProfileName.Clear();
378 return 0;
379 }
380 if (GetManager()->GetProfileManager()->HasProfile(getDesc()->GetProfileType(), name))
381 {
382 ProfileName = name;
383 return true;
384 }
385 return false;
386 }
388 OVR::SensorDevice* HMDDevice::GetSensor()
389 {
390 // Just return first sensor found since we have no way to match it yet.
391 OVR::SensorDevice* sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice();
392 if (sensor)
393 sensor->SetCoordinateFrame(SensorDevice::Coord_HMD);
394 return sensor;
395 }
398 }} // namespace OVR::OSX