Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_Linux_HMDDevice.cpp
Go to the documentation of this file.
1 /************************************************************************************
2 
3 Filename : OVR_Linux_HMDDevice.h
4 Content : Linux HMDDevice implementation
5 Created : June 17, 2013
6 Authors : Brant Lewis
7 
8 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
9 
10 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
14 
15 You may obtain a copy of the License at
16 
17 http://www.oculusvr.com/licenses/LICENSE-3.1
18 
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24 
25 *************************************************************************************/
26 
27 #include "OVR_Linux_HMDDevice.h"
28 
30 
31 #include "OVR_Profile.h"
32 
33 #include "third_party/edid/edid.h"
34 
35 namespace OVR { namespace Linux {
36 
37 //-------------------------------------------------------------------------------------
38 
39 HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, const String& displayDeviceName, long dispId)
41  DisplayDeviceName(displayDeviceName),
42  Contents(0),
43  DisplayId(dispId)
44 {
45  DeviceId = DisplayDeviceName;
46 
47  Desktop.X = 0;
48  Desktop.Y = 0;
49  ResolutionInPixels = Sizei(0);
50  ScreenSizeInMeters = Sizef(0.0f);
51  VCenterFromTopInMeters = 0.0f;
52  LensSeparationInMeters = 0.0f;
53 }
54 
55 HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other)
56  : DeviceCreateDesc(other.pFactory, Device_HMD),
57  DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName),
58  Contents(other.Contents),
59  DisplayId(other.DisplayId)
60 {
61  Desktop.X = other.Desktop.X;
62  Desktop.Y = other.Desktop.Y;
63  ResolutionInPixels = other.ResolutionInPixels;
64  ScreenSizeInMeters = other.ScreenSizeInMeters;
65  VCenterFromTopInMeters = other.VCenterFromTopInMeters;
66  LensSeparationInMeters = other.LensSeparationInMeters;
67 }
68 
70  DeviceCreateDesc** pcandidate) const
71 {
72  if ((other.Type != Device_HMD) || (other.pFactory != pFactory))
73  return Match_None;
74 
75  // There are several reasons we can come in here:
76  // a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc
77  // - Require exact device DeviceId/DeviceName match
78  // b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc
79  // - This DeviceId is empty; becomes candidate
80  // c) Matching this HMD Monitor created desc to SensorDisplayInfo desc
81  // - This other.DeviceId is empty; becomes candidate
82 
83  const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
84 
85  if ((DeviceId == s2.DeviceId) &&
86  (DisplayId == s2.DisplayId))
87  {
88  // Non-null DeviceId may match while size is different if screen size was overwritten
89  // by SensorDisplayInfo in prior iteration.
90  if (!DeviceId.IsEmpty() ||
91  (ScreenSizeInMeters == s2.ScreenSizeInMeters) )
92  {
93  *pcandidate = 0;
94  return Match_Found;
95  }
96  }
97 
98 
99  // DisplayInfo takes precedence, although we try to match it first.
100  if ((ResolutionInPixels == s2.ResolutionInPixels) &&
101  (ScreenSizeInMeters == s2.ScreenSizeInMeters))
102  {
103  if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty())
104  {
105  *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
107  }
108 
109  *pcandidate = 0;
110  return Match_Found;
111  }
112 
113  // SensorDisplayInfo may override resolution settings, so store as candidate.
114  if (s2.DeviceId.IsEmpty())
115  {
116  *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
117  return Match_Candidate;
118  }
119  // OTHER HMD Monitor desc may initialize DeviceName/Id
120  else if (DeviceId.IsEmpty())
121  {
122  *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
124  }
125 
126  return Match_None;
127 }
128 
131  bool* newDeviceFlag)
132 {
133  // This candidate was the the "best fit" to apply sensor DisplayInfo to.
134  OVR_ASSERT(other.Type == Device_HMD);
135 
136  const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
137 
138  // Force screen size on resolution from SensorDisplayInfo.
139  // We do this because USB detection is more reliable as compared to HDMI EDID,
140  // which may be corrupted by splitter reporting wrong monitor
141  if (s2.DeviceId.IsEmpty())
142  {
143  ScreenSizeInMeters = s2.ScreenSizeInMeters;
145 
147  {
148  memcpy(DistortionK, s2.DistortionK, sizeof(float)*4);
149  // TODO: DistortionEqn
151  }
152  DeviceId = s2.DeviceId;
153  DisplayId = s2.DisplayId;
154  DisplayDeviceName = s2.DisplayDeviceName;
155  Desktop.X = s2.Desktop.X;
156  Desktop.Y = s2.Desktop.Y;
157  if (newDeviceFlag) *newDeviceFlag = true;
158  }
159  else if (DeviceId.IsEmpty())
160  {
161  // This branch is executed when 'fake' HMD descriptor is being replaced by
162  // the real one.
163  DeviceId = s2.DeviceId;
164  DisplayId = s2.DisplayId;
165  DisplayDeviceName = s2.DisplayDeviceName;
166  Desktop.X = s2.Desktop.X;
167  Desktop.Y = s2.Desktop.Y;
168 
169  // ScreenSize and Resolution are NOT assigned here, since they may have
170  // come from a sensor DisplayInfo (which has precedence over HDMI).
171 
172  if (newDeviceFlag) *newDeviceFlag = true;
173  }
174  else
175  {
176  if (newDeviceFlag) *newDeviceFlag = false;
177  }
178 
179  return true;
180 }
181 
183 {
184  return DeviceId.CompareNoCase(path) == 0;
185 }
186 
187 //-------------------------------------------------------------------------------------
188 // ***** HMDDeviceFactory
189 
191 {
192  static HMDDeviceFactory instance;
193  return instance;
194 }
195 
197 {
198  // For now we'll assume the Rift DK1 is attached in extended monitor mode. Ultimately we need to
199  // use XFree86 to enumerate X11 screens in case the Rift is attached as a separate screen.
200 
201  bool foundHMD = false;
202  Display* display = XOpenDisplay(NULL);
203  XRRScreenResources *screen = XRRGetScreenResources(display, DefaultRootWindow(display));
204  for (int iscres = screen->noutput - 1; iscres >= 0; --iscres) {
205  RROutput output = screen->outputs[iscres];
206  MonitorInfo * mi = read_edid_data(display, output);
207  if (mi == NULL) {
208  continue;
209  }
210 
211  XRROutputInfo * info = XRRGetOutputInfo (display, screen, output);
212  if (info && (0 == memcmp(mi->manufacturer_code, "OVR", 3))) {
214  // Generate a device ID string similar to the way Windows does it
215  char device_id[32];
216  OVR_sprintf(device_id, 32, "%s%04d", mi->manufacturer_code, mi->product_code);
217 
218  // The default monitor coordinates
219  int mx = 0;
220  int my = 0;
221  int mwidth = 1280;
222  int mheight = 800;
223 
224  if (info->connection == RR_Connected && info->crtc) {
225  XRRCrtcInfo * crtc_info = XRRGetCrtcInfo (display, screen, info->crtc);
226  if (crtc_info)
227  {
228  mx = crtc_info->x;
229  my = crtc_info->y;
230  //mwidth = crtc_info->width;
231  //mheight = crtc_info->height;
232  XRRFreeCrtcInfo(crtc_info);
233  }
234  }
235 
236  String deviceID = device_id;
237  HMDDeviceCreateDesc hmdCreateDesc(this, deviceID, iscres);
238 
239  // Hard-coded defaults in case the device doesn't have the data itself.
240  if (strstr(device_id, "OVR0003"))
241  { // DK2 prototypes and variants (default to HmdType_DK2)
242  hmdCreateDesc.SetScreenParameters(mx, my, 1920, 1080, 0.12576f, 0.07074f, 0.12576f*0.5f, 0.0635f );
243  }
244  else if (strstr(device_id, "OVR0002"))
245  { // HD Prototypes (default to HmdType_DKHDProto)
246  hmdCreateDesc.SetScreenParameters(mx, my, 1920, 1080, 0.12096f, 0.06804f, 0.06804f*0.5f, 0.0635f );
247  }
248  else if (strstr(device_id, "OVR0001"))
249  { // DK1
250  hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.14976f, 0.0936f, 0.0936f*0.5f, 0.0635f);
251  }
252  else if (strstr(device_id, "OVR00"))
253  { // Future Oculus HMD devices (default to DK1 dimensions)
254  hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.14976f, 0.0936f, 0.0936f*0.5f, 0.0635f);
255  }
256  else
257  { // Duct-tape prototype
258  hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.12096f, 0.0756f, 0.0756f*0.5f, 0.0635f);
259  }
260 
261  OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %s - %s\n", device_id, mi->dsc_product_name));
262 
263  // Notify caller about detected device. This will call EnumerateAddDevice
264  // if the this is the first time device was detected.
265  visitor.Visit(hmdCreateDesc);
266  foundHMD = true;
267  break;
268  } // if
270  XRRFreeOutputInfo(info);
271  delete mi;
272  } // for
273  XRRFreeScreenResources(screen);
276  // Real HMD device is not found; however, we still may have a 'fake' HMD
277  // device created via SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo.
278  // Need to find it and set 'Enumerated' to true to avoid Removal notification.
279  if (!foundHMD)
280  {
281  Ptr<DeviceCreateDesc> hmdDevDesc = getManager()->FindDevice("", Device_HMD);
282  if (hmdDevDesc)
283  hmdDevDesc->Enumerated = true;
284  }
285 }
286 
287 #include "OVR_Common_HMDDevice.cpp"
288 
289 }} // namespace OVR::Linux
290 
291 
virtual void EnumerateDevices(EnumerateVisitor &visitor)
DeviceFactory *const pFactory
char dsc_product_name[14]
Definition: edid.h:170
virtual MatchResult MatchDevice(const DeviceCreateDesc &other, DeviceCreateDesc **) const
#define NULL
__BEGIN_NAMESPACE_STD void * memcpy(void *__restrict __dest, const void *__restrict __src, size_t __n) __THROW __nonnull((1
Ptr< DeviceCreateDesc > FindDevice(const String &path, DeviceType=Device_None)
#define OVR_ASSERT(p)
const DeviceType Type
int memcmp(const void *__s1, const void *__s2, size_t __n) __THROW __attribute_pure__ __nonnull((1
HMDDeviceCreateDesc(DeviceFactory *factory, const String &displayDeviceName, long dispId)
virtual bool UpdateMatchedCandidate(const DeviceCreateDesc &, bool *newDeviceFlag=NULL)
#define OVR_DEBUG_LOG_TEXT(args)
Definition: OVR_Log.h:197
struct OVR::Linux::HMDDeviceCreateDesc::@37 Desktop
virtual void Visit(const DeviceCreateDesc &createDesc)=0
bool IsEmpty() const
Definition: OVR_String.h:191
DeviceCreateDesc(DeviceFactory *factory, DeviceType type)
Size< float > Sizef
Definition: OVR_Math.h:638
MonitorInfo * read_edid_data(Display *disp, RROutput id)
Definition: edid.cpp:428
int product_code
Definition: edid.h:97
char manufacturer_code[4]
Definition: edid.h:96
UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char *format,...)
Definition: OVR_Std.h:280
static HMDDeviceFactory & GetInstance()
DeviceManager * getManager() const
static int OVR_STDCALL CompareNoCase(const char *a, const char *b)
Definition: OVR_String.cpp:488
__END_NAMESPACE_STD __BEGIN_NAMESPACE_STD size_t size_t char char * strstr(const char *__haystack, const char *__needle) __THROW __attribute_pure__ __nonnull((1
Size< int > Sizei
Definition: OVR_Math.h:636