summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/amdgpu_drv.h7
-rw-r--r--src/amdgpu_kms.c76
-rw-r--r--src/amdgpu_present.c30
-rw-r--r--src/drmmode_display.c64
-rw-r--r--src/drmmode_display.h4
5 files changed, 181 insertions, 0 deletions
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index ed9241b..a212b40 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -164,6 +164,7 @@ typedef enum {
OPTION_SHADOW_PRIMARY,
OPTION_TEAR_FREE,
OPTION_DELETE_DP12,
+ OPTION_VARIABLE_REFRESH,
} AMDGPUOpts;
static inline ScreenPtr
@@ -239,6 +240,10 @@ struct amdgpu_device_priv {
Bool sprite_visible;
};
+struct amdgpu_window_priv {
+ Bool variable_refresh;
+};
+
extern DevScreenPrivateKeyRec amdgpu_device_private_key;
typedef struct {
@@ -270,6 +275,7 @@ typedef struct {
Bool use_glamor;
Bool force_accel;
Bool shadow_primary;
+ Bool vrr_support;
int tear_free;
/* general */
@@ -346,6 +352,7 @@ typedef struct {
Bool amdgpu_dri3_screen_init(ScreenPtr screen);
/* amdgpu_kms.c */
+Bool amdgpu_window_has_variable_refresh(WindowPtr win);
Bool amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
PixmapPtr src_pix, BoxRec extents);
void AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 2622409..92782de 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -62,6 +62,7 @@
#include <gbm.h>
+static DevPrivateKeyRec amdgpu_window_private_key;
static DevScreenPrivateKeyRec amdgpu_client_private_key;
DevScreenPrivateKeyRec amdgpu_device_private_key;
@@ -79,6 +80,7 @@ const OptionInfoRec AMDGPUOptions_KMS[] = {
{OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE },
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
@@ -154,6 +156,58 @@ static void AMDGPUFreeRec(ScrnInfoPtr pScrn)
free(pEnt);
}
+
+static inline struct amdgpu_window_priv *get_window_priv(WindowPtr win) {
+ return dixLookupPrivate(&win->devPrivates, &amdgpu_window_private_key);
+}
+
+static void
+amdgpu_property_notify(ClientPtr client,
+ XID id,
+ int state,
+ ATOM property_name)
+{
+ WindowPtr win;
+ PropertyPtr prop;
+ struct amdgpu_window_priv *priv;
+ const char* str;
+ int res;
+
+ res = dixLookupWindow(&win, id, client, DixReadAccess);
+ if (res != Success)
+ return;
+
+ str = NameForAtom(property_name);
+ if (str == NULL)
+ return;
+
+ if (strcmp(str, "_VARIABLE_REFRESH") != 0)
+ return;
+
+ priv = get_window_priv(win);
+ if (!priv)
+ return;
+
+ priv->variable_refresh = 0;
+
+ res = dixLookupProperty(&prop,
+ win,
+ property_name,
+ client,
+ DixReadAccess);
+
+ if (res == Success && prop->format == 32 && prop->size == 1) {
+ uint32_t value = *(uint32_t*)prop->data;
+ priv->variable_refresh = (value != 0);
+ }
+}
+
+Bool amdgpu_window_has_variable_refresh(WindowPtr win) {
+ struct amdgpu_window_priv *priv = get_window_priv(win);
+
+ return priv->variable_refresh;
+}
+
static void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset,
int mode, CARD32 * size, void *closure)
{
@@ -195,6 +249,17 @@ amdgpu_event_callback(CallbackListPtr *list,
AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
int i;
+ if (info->vrr_support) {
+ for (i = 0; i < eventinfo->count; i++) {
+ xEventPtr ev = &eventinfo->events[i];
+ if (ev->u.u.type == PropertyNotify)
+ amdgpu_property_notify(eventinfo->client,
+ ev->u.property.window,
+ ev->u.property.state,
+ ev->u.property.atom);
+ }
+ }
+
if (callback_needs_flush(info, client_priv) ||
callback_needs_flush(info, server_priv))
return;
@@ -300,6 +365,11 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
}
}
+ if (!dixRegisterPrivateKey(&amdgpu_window_private_key,
+ PRIVATE_WINDOW,
+ sizeof(struct amdgpu_window_priv)))
+ return FALSE;
+
return TRUE;
}
@@ -1415,6 +1485,12 @@ Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
if (info->shadow_primary)
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
+
+ from = xf86GetOptValBool(info->Options, OPTION_VARIABLE_REFRESH,
+ &info->vrr_support) ? X_CONFIG : X_DEFAULT;
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n",
+ info->vrr_support ? "en" : "dis");
}
if (!pScrn->is_gpu) {
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index 85b2e67..f3af045 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -88,6 +88,23 @@ amdgpu_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
}
/*
+ * Changes the variable refresh state for every CRTC on the screen.
+ */
+static void
+amdgpu_present_set_screen_vrr(ScrnInfoPtr scrn)
+{
+ AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+ 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, info->drmmode.vrr_flipping);
+ }
+}
+
+/*
* Flush the DRM event queue when full; this
* makes space for new requests
*/
@@ -275,6 +292,16 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
info->flip_window = window;
+ /* 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.
+ */
+ info->drmmode.vrr_flipping =
+ info->vrr_support &&
+ amdgpu_window_has_variable_refresh(window);
+
return TRUE;
}
@@ -329,6 +356,7 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
event->event_id = event_id;
+ amdgpu_present_set_screen_vrr(scrn);
amdgpu_glamor_flush(scrn);
ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
@@ -362,6 +390,8 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
int i;
info->flip_window = NULL;
+ info->drmmode.vrr_flipping = FALSE;
+ amdgpu_present_set_screen_vrr(scrn);
if (!amdgpu_present_check_unflip(scrn))
goto modeset;
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1c62186..bd5eb5e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -268,6 +268,69 @@ int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
return Success;
}
+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);
+}
+
+void drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(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(pAMDGPUEnt->fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC,
+ drmmode->vrr_prop_id,
+ enabled) == 0)
+ drmmode_crtc->vrr_enabled = enabled;
+}
+
static void
drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
@@ -1953,6 +2016,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
drmmode_crtc_hw_id(crtc);
drmmode_crtc_cm_init(pAMDGPUEnt->fd, crtc);
+ drmmode_crtc_vrr_init(pAMDGPUEnt->fd, crtc);
/* Mark num'th crtc as in use on this device. */
pAMDGPUEnt->assigned_crtcs |= (1 << num);
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 3988631..b2b16df 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -65,6 +65,8 @@ typedef struct {
Bool dri2_flipping;
Bool present_flipping;
+ Bool vrr_flipping;
+ uint32_t vrr_prop_id;
/* Cache for DRM property type IDs for CRTC color management */
uint32_t cm_prop_ids[CM_NUM_PROPS];
@@ -108,6 +110,7 @@ typedef struct {
unsigned scanout_id;
uintptr_t scanout_update_pending;
Bool tear_free;
+ Bool vrr_enabled;
PixmapPtr prime_scanout_pixmap;
@@ -255,6 +258,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
uint32_t target_msc);
int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
int drmmode_get_current_ust(int drm_fd, CARD64 * ust);
+void drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled);
Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type,
uint32_t target_seq, unsigned long signal,