From 54dfbb2fed393b65d846e6ed9672acb47e0f19de Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Fri, 14 Mar 2014 18:23:04 +0100 Subject: dri2: Fix double-sync of pageflips on Linux 3.13+ - Part I Linux 3.13 and later sync kms pageflips to vblank in the kms driver, so we must not emit a sync to vblank pushbuf in the ddx on such kernels, or maximum framerate will be cut into half! A sync-to-vblank-pushbuf is emitted for copyswaps as in the past, also for older kernels which don't support async_pageflip's and don't sync by themselves. This adds the implementation, but not the detection logic for async_pageflip support in the kernel. Signed-off-by: Mario Kleiner Signed-off-by: Ben Skeggs --- src/nouveau_dri2.c | 17 ++++++++++++++--- src/nv_type.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 5848966..a9851cb 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -619,7 +619,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, struct nouveau_pushbuf *push = pNv->pushbuf; RegionRec reg; int type, ret; - Bool front_updated; + Bool front_updated, will_exchange; REGION_INIT(0, ®, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0); REGION_TRANSLATE(0, ®, draw->x, draw->y); @@ -648,7 +648,18 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, /* Throttle on the previous frame before swapping */ nouveau_bo_wait(dst_bo, NOUVEAU_BO_RD, push->client); - if (can_sync_to_vblank(draw)) { + /* Swap by buffer exchange possible? */ + will_exchange = front_updated && can_exchange(draw, dst_pix, src_pix); + + /* Only emit a wait for vblank pushbuf here if this is a copy-swap, or + * if it is a kms pageflip-swap on an old kernel. Pure exchange swaps + * don't need sync to vblank. kms pageflip-swaps on Linux 3.13+ are + * synced to vblank in the kms driver, so we must not sync here, or + * framerate will be cut in half! + */ + if (can_sync_to_vblank(draw) && + (!will_exchange || + (!pNv->has_async_pageflip && nouveau_exa_pixmap_is_onscreen(dst_pix)))) { /* Reference the back buffer to sync it to vblank */ nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) { src_bo, @@ -666,7 +677,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, nouveau_pushbuf_kick(push, push->channel); } - if (front_updated && can_exchange(draw, dst_pix, src_pix)) { + if (will_exchange) { type = DRI2_EXCHANGE_COMPLETE; DamageRegionAppend(draw, ®); diff --git a/src/nv_type.h b/src/nv_type.h index 3c52e4e..b4889bf 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -63,6 +63,7 @@ typedef struct _NVRec { Bool wfb_enabled; Bool tiled_scanout; Bool glx_vblank; + Bool has_async_pageflip; Bool has_pageflip; int swap_limit; int max_swap_limit; -- cgit v1.2.3