From 9edd8e37b5e2659a71b05dabed45fd7c3447de79 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 8 Jul 2019 18:35:27 +0200
Subject: [PATCH xserver 10/14] xwayland: Add xwlVidModeGetCurrentRRMode helper
 to the vidmode code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

crtc->mode reflects the mode set through the xrandr extension, once we
add support for also changing the mode through the vidmode extension this
will no longer correctly reflect the emulated resolution.

Add a new xwlVidModeGetCurrentRRMode helper which determines the mode by
looking at the emulated_mode instead.

Likewise add a xwlVidModeGetRRMode helper and use that in
xwlVidModeCheckModeForMonitor/xwlVidModeCheckModeForDriver to allow any
mode listed in the randr_output's mode list.

This is a preparation patch for adding emulated mode/resolution change
support to Xwayland's XF86 vidmode extension emulation.

Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Michel Dänzer <mdaenzer@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 hw/xwayland/xwayland-vidmode.c | 90 +++++++++++++++++++++-------------
 1 file changed, 56 insertions(+), 34 deletions(-)

diff --git a/hw/xwayland/xwayland-vidmode.c b/hw/xwayland/xwayland-vidmode.c
index a59c9f6a9..e9aea7269 100644
--- a/hw/xwayland/xwayland-vidmode.c
+++ b/hw/xwayland/xwayland-vidmode.c
@@ -103,26 +103,56 @@ xwlRRModeToDisplayMode(RRModePtr rrmode, DisplayModePtr mode)
     mode->HSync = mode_hsync(mode_info);
 }
 
+static RRModePtr
+xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height)
+{
+    RROutputPtr output = RRFirstOutput(pScreen);
+
+    if (output == NULL)
+        return NULL;
+
+    return xwl_output_find_mode(output->devPrivate, width, height);
+}
+
+static RRModePtr
+xwlVidModeGetCurrentRRMode(ScreenPtr pScreen)
+{
+    struct xwl_emulated_mode *emulated_mode;
+    struct xwl_output *xwl_output;
+    RROutputPtr output;
+
+    output = RRFirstOutput(pScreen);
+    if (output == NULL)
+        return NULL;
+
+    xwl_output = output->devPrivate;
+    emulated_mode =
+        xwl_output_get_emulated_mode_for_client(xwl_output, GetCurrentClient());
+
+    if (emulated_mode) {
+        return xwl_output_find_mode(xwl_output,
+                                    emulated_mode->width,
+                                    emulated_mode->height);
+    } else {
+        return xwl_output_find_mode(xwl_output, -1, -1);
+    }
+}
+
 static Bool
 xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
 {
     DisplayModePtr pMod;
-    RROutputPtr output;
-    RRCrtcPtr crtc;
+    RRModePtr rrmode;
 
     pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey);
     if (pMod == NULL)
         return FALSE;
 
-    output = RRFirstOutput(pScreen);
-    if (output == NULL)
-        return FALSE;
-
-    crtc = output->crtc;
-    if (crtc == NULL)
+    rrmode = xwlVidModeGetCurrentRRMode(pScreen);
+    if (rrmode == NULL)
         return FALSE;
 
-    xwlRRModeToDisplayMode(crtc->mode, pMod);
+    xwlRRModeToDisplayMode(rrmode, pMod);
 
     *mode = pMod;
     if (dotClock != NULL)
@@ -135,9 +165,10 @@ static vidMonitorValue
 xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
 {
     vidMonitorValue ret = { NULL, };
-    DisplayModePtr pMod;
+    RRModePtr rrmode;
 
-    if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
+    rrmode = xwlVidModeGetCurrentRRMode(pScreen);
+    if (rrmode == NULL)
         return ret;
 
     switch (valtyp) {
@@ -155,11 +186,11 @@ xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
         break;
     case VIDMODE_MON_HSYNC_LO:
     case VIDMODE_MON_HSYNC_HI:
-        ret.f = 100.0 * pMod->HSync;
+        ret.f = mode_hsync(&rrmode->mode) * 100.0;
         break;
     case VIDMODE_MON_VREFRESH_LO:
     case VIDMODE_MON_VREFRESH_HI:
-        ret.f = 100.0 * pMod->VRefresh;
+        ret.f = mode_refresh(&rrmode->mode) * 100.0;
         break;
     }
     return ret;
@@ -168,13 +199,13 @@ xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
 static int
 xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock)
 {
-    DisplayModePtr pMod;
+    RRModePtr rrmode;
 
-    if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
+    rrmode = xwlVidModeGetCurrentRRMode(pScreen);
+    if (rrmode == NULL)
         return 0;
 
-    return pMod->Clock;
-
+    return rrmode->mode.dotClock / 1000.0;
 }
 
 static int
@@ -272,14 +303,15 @@ xwlVidModeLockZoom(ScreenPtr pScreen, Bool lock)
 static ModeStatus
 xwlVidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode)
 {
-    DisplayModePtr pMod;
+    RRModePtr rrmode;
 
-    /* This should not happen */
-    if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
+    rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay);
+    if (rrmode == NULL)
         return MODE_ERROR;
 
     /* Only support mode with the same HSync/VRefresh as we advertise */
-    if (mode->HSync == pMod->HSync && mode->VRefresh == pMod->VRefresh)
+    if (mode->HSync == mode_hsync(&rrmode->mode) &&
+        mode->VRefresh == mode_refresh(&rrmode->mode))
         return MODE_OK;
 
     /* All the rest is unsupported - If we want to succeed, return MODE_OK instead */
@@ -289,20 +321,10 @@ xwlVidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode)
 static ModeStatus
 xwlVidModeCheckModeForDriver(ScreenPtr pScreen, DisplayModePtr mode)
 {
-    DisplayModePtr pMod;
-
-    /* This should not happen */
-    if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
-        return MODE_ERROR;
-
-    if (mode->HTotal != pMod->HTotal)
-        return MODE_BAD_HVALUE;
+    RRModePtr rrmode;
 
-    if (mode->VTotal != pMod->VTotal)
-        return MODE_BAD_VVALUE;
-
-    /* Unsupported for now, but pretend it works */
-    return MODE_OK;
+    rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay);
+    return rrmode ? MODE_OK : MODE_ERROR;
 }
 
 static void
-- 
2.23.0

