Zhiyi Zhang : winex11.drv: Support display orientations for XRandR 1.4 display settings handler.

Alexandre Julliard julliard at winehq.org
Tue Sep 22 15:46:40 CDT 2020


Module: wine
Branch: master
Commit: 4a330b29212402b9700828be82939112bd11a786
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=4a330b29212402b9700828be82939112bd11a786

Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date:   Tue Sep 22 15:02:24 2020 +0800

winex11.drv: Support display orientations for XRandR 1.4 display settings handler.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3d9/tests/d3d9ex.c  |   2 +-
 dlls/winex11.drv/xrandr.c | 156 +++++++++++++++++++++++++++++++++++-----------
 2 files changed, 121 insertions(+), 37 deletions(-)

diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c
index 97db3d445c..462037b2e0 100644
--- a/dlls/d3d9/tests/d3d9ex.c
+++ b/dlls/d3d9/tests/d3d9ex.c
@@ -621,7 +621,7 @@ static void test_get_adapter_displaymode_ex(void)
     ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
     /* Check that orientation is returned correctly by GetAdapterDisplayModeEx
      * and EnumDisplaySettingsEx(). */
-    todo_wine ok(S2(U1(devmode)).dmDisplayOrientation == DMDO_180 && rotation == D3DDISPLAYROTATION_180,
+    ok(S2(U1(devmode)).dmDisplayOrientation == DMDO_180 && rotation == D3DDISPLAYROTATION_180,
             "rotation is %d instead of %d\n", rotation, S2(U1(devmode)).dmDisplayOrientation);
 
     trace("GetAdapterDisplayModeEx returned Width = %d, Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d\n",
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index 6c16fb29ec..78ad98acd4 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -465,6 +465,55 @@ static unsigned int get_frequency( const XRRModeInfo *mode )
     return (mode->dotClock + dots / 2) / dots;
 }
 
+static DWORD get_orientation( Rotation rotation )
+{
+    if (rotation & RR_Rotate_270) return DMDO_270;
+    if (rotation & RR_Rotate_180) return DMDO_180;
+    if (rotation & RR_Rotate_90) return DMDO_90;
+    return DMDO_DEFAULT;
+}
+
+static DWORD get_orientation_count( Rotation rotations )
+{
+    DWORD count = 0;
+
+    if (rotations & RR_Rotate_0) ++count;
+    if (rotations & RR_Rotate_90) ++count;
+    if (rotations & RR_Rotate_180) ++count;
+    if (rotations & RR_Rotate_270) ++count;
+    return count;
+}
+
+static Rotation get_rotation( DWORD orientation )
+{
+    return (Rotation)(1 << orientation);
+}
+
+static RRCrtc get_output_free_crtc( XRRScreenResources *resources, XRROutputInfo *output_info )
+{
+    XRRCrtcInfo *crtc_info;
+    INT crtc_idx;
+    RRCrtc crtc;
+
+    for (crtc_idx = 0; crtc_idx < output_info->ncrtc; ++crtc_idx)
+    {
+        crtc_info = pXRRGetCrtcInfo( gdi_display, resources, output_info->crtcs[crtc_idx] );
+        if (!crtc_info)
+            continue;
+
+        if (!crtc_info->noutput)
+        {
+            crtc = output_info->crtcs[crtc_idx];
+            pXRRFreeCrtcInfo( crtc_info );
+            return crtc;
+        }
+
+        pXRRFreeCrtcInfo( crtc_info );
+    }
+
+    return 0;
+}
+
 static RECT get_primary_rect( XRRScreenResources *resources )
 {
     XRROutputInfo *output_info = NULL;
@@ -1137,7 +1186,8 @@ static BOOL xrandr14_get_id( const WCHAR *device_name, ULONG_PTR *id )
     return FALSE;
 }
 
-static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, DWORD frequency )
+static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, DWORD frequency,
+                               DWORD orientation )
 {
     mode->dmSize = sizeof(*mode);
     mode->dmDriverExtra = sizeof(RRMode);
@@ -1148,24 +1198,35 @@ static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, D
         mode->dmFields |= DM_DISPLAYFREQUENCY;
         mode->dmDisplayFrequency = frequency;
     }
-    mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+    if (orientation == DMDO_DEFAULT || orientation == DMDO_180)
+    {
+        mode->dmPelsWidth = info->width;
+        mode->dmPelsHeight = info->height;
+    }
+    else
+    {
+        mode->dmPelsWidth = info->height;
+        mode->dmPelsHeight = info->width;
+    }
+    mode->u1.s2.dmDisplayOrientation = orientation;
     mode->dmBitsPerPel = depth;
-    mode->dmPelsWidth = info->width;
-    mode->dmPelsHeight = info->height;
     mode->u2.dmDisplayFlags = 0;
     memcpy( (BYTE *)mode + sizeof(*mode), &info->id, sizeof(info->id) );
 }
 
 static BOOL xrandr14_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count )
 {
+    DWORD frequency, orientation, orientation_count;
     XRRScreenResources *screen_resources;
     XRROutputInfo *output_info = NULL;
     RROutput output = (RROutput)id;
+    XRRCrtcInfo *crtc_info = NULL;
     UINT depth_idx, mode_idx = 0;
     XRRModeInfo *mode_info;
     DEVMODEW *mode, *modes;
+    Rotation rotations;
     BOOL ret = FALSE;
-    DWORD frequency;
+    RRCrtc crtc;
     INT i, j;
 
     screen_resources = xrandr_get_screen_resources();
@@ -1184,9 +1245,44 @@ static BOOL xrandr14_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes,
         goto done;
     }
 
-    /* Allocate space for display modes in different color depths.
+    crtc = output_info->crtc;
+    if (!crtc)
+        crtc = get_output_free_crtc( screen_resources, output_info );
+    if (crtc)
+        crtc_info = pXRRGetCrtcInfo( gdi_display, screen_resources, crtc );
+
+    /* If the output is connected to a CRTC, use rotations reported by the CRTC */
+    if (crtc_info)
+    {
+        if (flags & EDS_ROTATEDMODE)
+        {
+            rotations = crtc_info->rotations;
+        }
+        else
+        {
+            /* According to the RandR spec, RRGetCrtcInfo should set the active rotation to Rotate_0
+             * when a CRTC is disabled. However, some RandR implementations report 0 in this case */
+            rotations = (crtc_info->rotation & 0xf) ? crtc_info->rotation : RR_Rotate_0;
+        }
+    }
+    /* Not connected to CRTC, assume all rotations are supported */
+    else
+    {
+        if (flags & EDS_ROTATEDMODE)
+        {
+            rotations = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270;
+        }
+        else
+        {
+            rotations = RR_Rotate_0;
+        }
+    }
+    orientation_count = get_orientation_count( rotations );
+
+    /* Allocate space for display modes in different color depths and orientations.
      * Store a RRMode at the end of each DEVMODEW as private driver data */
-    modes = heap_calloc( output_info->nmode * DEPTH_COUNT, sizeof(*modes) + sizeof(RRMode) );
+    modes = heap_calloc( output_info->nmode * DEPTH_COUNT * orientation_count,
+                         sizeof(*modes) + sizeof(RRMode) );
     if (!modes)
         goto done;
 
@@ -1202,9 +1298,15 @@ static BOOL xrandr14_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes,
 
             for (depth_idx = 0; depth_idx < DEPTH_COUNT; ++depth_idx)
             {
-                mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + sizeof(RRMode)) * mode_idx);
-                add_xrandr14_mode( mode, mode_info, depths[depth_idx], frequency );
-                ++mode_idx;
+                for (orientation = DMDO_DEFAULT; orientation <= DMDO_270; ++orientation)
+                {
+                    if (!((1 << orientation) & rotations))
+                        continue;
+
+                    mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + sizeof(RRMode)) * mode_idx);
+                    add_xrandr14_mode( mode, mode_info, depths[depth_idx], frequency, orientation );
+                    ++mode_idx;
+                }
             }
 
             break;
@@ -1215,6 +1317,8 @@ static BOOL xrandr14_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes,
     *new_modes = modes;
     *mode_count = mode_idx;
 done:
+    if (crtc_info)
+        pXRRFreeCrtcInfo( crtc_info );
     if (output_info)
         pXRRFreeOutputInfo( output_info );
     if (screen_resources)
@@ -1285,10 +1389,10 @@ static BOOL xrandr14_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
 
     mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
                      DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
-    mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+    mode->u1.s2.dmDisplayOrientation = get_orientation( crtc_info->rotation );
     mode->dmBitsPerPel = screen_bpp;
-    mode->dmPelsWidth = mode_info->width;
-    mode->dmPelsHeight = mode_info->height;
+    mode->dmPelsWidth = crtc_info->width;
+    mode->dmPelsHeight = crtc_info->height;
     mode->u2.dmDisplayFlags = 0;
     mode->dmDisplayFrequency = get_frequency( mode_info );
     /* Convert RandR coordinates to virtual screen coordinates */
@@ -1314,8 +1418,8 @@ static LONG xrandr14_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
     XRROutputInfo *output_info = NULL;
     XRRCrtcInfo *crtc_info = NULL;
     LONG ret = DISP_CHANGE_FAILED;
-    INT crtc_idx, output_count;
     Rotation rotation;
+    INT output_count;
     RRCrtc crtc = 0;
     Status status;
     RRMode rrmode;
@@ -1362,26 +1466,7 @@ static LONG xrandr14_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
     /* Detached, need to find a free CRTC */
     else
     {
-        for (crtc_idx = 0; crtc_idx < output_info->ncrtc; ++crtc_idx)
-        {
-            crtc_info = pXRRGetCrtcInfo( gdi_display, screen_resources, output_info->crtcs[crtc_idx] );
-            if (!crtc_info)
-                goto done;
-
-            if (!crtc_info->noutput)
-            {
-                crtc = output_info->crtcs[crtc_idx];
-                pXRRFreeCrtcInfo( crtc_info );
-                crtc_info = NULL;
-                break;
-            }
-
-            pXRRFreeCrtcInfo( crtc_info );
-            crtc_info = NULL;
-        }
-
-        /* Failed to find a free CRTC */
-        if (crtc_idx == output_info->ncrtc)
+        if (!(crtc = get_output_free_crtc( screen_resources, output_info )))
             goto done;
     }
 
@@ -1396,14 +1481,13 @@ static LONG xrandr14_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
     {
         outputs = crtc_info->outputs;
         output_count = crtc_info->noutput;
-        rotation = crtc_info->rotation;
     }
     else
     {
         outputs = &output;
         output_count = 1;
-        rotation = RR_Rotate_0;
     }
+    rotation = get_rotation( mode->u1.s2.dmDisplayOrientation );
 
     /* According to the RandR spec, the entire CRTC must fit inside the screen.
      * Since we use the union of all enabled CRTCs to determine the necessary




More information about the wine-cvs mailing list