diff options
author | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-10-16 21:40:59 +0200 |
---|---|---|
committer | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2018-03-14 09:04:05 +0100 |
commit | d0fad39b423b01f19cd7151fcd44dc629dc67927 (patch) | |
tree | c3aa18ef528d607c6b6671844dc49cdfa8e0ba08 | |
parent | 3c4a4a33e48184cb4d64c2dc5b5b9e5b38404668 (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.h | 4 | ||||
-rw-r--r-- | src/loader/loader_dri3_helper.c | 61 | ||||
-rw-r--r-- | src/loader/loader_dri3_helper.h | 1 | ||||
-rw-r--r-- | src/util/xmlpool/t_options.h | 5 |
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) \ |