xf86-video-amdgpu: Branch 'master' - 2 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Nov 30 15:49:46 UTC 2018


 man/amdgpu.man        |    7 ++++
 src/amdgpu_drv.h      |    8 +++++
 src/amdgpu_kms.c      |   76 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/amdgpu_present.c  |   37 +++++++++++++++++++++++-
 src/drmmode_display.c |   64 ++++++++++++++++++++++++++++++++++++++++++
 src/drmmode_display.h |    4 ++
 6 files changed, 194 insertions(+), 2 deletions(-)

New commits:
commit b11ee02c4596ddee3c9ff2141be5c91815efacc3
Author: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>
Date:   Thu Oct 4 09:51:40 2018 -0400

    Support CRTC variable refresh for windows using Present flips
    
    This patch adds support for setting the CRTC variable refresh property
    for suitable windows flipping via the Present extension.
    
    The "VariableRefresh" Option is added to AMDGPU in this patch. This
    option defaults to false, and must be set to "true" in an X conf
    file for variable refresh support in the driver.
    
    In order for a window to be suitable for variable refresh it must have
    the _VARIABLE_REFRESH property with a 32-bit CARDINAL value of 1.
    
    Then the window must pass the checks required to be suitable for
    Present extension flips - it must cover the entire X screen and no
    other window may already be flipping.
    
    With these conditions met every CRTC for the X screen will have their
    variable refresh property set to true.
    
    Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>

diff --git a/man/amdgpu.man b/man/amdgpu.man
index 2f9713b..2de34a3 100644
--- a/man/amdgpu.man
+++ b/man/amdgpu.man
@@ -83,6 +83,13 @@ accordingly. If this option isn't set, the default value of the property is
 which means that TearFree is on for rotated outputs, outputs with RandR
 transforms applied and for RandR 1.4 slave outputs, otherwise off.
 .TP
+.BI "Option \*qVariableRefresh\*q \*q" boolean \*q
+Enables support for enabling variable refresh on the Screen's CRTCs
+when an suitable application is flipping via the Present extension.
+.br
+The default is
+.B off.
+.TP
 .BI "Option \*qAccelMethod\*q \*q" string \*q
 Setting this option to
 .B none
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,
commit 2d18b37159edc526c73a36143fe9b5d6b75e610a
Author: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>
Date:   Tue Nov 13 09:08:01 2018 -0500

    Check last flip window instead of screen root before flipping
    
    A significant amount of time can pass between the X call into
    check_flip for a window and when amdgpu_present_flip actually occurs.
    To ensure that flipping is still possible there was an additional check
    performed on screen->root in amdgpu_present_flip - but what should
    be checked instead is the window itself. This only really worked before
    because X ensures that the window has the same dimensions as the screen
    to allow for present extension flipping.
    
    This patch tracks the flip window between calls to check_flip and flip
    and uses that window instead of screen->root.
    
    Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 44c769f..ed9241b 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -301,6 +301,7 @@ typedef struct {
 	int group_bytes;
 
 	/* kms pageflipping */
+	WindowPtr flip_window;
 	Bool allowPageFlip;
 
 	/* cursor size */
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index f9e07a5..85b2e67 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -273,6 +273,8 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	if (num_crtcs_on == 0)
 		return FALSE;
 
+	info->flip_window = window;
+
 	return TRUE;
 }
 
@@ -313,13 +315,12 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
                    PixmapPtr pixmap, Bool sync_flip)
 {
 	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
-	ScreenPtr screen = crtc->pScreen;
 	ScrnInfoPtr scrn = xf86_crtc->scrn;
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	struct amdgpu_present_vblank_event *event;
 	Bool ret = FALSE;
 
-	if (!amdgpu_present_check_flip(crtc, screen->root, pixmap, sync_flip))
+	if (!amdgpu_present_check_flip(crtc, info->flip_window , pixmap, sync_flip))
 		return ret;
 
 	event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
@@ -360,6 +361,8 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
 		FLIP_ASYNC : FLIP_VSYNC;
 	int i;
 
+	info->flip_window = NULL;
+
 	if (!amdgpu_present_check_unflip(scrn))
 		goto modeset;
 


More information about the xorg-commit mailing list