[PATCH xf86-video-ati 2/2] Keep track of damage event related flushes per-client

Michel Dänzer michel at daenzer.net
Mon Aug 1 09:59:20 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.

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---

This patch can't have an effect without a corresponding xserver patch
which passes the ClientPtr to the FlushCallback, so I'll only push this
one once the xserver patch has landed.

 src/radeon.h     |  5 ++++-
 src/radeon_kms.c | 34 ++++++++++++++++++++++++++++------
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/src/radeon.h b/src/radeon.h
index 25ff61c..b119241 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -448,6 +448,10 @@ struct radeon_accel_state {
     Bool              force;
 };
 
+struct radeon_client_priv {
+    uint_fast32_t     needs_flush[0];
+};
+
 typedef struct {
     EntityInfoPtr     pEnt;
     pciVideoPtr       PciInfo;
@@ -474,7 +478,6 @@ typedef struct {
     Bool              allowColorTiling;
     Bool              allowColorTiling2D;
     int               callback_event_type;
-    uint_fast32_t     callback_needs_flush;
     uint_fast32_t     gpu_flushed;
     uint_fast32_t     gpu_synced;
     struct radeon_accel_state *accel_state;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index da11358..7ede3a1 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -40,6 +40,7 @@
 
 #include "radeon_version.h"
 #include "shadow.h"
+#include <xf86Priv.h>
 
 #include "atipciids.h"
 
@@ -59,6 +60,8 @@
 #include "radeon_cs_gem.h"
 #include "radeon_vbo.h"
 
+static DevPrivateKeyRec radeon_client_private_key;
+
 extern SymTabRec RADEONChipsets[];
 static Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
 
@@ -241,9 +244,9 @@ radeonUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
 }
 
 static Bool
-callback_needs_flush(RADEONInfoPtr info)
+callback_needs_flush(RADEONInfoPtr info, uint_fast32_t needs_flush)
 {
-    return (int)(info->callback_needs_flush - info->gpu_flushed) > 0;
+    return (int)(needs_flush - info->gpu_flushed) > 0;
 }
 
 static void
@@ -251,21 +254,28 @@ radeon_event_callback(CallbackListPtr *list,
 		      pointer user_data, pointer call_data)
 {
     EventInfoRec *eventinfo = call_data;
+    struct radeon_client_priv *client_priv =
+	dixLookupPrivate(&eventinfo->client->devPrivates, &radeon_client_private_key);
+    struct radeon_client_priv *server_priv =
+	dixLookupPrivate(&serverClient->devPrivates, &radeon_client_private_key);
     ScrnInfoPtr pScrn = user_data;
     RADEONInfoPtr info = RADEONPTR(pScrn);
     int i;
 
-    if (callback_needs_flush(info))
+    if (callback_needs_flush(info, client_priv->needs_flush[pScrn->scrnIndex]) ||
+	callback_needs_flush(info, server_priv->needs_flush[pScrn->scrnIndex]))
 	return;
 
     /* Don't let gpu_flushed get too far ahead of callback_needs_flush,
      * in order to prevent false positives in callback_needs_flush()
      */
-    info->callback_needs_flush = info->gpu_flushed;
+    client_priv->needs_flush[pScrn->scrnIndex] = info->gpu_flushed;
+    server_priv->needs_flush[pScrn->scrnIndex] = 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[pScrn->scrnIndex]++;
+	    server_priv->needs_flush[pScrn->scrnIndex]++;
 	    return;
 	}
     }
@@ -276,9 +286,13 @@ radeon_flush_callback(CallbackListPtr *list,
 		      pointer user_data, pointer call_data)
 {
     ScrnInfoPtr pScrn = user_data;
+    ClientPtr client = call_data ? call_data : serverClient;
+    struct radeon_client_priv *client_priv =
+	dixLookupPrivate(&client->devPrivates, &radeon_client_private_key);
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
-    if (pScrn->vtSema && callback_needs_flush(info))
+    if (pScrn->vtSema &&
+	callback_needs_flush(info, client_priv->needs_flush[pScrn->scrnIndex]))
         radeon_cs_flush_indirect(pScrn);
 }
 
@@ -351,6 +365,14 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
 	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
 	    return FALSE;
 	}
+
+	if (!dixPrivateKeyRegistered(&radeon_client_private_key) &&
+	    !dixRegisterPrivateKey(&radeon_client_private_key, PRIVATE_CLIENT,
+				   xf86NumScreens * sizeof(uint_fast32_t))) {
+	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
+	    DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
+	    return FALSE;
+	}
     }
 
     return TRUE;
-- 
2.8.1



More information about the amd-gfx mailing list