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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Michel Dänzer <michel.daenzer@xxxxxxx>

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.

v2: Use ScreenPrivateKey, fixes invalid memory access with GPU screens
Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/radeon.h     |  5 ++++-
 src/radeon_kms.c | 41 +++++++++++++++++++++++++++++++++--------
 2 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/src/radeon.h b/src/radeon.h
index 25ff61c..f3a3e1c 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;
+};
+
 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..f525a2c 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 DevScreenPrivateKeyRec 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, struct radeon_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
@@ -252,20 +255,30 @@ radeon_event_callback(CallbackListPtr *list,
 {
     EventInfoRec *eventinfo = call_data;
     ScrnInfoPtr pScrn = user_data;
+    ScreenPtr pScreen = pScrn->pScreen;
+    struct radeon_client_priv *client_priv =
+	dixLookupScreenPrivate(&eventinfo->client->devPrivates,
+			       &radeon_client_private_key, pScreen);
+    struct radeon_client_priv *server_priv =
+	dixLookupScreenPrivate(&serverClient->devPrivates,
+			       &radeon_client_private_key, pScreen);
     RADEONInfoPtr info = RADEONPTR(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;
 	}
     }
@@ -276,9 +289,14 @@ radeon_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 radeon_client_priv *client_priv =
+	dixLookupScreenPrivate(&client->devPrivates,
+			       &radeon_client_private_key, pScreen);
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
-    if (pScrn->vtSema && callback_needs_flush(info))
+    if (pScrn->vtSema && callback_needs_flush(info, client_priv))
         radeon_cs_flush_indirect(pScrn);
 }
 
@@ -351,6 +369,13 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
 	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
 	    return FALSE;
 	}
+
+	if (!dixRegisterScreenPrivateKey(&radeon_client_private_key, pScreen,
+					 PRIVATE_CLIENT, sizeof(struct radeon_client_priv))) {
+	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
+	    DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
+	    return FALSE;
+	}
     }
 
     return TRUE;
-- 
2.8.1



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux