Enabled enumeration of mirroring displays.

This exposes all monitors in every mirroring group, which is needed for
robust detection of an Oculus Rift.
This commit is contained in:
Camilla Berglund 2014-09-12 17:00:05 +02:00
parent 8fd69bc6c2
commit 1b6d8a6ed6
5 changed files with 101 additions and 123 deletions

View File

@ -108,8 +108,8 @@ extern "C" {
*************************************************************************/ *************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32) #if defined(GLFW_EXPOSE_NATIVE_WIN32)
/*! @brief Returns the device name of the specified monitor. /*! @brief Returns the display device name of the specified monitor.
* @return The the device name of the specified monitor. * @return The the display device name of the specified monitor.
* @ingroup native * @ingroup native
*/ */
GLFWAPI const WCHAR* glfwGetWin32Monitor(GLFWmonitor* monitor); GLFWAPI const WCHAR* glfwGetWin32Monitor(GLFWmonitor* monitor);

View File

@ -252,18 +252,26 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
*count = 0; *count = 0;
CGGetActiveDisplayList(0, NULL, &displayCount); CGGetOnlineDisplayList(0, NULL, &displayCount);
displays = calloc(displayCount, sizeof(CGDirectDisplayID)); displays = calloc(displayCount, sizeof(CGDirectDisplayID));
monitors = calloc(displayCount, sizeof(_GLFWmonitor*)); monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
CGGetActiveDisplayList(displayCount, displays, &displayCount); CGGetOnlineDisplayList(displayCount, displays, &displayCount);
NSArray* screens = [NSScreen screens]; NSArray* screens = [NSScreen screens];
for (i = 0; i < displayCount; i++) for (i = 0; i < displayCount; i++)
{ {
int j; int j;
if (CGDisplayIsAsleep(displays[i]))
continue;
CGDirectDisplayID screenDisplayID = CGDisplayMirrorsDisplay(displays[i]);
if (screenDisplayID == kCGNullDirectDisplay)
screenDisplayID = displays[i];
const CGSize size = CGDisplayScreenSize(displays[i]); const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]); char* name = getDisplayName(displays[i]);
@ -278,7 +286,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
NSDictionary* dictionary = [screen deviceDescription]; NSDictionary* dictionary = [screen deviceDescription];
NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"]; NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"];
if (monitors[found]->ns.displayID == [number unsignedIntegerValue]) if ([number unsignedIntegerValue] == screenDisplayID)
{ {
monitors[found]->ns.screen = screen; monitors[found]->ns.screen = screen;
break; break;

View File

@ -70,7 +70,7 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired)
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
dm.dmBitsPerPel = 32; dm.dmBitsPerPel = 32;
if (ChangeDisplaySettingsExW(monitor->win32.name, if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
&dm, &dm,
NULL, NULL,
CDS_FULLSCREEN, CDS_FULLSCREEN,
@ -90,7 +90,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
{ {
if (monitor->win32.modeChanged) if (monitor->win32.modeChanged)
{ {
ChangeDisplaySettingsExW(monitor->win32.name, ChangeDisplaySettingsExW(monitor->win32.adapterName,
NULL, NULL, CDS_FULLSCREEN, NULL); NULL, NULL, CDS_FULLSCREEN, NULL);
monitor->win32.modeChanged = GL_FALSE; monitor->win32.modeChanged = GL_FALSE;
} }
@ -105,16 +105,13 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{ {
int size = 0, found = 0; int size = 0, found = 0;
_GLFWmonitor** monitors = NULL; _GLFWmonitor** monitors = NULL;
DWORD adapterIndex = 0; DWORD adapterIndex, displayIndex;
int primaryIndex = 0;
*count = 0; *count = 0;
for (;;) for (adapterIndex = 0; ; adapterIndex++)
{ {
DISPLAY_DEVICEW adapter, display; DISPLAY_DEVICEW adapter;
char* name;
HDC dc;
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW)); ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW); adapter.cb = sizeof(DISPLAY_DEVICEW);
@ -122,60 +119,55 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0)) if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break; break;
adapterIndex++; if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
if ((adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) ||
!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
{
continue; continue;
}
if (found == size) for (displayIndex = 0; ; displayIndex++)
{ {
if (size) DISPLAY_DEVICEW display;
size *= 2; char* name;
else HDC dc;
size = 4;
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; *count = found;
@ -184,7 +176,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) 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) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
@ -193,7 +185,7 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
ZeroMemory(&settings, sizeof(DEVMODEW)); ZeroMemory(&settings, sizeof(DEVMODEW));
settings.dmSize = sizeof(DEVMODEW); settings.dmSize = sizeof(DEVMODEW);
EnumDisplaySettingsExW(monitor->win32.name, EnumDisplaySettingsExW(monitor->win32.adapterName,
ENUM_CURRENT_SETTINGS, ENUM_CURRENT_SETTINGS,
&settings, &settings,
EDS_ROTATEDMODE); EDS_ROTATEDMODE);
@ -220,7 +212,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
ZeroMemory(&dm, sizeof(DEVMODEW)); ZeroMemory(&dm, sizeof(DEVMODEW));
dm.dmSize = sizeof(DEVMODEW); dm.dmSize = sizeof(DEVMODEW);
if (!EnumDisplaySettingsW(monitor->win32.name, modeIndex, &dm)) if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
break; break;
modeIndex++; modeIndex++;
@ -275,7 +267,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
ZeroMemory(&dm, sizeof(DEVMODEW)); ZeroMemory(&dm, sizeof(DEVMODEW));
dm.dmSize = 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->width = dm.dmPelsWidth;
mode->height = dm.dmPelsHeight; mode->height = dm.dmPelsHeight;
@ -291,7 +283,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
HDC dc; HDC dc;
WORD values[768]; WORD values[768];
dc = CreateDCW(L"DISPLAY", monitor->win32.name, NULL, NULL); dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
GetDeviceGammaRamp(dc, values); GetDeviceGammaRamp(dc, values);
DeleteDC(dc); DeleteDC(dc);
@ -318,7 +310,7 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short)); memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short));
memcpy(values + 512, ramp->blue, 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); SetDeviceGammaRamp(dc, values);
DeleteDC(dc); DeleteDC(dc);
} }
@ -332,6 +324,6 @@ GLFWAPI const WCHAR* glfwGetWin32Monitor(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return monitor->win32.name; return monitor->win32.displayName;
} }

View File

@ -203,7 +203,8 @@ typedef struct _GLFWlibraryWin32
typedef struct _GLFWmonitorWin32 typedef struct _GLFWmonitorWin32
{ {
// This size matches the static size of DISPLAY_DEVICE.DeviceName // This size matches the static size of DISPLAY_DEVICE.DeviceName
WCHAR name[32]; WCHAR adapterName[32];
WCHAR displayName[32];
GLboolean modeChanged; GLboolean modeChanged;
} _GLFWmonitorWin32; } _GLFWmonitorWin32;

View File

@ -200,87 +200,64 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
_GLFWmonitor** _glfwPlatformGetMonitors(int* count) _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{ {
int i, found = 0; int i, j, size = 0, found = 0;
_GLFWmonitor** monitors = NULL; _GLFWmonitor** monitors = NULL;
*count = 0; *count = 0;
if (_glfw.x11.randr.available) if (_glfw.x11.randr.available)
{ {
RROutput primary; XRRScreenResources* sr = XRRGetScreenResources(_glfw.x11.display,
XRRScreenResources* sr; _glfw.x11.root);
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); _glfw.x11.root);
primary = XRRGetOutputPrimary(_glfw.x11.display, _glfw.x11.root);
monitors = calloc(sr->ncrtc, sizeof(_GLFWmonitor*));
for (i = 0; i < sr->ncrtc; i++) for (i = 0; i < sr->ncrtc; i++)
{ {
int j; XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display,
XRROutputInfo* oi; sr, sr->crtcs[i]);
XRRCrtcInfo* ci;
RROutput output;
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, sr->crtcs[i]);
if (ci->noutput == 0)
{
XRRFreeCrtcInfo(ci);
continue;
}
output = ci->outputs[0];
for (j = 0; j < ci->noutput; j++) 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; XRRFreeOutputInfo(oi);
break; continue;
} }
}
oi = XRRGetOutputInfo(_glfw.x11.display, sr, output); if (found == size)
if (oi->connection != RR_Connected) {
{ 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); 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); XRRFreeCrtcInfo(ci);
found++;
} }
XRRFreeScreenResources(sr); 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) if (found == 0)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"X11: RandR monitor support seems broken"); "X11: RandR monitor support seems broken");
_glfw.x11.randr.monitorBroken = GL_TRUE; _glfw.x11.randr.monitorBroken = GL_TRUE;
free(monitors);
monitors = NULL;
} }
} }