diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-08-02 09:06:50 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2016-08-02 13:03:26 +0100 |
commit | 1f6dfc9df6780bd3768bf065156b6e8dae05b80c (patch) | |
tree | a8826a476f5a257039059dbf30e9b82f8658a94b | |
parent | 49daf5df124b5ae6c7508e934768c292f4143040 (diff) |
sna: Only flush GPU bo for a damage event
Based on xf86-video-ati
commit 9a1afbf61fbb2827c86bd86d295fa0848980d60b
Author: Michel Dänzer <michel.daenzer@amd.com>
Date: Mon Jul 11 12:22:09 2016 +0900
Use EventCallback to avoid flushing every time in the FlushCallback
reports seeing an improvement in reducing flushes at the expense of
checking every event for a DamageNotifyEvent. Since we also mix
rendering with SHM buffers, we have a more diverse set of conditions
under which to flush - but maybe we will see enough of a win for DRI to
merit. So far seeing improvement of ~20% for series of small operations
under the compositor without seeing any regressions, should benefit
composited desktop users. The biggest danger here is missed flushes.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/sna/sna.h | 2 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 68 | ||||
-rw-r--r-- | src/sna/sna_render.c | 2 |
4 files changed, 68 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac index a08661e7..d13917ec 100644 --- a/configure.ac +++ b/configure.ac @@ -445,7 +445,7 @@ if test "x$UXA" != "xno"; then UXA=yes fi -PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES]) +PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto damageproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES]) ABI_VERSION=`$PKG_CONFIG --variable=abi_videodrv xorg-server` XSERVER_VERSION=`$PKG_CONFIG --modversion xorg-server` PIXMAN_VERSION=`$PKG_CONFIG --modversion pixman-1` diff --git a/src/sna/sna.h b/src/sna/sna.h index 76d66cb8..9adef0eb 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -283,6 +283,8 @@ struct sna { bool ignore_copy_area : 1; unsigned watch_flush; + unsigned damage_event; + bool needs_flush; struct timeval timer_tv; uint32_t timer_expire[NUM_TIMERS]; diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index c5c4b6a4..2f851548 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -50,6 +50,8 @@ #endif #include <shmint.h> +#include <X11/extensions/damageproto.h> + #include <sys/time.h> #include <sys/mman.h> #include <sys/ioctl.h> @@ -3461,6 +3463,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl if (priv->shm) { assert(!priv->flush); sna_add_flush_pixmap(sna, priv, priv->cpu_bo); + sna->needs_flush = true; } assert(priv->cpu_damage); @@ -4075,6 +4078,8 @@ prefer_gpu_bo: /* As we may have flushed and retired,, recheck for busy bo */ if ((flags & FORCE_GPU) == 0 && !kgem_bo_is_busy(priv->cpu_bo)) return NULL; + + sna->needs_flush = true; } if (priv->flush) { assert(!priv->shm); @@ -4381,6 +4386,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags) if (priv->shm) { assert(!priv->flush); sna_add_flush_pixmap(sna, priv, priv->cpu_bo); + sna->needs_flush = true; } n = sna_damage_get_boxes(priv->cpu_damage, &box); @@ -5025,8 +5031,10 @@ done: sna_damage_all(&priv->gpu_damage, pixmap); } - if (priv->shm) + if (priv->shm) { sna_add_flush_pixmap(sna, priv, priv->cpu_bo); + sna->needs_flush = true; + } } assert(!priv->clear); @@ -6629,8 +6637,10 @@ discard_cow: sna_damage_all(&dst_priv->gpu_damage, dst_pixmap); sna_damage_destroy(&dst_priv->cpu_damage); list_del(&dst_priv->flush_list); - if (dst_priv->shm) + if (dst_priv->shm) { sna_add_flush_pixmap(sna, dst_priv, dst_priv->cpu_bo); + sna->needs_flush = true; + } return; } } @@ -6712,6 +6722,7 @@ discard_cow: if (src_priv->shm) { assert(!src_priv->flush); sna_add_flush_pixmap(sna, src_priv, src_priv->cpu_bo); + sna->needs_flush = true; } if (!sna->render.copy_boxes(sna, alu, @@ -17381,7 +17392,32 @@ static void sna_accel_flush_callback(CallbackListPtr *list, pointer user_data, pointer call_data) { - sna_accel_flush(user_data); + struct sna *sna = user_data; + + if (!sna->needs_flush) + return; + + sna_accel_flush(sna); + sna->needs_flush = false; +} + +static void +sna_accel_event_callback(CallbackListPtr *list, + pointer user_data, pointer call_data) +{ + EventInfoRec *eventinfo = call_data; + struct sna *sna = user_data; + int i; + + if (sna->needs_flush) + return; + + for (i = 0; i < eventinfo->count; i++) { + if (eventinfo->events[i].u.u.type == sna->damage_event) { + sna->needs_flush = true; + return; + } + } } static struct sna_pixmap *sna_accel_scanout(struct sna *sna) @@ -18151,8 +18187,14 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna) void sna_accel_create(struct sna *sna) { + ExtensionEntry *damage; + DBG(("%s\n", __FUNCTION__)); + damage = CheckExtension("DAMAGE"); + if (damage) + sna->damage_event = damage->eventBase + XDamageNotify; + if (!sna_glyphs_create(sna)) goto fail; @@ -18176,12 +18218,23 @@ void sna_accel_watch_flush(struct sna *sna, int enable) assert(enable); if (sna->watch_flush == 0) { + int err = 0; + DBG(("%s: installing watchers\n", __FUNCTION__)); assert(enable > 0); - if (!AddCallback(&FlushCallback, sna_accel_flush_callback, sna)) { + + if (sna->damage_event && + !AddCallback(&EventCallback, sna_accel_event_callback, sna)) + err = 1; + + if (!AddCallback(&FlushCallback, sna_accel_flush_callback, sna)) + err = 1; + + if (err) { xf86DrvMsg(sna->scrn->scrnIndex, X_Error, "Failed to attach ourselves to the flush callbacks, expect missing synchronisation with DRI clients (e.g a compositor)\n"); } + sna->watch_flush++; } @@ -18226,6 +18279,7 @@ void sna_accel_close(struct sna *sna) sna_pixmap_expire(sna); DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna); + DeleteCallback(&EventCallback, sna_accel_event_callback, sna); RemoveNotifyFd(sna->kgem.fd); kgem_cleanup_cache(&sna->kgem); @@ -18274,7 +18328,11 @@ restart: if (sna->watch_flush == 1) { DBG(("%s: removing watchers\n", __FUNCTION__)); - DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna); + DeleteCallback(&FlushCallback, + sna_accel_flush_callback, sna); + if (sna->damage_event) + DeleteCallback(&EventCallback, + sna_accel_event_callback, sna); sna->watch_flush = 0; } diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index f8281e99..a5b0935c 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -396,6 +396,7 @@ use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box, bool blt) if (priv->shm) { assert(!priv->flush); sna_add_flush_pixmap(sna, priv, priv->cpu_bo); + sna->needs_flush = true; } DBG(("%s for box=(%d, %d), (%d, %d)\n", @@ -617,6 +618,7 @@ sna_render_pixmap_bo(struct sna *sna, if (priv->shm) { assert(!priv->flush); sna_add_flush_pixmap(sna, priv, priv->cpu_bo); + sna->needs_flush = true; } goto done; } |