summaryrefslogtreecommitdiff
path: root/src/radeon_kms.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2016-07-11 12:22:09 +0900
committerMichel Dänzer <michel@daenzer.net>2016-08-01 18:51:03 +0900
commit9a1afbf61fbb2827c86bd86d295fa0848980d60b (patch)
tree317b988923b325bd8f35a8505f7cefb3de89e44a /src/radeon_kms.c
parent94fe42f29e0b00a26e810581d6c438ac6d8ecd8a (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. Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src/radeon_kms.c')
-rw-r--r--src/radeon_kms.c79
1 files changed, 64 insertions, 15 deletions
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 122b9325..da11358a 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -51,6 +51,8 @@
#include <X11/extensions/dpms.h>
#endif
+#include <X11/extensions/damageproto.h>
+
#include "radeon_chipinfo_gen.h"
#include "radeon_bo_gem.h"
@@ -91,10 +93,11 @@ void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
struct radeon_accel_state *accel_state;
int ret;
+ info->gpu_flushed++;
+
#ifdef USE_GLAMOR
if (info->use_glamor) {
glamor_block_handler(pScrn->pScreen);
- info->gpu_flushed++;
return;
}
#endif
@@ -237,8 +240,51 @@ radeonUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
shadowUpdatePacked(pScreen, pBuf);
}
+static Bool
+callback_needs_flush(RADEONInfoPtr info)
+{
+ return (int)(info->callback_needs_flush - info->gpu_flushed) > 0;
+}
+
+static void
+radeon_event_callback(CallbackListPtr *list,
+ pointer user_data, pointer call_data)
+{
+ EventInfoRec *eventinfo = call_data;
+ ScrnInfoPtr pScrn = user_data;
+ RADEONInfoPtr info = RADEONPTR(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
+radeon_flush_callback(CallbackListPtr *list,
+ pointer user_data, pointer call_data)
+{
+ ScrnInfoPtr pScrn = user_data;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (pScrn->vtSema && callback_needs_flush(info))
+ radeon_cs_flush_indirect(pScrn);
+}
+
static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
{
+ ExtensionEntry *damage_ext = CheckExtension("DAMAGE");
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
PixmapPtr pixmap;
@@ -294,6 +340,19 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
if (info->use_glamor)
radeon_glamor_create_screen_resources(pScreen);
+ info->callback_event_type = -1;
+ if (damage_ext) {
+ info->callback_event_type = damage_ext->eventBase + XDamageNotify;
+
+ if (!AddCallback(&FlushCallback, radeon_flush_callback, pScrn))
+ return FALSE;
+
+ if (!AddCallback(&EventCallback, radeon_event_callback, pScrn)) {
+ DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
+ return FALSE;
+ }
+ }
+
return TRUE;
}
@@ -641,16 +700,6 @@ static void RADEONBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL)
drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
}
-static void
-radeon_flush_callback(CallbackListPtr *list,
- pointer user_data, pointer call_data)
-{
- ScrnInfoPtr pScrn = user_data;
-
- if (pScrn->vtSema)
- radeon_cs_flush_indirect(pScrn);
-}
-
static Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -1564,7 +1613,10 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
radeon_drm_queue_close(pScrn);
radeon_cs_flush_indirect(pScrn);
- DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
+ if (info->callback_event_type != -1) {
+ DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
+ DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
+ }
if (info->accel_state->exa) {
exaDriverFini(pScreen);
@@ -1838,9 +1890,6 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
info->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = RADEONBlockHandler_oneshot;
- if (!AddCallback(&FlushCallback, radeon_flush_callback, pScrn))
- return FALSE;
-
info->CreateScreenResources = pScreen->CreateScreenResources;
pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;