[Mesa-dev] [PATCH v2 4/4] loader/dri3: Enable adaptive sync via _VARIABLE_REFRESH property

Nicholas Kazlauskas nicholas.kazlauskas at amd.com
Mon Sep 24 18:18:39 UTC 2018


The DDX driver can be notified of adaptive sync suitability by
flagging the application's window with the _VARIABLE_REFRESH property.

This property is set on the first swap the application performs
when adaptive_sync_enable is set to true in the drirc.

It's performed here instead of when the loader is initialized for
two reasons:

(1) The window's drawable can be missing during loader init.
    This can be observed during the Unigine Superposition benchmark.

(2) Adaptive sync will only be enabled closer to when the application
    actually begins rendering. For some displays this means there is
    less time spent watching flickering occur during application load.

For now this property is only set on the glx DRI3 backend. This should
cover most common applications and games on modern hardware.

Vulkan support can be implemented in a similar manner but would likely
require splitting the function out into a common helper function.

Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>
---
 src/loader/loader_dri3_helper.c | 46 ++++++++++++++++++++++++++++++++-
 src/loader/loader_dri3_helper.h |  2 ++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index f641a34e6d..a485e241ae 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -101,6 +101,34 @@ get_xcb_visualtype_for_depth(struct loader_dri3_drawable *draw, int depth)
    return NULL;
 }
 
+/* Sets the adaptive sync window property state. */
+static void
+set_adaptive_sync_property(xcb_connection_t *conn,
+                           xcb_window_t window,
+                           uint32_t state)
+{
+   static char const name[] = "_VARIABLE_REFRESH";
+   xcb_intern_atom_cookie_t cookie;
+   xcb_intern_atom_reply_t* reply;
+
+   cookie = xcb_intern_atom(conn, 0, sizeof(name), name);
+   reply = xcb_intern_atom_reply(conn, cookie, NULL);
+   if (reply == NULL)
+      return;
+
+   xcb_change_property(conn,
+                       XCB_PROP_MODE_REPLACE,
+                       window,
+                       reply->atom,
+                       XCB_ATOM_CARDINAL,
+                       32,
+                       1,
+                       &state);
+
+   xcb_flush(conn);
+   free(reply);
+}
+
 /* Get red channel mask for given drawable at given depth. */
 static unsigned int
 dri3_get_red_mask_for_depth(struct loader_dri3_drawable *draw, int depth)
@@ -318,6 +346,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
    xcb_get_geometry_reply_t *reply;
    xcb_generic_error_t *error;
    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+   unsigned char adaptive_sync_enable;
    int swap_interval;
 
    draw->conn = conn;
@@ -331,16 +360,25 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
    draw->have_back = 0;
    draw->have_fake_front = 0;
    draw->first_init = true;
+   draw->adaptive_sync_enable = false;
+   draw->adaptive_sync_active = false;
 
    draw->cur_blit_source = -1;
    draw->back_format = __DRI_IMAGE_FORMAT_NONE;
    mtx_init(&draw->mtx, mtx_plain);
    cnd_init(&draw->event_cnd);
 
-   if (draw->ext->config)
+   if (draw->ext->config) {
       draw->ext->config->configQueryi(draw->dri_screen,
                                       "vblank_mode", &vblank_mode);
 
+      draw->ext->config->configQueryb(draw->dri_screen,
+                                      "adaptive_sync_enable",
+                                      &adaptive_sync_enable);
+
+      draw->adaptive_sync_enable = adaptive_sync_enable;
+   }
+
    switch (vblank_mode) {
    case DRI_CONF_VBLANK_NEVER:
    case DRI_CONF_VBLANK_DEF_INTERVAL_0:
@@ -879,6 +917,12 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
    back = dri3_find_back_alloc(draw);
 
    mtx_lock(&draw->mtx);
+
+   if (draw->adaptive_sync_enable && !draw->adaptive_sync_active) {
+      set_adaptive_sync_property(draw->conn, (xcb_window_t)draw->drawable, true);
+      draw->adaptive_sync_active = true;
+   }
+
    if (draw->is_different_gpu && back) {
       /* Update the linear buffer before presenting the pixmap */
       (void) loader_dri3_blit_image(draw,
diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
index 0d18181312..86f994cb2a 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -156,6 +156,8 @@ struct loader_dri3_drawable {
    xcb_special_event_t *special_event;
 
    bool first_init;
+   bool adaptive_sync_enable;
+   bool adaptive_sync_active;
    int swap_interval;
 
    struct loader_dri3_extensions *ext;
-- 
2.19.0



More information about the mesa-dev mailing list