浏览代码

Enabled enumeration of mirroring displays.

This exposes all monitors in every mirroring group, which is needed for
robust detection of an Oculus Rift.
Camilla Berglund 11 年之前
父节点
当前提交
1b6d8a6ed6
共有 5 个文件被更改,包括 92 次插入114 次删除
  1. 2 2
      include/GLFW/glfw3native.h
  2. 11 3
      src/cocoa_monitor.m
  3. 48 56
      src/win32_monitor.c
  4. 2 1
      src/win32_platform.h
  5. 29 52
      src/x11_monitor.c

+ 2 - 2
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);

+ 11 - 3
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;

+ 48 - 56
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);
 
-        ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
-        display.cb = sizeof(DISPLAY_DEVICEW);
+            if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
+                break;
 
-        EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0);
-        dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL);
+            if (found == size)
+            {
+                size += 4;
+                monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);
+            }
 
-        if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
-            primaryIndex = found;
+            name = _glfwCreateUTF8FromWideString(display.DeviceString);
+            if (!name)
+            {
+                _glfwInputError(GLFW_PLATFORM_ERROR,
+                                "Failed to convert string to UTF-8");
+                continue;
+            }
 
-        name = _glfwCreateUTF8FromWideString(display.DeviceString);
-        if (!name)
-        {
-            _glfwFreeMonitors(monitors, found);
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Failed to convert string to UTF-8");
+            dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL);
 
-            free(monitors);
-            return NULL;
-        }
+            monitors[found] = _glfwAllocMonitor(name,
+                                                GetDeviceCaps(dc, HORZSIZE),
+                                                GetDeviceCaps(dc, VERTSIZE));
 
-        monitors[found] = _glfwAllocMonitor(name,
-                                             GetDeviceCaps(dc, HORZSIZE),
-                                             GetDeviceCaps(dc, VERTSIZE));
+            DeleteDC(dc);
+            free(name);
 
-        free(name);
-        DeleteDC(dc);
+            wcscpy(monitors[found]->win32.adapterName, adapter.DeviceName);
+            wcscpy(monitors[found]->win32.displayName, display.DeviceName);
 
-        wcscpy(monitors[found]->win32.name, adapter.DeviceName);
-        found++;
-    }
+            if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&
+                displayIndex == 0)
+            {
+                _GLFW_SWAP_POINTERS(monitors[0], monitors[found]);
+            }
 
-    if (primaryIndex > 0)
-    {
-        _GLFWmonitor* temp = monitors[0];
-        monitors[0] = monitors[primaryIndex];
-        monitors[primaryIndex] = temp;
+            found++;
+        }
     }
 
     *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;
 }
 

+ 2 - 1
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;

+ 29 - 52
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;
-            }
 
-            monitors[found] = _glfwAllocMonitor(oi->name,
-                                                oi->mm_width, oi->mm_height);
+                if (ci->outputs[j] == primary)
+                    _GLFW_SWAP_POINTERS(monitors[0], monitors[found]);
 
-            monitors[found]->x11.output = output;
-            monitors[found]->x11.crtc   = oi->crtc;
+                found++;
+            }
 
-            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;
         }
     }