summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2016-09-07 18:28:23 +0900
committerMichel Dänzer <michel@daenzer.net>2016-09-09 19:02:11 +0900
commitc7d27c94cb656899746898c2e55407c3e3d7cdc8 (patch)
tree047afa799841e7054d74d297cb3336614cf1ce29
parent58773d1945cfa8155d8a6c5eb3f95097535604ef (diff)
Keep track of damage event related flushes per-client
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) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--src/amdgpu_drv.h5
-rw-r--r--src/amdgpu_kms.c41
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;