From 1b6d8a6ed6375ec37ebc6f209fe1a75d689ec908 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Fri, 12 Sep 2014 17:00:05 +0200 Subject: [PATCH] Enabled enumeration of mirroring displays. This exposes all monitors in every mirroring group, which is needed for robust detection of an Oculus Rift. --- include/GLFW/glfw3native.h | 4 +- src/cocoa_monitor.m | 14 ++++- src/win32_monitor.c | 120 +++++++++++++++++-------------------- src/win32_platform.h | 3 +- src/x11_monitor.c | 83 ++++++++++--------------- 5 files changed, 101 insertions(+), 123 deletions(-) diff --git a/include/GLFW/glfw3native.h b/include/GLFW/glfw3native.h index 35d6f49b..13c9f81e 100644 --- a/include/GLFW/glfw3native.h +++ b/include/GLFW/glfw3native.h @@ -108,8 +108,8 @@ extern "C" { *************************************************************************/ #if defined(GLFW_EXPOSE_NATIVE_WIN32) -/*! @brief Returns the device name of the specified monitor. - * @return The the device name of the specified monitor. +/*! @brief Returns the display device name of the specified monitor. + * @return The the display device name of the specified monitor. * @ingroup native */ GLFWAPI const WCHAR* glfwGetWin32Monitor(GLFWmonitor* monitor); diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 19187733..de7c6245 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -252,18 +252,26 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) *count = 0; - CGGetActiveDisplayList(0, NULL, &displayCount); + CGGetOnlineDisplayList(0, NULL, &displayCount); displays = calloc(displayCount, sizeof(CGDirectDisplayID)); monitors = calloc(displayCount, sizeof(_GLFWmonitor*)); - CGGetActiveDisplayList(displayCount, displays, &displayCount); + CGGetOnlineDisplayList(displayCount, displays, &displayCount); NSArray* screens = [NSScreen screens]; for (i = 0; i < displayCount; i++) { int j; + + if (CGDisplayIsAsleep(displays[i])) + continue; + + CGDirectDisplayID screenDisplayID = CGDisplayMirrorsDisplay(displays[i]); + if (screenDisplayID == kCGNullDirectDisplay) + screenDisplayID = displays[i]; + const CGSize size = CGDisplayScreenSize(displays[i]); char* name = getDisplayName(displays[i]); @@ -278,7 +286,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) NSDictionary* dictionary = [screen deviceDescription]; NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"]; - if (monitors[found]->ns.displayID == [number unsignedIntegerValue]) + if ([number unsignedIntegerValue] == screenDisplayID) { monitors[found]->ns.screen = screen; break; diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 573de880..bc528b1f 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -70,7 +70,7 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) dm.dmBitsPerPel = 32; - if (ChangeDisplaySettingsExW(monitor->win32.name, + if (ChangeDisplaySettingsExW(monitor->win32.adapterName, &dm, NULL, CDS_FULLSCREEN, @@ -90,7 +90,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor) { if (monitor->win32.modeChanged) { - ChangeDisplaySettingsExW(monitor->win32.name, + ChangeDisplaySettingsExW(monitor->win32.adapterName, NULL, NULL, CDS_FULLSCREEN, NULL); monitor->win32.modeChanged = GL_FALSE; } @@ -105,16 +105,13 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) { int size = 0, found = 0; _GLFWmonitor** monitors = NULL; - DWORD adapterIndex = 0; - int primaryIndex = 0; + DWORD adapterIndex, displayIndex; *count = 0; - for (;;) + for (adapterIndex = 0; ; adapterIndex++) { - DISPLAY_DEVICEW adapter, display; - char* name; - HDC dc; + DISPLAY_DEVICEW adapter; ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW)); adapter.cb = sizeof(DISPLAY_DEVICEW); @@ -122,60 +119,55 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0)) break; - adapterIndex++; - - if ((adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) || - !(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) - { + if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) continue; - } - if (found == size) + for (displayIndex = 0; ; displayIndex++) { - if (size) - size *= 2; - else - size = 4; + DISPLAY_DEVICEW display; + char* name; + HDC dc; - monitors = (_GLFWmonitor**) realloc(monitors, sizeof(_GLFWmonitor*) * size); + ZeroMemory(&display, sizeof(DISPLAY_DEVICEW)); + display.cb = sizeof(DISPLAY_DEVICEW); + + if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0)) + break; + + if (found == size) + { + size += 4; + monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size); + } + + name = _glfwCreateUTF8FromWideString(display.DeviceString); + if (!name) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Failed to convert string to UTF-8"); + continue; + } + + dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL); + + monitors[found] = _glfwAllocMonitor(name, + GetDeviceCaps(dc, HORZSIZE), + GetDeviceCaps(dc, VERTSIZE)); + + DeleteDC(dc); + free(name); + + wcscpy(monitors[found]->win32.adapterName, adapter.DeviceName); + wcscpy(monitors[found]->win32.displayName, display.DeviceName); + + if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE && + displayIndex == 0) + { + _GLFW_SWAP_POINTERS(monitors[0], monitors[found]); + } + + found++; } - - ZeroMemory(&display, sizeof(DISPLAY_DEVICEW)); - display.cb = sizeof(DISPLAY_DEVICEW); - - EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0); - dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL); - - if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - primaryIndex = found; - - name = _glfwCreateUTF8FromWideString(display.DeviceString); - if (!name) - { - _glfwFreeMonitors(monitors, found); - _glfwInputError(GLFW_PLATFORM_ERROR, - "Failed to convert string to UTF-8"); - - free(monitors); - return NULL; - } - - monitors[found] = _glfwAllocMonitor(name, - GetDeviceCaps(dc, HORZSIZE), - GetDeviceCaps(dc, VERTSIZE)); - - free(name); - DeleteDC(dc); - - wcscpy(monitors[found]->win32.name, adapter.DeviceName); - found++; - } - - if (primaryIndex > 0) - { - _GLFWmonitor* temp = monitors[0]; - monitors[0] = monitors[primaryIndex]; - monitors[primaryIndex] = temp; } *count = found; @@ -184,7 +176,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) { - return wcscmp(first->win32.name, second->win32.name) == 0; + return wcscmp(first->win32.displayName, second->win32.displayName) == 0; } void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) @@ -193,7 +185,7 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) ZeroMemory(&settings, sizeof(DEVMODEW)); settings.dmSize = sizeof(DEVMODEW); - EnumDisplaySettingsExW(monitor->win32.name, + EnumDisplaySettingsExW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &settings, EDS_ROTATEDMODE); @@ -220,7 +212,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) ZeroMemory(&dm, sizeof(DEVMODEW)); dm.dmSize = sizeof(DEVMODEW); - if (!EnumDisplaySettingsW(monitor->win32.name, modeIndex, &dm)) + if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm)) break; modeIndex++; @@ -275,7 +267,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) ZeroMemory(&dm, sizeof(DEVMODEW)); dm.dmSize = sizeof(DEVMODEW); - EnumDisplaySettingsW(monitor->win32.name, ENUM_CURRENT_SETTINGS, &dm); + EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm); mode->width = dm.dmPelsWidth; mode->height = dm.dmPelsHeight; @@ -291,7 +283,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) HDC dc; WORD values[768]; - dc = CreateDCW(L"DISPLAY", monitor->win32.name, NULL, NULL); + dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL); GetDeviceGammaRamp(dc, values); DeleteDC(dc); @@ -318,7 +310,7 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short)); memcpy(values + 512, ramp->blue, 256 * sizeof(unsigned short)); - dc = CreateDCW(L"DISPLAY", monitor->win32.name, NULL, NULL); + dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL); SetDeviceGammaRamp(dc, values); DeleteDC(dc); } @@ -332,6 +324,6 @@ GLFWAPI const WCHAR* glfwGetWin32Monitor(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - return monitor->win32.name; + return monitor->win32.displayName; } diff --git a/src/win32_platform.h b/src/win32_platform.h index 697ade4a..09dab722 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -203,7 +203,8 @@ typedef struct _GLFWlibraryWin32 typedef struct _GLFWmonitorWin32 { // This size matches the static size of DISPLAY_DEVICE.DeviceName - WCHAR name[32]; + WCHAR adapterName[32]; + WCHAR displayName[32]; GLboolean modeChanged; } _GLFWmonitorWin32; diff --git a/src/x11_monitor.c b/src/x11_monitor.c index 498d7e88..a8c17511 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -200,87 +200,64 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor) _GLFWmonitor** _glfwPlatformGetMonitors(int* count) { - int i, found = 0; + int i, j, size = 0, found = 0; _GLFWmonitor** monitors = NULL; *count = 0; if (_glfw.x11.randr.available) { - RROutput primary; - XRRScreenResources* sr; - - sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); - primary = XRRGetOutputPrimary(_glfw.x11.display, _glfw.x11.root); - - monitors = calloc(sr->ncrtc, sizeof(_GLFWmonitor*)); + XRRScreenResources* sr = XRRGetScreenResources(_glfw.x11.display, + _glfw.x11.root); + RROutput primary = XRRGetOutputPrimary(_glfw.x11.display, + _glfw.x11.root); for (i = 0; i < sr->ncrtc; i++) { - int j; - XRROutputInfo* oi; - XRRCrtcInfo* ci; - RROutput output; - - ci = XRRGetCrtcInfo(_glfw.x11.display, sr, sr->crtcs[i]); - if (ci->noutput == 0) - { - XRRFreeCrtcInfo(ci); - continue; - } - - output = ci->outputs[0]; + XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, + sr, sr->crtcs[i]); for (j = 0; j < ci->noutput; j++) { - if (ci->outputs[j] == primary) + XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, + sr, ci->outputs[j]); + if (oi->connection != RR_Connected) { - output = primary; - break; + XRRFreeOutputInfo(oi); + continue; } - } - oi = XRRGetOutputInfo(_glfw.x11.display, sr, output); - if (oi->connection != RR_Connected) - { + if (found == size) + { + size += 4; + monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size); + } + + monitors[found] = _glfwAllocMonitor(oi->name, + oi->mm_width, + oi->mm_height); + + monitors[found]->x11.output = ci->outputs[j]; + monitors[found]->x11.crtc = oi->crtc; + XRRFreeOutputInfo(oi); - XRRFreeCrtcInfo(ci); - continue; + + if (ci->outputs[j] == primary) + _GLFW_SWAP_POINTERS(monitors[0], monitors[found]); + + found++; } - monitors[found] = _glfwAllocMonitor(oi->name, - oi->mm_width, oi->mm_height); - - monitors[found]->x11.output = output; - monitors[found]->x11.crtc = oi->crtc; - - XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); - - found++; } XRRFreeScreenResources(sr); - for (i = 0; i < found; i++) - { - if (monitors[i]->x11.output == primary) - { - _GLFWmonitor* temp = monitors[0]; - monitors[0] = monitors[i]; - monitors[i] = temp; - break; - } - } - if (found == 0) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: RandR monitor support seems broken"); _glfw.x11.randr.monitorBroken = GL_TRUE; - - free(monitors); - monitors = NULL; } }