[PATCH 3/6] winex11.drv: Migrate XRandR 1.0 display settings handler to a new interface.

Zhiyi Zhang zzhang at codeweavers.com
Mon Jul 27 03:01:15 CDT 2020


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/winex11.drv/xrandr.c | 304 +++++++++++++++++++++-----------------
 1 file changed, 168 insertions(+), 136 deletions(-)

diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index 67fd2851825..155bd85d811 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -83,11 +83,6 @@ MAKE_FUNCPTR(XRRFreeProviderInfo)
 
 #undef MAKE_FUNCPTR
 
-static struct x11drv_mode_info *dd_modes;
-static SizeID *xrandr10_modes;
-static unsigned int xrandr_mode_count;
-static int xrandr_current_mode = -1;
-
 static int load_xrandr(void)
 {
     int r = 0;
@@ -144,157 +139,187 @@ static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
     return 1;
 }
 
-static int xrandr10_get_current_mode(void)
+/* XRandR 1.0 display settings handler */
+static BOOL xrandr10_get_id( const WCHAR *device_name, ULONG_PTR *id )
 {
-    SizeID size;
-    Rotation rot;
-    XRRScreenConfiguration *sc;
-    short rate;
-    unsigned int i;
-    int res = -1;
+    WCHAR primary_adapter[CCHDEVICENAME];
 
-    if (xrandr_current_mode != -1)
-        return xrandr_current_mode;
+    if (!get_primary_adapter( primary_adapter ))
+        return FALSE;
 
-    sc = pXRRGetScreenInfo (gdi_display, DefaultRootWindow( gdi_display ));
-    size = pXRRConfigCurrentConfiguration (sc, &rot);
-    rate = pXRRConfigCurrentRate (sc);
-    pXRRFreeScreenConfigInfo(sc);
-
-    for (i = 0; i < xrandr_mode_count; ++i)
-    {
-        if (xrandr10_modes[i] == size && dd_modes[i].refresh_rate == rate)
-        {
-            res = i;
-            break;
-        }
-    }
-    if (res == -1)
-    {
-        ERR("In unknown mode, returning default\n");
-        return 0;
-    }
-
-    xrandr_current_mode = res;
-    return res;
+    /* RandR 1.0 only supports changing the primary adapter settings.
+     * For non-primary adapters, an id is still provided but getting
+     * and changing non-primary adapters' settings will be ignored. */
+    *id = !lstrcmpiW( device_name, primary_adapter ) ? 1 : 0;
+    return TRUE;
 }
 
-static LONG xrandr10_set_current_mode( int mode )
+static void add_xrandr10_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD height,
+                               DWORD frequency, SizeID size_id )
 {
-    SizeID size;
-    Rotation rot;
-    Window root;
-    XRRScreenConfiguration *sc;
-    Status stat;
+    mode->dmSize = sizeof(*mode);
+    mode->dmDriverExtra = sizeof(SizeID);
+    mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH |
+                     DM_PELSHEIGHT | DM_DISPLAYFLAGS;
+    if (frequency)
+    {
+        mode->dmFields |= DM_DISPLAYFREQUENCY;
+        mode->dmDisplayFrequency = frequency;
+    }
+    mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+    mode->dmBitsPerPel = depth;
+    mode->dmPelsWidth = width;
+    mode->dmPelsHeight = height;
+    mode->u2.dmDisplayFlags = 0;
+    memcpy( (BYTE *)mode + sizeof(*mode), &size_id, sizeof(size_id) );
+}
+
+static BOOL xrandr10_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *new_mode_count )
+{
+    INT size_idx, depth_idx, rate_idx, mode_idx = 0;
+    INT size_count, rate_count, mode_count = 0;
+    DEVMODEW *modes, *mode;
+    XRRScreenSize *sizes;
+    short *rates;
+
+    sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count );
+    if (size_count <= 0)
+        return FALSE;
+
+    for (size_idx = 0; size_idx < size_count; ++size_idx)
+    {
+        rates = pXRRRates( gdi_display, DefaultScreen( gdi_display ), size_idx, &rate_count );
+        if (rate_count)
+            mode_count += rate_count;
+        else
+            ++mode_count;
+    }
+
+    /* Allocate space for reported modes in three depths, and put an SizeID at the end of DEVMODEW as
+     * driver private data */
+    modes = heap_calloc( mode_count * DEPTH_COUNT, sizeof(*modes) + sizeof(SizeID) );
+    if (!modes)
+    {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return FALSE;
+    }
+
+    for (size_idx = 0; size_idx < size_count; ++size_idx)
+    {
+        for (depth_idx = 0; depth_idx < DEPTH_COUNT; ++depth_idx)
+        {
+            rates = pXRRRates( gdi_display, DefaultScreen( gdi_display ), size_idx, &rate_count );
+            if (!rate_count)
+            {
+                mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*mode) + sizeof(SizeID)) * mode_idx++);
+                add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width,
+                                   sizes[size_idx].height, 0, size_idx );
+                continue;
+            }
+
+            for (rate_idx = 0; rate_idx < rate_count; ++rate_idx)
+            {
+                mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*mode) + sizeof(SizeID)) * mode_idx++);
+                add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width,
+                                   sizes[size_idx].height, rates[rate_idx], size_idx );
+            }
+        }
+    }
+
+    *new_modes = modes;
+    *new_mode_count = mode_idx;
+    return TRUE;
+}
+
+static void xrandr10_free_modes( DEVMODEW *modes )
+{
+    heap_free( modes );
+}
+
+static BOOL xrandr10_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
+{
+    XRRScreenConfiguration *screen_config;
+    XRRScreenSize *sizes;
+    Rotation rotation;
+    SizeID size_id;
+    INT size_count;
     short rate;
 
-    root = DefaultRootWindow( gdi_display );
-    sc = pXRRGetScreenInfo (gdi_display, root);
-    pXRRConfigCurrentConfiguration (sc, &rot);
-    mode = mode % xrandr_mode_count;
+    mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
+                     DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
+    mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+    mode->u2.dmDisplayFlags = 0;
+    mode->u1.s2.dmPosition.x = 0;
+    mode->u1.s2.dmPosition.y = 0;
 
-    TRACE("Changing Resolution to %dx%d @%d Hz\n",
-          dd_modes[mode].width,
-          dd_modes[mode].height,
-          dd_modes[mode].refresh_rate);
-
-    size = xrandr10_modes[mode];
-    rate = dd_modes[mode].refresh_rate;
-
-    if (rate)
-        stat = pXRRSetScreenConfigAndRate( gdi_display, sc, root, size, rot, rate, CurrentTime );
-    else
-        stat = pXRRSetScreenConfig( gdi_display, sc, root, size, rot, CurrentTime );
-
-    pXRRFreeScreenConfigInfo(sc);
-
-    if (stat == RRSetConfigSuccess)
+    if (id != 1)
     {
-        xrandr_current_mode = mode;
-        X11DRV_DisplayDevices_Update( TRUE );
+        FIXME("Non-primary adapters are unsupported.\n");
+        mode->dmBitsPerPel = 0;
+        mode->dmPelsWidth = 0;
+        mode->dmPelsHeight = 0;
+        mode->dmDisplayFrequency = 0;
+        return TRUE;
+    }
+
+    sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count );
+    if (size_count <= 0)
+        return FALSE;
+
+    screen_config = pXRRGetScreenInfo( gdi_display, DefaultRootWindow( gdi_display ) );
+    size_id = pXRRConfigCurrentConfiguration( screen_config, &rotation );
+    rate = pXRRConfigCurrentRate( screen_config );
+    pXRRFreeScreenConfigInfo( screen_config );
+
+    mode->dmBitsPerPel = screen_bpp;
+    mode->dmPelsWidth = sizes[size_id].width;
+    mode->dmPelsHeight = sizes[size_id].height;
+    mode->dmDisplayFrequency = rate;
+    return TRUE;
+}
+
+static LONG xrandr10_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
+{
+    XRRScreenConfiguration *screen_config;
+    Rotation rotation;
+    SizeID size_id;
+    Window root;
+    Status stat;
+
+    if (id != 1)
+    {
+        FIXME("Non-primary adapters are unsupported.\n");
         return DISP_CHANGE_SUCCESSFUL;
     }
 
-    ERR("Resolution change not successful -- perhaps display has changed?\n");
-    return DISP_CHANGE_FAILED;
-}
-
-static void xrandr10_init_modes(void)
-{
-    XRRScreenSize *sizes;
-    int sizes_count;
-    int i, j, nmodes = 0;
-
-    sizes = pXRRSizes( gdi_display, DefaultScreen(gdi_display), &sizes_count );
-    if (sizes_count <= 0) return;
-
-    TRACE("XRandR: found %d sizes.\n", sizes_count);
-    for (i = 0; i < sizes_count; ++i)
+    if (is_detached_mode(mode))
     {
-        int rates_count;
-        short *rates;
-
-        rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &rates_count );
-        TRACE("- at %d: %dx%d (%d rates):", i, sizes[i].width, sizes[i].height, rates_count);
-        if (rates_count)
-        {
-            nmodes += rates_count;
-            for (j = 0; j < rates_count; ++j)
-            {
-                if (j > 0)
-                    TRACE(",");
-                TRACE("  %d", rates[j]);
-            }
-        }
-        else
-        {
-            ++nmodes;
-            TRACE(" <default>");
-        }
-        TRACE(" Hz\n");
+        FIXME("Detaching adapters is unsupported.\n");
+        return DISP_CHANGE_SUCCESSFUL;
     }
 
-    TRACE("XRandR modes: count=%d\n", nmodes);
+    if (mode->dmFields & DM_BITSPERPEL && mode->dmBitsPerPel != screen_bpp)
+        WARN("Cannot change screen bit depth from %dbits to %dbits!\n", screen_bpp, mode->dmBitsPerPel);
 
-    if (!(xrandr10_modes = HeapAlloc( GetProcessHeap(), 0, sizeof(*xrandr10_modes) * nmodes )))
-    {
-        ERR("Failed to allocate xrandr mode info array.\n");
-        return;
-    }
+    root = DefaultRootWindow( gdi_display );
+    screen_config = pXRRGetScreenInfo( gdi_display, root );
+    pXRRConfigCurrentConfiguration( screen_config, &rotation );
 
-    dd_modes = X11DRV_Settings_SetHandlers( "XRandR 1.0",
-                                            xrandr10_get_current_mode,
-                                            xrandr10_set_current_mode,
-                                            nmodes, 1 );
+    assert( mode->dmDriverExtra == sizeof(SizeID) );
+    memcpy( &size_id, (BYTE *)mode + sizeof(*mode), sizeof(size_id) );
 
-    xrandr_mode_count = 0;
-    for (i = 0; i < sizes_count; ++i)
-    {
-        int rates_count;
-        short *rates;
+    if (mode->dmFields & DM_DISPLAYFREQUENCY && mode->dmDisplayFrequency)
+        stat = pXRRSetScreenConfigAndRate( gdi_display, screen_config, root, size_id, rotation,
+                                           mode->dmDisplayFrequency, CurrentTime );
+    else
+        stat = pXRRSetScreenConfig( gdi_display, screen_config, root, size_id, rotation, CurrentTime );
+    pXRRFreeScreenConfigInfo( screen_config );
 
-        rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &rates_count );
+    if (stat != RRSetConfigSuccess)
+        return DISP_CHANGE_FAILED;
 
-        if (rates_count)
-        {
-            for (j = 0; j < rates_count; ++j)
-            {
-                X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, rates[j] );
-                xrandr10_modes[xrandr_mode_count++] = i;
-            }
-        }
-        else
-        {
-            X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, 0 );
-            xrandr10_modes[xrandr_mode_count++] = i;
-        }
-    }
-
-    X11DRV_Settings_AddDepthModes();
-    nmodes = X11DRV_Settings_GetModeCount();
-
-    TRACE("Available DD modes: count=%d\n", nmodes);
-    TRACE("Enabling XRandR\n");
+    XFlush( gdi_display );
+    return DISP_CHANGE_SUCCESSFUL;
 }
 
 #ifdef HAVE_XRRGETPROVIDERRESOURCES
@@ -1432,7 +1457,14 @@ void X11DRV_XRandR_Init(void)
 
     TRACE("Found XRandR %d.%d.\n", major, minor);
 
-    xrandr10_init_modes();
+    settings_handler.name = "XRandR 1.0";
+    settings_handler.priority = 200;
+    settings_handler.get_id = xrandr10_get_id;
+    settings_handler.get_modes = xrandr10_get_modes;
+    settings_handler.free_modes = xrandr10_free_modes;
+    settings_handler.get_current_mode = xrandr10_get_current_mode;
+    settings_handler.set_current_mode = xrandr10_set_current_mode;
+    X11DRV_Settings_SetHandler( &settings_handler );
 
 #ifdef HAVE_XRRGETPROVIDERRESOURCES
     if (ret >= 4 && (major > 1 || (major == 1 && minor >= 4)))
-- 
2.25.1




More information about the wine-devel mailing list