xserver: Branch 'master' - 3 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Sep 8 08:42:32 UTC 2020


 hw/xfree86/drivers/modesetting/driver.c          |  161 +++++++++++++++++++++++
 hw/xfree86/drivers/modesetting/driver.h          |   14 ++
 hw/xfree86/drivers/modesetting/drmmode_display.c |  103 ++++++++++++++
 hw/xfree86/drivers/modesetting/drmmode_display.h |    6 
 hw/xfree86/drivers/modesetting/present.c         |   38 +++++
 5 files changed, 320 insertions(+), 2 deletions(-)

New commits:
commit 97f858d336a85cb49de6275918793c773d5d9db1
Author: Uday Kiran Pichika <pichika.uday.kiran at intel.com>
Date:   Wed Aug 19 16:20:15 2020 +0530

    modesetting: Allow users to opt-in VRR support
    
    Fetch VariableRefresh option value from X conf file for
    modesetting backend DDX driver. This option defaults to false,
    and must be set to "true" in conf file for variable refresh
    support in the DDX driver.
    
    Signed-off-by: Uday Kiran Pichika <pichika.uday.kiran at intel.com>

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 63ec0ba92..12e58e4f6 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -139,6 +139,7 @@ static const OptionInfoRec Options[] = {
     {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
     {OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE},
     {OPTION_ATOMIC, "Atomic", OPTV_BOOLEAN, {0}, FALSE},
+    {OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE},
     {-1, NULL, OPTV_NONE, {0}, FALSE}
 };
 
@@ -1188,6 +1189,13 @@ PreInit(ScrnInfoPtr pScrn, int flags)
                    ms->drmmode.shadow_enable ? "YES" : "NO");
 
         ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms);
+    } else {
+        if (!pScrn->is_gpu) {
+            MessageType from = xf86GetOptValBool(ms->drmmode.Options, OPTION_VARIABLE_REFRESH,
+                                                 &ms->vrr_support) ? X_CONFIG : X_DEFAULT;
+            xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n",
+                       ms->vrr_support ? "en" : "dis");
+        }
     }
 
     ms->drmmode.pageflip =
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 7391bc4ab..2791b97c1 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -56,6 +56,7 @@ typedef enum {
     OPTION_ZAPHOD_HEADS,
     OPTION_DOUBLE_SHADOW,
     OPTION_ATOMIC,
+    OPTION_VARIABLE_REFRESH,
 } modesettingOpts;
 
 typedef struct
commit ede2c32ce116138ddf081932ea2c33bd6f4b6990
Author: Uday Kiran Pichika <pichika.uday.kiran at intel.com>
Date:   Thu Jun 18 16:07:33 2020 +0530

    modesetting: Detect changes to the _VARIABLE_REFRESH window properties
    
    Window wrappers gets the notification when the window
    properties changes. These wrappers are mainly used to
    keep track of per-window _VARIABLE_REFRESH property values.
    
    These changes have been ported from AMDGPU
    
    Signed-off-by: Uday Kiran Pichika <pichika.uday.kiran at intel.com>

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 513816c70..63ec0ba92 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -80,6 +80,14 @@ static Bool ms_pci_probe(DriverPtr driver,
                          intptr_t match_data);
 static Bool ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data);
 
+/* window wrapper functions used to get the notification when
+ * the window property changes */
+static Atom vrr_atom;
+static Bool property_vectors_wrapped;
+static Bool restore_property_vector;
+static int (*saved_change_property) (ClientPtr client);
+static int (*saved_delete_property) (ClientPtr client);
+
 #ifdef XSERVER_LIBPCIACCESS
 static const struct pci_id_match ms_device_match[] = {
     {
@@ -712,6 +720,126 @@ ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win) {
 
 	return priv->variable_refresh;
 }
+
+static void
+ms_vrr_property_update(WindowPtr window, Bool variable_refresh)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen);
+    modesettingPtr ms = modesettingPTR(scrn);
+
+    struct ms_vrr_priv *priv = dixLookupPrivate(&window->devPrivates,
+                                                &ms->drmmode.vrrPrivateKeyRec);
+    priv->variable_refresh = variable_refresh;
+
+    if (ms->flip_window == window && ms->drmmode.present_flipping)
+        ms_present_set_screen_vrr(scrn, variable_refresh);
+}
+
+/* Wrapper for xserver/dix/property.c:ProcChangeProperty */
+static int
+ms_change_property(ClientPtr client)
+{
+    WindowPtr window = NULL;
+    int ret = 0;
+
+    REQUEST(xChangePropertyReq);
+
+    client->requestVector[X_ChangeProperty] = saved_change_property;
+    ret = saved_change_property(client);
+    if (ret != Success)
+        return ret;
+
+    if (restore_property_vector)
+        return ret;
+
+    client->requestVector[X_ChangeProperty] = ms_change_property;
+
+    ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
+    if (ret != Success)
+        return ret;
+
+    // Checking for the VRR property change on the window
+    if (stuff->property == vrr_atom &&
+        xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit &&
+        stuff->format == 32 && stuff->nUnits == 1) {
+        uint32_t *value = (uint32_t *)(stuff + 1);
+        ms_vrr_property_update(window, *value != 0);
+    }
+
+    return ret;
+}
+
+/* Wrapper for xserver/dix/property.c:ProcDeleteProperty */
+static int
+ms_delete_property(ClientPtr client)
+{
+    WindowPtr window;
+    int ret;
+
+    REQUEST(xDeletePropertyReq);
+
+    client->requestVector[X_DeleteProperty] = saved_delete_property;
+    ret = saved_delete_property(client);
+
+    if (restore_property_vector)
+        return ret;
+
+    client->requestVector[X_DeleteProperty] = ms_delete_property;
+
+    if (ret != Success)
+        return ret;
+
+    ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess);
+    if (ret != Success)
+        return ret;
+
+    if (stuff->property == vrr_atom &&
+        xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit)
+        ms_vrr_property_update(window, FALSE);
+
+    return ret;
+}
+
+static void
+ms_unwrap_property_requests(ScrnInfoPtr scrn)
+{
+    int i;
+
+    if (!property_vectors_wrapped)
+        return;
+
+    if (ProcVector[X_ChangeProperty] == ms_change_property)
+        ProcVector[X_ChangeProperty] = saved_change_property;
+    else
+        restore_property_vector = TRUE;
+
+    if (ProcVector[X_DeleteProperty] == ms_delete_property)
+        ProcVector[X_DeleteProperty] = saved_delete_property;
+    else
+        restore_property_vector = TRUE;
+
+    for (i = 0; i < currentMaxClients; i++) {
+        if (clients[i]->requestVector[X_ChangeProperty] == ms_change_property) {
+            clients[i]->requestVector[X_ChangeProperty] = saved_change_property;
+        } else {
+            restore_property_vector = TRUE;
+        }
+
+        if (clients[i]->requestVector[X_DeleteProperty] == ms_delete_property) {
+            clients[i]->requestVector[X_DeleteProperty] = saved_delete_property;
+        } else {
+            restore_property_vector = TRUE;
+        }
+    }
+
+    if (restore_property_vector) {
+        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+                   "Couldn't unwrap some window property request vectors\n");
+    }
+
+    property_vectors_wrapped = FALSE;
+}
+
 static void
 FreeRec(ScrnInfoPtr pScrn)
 {
@@ -731,6 +859,7 @@ FreeRec(ScrnInfoPtr pScrn)
         ms_ent = ms_ent_priv(pScrn);
         ms_ent->fd_ref--;
         if (!ms_ent->fd_ref) {
+            ms_unwrap_property_requests(pScrn);
             if (ms->pEnt->location.type == BUS_PCI)
                 ret = drmClose(ms->fd);
             else
@@ -1817,6 +1946,18 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
 
     pScrn->vtSema = TRUE;
 
+    if (ms->vrr_support) {
+        if (!property_vectors_wrapped) {
+            saved_change_property = ProcVector[X_ChangeProperty];
+            ProcVector[X_ChangeProperty] = ms_change_property;
+            saved_delete_property = ProcVector[X_DeleteProperty];
+            ProcVector[X_DeleteProperty] = ms_delete_property;
+            property_vectors_wrapped = TRUE;
+        }
+        vrr_atom = MakeAtom("_VARIABLE_REFRESH",
+                             strlen("_VARIABLE_REFRESH"), TRUE);
+    }
+
     return TRUE;
 }
 
commit 9823ea4ed24db76b1e61d69a8da8f7599857d02a
Author: Uday Kiran Pichika <pichika.uday.kiran at intel.com>
Date:   Thu Jun 18 11:31:31 2020 +0530

    modesetting: Lay the foundation for enabling VRR
    
    These changes have been ported from AMD GPU DDX driver.
    
    This patch adds support for setting the CRTC variable refresh property
    for suitable windows flipping via the Present extension.
    
    In order for a window to be suitable for variable refresh it must have
    the _VARIABLE_REFRESH property set by the MESA and inform Modesetting
    DDX driver with window property updates.
    
    Then the window must pass the checks required to be suitable for
    Present extension flips - it must cover the entire X screen and no
    other window may already be flipping. And also DRM connector should
    be VRR capable.
    
    With these conditions met every CRTC for the X screen will have their
    variable refresh property set to true.
    
    Kernel Changes to support this feature in I915 driver is under development.
    
    Tested with DOTA2, Xonotic and custom GLX apps.
    
    Signed-off-by: Uday Kiran Pichika <pichika.uday.kiran at intel.com>

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 37bc51657..513816c70 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -706,6 +706,12 @@ msBlockHandler_oneshot(ScreenPtr pScreen, void *pTimeout)
     drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE);
 }
 
+Bool
+ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win) {
+	struct ms_vrr_priv *priv = dixLookupPrivate(&win->devPrivates, &ms->drmmode.vrrPrivateKeyRec);
+
+	return priv->variable_refresh;
+}
 static void
 FreeRec(ScrnInfoPtr pScrn)
 {
@@ -1451,6 +1457,12 @@ CreateScreenResources(ScreenPtr pScreen)
         pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
     }
 
+    if (ms->vrr_support &&
+        !dixRegisterPrivateKey(&ms->drmmode.vrrPrivateKeyRec,
+                               PRIVATE_WINDOW,
+                               sizeof(struct ms_vrr_priv)))
+            return FALSE;
+
     return ret;
 }
 
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 7ee9f6827..7391bc4ab 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -43,6 +43,10 @@
 #include "drmmode_display.h"
 #define MS_LOGLEVEL_DEBUG 4
 
+struct ms_vrr_priv {
+    Bool variable_refresh;
+};
+
 typedef enum {
     OPTION_SW_CURSOR,
     OPTION_DEVICE_PATH,
@@ -122,6 +126,13 @@ typedef struct _modesettingRec {
 
     Bool kms_has_modifiers;
 
+    /* VRR support */
+    Bool vrr_support;
+    WindowPtr flip_window;
+
+    Bool is_connector_vrr_capable;
+    uint32_t connector_prop_id;
+
     /* shadow API */
     struct {
         Bool (*Setup)(ScreenPtr);
@@ -224,3 +235,5 @@ Bool ms_do_pageflip(ScreenPtr screen,
 #endif
 
 int ms_flush_drm_events(ScreenPtr screen);
+Bool ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win);
+void ms_present_set_screen_vrr(ScrnInfoPtr scrn, Bool vrr_enabled);
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 9dd4b298f..5dbfa4149 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -2208,6 +2208,53 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
     drmModeFreePlaneResources(kplane_res);
 }
 
+static uint32_t
+drmmode_crtc_get_prop_id(uint32_t drm_fd,
+                         drmModeObjectPropertiesPtr props,
+                         char const* name)
+{
+    uint32_t i, prop_id = 0;
+
+    for (i = 0; !prop_id && i < props->count_props; ++i) {
+        drmModePropertyPtr drm_prop =
+                     drmModeGetProperty(drm_fd, props->props[i]);
+
+        if (!drm_prop)
+            continue;
+
+        if (strcmp(drm_prop->name, name) == 0)
+            prop_id = drm_prop->prop_id;
+
+        drmModeFreeProperty(drm_prop);
+    }
+
+    return prop_id;
+}
+
+static void
+drmmode_crtc_vrr_init(int drm_fd, xf86CrtcPtr crtc)
+{
+    drmModeObjectPropertiesPtr drm_props;
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+    if (drmmode->vrr_prop_id)
+        return;
+
+    drm_props = drmModeObjectGetProperties(drm_fd,
+                                           drmmode_crtc->mode_crtc->crtc_id,
+                                           DRM_MODE_OBJECT_CRTC);
+
+    if (!drm_props)
+        return;
+
+    drmmode->vrr_prop_id = drmmode_crtc_get_prop_id(drm_fd,
+                                                    drm_props,
+                                                    "VRR_ENABLED");
+
+    drmModeFreeObjectProperties(drm_props);
+}
+
 static unsigned int
 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
 {
@@ -2250,6 +2297,8 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
     /* Hide any cursors which may be active from previous users */
     drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0);
 
+    drmmode_crtc_vrr_init(drmmode->fd, crtc);
+
     /* Mark num'th crtc as in use on this device. */
     ms_ent->assigned_crtcs |= (1 << num);
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
@@ -2918,6 +2967,40 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
         snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id);
 }
 
+static Bool
+drmmode_connector_check_vrr_capable(uint32_t drm_fd, int connector_id)
+{
+    uint32_t i;
+    Bool found = FALSE;
+    uint64_t prop_value = 0;
+    drmModeObjectPropertiesPtr props;
+    const char* prop_name = "VRR_CAPABLE";
+
+    props = drmModeObjectGetProperties(drm_fd, connector_id,
+                                    DRM_MODE_OBJECT_CONNECTOR);
+
+    for (i = 0; !found && i < props->count_props; ++i) {
+        drmModePropertyPtr drm_prop = drmModeGetProperty(drm_fd, props->props[i]);
+
+        if (!drm_prop)
+            continue;
+
+        if (strcasecmp(drm_prop->name, prop_name) == 0) {
+            prop_value = props->prop_values[i];
+            found = TRUE;
+        }
+
+        drmModeFreeProperty(drm_prop);
+    }
+
+    drmModeFreeObjectProperties(props);
+
+    if(found)
+        return prop_value ? TRUE : FALSE;
+
+    return FALSE;
+}
+
 static unsigned int
 drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, Bool dynamic, int crtcshift)
 {
@@ -3049,6 +3132,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
         }
     }
 
+    ms->is_connector_vrr_capable =
+	         drmmode_connector_check_vrr_capable(drmmode->fd,
+                                                  drmmode_output->output_id);
     return 1;
 
  out_free_encoders:
@@ -3968,6 +4054,23 @@ drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int *depth,
     return;
 }
 
+void
+drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    modesettingPtr ms = modesettingPTR(pScrn);
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+    if (drmmode->vrr_prop_id && drmmode_crtc->vrr_enabled != enabled &&
+        drmModeObjectSetProperty(ms->fd,
+                                 drmmode_crtc->mode_crtc->crtc_id,
+                                 DRM_MODE_OBJECT_CRTC,
+                                 drmmode->vrr_prop_id,
+                                 enabled) == 0)
+        drmmode_crtc->vrr_enabled = enabled;
+}
+
 /*
  * We hook the screen's cursor-sprite (swcursor) functions to see if a swcursor
  * is active. When a swcursor is active we disable page-flipping.
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 2fb049bca..6360dd048 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -112,6 +112,7 @@ typedef struct {
 
     DevPrivateKeyRec pixmapPrivateKeyRec;
     DevScreenPrivateKeyRec spritePrivateKeyRec;
+    DevPrivateKeyRec vrrPrivateKeyRec;
     /* Number of SW cursors currently visible on this screen */
     int sprites_visible;
 
@@ -127,6 +128,8 @@ typedef struct {
 
     Bool dri2_enable;
     Bool present_enable;
+
+    uint32_t vrr_prop_id;
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
@@ -193,6 +196,8 @@ typedef struct {
 
     Bool enable_flipping;
     Bool flipping_active;
+
+    Bool vrr_enabled;
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
@@ -293,5 +298,6 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 int drmmode_crtc_flip(xf86CrtcPtr crtc, uint32_t fb_id, uint32_t flags, void *data);
 
 void drmmode_set_dpms(ScrnInfoPtr scrn, int PowerManagementMode, int flags);
+void drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled);
 
 #endif
diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c
index fea2d663e..6e5b58938 100644
--- a/hw/xfree86/drivers/modesetting/present.c
+++ b/hw/xfree86/drivers/modesetting/present.c
@@ -70,6 +70,22 @@ ms_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
     return ms_get_crtc_ust_msc(xf86_crtc, ust, msc);
 }
 
+/*
+ * Changes the variable refresh state for every CRTC on the screen.
+ */
+void
+ms_present_set_screen_vrr(ScrnInfoPtr scrn, Bool vrr_enabled)
+{
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CrtcPtr crtc;
+    int i;
+
+    for (i = 0; i < config->num_crtc; i++) {
+        crtc = config->crtc[i];
+        drmmode_crtc_set_vrr(crtc, vrr_enabled);
+    }
+}
+
 /*
  * Called when the queued vblank event has occurred
  */
@@ -299,7 +315,12 @@ ms_present_check_flip(RRCrtcPtr crtc,
     if (ms->drmmode.sprites_visible > 0)
         return FALSE;
 
-    return ms_present_check_unflip(crtc, window, pixmap, sync_flip, reason);
+    if(!ms_present_check_unflip(crtc, window, pixmap, sync_flip, reason))
+        return FALSE;
+
+    ms->flip_window = window;
+
+    return TRUE;
 }
 
 /*
@@ -321,7 +342,7 @@ ms_present_flip(RRCrtcPtr crtc,
     Bool ret;
     struct ms_present_vblank_event *event;
 
-    if (!ms_present_check_flip(crtc, screen->root, pixmap, sync_flip, NULL))
+    if (!ms_present_check_flip(crtc, ms->flip_window, pixmap, sync_flip, NULL))
         return FALSE;
 
     event = calloc(1, sizeof(struct ms_present_vblank_event));
@@ -334,6 +355,17 @@ ms_present_flip(RRCrtcPtr crtc,
     event->event_id = event_id;
     event->unflip = FALSE;
 
+    /* A window can only flip if it covers the entire X screen.
+     * Only one window can flip at a time.
+     *
+     * If the window also has the variable refresh property then
+     * variable refresh supported can be enabled on every CRTC.
+     */
+    if (ms->vrr_support && ms->is_connector_vrr_capable &&
+          ms_window_has_variable_refresh(ms, ms->flip_window)) {
+        ms_present_set_screen_vrr(scrn, TRUE);
+    }
+
     ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip,
                          ms_present_flip_handler, ms_present_flip_abort,
                          "Present-flip");
@@ -356,6 +388,8 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id)
     int i;
     struct ms_present_vblank_event *event;
 
+    ms_present_set_screen_vrr(scrn, FALSE);
+
     event = calloc(1, sizeof(struct ms_present_vblank_event));
     if (!event)
         return;


More information about the xorg-commit mailing list