[PATCH xf86-video-amdgpu 03/12] Keep track of damage event related flushes per-client

Michel Dänzer michel at daenzer.net
Thu Sep 8 10:02:36 UTC 2016


From: Michel Dänzer <michel.daenzer at amd.com>

This further reduces the compositing slowdown due to flushing overhead,
by only flushing when the X server actually sends XDamageNotify events
to a client, and there hasn't been a flush yet in the meantime.

(Ported from radeon commit 121a6de72da5fcf9a32408eff36b2235f3dfbcfe)

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/amdgpu_drv.h |  5 ++++-
 src/amdgpu_kms.c | 41 +++++++++++++++++++++++++++++++++--------
 2 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index d2b3a6b..fc6a79d 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -185,6 +185,10 @@ struct amdgpu_buffer {
 	uint32_t flags;
 };
 
+struct amdgpu_client_priv {
+	uint_fast32_t needs_flush;
+};
+
 typedef struct {
 	EntityInfoPtr pEnt;
 	pciVideoPtr PciInfo;
@@ -210,7 +214,6 @@ typedef struct {
 	/* accel */
 	PixmapPtr fbcon_pixmap;
 	int callback_event_type;
-	uint_fast32_t callback_needs_flush;
 	uint_fast32_t gpu_flushed;
 	uint_fast32_t gpu_synced;
 	Bool use_glamor;
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index b1f6bd7..d557313 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -39,6 +39,7 @@
 
 #include "amdgpu_version.h"
 #include "shadow.h"
+#include <xf86Priv.h>
 
 #include "amdpciids.h"
 
@@ -58,6 +59,8 @@
 
 #include <gbm.h>
 
+static DevScreenPrivateKeyRec amdgpu_client_private_key;
+
 extern SymTabRec AMDGPUChipsets[];
 static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen);
 
@@ -166,9 +169,9 @@ amdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
 }
 
 static Bool
-callback_needs_flush(AMDGPUInfoPtr info)
+callback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv)
 {
-	return (int)(info->callback_needs_flush - info->gpu_flushed) > 0;
+	return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
 }
 
 static void
@@ -177,20 +180,30 @@ amdgpu_event_callback(CallbackListPtr *list,
 {
 	EventInfoRec *eventinfo = call_data;
 	ScrnInfoPtr pScrn = user_data;
+	ScreenPtr pScreen = pScrn->pScreen;
+	struct amdgpu_client_priv *client_priv =
+		dixLookupScreenPrivate(&eventinfo->client->devPrivates,
+				       &amdgpu_client_private_key, pScreen);
+	struct amdgpu_client_priv *server_priv =
+		dixLookupScreenPrivate(&serverClient->devPrivates,
+				       &amdgpu_client_private_key, pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 	int i;
 
-	if (callback_needs_flush(info))
+	if (callback_needs_flush(info, client_priv) ||
+	    callback_needs_flush(info, server_priv))
 		return;
 
-	/* Don't let gpu_flushed get too far ahead of callback_needs_flush,
-	 * in order to prevent false positives in callback_needs_flush()
+	/* Don't let gpu_flushed get too far ahead of needs_flush, in order
+	 * to prevent false positives in callback_needs_flush()
 	 */
-	info->callback_needs_flush = info->gpu_flushed;
+	client_priv->needs_flush = info->gpu_flushed;
+	server_priv->needs_flush = info->gpu_flushed;
 	
 	for (i = 0; i < eventinfo->count; i++) {
 		if (eventinfo->events[i].u.u.type == info->callback_event_type) {
-			info->callback_needs_flush++;
+			client_priv->needs_flush++;
+			server_priv->needs_flush++;
 			return;
 		}
 	}
@@ -201,9 +214,14 @@ amdgpu_flush_callback(CallbackListPtr *list,
 		      pointer user_data, pointer call_data)
 {
 	ScrnInfoPtr pScrn = user_data;
+	ScreenPtr pScreen = pScrn->pScreen;
+	ClientPtr client = call_data ? call_data : serverClient;
+	struct amdgpu_client_priv *client_priv =
+		dixLookupScreenPrivate(&client->devPrivates,
+				       &amdgpu_client_private_key, pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 
-	if (pScrn->vtSema && callback_needs_flush(info))
+	if (pScrn->vtSema && callback_needs_flush(info, client_priv))
 		amdgpu_glamor_flush(pScrn);
 }
 
@@ -273,6 +291,13 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
 			return FALSE;
 		}
+
+		if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen,
+						 PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) {
+			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+			DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
+			return FALSE;
+		}
 	}
 
 	return TRUE;
-- 
2.9.3



More information about the amd-gfx mailing list