Cleaned up monitor and video mode enumeration.

This commit is contained in:
Camilla Berglund 2015-03-23 00:08:28 +01:00
parent 6412dcb896
commit 49cf82a0ac
3 changed files with 83 additions and 100 deletions

View File

@ -252,30 +252,21 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
*count = 0; *count = 0;
CGGetOnlineDisplayList(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*));
CGGetOnlineDisplayList(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; NSUInteger j;
_GLFWmonitor* monitor;
CGDirectDisplayID screenDisplayID = CGDisplayMirrorsDisplay(displays[i]); CGDirectDisplayID screenDisplayID = CGDisplayMirrorsDisplay(displays[i]);
if (screenDisplayID == kCGNullDirectDisplay) if (screenDisplayID == kCGNullDirectDisplay)
screenDisplayID = displays[i]; screenDisplayID = displays[i];
const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]);
monitors[found] = _glfwAllocMonitor(name, size.width, size.height);
monitors[found]->ns.displayID = displays[i];
free(name);
for (j = 0; j < [screens count]; j++) for (j = 0; j < [screens count]; j++)
{ {
NSScreen* screen = [screens objectAtIndex:j]; NSScreen* screen = [screens objectAtIndex:j];
@ -283,19 +274,24 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"]; NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"];
if ([number unsignedIntegerValue] == screenDisplayID) if ([number unsignedIntegerValue] == screenDisplayID)
{
monitors[found]->ns.screen = screen;
break; break;
}
} }
if (monitors[found]->ns.screen) // Skip displays that has no screen
found++; if (j == [screens count])
else continue;
{
_glfwFreeMonitor(monitors[found]); const CGSize size = CGDisplayScreenSize(displays[i]);
monitors[found] = NULL; char* name = getDisplayName(displays[i]);
}
monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i];
monitor->ns.screen = [screens objectAtIndex:j];
free(name);
found++;
monitors[found - 1] = monitor;
} }
free(displays); free(displays);
@ -319,22 +315,22 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
*ypos = (int) bounds.origin.y; *ypos = (int) bounds.origin.y;
} }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{ {
CFArrayRef modes; CFArrayRef modes;
CFIndex count, i, j; CFIndex found, i, j;
GLFWvidmode* result; GLFWvidmode* result;
CVDisplayLinkRef link; CVDisplayLinkRef link;
*count = 0;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
count = CFArrayGetCount(modes); found = CFArrayGetCount(modes);
result = calloc(found, sizeof(GLFWvidmode));
result = calloc(count, sizeof(GLFWvidmode)); for (i = 0; i < found; i++)
*found = 0;
for (i = 0; i < count; i++)
{ {
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
if (!modeIsGood(dm)) if (!modeIsGood(dm))
@ -342,24 +338,21 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link); const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
for (j = 0; j < *found; j++) for (j = 0; j < *count; j++)
{ {
if (_glfwCompareVideoModes(result + j, &mode) == 0) if (_glfwCompareVideoModes(result + j, &mode) == 0)
break; break;
} }
if (i < *found) // Skip duplicate modes
{ if (i < *count)
// This is a duplicate, so skip it
continue; continue;
}
result[*found] = mode; (*count)++;
(*found)++; result[*count - 1] = mode;
} }
CFRelease(modes); CFRelease(modes);
CVDisplayLinkRelease(link); CVDisplayLinkRelease(link);
return result; return result;
} }

View File

@ -103,7 +103,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
_GLFWmonitor** _glfwPlatformGetMonitors(int* count) _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{ {
int size = 0, found = 0; int found = 0;
_GLFWmonitor** monitors = NULL; _GLFWmonitor** monitors = NULL;
DWORD adapterIndex, displayIndex; DWORD adapterIndex, displayIndex;
@ -125,6 +125,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
for (displayIndex = 0; ; displayIndex++) for (displayIndex = 0; ; displayIndex++)
{ {
DISPLAY_DEVICEW display; DISPLAY_DEVICEW display;
_GLFWmonitor* monitor;
char* name; char* name;
HDC dc; HDC dc;
@ -134,12 +135,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0)) if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break; break;
if (found == size)
{
size += 4;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);
}
name = _glfwCreateUTF8FromWideString(display.DeviceString); name = _glfwCreateUTF8FromWideString(display.DeviceString);
if (!name) if (!name)
{ {
@ -150,35 +145,37 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL); dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL);
monitors[found] = _glfwAllocMonitor(name, monitor = _glfwAllocMonitor(name,
GetDeviceCaps(dc, HORZSIZE), GetDeviceCaps(dc, HORZSIZE),
GetDeviceCaps(dc, VERTSIZE)); GetDeviceCaps(dc, VERTSIZE));
DeleteDC(dc); DeleteDC(dc);
free(name); free(name);
wcscpy(monitors[found]->win32.adapterName, adapter.DeviceName); wcscpy(monitor->win32.adapterName, adapter.DeviceName);
wcscpy(monitors[found]->win32.displayName, display.DeviceName); wcscpy(monitor->win32.displayName, display.DeviceName);
WideCharToMultiByte(CP_UTF8, 0, WideCharToMultiByte(CP_UTF8, 0,
adapter.DeviceName, -1, adapter.DeviceName, -1,
monitors[found]->win32.publicAdapterName, monitor->win32.publicAdapterName,
sizeof(monitors[found]->win32.publicAdapterName), sizeof(monitor->win32.publicAdapterName),
NULL, NULL); NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, WideCharToMultiByte(CP_UTF8, 0,
display.DeviceName, -1, display.DeviceName, -1,
monitors[found]->win32.publicDisplayName, monitor->win32.publicDisplayName,
sizeof(monitors[found]->win32.publicDisplayName), sizeof(monitor->win32.publicDisplayName),
NULL, NULL); NULL, NULL);
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = monitor;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE && if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&
displayIndex == 0) displayIndex == 0)
{ {
_GLFW_SWAP_POINTERS(monitors[0], monitors[found]); _GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
} }
found++;
} }
} }
@ -208,12 +205,12 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
*ypos = settings.dmPosition.y; *ypos = settings.dmPosition.y;
} }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{ {
int modeIndex = 0, count = 0; int modeIndex = 0, size = 0;
GLFWvidmode* result = NULL; GLFWvidmode* result = NULL;
*found = 0; *count = 0;
for (;;) for (;;)
{ {
@ -229,11 +226,9 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
modeIndex++; modeIndex++;
// Skip modes with less than 15 BPP
if (dm.dmBitsPerPel < 15) if (dm.dmBitsPerPel < 15)
{
// Skip modes with less than 15 BPP
continue; continue;
}
mode.width = dm.dmPelsWidth; mode.width = dm.dmPelsWidth;
mode.height = dm.dmPelsHeight; mode.height = dm.dmPelsHeight;
@ -243,30 +238,28 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
&mode.greenBits, &mode.greenBits,
&mode.blueBits); &mode.blueBits);
for (i = 0; i < *found; i++) for (i = 0; i < *count; i++)
{ {
if (_glfwCompareVideoModes(result + i, &mode) == 0) if (_glfwCompareVideoModes(result + i, &mode) == 0)
break; break;
} }
if (i < *found) // Skip duplicate modes
{ if (i < *count)
// This is a duplicate, so skip it
continue; continue;
}
if (*found == count) if (*count == size)
{ {
if (count) if (*count)
count *= 2; size *= 2;
else else
count = 128; size = 128;
result = (GLFWvidmode*) realloc(result, count * sizeof(GLFWvidmode)); result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
} }
result[*found] = mode; (*count)++;
(*found)++; result[*count - 1] = mode;
} }
return result; return result;

View File

@ -200,8 +200,8 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
_GLFWmonitor** _glfwPlatformGetMonitors(int* count) _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{ {
int i, j, k, size = 0, found = 0; int i, j, k, found = 0;
_GLFWmonitor** monitors = NULL; _GLFWmonitor** monitors;
*count = 0; *count = 0;
@ -214,6 +214,8 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display, RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
_glfw.x11.root); _glfw.x11.root);
monitors = calloc(sizeof(_GLFWmonitor*), sr->noutput);
if (_glfw.x11.xinerama.available) if (_glfw.x11.xinerama.available)
screens = XineramaQueryScreens(_glfw.x11.display, &screenCount); screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
@ -225,6 +227,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
for (j = 0; j < ci->noutput; j++) for (j = 0; j < ci->noutput; j++)
{ {
int widthMM, heightMM; int widthMM, heightMM;
_GLFWmonitor* monitor;
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display,
sr, ci->outputs[j]); sr, ci->outputs[j]);
if (oi->connection != RR_Connected) if (oi->connection != RR_Connected)
@ -233,12 +236,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
continue; continue;
} }
if (found == size)
{
size += 4;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);
}
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
{ {
widthMM = oi->mm_height; widthMM = oi->mm_height;
@ -250,9 +247,9 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
heightMM = oi->mm_height; heightMM = oi->mm_height;
} }
monitors[found] = _glfwAllocMonitor(oi->name, widthMM, heightMM); monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
monitors[found]->x11.output = ci->outputs[j]; monitor->x11.output = ci->outputs[j];
monitors[found]->x11.crtc = oi->crtc; monitor->x11.crtc = oi->crtc;
for (k = 0; k < screenCount; k++) for (k = 0; k < screenCount; k++)
{ {
@ -261,17 +258,18 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
screens[k].width == ci->width && screens[k].width == ci->width &&
screens[k].height == ci->height) screens[k].height == ci->height)
{ {
monitors[found]->x11.index = k; monitor->x11.index = k;
break; break;
} }
} }
XRRFreeOutputInfo(oi); XRRFreeOutputInfo(oi);
if (ci->outputs[j] == primary)
_GLFW_SWAP_POINTERS(monitors[0], monitors[found]);
found++; found++;
monitors[found - 1] = monitor;
if (ci->outputs[j] == primary)
_GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
} }
XRRFreeCrtcInfo(ci); XRRFreeCrtcInfo(ci);
@ -286,7 +284,10 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{ {
_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;
} }
} }
@ -330,13 +331,11 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
} }
} }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{ {
GLFWvidmode* result; GLFWvidmode* result;
*found = 0; *count = 0;
// Build array of available resolutions
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
@ -359,20 +358,18 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
for (j = 0; j < *found; j++) for (j = 0; j < *count; j++)
{ {
if (_glfwCompareVideoModes(result + j, &mode) == 0) if (_glfwCompareVideoModes(result + j, &mode) == 0)
break; break;
} }
if (j < *found) // Skip duplicate modes
{ if (j < *count)
// This is a duplicate, so skip it
continue; continue;
}
result[*found] = mode; (*count)++;
(*found)++; result[*count - 1] = mode;
} }
XRRFreeOutputInfo(oi); XRRFreeOutputInfo(oi);
@ -381,7 +378,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
} }
else else
{ {
*found = 1; *count = 1;
result = calloc(1, sizeof(GLFWvidmode)); result = calloc(1, sizeof(GLFWvidmode));
_glfwPlatformGetVideoMode(monitor, result); _glfwPlatformGetVideoMode(monitor, result);
} }