summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2016-09-07 18:14:10 +0900
committerMichel Dänzer <michel@daenzer.net>2016-09-09 19:02:02 +0900
commit58773d1945cfa8155d8a6c5eb3f95097535604ef (patch)
tree319f6a16c8c6adddb54d7c4cd4cff0fe47d01e9d
parentd166d04f6951f6a48d7d5ce5d31bba857fe0cb06 (diff)
Use EventCallback to avoid flushing every time in the FlushCallback
We only need to flush for XDamageNotify events. Significantly reduces compositing slowdown due to flushing overhead, in particular with glamor. (Ported from radeon commit 9a1afbf61fbb2827c86bd86d295fa0848980d60b) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--src/amdgpu_drv.h2
-rw-r--r--src/amdgpu_glamor.c3
-rw-r--r--src/amdgpu_kms.c77
3 files changed, 66 insertions, 16 deletions
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 60aa0be..d2b3a6b 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -209,6 +209,8 @@ 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_glamor.c b/src/amdgpu_glamor.c
index 62831d0..d29b096 100644
--- a/src/amdgpu_glamor.c
+++ b/src/amdgpu_glamor.c
@@ -460,8 +460,9 @@ void amdgpu_glamor_flush(ScrnInfoPtr pScrn)
if (info->use_glamor) {
glamor_block_handler(pScrn->pScreen);
- info->gpu_flushed++;
}
+
+ info->gpu_flushed++;
}
void amdgpu_glamor_finish(ScrnInfoPtr pScrn)
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 9f023cf..b1f6bd7 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -50,6 +50,8 @@
#include <X11/extensions/dpms.h>
#endif
+#include <X11/extensions/damageproto.h>
+
#include "amdgpu_chipinfo_gen.h"
#include "amdgpu_bo_helper.h"
#include "amdgpu_pixmap.h"
@@ -163,8 +165,51 @@ amdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
shadowUpdatePacked(pScreen, pBuf);
}
+static Bool
+callback_needs_flush(AMDGPUInfoPtr info)
+{
+ return (int)(info->callback_needs_flush - info->gpu_flushed) > 0;
+}
+
+static void
+amdgpu_event_callback(CallbackListPtr *list,
+ pointer user_data, pointer call_data)
+{
+ EventInfoRec *eventinfo = call_data;
+ ScrnInfoPtr pScrn = user_data;
+ AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+ int i;
+
+ if (callback_needs_flush(info))
+ 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;
+
+ for (i = 0; i < eventinfo->count; i++) {
+ if (eventinfo->events[i].u.u.type == info->callback_event_type) {
+ info->callback_needs_flush++;
+ return;
+ }
+ }
+}
+
+static void
+amdgpu_flush_callback(CallbackListPtr *list,
+ pointer user_data, pointer call_data)
+{
+ ScrnInfoPtr pScrn = user_data;
+ AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+
+ if (pScrn->vtSema && callback_needs_flush(info))
+ amdgpu_glamor_flush(pScrn);
+}
+
static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
{
+ ExtensionEntry *damage_ext = CheckExtension("DAMAGE");
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
PixmapPtr pixmap;
@@ -217,6 +262,19 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
if (info->use_glamor)
amdgpu_glamor_create_screen_resources(pScreen);
+ info->callback_event_type = -1;
+ if (damage_ext) {
+ info->callback_event_type = damage_ext->eventBase + XDamageNotify;
+
+ if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
+ return FALSE;
+
+ if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) {
+ DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+ return FALSE;
+ }
+ }
+
return TRUE;
}
@@ -542,17 +600,6 @@ static void AMDGPUBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL)
drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
}
-static void
-amdgpu_flush_callback(CallbackListPtr * list,
- pointer user_data, pointer call_data)
-{
- ScrnInfoPtr pScrn = user_data;
-
- if (pScrn->vtSema) {
- amdgpu_glamor_flush(pScrn);
- }
-}
-
/* This is called by AMDGPUPreInit to set up the default visual */
static Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn)
{
@@ -1108,7 +1155,10 @@ static Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
drmmode_uevent_fini(pScrn, &info->drmmode);
amdgpu_drm_queue_close(pScrn);
- DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+ if (info->callback_event_type != -1) {
+ DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
+ DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+ }
amdgpu_sync_close(pScreen);
amdgpu_drop_drm_master(pScrn);
@@ -1347,9 +1397,6 @@ Bool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
info->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = AMDGPUBlockHandler_oneshot;
- if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
- return FALSE;
-
info->CreateScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;