summaryrefslogtreecommitdiff
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
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>
-rw-r--r--src/radeon.h2
-rw-r--r--src/radeon_kms.c79
2 files changed, 66 insertions, 15 deletions
diff --git a/src/radeon.h b/src/radeon.h
index 37d5fb60..25ff61c6 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -473,6 +473,8 @@ typedef struct {
Bool RenderAccel; /* Render */
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 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;