summaryrefslogtreecommitdiff
path: root/src/amdgpu_kms.c
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 /src/amdgpu_kms.c
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>
Diffstat (limited to 'src/amdgpu_kms.c')
-rw-r--r--src/amdgpu_kms.c77
1 files changed, 62 insertions, 15 deletions
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;