[Mesa-dev] [PATCH 1/4] dri3: Add adaptive_sync_enable driconf option

Nicholas Kazlauskas nicholas.kazlauskas at amd.com
Tue Sep 11 16:24:14 UTC 2018


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

When enabled, this will request FreeSync via the hybrid amdgpu DDX's
AMDGPU X11 protocol extension.

Due to limitations in the DDX this will only work for applications
that cover the entire X screen (which is important to keep in mind when
you have a multi-monitor setup).

v2: set adaptive_sync_enable = 0 by default

Reviewed-By: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>
---
 .../drivers/radeonsi/driinfo_radeonsi.h       |  4 ++
 src/loader/loader_dri3_helper.c               | 61 ++++++++++++++++++-
 src/loader/loader_dri3_helper.h               |  1 +
 src/util/xmlpool/t_options.h                  |  5 ++
 4 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/radeonsi/driinfo_radeonsi.h b/src/gallium/drivers/radeonsi/driinfo_radeonsi.h
index 8c5078c13f..dbaa7c8f17 100644
--- a/src/gallium/drivers/radeonsi/driinfo_radeonsi.h
+++ b/src/gallium/drivers/radeonsi/driinfo_radeonsi.h
@@ -1,4 +1,8 @@
 // DriConf options specific to radeonsi
+DRI_CONF_SECTION_QUALITY
+   DRI_CONF_ADAPTIVE_SYNC_ENABLE("false")
+DRI_CONF_SECTION_END
+
 DRI_CONF_SECTION_PERFORMANCE
     DRI_CONF_RADEONSI_ENABLE_SISCHED("false")
     DRI_CONF_RADEONSI_ASSUME_NO_Z_FIGHTS("false")
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index b625214858..dd70a73f3d 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -22,12 +22,14 @@
  */
 
 #include <fcntl.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 
 #include <X11/xshmfence.h>
 #include <xcb/xcb.h>
+#include <xcb/xcbext.h>
 #include <xcb/dri3.h>
 #include <xcb/present.h>
 
@@ -303,6 +305,50 @@ loader_dri3_drawable_fini(struct loader_dri3_drawable *draw)
    mtx_destroy(&draw->mtx);
 }
 
+#define X_AMDGPUFreesyncCapability	0
+
+/* Requests must be mulitple of 4 bytes */
+typedef struct _AMDGPUFreesyncCapabilityReq {
+   uint8_t reqType;
+   uint8_t amdgpuReqType;
+   uint16_t length;
+   uint32_t screen;
+   uint32_t drawable;
+} xAMDGPUFreesyncCapabilityReq;
+
+static xcb_extension_t amdgpu_ext_id = { "AMDGPU", 0 };
+
+static bool
+loader_dri3_amdgpu_freesync_enable(xcb_connection_t *conn,
+                                   xcb_drawable_t drawable)
+{
+   const xcb_query_extension_reply_t *extension;
+
+   extension = xcb_get_extension_data(conn, &amdgpu_ext_id);
+   if (!(extension && extension->present)) {
+      fprintf(stderr, "AMDGPU extension not present -- cannot enable FreeSync\n");
+      return false;
+   }
+
+   const xcb_protocol_request_t xcb_req = {
+      .count = 1,
+      .ext = &amdgpu_ext_id,
+      .opcode = X_AMDGPUFreesyncCapability,
+      .isvoid = 1,
+   };
+   xAMDGPUFreesyncCapabilityReq req;
+   struct iovec xcb_parts[3];
+
+   req.screen = 0; /* TODO: do we need to support multiple screens? */
+   req.drawable = drawable;
+
+   xcb_parts[2].iov_base = (char *)&req;
+   xcb_parts[2].iov_len = sizeof(req);
+
+   xcb_send_request(conn, 0, xcb_parts + 2, &xcb_req);
+   return true;
+}
+
 int
 loader_dri3_drawable_init(xcb_connection_t *conn,
                           xcb_drawable_t drawable,
@@ -334,13 +380,20 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
 
    draw->cur_blit_source = -1;
    draw->back_format = __DRI_IMAGE_FORMAT_NONE;
+   draw->adaptive_sync = false;
    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);
 
+      unsigned char adaptive_sync_enable = 0;
+      draw->ext->config->configQueryb(draw->dri_screen,
+                                      "adaptive_sync_enable", &adaptive_sync_enable);
+      draw->adaptive_sync = adaptive_sync_enable;
+   }
+
    switch (vblank_mode) {
    case DRI_CONF_VBLANK_NEVER:
    case DRI_CONF_VBLANK_DEF_INTERVAL_0:
@@ -879,6 +932,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) {
+      if (!loader_dri3_amdgpu_freesync_enable(draw->conn, draw->drawable))
+         draw->adaptive_sync = false;
+   }
+
    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..3309df31cf 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -156,6 +156,7 @@ struct loader_dri3_drawable {
    xcb_special_event_t *special_event;
 
    bool first_init;
+   bool adaptive_sync;
    int swap_interval;
 
    struct loader_dri3_extensions *ext;
diff --git a/src/util/xmlpool/t_options.h b/src/util/xmlpool/t_options.h
index b6f7eed80b..7da731f601 100644
--- a/src/util/xmlpool/t_options.h
+++ b/src/util/xmlpool/t_options.h
@@ -292,6 +292,11 @@ DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \
         DRI_CONF_DESC_END \
 DRI_CONF_OPT_END
 
+#define DRI_CONF_ADAPTIVE_SYNC_ENABLE(def) \
+DRI_CONF_OPT_BEGIN_B(adaptive_sync_enable,def) \
+        DRI_CONF_DESC(en,gettext("Adapt the monitor sync to the application performance (when possible)")) \
+DRI_CONF_OPT_END
+
 #define DRI_CONF_MESA_GLTHREAD(def) \
 DRI_CONF_OPT_BEGIN_B(mesa_glthread, def) \
         DRI_CONF_DESC(en,gettext("Enable offloading GL driver work to a separate thread")) \
-- 
2.18.0



More information about the mesa-dev mailing list