rev |
line source |
nuclear@0
|
1 /************************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 Filename : OVR_Linux_Display.cpp
|
nuclear@0
|
4 Content : Linux-specific Display declarations
|
nuclear@0
|
5 Created : July 2, 2014
|
nuclear@0
|
6 Authors : James Hughes
|
nuclear@0
|
7
|
nuclear@0
|
8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
12 which is provided at the time of installation or download, or which
|
nuclear@0
|
13 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
14
|
nuclear@0
|
15 You may obtain a copy of the License at
|
nuclear@0
|
16
|
nuclear@0
|
17 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
18
|
nuclear@0
|
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
20 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
22 See the License for the specific language governing permissions and
|
nuclear@0
|
23 limitations under the License.
|
nuclear@0
|
24
|
nuclear@0
|
25 *************************************************************************************/
|
nuclear@0
|
26
|
nuclear@0
|
27 #include "OVR_Linux_Display.h"
|
nuclear@0
|
28 #include "../Kernel/OVR_Log.h"
|
nuclear@0
|
29
|
nuclear@0
|
30 #include "../../../3rdParty/EDID/edid.h"
|
nuclear@0
|
31
|
nuclear@0
|
32 #include <X11/Xlib.h>
|
nuclear@0
|
33 #include <X11/Xutil.h>
|
nuclear@0
|
34 #include <X11/extensions/Xrandr.h>
|
nuclear@0
|
35 #include <X11/Xatom.h>
|
nuclear@0
|
36
|
nuclear@0
|
37 //-------------------------------------------------------------------------------------
|
nuclear@0
|
38 // ***** Display enumeration Helpers
|
nuclear@0
|
39
|
nuclear@0
|
40 namespace OVR {
|
nuclear@0
|
41
|
nuclear@0
|
42 static const uint8_t edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
|
nuclear@0
|
43 0xff, 0xff, 0xff, 0x00 };
|
nuclear@0
|
44
|
nuclear@0
|
45 static const uint8_t edid_v1_descriptor_flag[] = { 0x00, 0x00 };
|
nuclear@0
|
46
|
nuclear@0
|
47 static const int DESCRIPTOR_DATA = 5;
|
nuclear@0
|
48 static const int UNKNOWN_DESCRIPTOR = -1;
|
nuclear@0
|
49 static const int DETAILED_TIMING_BLOCK = -2;
|
nuclear@0
|
50
|
nuclear@0
|
51 // The following three functions were pulled from OVR_Linux_Display.cpp
|
nuclear@0
|
52 // and modified slightly.
|
nuclear@0
|
53 static int blockType(uint8_t* block)
|
nuclear@0
|
54 {
|
nuclear@0
|
55 if (!strncmp((const char*)edid_v1_descriptor_flag, (const char*)block, 2))
|
nuclear@0
|
56 {
|
nuclear@0
|
57 if (block[2] != 0)
|
nuclear@0
|
58 {
|
nuclear@0
|
59 return UNKNOWN_DESCRIPTOR;
|
nuclear@0
|
60 }
|
nuclear@0
|
61 else
|
nuclear@0
|
62 {
|
nuclear@0
|
63 return block[3];
|
nuclear@0
|
64 }
|
nuclear@0
|
65 }
|
nuclear@0
|
66 else
|
nuclear@0
|
67 {
|
nuclear@0
|
68 return DETAILED_TIMING_BLOCK;
|
nuclear@0
|
69 }
|
nuclear@0
|
70 }
|
nuclear@0
|
71
|
nuclear@0
|
72 static char* getMonitorName(const uint8_t* block)
|
nuclear@0
|
73 {
|
nuclear@0
|
74 static char name[13];
|
nuclear@0
|
75 uint8_t const* ptr = block + DESCRIPTOR_DATA;
|
nuclear@0
|
76
|
nuclear@0
|
77 for (int i = 0; i < 13; i++, ptr++)
|
nuclear@0
|
78 {
|
nuclear@0
|
79 if (*ptr == 0xa)
|
nuclear@0
|
80 {
|
nuclear@0
|
81 name[i] = 0;
|
nuclear@0
|
82 return name;
|
nuclear@0
|
83 }
|
nuclear@0
|
84
|
nuclear@0
|
85 name[i] = *ptr;
|
nuclear@0
|
86 }
|
nuclear@0
|
87
|
nuclear@0
|
88 return name;
|
nuclear@0
|
89 }
|
nuclear@0
|
90
|
nuclear@0
|
91 // Returns -1 on failure, 0 otherwise.
|
nuclear@0
|
92 static int parseEdid(uint8_t* edid, Linux::DisplayEDID& edidResult)
|
nuclear@0
|
93 {
|
nuclear@0
|
94 const int EDID_LENGTH = 0x80;
|
nuclear@0
|
95 const int EDID_HEADER = 0x00;
|
nuclear@0
|
96 const int EDID_HEADER_END = 0x07;
|
nuclear@0
|
97
|
nuclear@0
|
98 // const int EDID_STRUCT_VERSION = 0x12;
|
nuclear@0
|
99 // const int EDID_STRUCT_REVISION = 0x13;
|
nuclear@0
|
100
|
nuclear@0
|
101 const int MONITOR_NAME = 0xfc;
|
nuclear@0
|
102 // const int MONITOR_LIMITS = 0xfd;
|
nuclear@0
|
103 const int MONITOR_SERIAL = 0xff;
|
nuclear@0
|
104
|
nuclear@0
|
105 // const int ESTABLISHED_TIMING_1 = 0x23;
|
nuclear@0
|
106 // const int ESTABLISHED_TIMING_2 = 0x24;
|
nuclear@0
|
107 // const int MANUFACTURERS_TIMINGS = 0x25;
|
nuclear@0
|
108
|
nuclear@0
|
109 const int DETAILED_TIMING_DESCRIPTIONS_START = 0x36;
|
nuclear@0
|
110 const int DETAILED_TIMING_DESCRIPTION_SIZE = 18;
|
nuclear@0
|
111 const int NO_DETAILED_TIMING_DESCRIPTIONS = 4;
|
nuclear@0
|
112
|
nuclear@0
|
113 // const int DETAILED_TIMING_DESCRIPTION_1 = 0x36;
|
nuclear@0
|
114 // const int DETAILED_TIMING_DESCRIPTION_2 = 0x48;
|
nuclear@0
|
115 // const int DETAILED_TIMING_DESCRIPTION_3 = 0x5a;
|
nuclear@0
|
116 // const int DETAILED_TIMING_DESCRIPTION_4 = 0x6c;
|
nuclear@0
|
117
|
nuclear@0
|
118 const char* monitorName = "Unknown";
|
nuclear@0
|
119 uint8_t* block = NULL;
|
nuclear@0
|
120 uint8_t checksum = 0;
|
nuclear@0
|
121
|
nuclear@0
|
122 for (int i = 0; i < EDID_LENGTH; i++)
|
nuclear@0
|
123 {
|
nuclear@0
|
124 checksum += edid[i];
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 // Bad checksum, fail EDID
|
nuclear@0
|
128 if (checksum != 0)
|
nuclear@0
|
129 {
|
nuclear@0
|
130 return -1;
|
nuclear@0
|
131 }
|
nuclear@0
|
132
|
nuclear@0
|
133 if (strncmp((const char*)edid + EDID_HEADER,
|
nuclear@0
|
134 (const char*)edid_v1_header, EDID_HEADER_END + 1))
|
nuclear@0
|
135 {
|
nuclear@0
|
136 // First bytes don't match EDID version 1 header
|
nuclear@0
|
137 return -1;
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 // Monitor name and timings
|
nuclear@0
|
141 char serialNumber[14];
|
nuclear@0
|
142 memset(serialNumber, 0, 14);
|
nuclear@0
|
143
|
nuclear@0
|
144 block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
|
nuclear@0
|
145
|
nuclear@0
|
146 for (int i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS;
|
nuclear@0
|
147 i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
|
nuclear@0
|
148 {
|
nuclear@0
|
149
|
nuclear@0
|
150 if (blockType(block) == MONITOR_NAME)
|
nuclear@0
|
151 {
|
nuclear@0
|
152 monitorName = getMonitorName(block);
|
nuclear@0
|
153 }
|
nuclear@0
|
154
|
nuclear@0
|
155 if (blockType(block) == MONITOR_SERIAL)
|
nuclear@0
|
156 {
|
nuclear@0
|
157 memcpy(serialNumber, block + 5, 13);
|
nuclear@0
|
158 break;
|
nuclear@0
|
159 }
|
nuclear@0
|
160 }
|
nuclear@0
|
161
|
nuclear@0
|
162 uint8_t vendorString[4] = {0};
|
nuclear@0
|
163
|
nuclear@0
|
164 vendorString[0] = (edid[8] >> 2 & 31) + 64;
|
nuclear@0
|
165 vendorString[1] = (((edid[8] & 3) << 3) | (edid[9] >> 5)) + 64;
|
nuclear@0
|
166 vendorString[2] = (edid[9] & 31) + 64;
|
nuclear@0
|
167
|
nuclear@0
|
168 edidResult.ModelNumber = *(uint16_t*)&edid[10];
|
nuclear@0
|
169 edidResult.MonitorName = monitorName;
|
nuclear@0
|
170 edidResult.VendorName = reinterpret_cast<const char*>(vendorString);
|
nuclear@0
|
171 edidResult.SerialNumber = serialNumber;
|
nuclear@0
|
172
|
nuclear@0
|
173 // FIXME: Get timings as well
|
nuclear@0
|
174
|
nuclear@0
|
175 // std::cout << "# EDID version " << static_cast<int>(edid[EDID_STRUCT_VERSION])
|
nuclear@0
|
176 // << " revision " << static_cast<int>(edid[EDID_STRUCT_REVISION])
|
nuclear@0
|
177 // << std::endl;
|
nuclear@0
|
178
|
nuclear@0
|
179 return 0;
|
nuclear@0
|
180 }
|
nuclear@0
|
181
|
nuclear@0
|
182
|
nuclear@0
|
183 // Returns -1 in the case of failure, 0 otherwise.
|
nuclear@0
|
184 // Parameters:
|
nuclear@0
|
185 // data OUT This pointer is modified to point to the output from
|
nuclear@0
|
186 // XRRGetOutputProperty. You *must* call XFree on this pointer.
|
nuclear@0
|
187 // dataLen OUT The length of the data returned in 'data'.
|
nuclear@0
|
188 static int getXRRProperty(struct _XDisplay* display, RROutput output, Atom atom,
|
nuclear@0
|
189 uint8_t** data, int* dataLen)
|
nuclear@0
|
190 {
|
nuclear@0
|
191 unsigned long nitems;
|
nuclear@0
|
192 unsigned long bytesAfter;
|
nuclear@0
|
193 int actualFormat;
|
nuclear@0
|
194 Atom actualType;
|
nuclear@0
|
195
|
nuclear@0
|
196 int ret = XRRGetOutputProperty(display, output, atom, 0, 100,
|
nuclear@0
|
197 False, False, AnyPropertyType,
|
nuclear@0
|
198 &actualType, &actualFormat, &nitems,
|
nuclear@0
|
199 &bytesAfter, data);
|
nuclear@0
|
200
|
nuclear@0
|
201 if (None != ret)
|
nuclear@0
|
202 {
|
nuclear@0
|
203 *dataLen = nitems;
|
nuclear@0
|
204 return 0;
|
nuclear@0
|
205 }
|
nuclear@0
|
206 else
|
nuclear@0
|
207 {
|
nuclear@0
|
208 return -1;
|
nuclear@0
|
209 }
|
nuclear@0
|
210 }
|
nuclear@0
|
211
|
nuclear@0
|
212 static XRRModeInfo* findModeByXID(XRRScreenResources* screen, RRMode xid)
|
nuclear@0
|
213 {
|
nuclear@0
|
214 for (int m = 0; m < screen->nmode; ++m)
|
nuclear@0
|
215 {
|
nuclear@0
|
216 XRRModeInfo* mode = &screen->modes[m];
|
nuclear@0
|
217 if (xid == mode->id)
|
nuclear@0
|
218 {
|
nuclear@0
|
219 return mode;
|
nuclear@0
|
220 }
|
nuclear@0
|
221 }
|
nuclear@0
|
222 return NULL;
|
nuclear@0
|
223 }
|
nuclear@0
|
224
|
nuclear@0
|
225 static int discoverExtendedRifts(OVR::Linux::DisplayDesc* descriptorArray, int inputArraySize, bool /*edidInfo*/)
|
nuclear@0
|
226 {
|
nuclear@0
|
227 int result = 0;
|
nuclear@0
|
228
|
nuclear@0
|
229 struct _XDisplay* display = XOpenDisplay(NULL);
|
nuclear@0
|
230
|
nuclear@0
|
231 if (display == NULL)
|
nuclear@0
|
232 {
|
nuclear@0
|
233 OVR::LogError("[Linux Display] Unable to open X Display!");
|
nuclear@0
|
234 return 0;
|
nuclear@0
|
235 }
|
nuclear@0
|
236
|
nuclear@0
|
237 Atom EDIDAtom = XInternAtom(display, RR_PROPERTY_RANDR_EDID, False);
|
nuclear@0
|
238 int numScreens = XScreenCount(display);
|
nuclear@0
|
239 for (int i = 0; i < numScreens; ++i)
|
nuclear@0
|
240 {
|
nuclear@0
|
241 Window sr = XRootWindow(display, i);
|
nuclear@0
|
242 XRRScreenResources* screen = XRRGetScreenResources(display, sr);
|
nuclear@0
|
243
|
nuclear@0
|
244 for (int ii = 0; ii < screen->ncrtc; ++ii)
|
nuclear@0
|
245 {
|
nuclear@0
|
246 XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(display, screen, screen->crtcs[ii]);
|
nuclear@0
|
247
|
nuclear@0
|
248 if (0 == crtcInfo->noutput)
|
nuclear@0
|
249 {
|
nuclear@0
|
250 XRRFreeCrtcInfo(crtcInfo);
|
nuclear@0
|
251 continue;
|
nuclear@0
|
252 }
|
nuclear@0
|
253
|
nuclear@0
|
254 bool foundOutput = false;
|
nuclear@0
|
255 RROutput output = crtcInfo->outputs[0];
|
nuclear@0
|
256 for (int k = 0; k < crtcInfo->noutput; ++k)
|
nuclear@0
|
257 {
|
nuclear@0
|
258 XRROutputInfo* outputInfo =
|
nuclear@0
|
259 XRRGetOutputInfo(display, screen, crtcInfo->outputs[k]);
|
nuclear@0
|
260
|
nuclear@0
|
261 for (int kk = 0; kk < outputInfo->nmode; ++kk)
|
nuclear@0
|
262 {
|
nuclear@0
|
263 if (outputInfo->modes[kk] == crtcInfo->mode)
|
nuclear@0
|
264 {
|
nuclear@0
|
265 output = crtcInfo->outputs[k];
|
nuclear@0
|
266 foundOutput = true;
|
nuclear@0
|
267 break;
|
nuclear@0
|
268 }
|
nuclear@0
|
269 }
|
nuclear@0
|
270 XRRFreeOutputInfo(outputInfo);
|
nuclear@0
|
271 if (foundOutput)
|
nuclear@0
|
272 {
|
nuclear@0
|
273 break;
|
nuclear@0
|
274 }
|
nuclear@0
|
275 }
|
nuclear@0
|
276
|
nuclear@0
|
277 if (!foundOutput)
|
nuclear@0
|
278 {
|
nuclear@0
|
279 XRRFreeCrtcInfo(crtcInfo);
|
nuclear@0
|
280 continue;
|
nuclear@0
|
281 }
|
nuclear@0
|
282
|
nuclear@0
|
283 XRROutputInfo* outputInfo = XRRGetOutputInfo(display, screen, output);
|
nuclear@0
|
284 if (RR_Connected != outputInfo->connection)
|
nuclear@0
|
285 {
|
nuclear@0
|
286 XRRFreeOutputInfo(outputInfo);
|
nuclear@0
|
287 XRRFreeCrtcInfo(crtcInfo);
|
nuclear@0
|
288 continue;
|
nuclear@0
|
289 }
|
nuclear@0
|
290
|
nuclear@0
|
291 // Read EDID associated with crtc.
|
nuclear@0
|
292 uint8_t* data = NULL;
|
nuclear@0
|
293 int dataLen = 0;
|
nuclear@0
|
294 if (getXRRProperty(display, output, EDIDAtom, &data, &dataLen) != 0)
|
nuclear@0
|
295 {
|
nuclear@0
|
296 // Identify rifts based on EDID.
|
nuclear@0
|
297 Linux::DisplayEDID edid;
|
nuclear@0
|
298 parseEdid(data, edid);
|
nuclear@0
|
299 XFree(data);
|
nuclear@0
|
300 data = NULL;
|
nuclear@0
|
301
|
nuclear@0
|
302 // TODO: Remove either this 3rdParty call to read EDID data
|
nuclear@0
|
303 // or remove our own parsing of the EDID. Probably opt
|
nuclear@0
|
304 // to remove our parsing.
|
nuclear@0
|
305 MonitorInfo* mi = read_edid_data(display, output);
|
nuclear@0
|
306 if (mi == NULL)
|
nuclear@0
|
307 {
|
nuclear@0
|
308 XRRFreeOutputInfo(outputInfo);
|
nuclear@0
|
309 XRRFreeCrtcInfo(crtcInfo);
|
nuclear@0
|
310 continue;
|
nuclear@0
|
311 }
|
nuclear@0
|
312
|
nuclear@0
|
313 if (edid.VendorName == "OVR")
|
nuclear@0
|
314 {
|
nuclear@0
|
315 if( result >= inputArraySize )
|
nuclear@0
|
316 {
|
nuclear@0
|
317 delete mi;
|
nuclear@0
|
318 XRRFreeOutputInfo(outputInfo);
|
nuclear@0
|
319 XRRFreeCrtcInfo(crtcInfo);
|
nuclear@0
|
320 return result;
|
nuclear@0
|
321 }
|
nuclear@0
|
322
|
nuclear@0
|
323 XRRModeInfo* modeInfo = findModeByXID(screen, crtcInfo->mode);
|
nuclear@0
|
324
|
nuclear@0
|
325 int width = modeInfo->width;
|
nuclear@0
|
326 int height = modeInfo->height;
|
nuclear@0
|
327
|
nuclear@0
|
328 if ( crtcInfo->rotation == RR_Rotate_90
|
nuclear@0
|
329 || crtcInfo->rotation == RR_Rotate_270 )
|
nuclear@0
|
330 {
|
nuclear@0
|
331 width = modeInfo->height;
|
nuclear@0
|
332 height = modeInfo->width;
|
nuclear@0
|
333 }
|
nuclear@0
|
334
|
nuclear@0
|
335 int x = crtcInfo->x;
|
nuclear@0
|
336 int y = crtcInfo->y;
|
nuclear@0
|
337
|
nuclear@0
|
338 // Generate a device ID string similar Windows does it
|
nuclear@0
|
339 char device_id[32];
|
nuclear@0
|
340 OVR_sprintf(device_id, 32, "%s%04d-%d",
|
nuclear@0
|
341 mi->manufacturer_code, mi->product_code,
|
nuclear@0
|
342 screen->crtcs[ii]);
|
nuclear@0
|
343
|
nuclear@0
|
344 OVR::Linux::DisplayDesc& desc = descriptorArray[result++];
|
nuclear@0
|
345 desc.DisplayID = device_id;
|
nuclear@0
|
346 desc.ModelName = edid.MonitorName;
|
nuclear@0
|
347 desc.EdidSerialNumber = edid.SerialNumber;
|
nuclear@0
|
348 desc.LogicalResolutionInPixels = Sizei(width, height);
|
nuclear@0
|
349 desc.DesktopDisplayOffset = Vector2i(x, y);
|
nuclear@0
|
350
|
nuclear@0
|
351 switch (mi->product_code)
|
nuclear@0
|
352 {
|
nuclear@0
|
353 case 3: desc.DeviceTypeGuess = HmdType_DK2; break;
|
nuclear@0
|
354 case 2: desc.DeviceTypeGuess = HmdType_DKHDProto; break;
|
nuclear@0
|
355 case 1: desc.DeviceTypeGuess = HmdType_DK1; break;
|
nuclear@0
|
356
|
nuclear@0
|
357 default:
|
nuclear@0
|
358 case 0: desc.DeviceTypeGuess = HmdType_Unknown; break;
|
nuclear@0
|
359 }
|
nuclear@0
|
360
|
nuclear@0
|
361 // Hard-coded defaults in case the device doesn't have the
|
nuclear@0
|
362 // data itself. DK2 prototypes (0003) or DK HD Prototypes (0002).
|
nuclear@0
|
363 if ( desc.DeviceTypeGuess == HmdType_DK2
|
nuclear@0
|
364 || desc.DeviceTypeGuess == HmdType_DKHDProto)
|
nuclear@0
|
365 {
|
nuclear@0
|
366 desc.LogicalResolutionInPixels = Sizei(1920, 1080);
|
nuclear@0
|
367 desc.NativeResolutionInPixels = Sizei(1080, 1920);
|
nuclear@0
|
368 }
|
nuclear@0
|
369 else
|
nuclear@0
|
370 {
|
nuclear@0
|
371 desc.LogicalResolutionInPixels = Sizei(width, height);
|
nuclear@0
|
372 desc.NativeResolutionInPixels = Sizei(width, height);
|
nuclear@0
|
373 }
|
nuclear@0
|
374 }
|
nuclear@0
|
375
|
nuclear@0
|
376 delete mi;
|
nuclear@0
|
377 mi = NULL;
|
nuclear@0
|
378 }
|
nuclear@0
|
379
|
nuclear@0
|
380 XRRFreeOutputInfo(outputInfo);
|
nuclear@0
|
381 XRRFreeCrtcInfo(crtcInfo);
|
nuclear@0
|
382 }
|
nuclear@0
|
383
|
nuclear@0
|
384 XRRFreeScreenResources(screen);
|
nuclear@0
|
385 }
|
nuclear@0
|
386
|
nuclear@0
|
387 XCloseDisplay(display);
|
nuclear@0
|
388
|
nuclear@0
|
389 return result;
|
nuclear@0
|
390 }
|
nuclear@0
|
391
|
nuclear@0
|
392
|
nuclear@0
|
393 //-------------------------------------------------------------------------------------
|
nuclear@0
|
394 // ***** Display
|
nuclear@0
|
395
|
nuclear@0
|
396 bool Display::Initialize()
|
nuclear@0
|
397 {
|
nuclear@0
|
398 // Nothing to initialize. OS X only supports compatibility mode.
|
nuclear@0
|
399 return true;
|
nuclear@0
|
400 }
|
nuclear@0
|
401
|
nuclear@0
|
402 bool Display::GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode)
|
nuclear@0
|
403 {
|
nuclear@0
|
404 driverInstalled = false;
|
nuclear@0
|
405 compatMode = true;
|
nuclear@0
|
406 hideDK1Mode = false;
|
nuclear@0
|
407 return true;
|
nuclear@0
|
408 }
|
nuclear@0
|
409
|
nuclear@0
|
410 bool Display::SetDriverMode(bool /*compatMode*/, bool /*hideDK1Mode*/)
|
nuclear@0
|
411 {
|
nuclear@0
|
412 return false;
|
nuclear@0
|
413 }
|
nuclear@0
|
414
|
nuclear@0
|
415 DisplaySearchHandle* Display::GetDisplaySearchHandle()
|
nuclear@0
|
416 {
|
nuclear@0
|
417 return new Linux::LinuxDisplaySearchHandle();
|
nuclear@0
|
418 }
|
nuclear@0
|
419
|
nuclear@0
|
420 bool Display::InCompatibilityMode( bool displaySearch )
|
nuclear@0
|
421 {
|
nuclear@0
|
422 OVR_UNUSED( displaySearch );
|
nuclear@0
|
423 return true;
|
nuclear@0
|
424 }
|
nuclear@0
|
425
|
nuclear@0
|
426 int Display::GetDisplayCount(DisplaySearchHandle* handle, bool extended, bool applicationOnly, bool edidInfo)
|
nuclear@0
|
427 {
|
nuclear@0
|
428 OVR_UNUSED4(handle, extended, applicationOnly, edidInfo);
|
nuclear@0
|
429
|
nuclear@0
|
430 static int extendedCount = -1;
|
nuclear@0
|
431
|
nuclear@0
|
432 Linux::LinuxDisplaySearchHandle* localHandle = (Linux::LinuxDisplaySearchHandle*)handle;
|
nuclear@0
|
433 if (localHandle == NULL)
|
nuclear@0
|
434 {
|
nuclear@0
|
435 OVR::LogError("[Linux Display] No search handle passed into GetDisplayCount. Return 0 rifts.");
|
nuclear@0
|
436 return 0;
|
nuclear@0
|
437 }
|
nuclear@0
|
438
|
nuclear@0
|
439 if (extendedCount == -1 || extended)
|
nuclear@0
|
440 {
|
nuclear@0
|
441 extendedCount = discoverExtendedRifts(localHandle->cachedDescriptorArray, Linux::LinuxDisplaySearchHandle::DescArraySize, edidInfo);
|
nuclear@0
|
442 }
|
nuclear@0
|
443
|
nuclear@0
|
444 localHandle->extended = true;
|
nuclear@0
|
445 localHandle->extendedDisplayCount = extendedCount;
|
nuclear@0
|
446 int totalCount = extendedCount;
|
nuclear@0
|
447
|
nuclear@0
|
448 /// FIXME: Implement application mode for OS X.
|
nuclear@0
|
449 localHandle->application = false;
|
nuclear@0
|
450 localHandle->applicationDisplayCount = 0;
|
nuclear@0
|
451
|
nuclear@0
|
452 localHandle->displayCount = totalCount;
|
nuclear@0
|
453
|
nuclear@0
|
454 return totalCount;
|
nuclear@0
|
455 }
|
nuclear@0
|
456
|
nuclear@0
|
457
|
nuclear@0
|
458 Ptr<Display> Display::GetDisplay( int index, DisplaySearchHandle* handle )
|
nuclear@0
|
459 {
|
nuclear@0
|
460 Ptr<Display> result = NULL;
|
nuclear@0
|
461
|
nuclear@0
|
462 if (index < 0)
|
nuclear@0
|
463 {
|
nuclear@0
|
464 OVR::LogError("[Linux Display] Invalid index given to GetDisplay.");
|
nuclear@0
|
465 return NULL;
|
nuclear@0
|
466 }
|
nuclear@0
|
467
|
nuclear@0
|
468 Linux::LinuxDisplaySearchHandle* localHandle = (Linux::LinuxDisplaySearchHandle*)handle;
|
nuclear@0
|
469 if (localHandle == NULL)
|
nuclear@0
|
470 {
|
nuclear@0
|
471 OVR::LogError("[Linux Display] No search handle passed into GetDisplay. Return 0 rifts.");
|
nuclear@0
|
472 return NULL;
|
nuclear@0
|
473 }
|
nuclear@0
|
474
|
nuclear@0
|
475 if (localHandle->extended)
|
nuclear@0
|
476 {
|
nuclear@0
|
477 if (index >= 0 && index < (int)localHandle->extendedDisplayCount)
|
nuclear@0
|
478 {
|
nuclear@0
|
479 return *new Linux::LinuxDisplayGeneric(localHandle->cachedDescriptorArray[index]);
|
nuclear@0
|
480 }
|
nuclear@0
|
481
|
nuclear@0
|
482 index -= localHandle->extendedDisplayCount;
|
nuclear@0
|
483 }
|
nuclear@0
|
484
|
nuclear@0
|
485 if (localHandle->application)
|
nuclear@0
|
486 {
|
nuclear@0
|
487 OVR::LogError("[Linux Display] Mac does not support application displays.");
|
nuclear@0
|
488 }
|
nuclear@0
|
489
|
nuclear@0
|
490 return result;
|
nuclear@0
|
491 }
|
nuclear@0
|
492
|
nuclear@0
|
493
|
nuclear@0
|
494 } // namespace OVR
|