[PATCH xf86-video-amdgpu 1/6] Enable/Disable freesync when enter/exit fullscreen game v2

Nicholas Kazlauskas nicholas.kazlauskas at amd.com
Tue Sep 11 16:18:37 UTC 2018


From: Hawking Zhang <Hawking.Zhang at amd.com>

v2:
resolve undefined symbol in xserver 1.16

Signed-off-by: Hawking Zhang <Hawking.Zhang at amd.com>
Signed-off-by: Nicholas Kazlauskas <Nicholas.Kazlauskas at amd.com>
---
 src/Makefile.am        |   2 +
 src/amdgpu_dri2.c      |  24 ++++++
 src/amdgpu_drv.h       |   5 ++
 src/amdgpu_extension.c | 176 +++++++++++++++++++++++++++++++++++++++++
 src/amdgpu_extension.h |  52 ++++++++++++
 src/amdgpu_kms.c       |   4 +
 src/amdgpu_present.c   |  14 ++++
 7 files changed, 277 insertions(+)
 create mode 100644 src/amdgpu_extension.c
 create mode 100644 src/amdgpu_extension.h

diff --git a/src/Makefile.am b/src/Makefile.am
index c23c87d..240cb89 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,7 @@ amdgpu_drv_ladir = @moduledir@/drivers
 amdgpu_drv_la_SOURCES = \
 	amdgpu_video.c \
 	amdgpu_misc.c amdgpu_probe.c \
+	amdgpu_extension.c \
 	$(AMDGPU_KMS_SRCS)
 
 AM_CFLAGS += @LIBGLAMOR_CFLAGS@
@@ -64,6 +65,7 @@ EXTRA_DIST = \
 	amdgpu_drv.h \
 	amdgpu_pixmap.h \
 	amdgpu_probe.h \
+	amdgpu_extension.h \
 	amdgpu_version.h \
 	amdgpu_video.h \
 	simple_list.h \
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 96b2d17..8c601c8 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -34,6 +34,7 @@
 #include "amdgpu_glamor.h"
 #include "amdgpu_video.h"
 #include "amdgpu_pixmap.h"
+#include "amdgpu_extension.h"
 
 #ifdef DRI2
 
@@ -527,6 +528,13 @@ amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
 	xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
 		       "%s:%d fevent[%p]\n", __func__, __LINE__, flip_info);
 
+	if (info->freesync_capable_client &&
+	    info->freesync_enabled == FALSE) {
+		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+		if (!AMDGPUFreesyncControl(pAMDGPUEnt->fd, TRUE))
+			info->freesync_enabled = TRUE;
+	}
+
 	/* Page flip the full screen buffer */
 	back_priv = back->driverPrivate;
 	if (amdgpu_do_pageflip(scrn, client, back_priv->pixmap,
@@ -680,6 +688,8 @@ static void amdgpu_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq,
 {
 	DRI2FrameEventPtr event = event_data;
 	ScrnInfoPtr scrn = crtc->scrn;
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
 	DrawablePtr drawable;
 	int status;
 	int swap_type;
@@ -710,6 +720,12 @@ static void amdgpu_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq,
 		}
 		/* else fall through to exchange/blit */
 	case DRI2_SWAP:
+		if (info->freesync_capable_client &&
+		    info->freesync_enabled == TRUE) {
+			if (!AMDGPUFreesyncControl(pAMDGPUEnt->fd, FALSE))
+				info->freesync_enabled = FALSE;
+		}
+
 		if (DRI2CanExchange(drawable) &&
 		    can_exchange(scrn, drawable, event->front, event->back)) {
 			amdgpu_dri2_exchange_buffers(drawable, event->front,
@@ -1076,6 +1092,8 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 {
 	ScreenPtr screen = draw->pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
 	uint32_t msc_delta;
 	drmVBlankSeqType type;
@@ -1248,6 +1266,12 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	return TRUE;
 
 blit_fallback:
+	if (info->freesync_capable_client &&
+	    info->freesync_enabled == TRUE) {
+		if (!AMDGPUFreesyncControl(pAMDGPUEnt->fd, FALSE))
+			info->freesync_enabled = FALSE;
+	}
+
 	if (swap_info) {
 		swap_info->type = DRI2_SWAP;
 		amdgpu_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 45bc394..91bb829 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -303,6 +303,11 @@ typedef struct {
 	/* kms pageflipping */
 	Bool allowPageFlip;
 
+	/* freesync */
+	ClientPtr freesync_capable_client;
+	uint32_t client_resource_id;
+	Bool freesync_enabled;
+
 	/* cursor size */
 	int cursor_w;
 	int cursor_h;
diff --git a/src/amdgpu_extension.c b/src/amdgpu_extension.c
new file mode 100644
index 0000000..1c984df
--- /dev/null
+++ b/src/amdgpu_extension.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86Crtc.h"
+#include "xf86drm.h"
+#include "dix.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "resource.h"
+#include "scrnintstr.h"
+
+#include "amdgpu_drm.h"
+#include "amdgpu_extension.h"
+#include "amdgpu_drv.h"
+
+static RESTYPE RT_AMDGPUCLIENT;
+
+static int ProcAMDGPUFreesyncCapability(ClientPtr client)
+{
+	REQUEST(xAMDGPUFreesyncCapabilityReq);
+	REQUEST_SIZE_MATCH(xAMDGPUFreesyncCapabilityReq);
+
+	if (stuff->screen >= screenInfo.numScreens) {
+		client->errorValue = stuff->screen;
+		return BadValue;
+	}
+
+	ScreenPtr pScreen = screenInfo.screens[stuff->screen];
+	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+	XID cliResId;
+
+	if (info->freesync_capable_client == NULL) {
+		info->freesync_capable_client = client;
+		cliResId = FakeClientID(client->index);
+		if (AddResource(cliResId, RT_AMDGPUCLIENT, (void *)pScrn))
+			info->client_resource_id = cliResId;
+	}
+
+	return client->noClientException;
+}
+
+static int AMDGPUDispatch(ClientPtr client)
+{
+	REQUEST(xReq);
+
+	switch(stuff->data) {
+	case X_AMDGPUFreesyncCapability:
+		return ProcAMDGPUFreesyncCapability(client);
+	default:
+		return BadRequest;
+	}
+}
+
+static int AMDGPUSwapDispatch(ClientPtr client __attribute__((unused)))
+{
+	return BadRequest;
+}
+
+static void AMDGPUResetExtension(ExtensionEntry *extEntry __attribute__((unused)))
+{
+	RT_AMDGPUCLIENT = RT_NONE;
+}
+
+static void AMDGPUExtensionInit (void)
+{
+	ExtensionEntry *extEntry = NULL;
+
+	extEntry = AddExtension(AMDGPU_EXTENSION_NAME,
+				AMDGPU_EXTENSION_EVENTS,
+				AMDGPU_EXTENSION_ERRORS,
+				AMDGPUDispatch,
+				AMDGPUSwapDispatch,
+				AMDGPUResetExtension,
+				StandardMinorOpcode);
+	if (!extEntry) {
+		ErrorF("AddExtension failed\n");
+		return;
+	}
+
+	RT_AMDGPUCLIENT = CreateNewResourceType(AMDGPUClientGone, "AMDGPUClient");
+}
+
+static ExtensionModule AMDGPU_Ext = {
+	AMDGPUExtensionInit,
+	AMDGPU_EXTENSION_NAME,
+	NULL
+};
+
+void AMDGPUExtensionSetup(void)
+{
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,15,99,904,0)
+	LoadExtension(&AMDGPU_Ext, FALSE);
+#else
+	int size = 1;
+	LoadExtensionList(&AMDGPU_Ext, size, FALSE);
+#endif
+}
+
+int AMDGPUFreesyncControl(int fd, Bool enable_freesync)
+{
+	int ret = -1;
+	struct drm_amdgpu_freesync args;
+
+	memset(&args, 0, sizeof(args));
+	if (enable_freesync) {
+		args.op = AMDGPU_FREESYNC_FULLSCREEN_ENTER;
+                ret = drmCommandWriteRead(fd, DRM_AMDGPU_FREESYNC,
+                                          &args, sizeof(args));
+                if (ret)
+                        ErrorF("Fail to enable freesync mode.\n");
+
+	} else {
+		args.op = AMDGPU_FREESYNC_FULLSCREEN_EXIT;
+		ret = drmCommandWriteRead(fd, DRM_AMDGPU_FREESYNC,
+					  &args, sizeof(args));
+		if (ret)
+			ErrorF("Fail to disable freesync mode.\n");
+	}
+
+	return ret;
+}
+
+void AMDGPUFreeResourceByType(ScreenPtr pScreen)
+{
+	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+
+	if (info->client_resource_id)
+		FreeResourceByType(info->client_resource_id,
+				   RT_AMDGPUCLIENT, FALSE);
+	return;
+}
+
+int AMDGPUClientGone(void *data, XID id)
+{
+	ScrnInfoPtr pScrn = (ScrnInfoPtr)data;
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
+
+	if (id == (XID)info->client_resource_id) {
+		info->client_resource_id = None;
+		info->freesync_capable_client = NULL;
+	}
+
+	if (info->freesync_enabled == TRUE) {
+		if (!AMDGPUFreesyncControl(pAMDGPUEnt->fd, FALSE))
+			info->freesync_enabled = FALSE;
+	}
+
+        return 1;
+}
diff --git a/src/amdgpu_extension.h b/src/amdgpu_extension.h
new file mode 100644
index 0000000..87f479f
--- /dev/null
+++ b/src/amdgpu_extension.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#ifndef _AMDGPU_EXTENSION_H_
+#define _AMDGPU_EXTENSION_H_
+
+#include "screenint.h"
+
+#define AMDGPU_EXTENSION_NAME	"AMDGPU"
+#define AMDGPU_EXTENSION_EVENTS	1
+#define AMDGPU_EXTENSION_ERRORS 0
+
+#ifndef	XREQ_SZ
+#define XREQ_SZ(name)	sizeof(x##name##Req)
+#endif
+
+#define X_AMDGPUFreesyncCapability	0
+
+/* Requests must be mulitple of 4 bytes */
+typedef struct _AMDGPUFreesyncCapabilityReq {
+	CARD8	reqType;
+	CARD8	amdgpuReqType;
+	CARD16	length	B16;
+	CARD32	screen	B32;
+	CARD32	drawable B32;
+} xAMDGPUFreesyncCapabilityReq;
+
+#define sz_xAMDGPUFreesyncCapabilityReq		XREQ_SZ(AMDGPUFreesyncCapability)
+
+extern void AMDGPUExtensionSetup(void);
+extern int AMDGPUFreesyncControl(int fd, Bool enable_freesync);
+extern void AMDGPUFreeResourceByType(ScreenPtr pScreen);
+extern int AMDGPUClientGone(void *data, XID id);
+#endif /* _AMDGPU_EXTENSION_H_ */
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 6017c91..dc98473 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -59,6 +59,7 @@
 
 #include "amdgpu_bo_helper.h"
 #include "amdgpu_pixmap.h"
+#include "amdgpu_extension.h"
 
 #include <gbm.h>
 
@@ -1885,6 +1886,9 @@ Bool AMDGPUScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv)
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D acceleration disabled\n");
 	}
 
+	/* AMDGPU extension setup */
+	AMDGPUExtensionSetup();
+
 	/* Init DPMS */
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
 		       "Initializing DPMS\n");
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index eabe0f3..8b70b38 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -45,6 +45,7 @@
 #include "amdgpu_glamor.h"
 #include "amdgpu_pixmap.h"
 #include "amdgpu_video.h"
+#include "amdgpu_extension.h"
 
 #include "present.h"
 
@@ -321,6 +322,13 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
 	if (!amdgpu_present_check_flip(crtc, screen->root, pixmap, sync_flip))
 		return ret;
 
+	if (info->freesync_capable_client &&
+	    info->freesync_enabled == FALSE) {
+		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+		if (!AMDGPUFreesyncControl(pAMDGPUEnt->fd, TRUE))
+			info->freesync_enabled = TRUE;
+	}
+
 	event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
 	if (!event)
 		return ret;
@@ -362,6 +370,12 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
 	if (!amdgpu_present_check_unflip(scrn))
 		goto modeset;
 
+	if (info->freesync_capable_client &&
+		info->freesync_enabled == TRUE) {
+				if (!AMDGPUFreesyncControl(pAMDGPUEnt->fd, FALSE))
+			info->freesync_enabled = FALSE;
+		}
+
 	event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
 	if (!event) {
 		ErrorF("%s: calloc failed, display might freeze\n", __func__);
-- 
2.18.0



More information about the amd-gfx mailing list