summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2017-10-16 21:40:59 +0200
committerNicolai Hähnle <nicolai.haehnle@amd.com>2018-03-14 09:04:05 +0100
commitd0fad39b423b01f19cd7151fcd44dc629dc67927 (patch)
treec3aa18ef528d607c6b6671844dc49cdfa8e0ba08
parent3c4a4a33e48184cb4d64c2dc5b5b9e5b38404668 (diff)
[AMD] dri3: Add adaptive_sync_enable driconf option
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
-rw-r--r--src/gallium/drivers/radeonsi/driinfo_radeonsi.h4
-rw-r--r--src/loader/loader_dri3_helper.c61
-rw-r--r--src/loader/loader_dri3_helper.h1
-rw-r--r--src/util/xmlpool/t_options.h5
4 files changed, 70 insertions, 1 deletions
diff --git a/src/gallium/drivers/radeonsi/driinfo_radeonsi.h b/src/gallium/drivers/radeonsi/driinfo_radeonsi.h
index 7f57b4ea89..ebbbf6a626 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 585f7ce3ec..082d3396cb 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>
@@ -254,6 +256,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,
@@ -285,13 +331,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:
@@ -828,6 +881,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 de22c19a57..2fa9555a85 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -154,6 +154,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 3ada813d63..7ddf24d6b5 100644
--- a/src/util/xmlpool/t_options.h
+++ b/src/util/xmlpool/t_options.h
@@ -297,6 +297,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_HYPERZ_DISABLED 0
#define DRI_CONF_HYPERZ_ENABLED 1
#define DRI_CONF_HYPERZ(def) \