summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner.de@gmail.com>2014-03-14 18:23:04 +0100
committerBen Skeggs <bskeggs@redhat.com>2014-06-21 17:04:44 +1000
commit54dfbb2fed393b65d846e6ed9672acb47e0f19de (patch)
tree5c276b0c7cb6eeab183953164892fc54b1afbbbf
parent303402e00d55b5296311738184cd61f4aadab74d (diff)
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 <mario.kleiner.de@gmail.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--src/nouveau_dri2.c17
-rw-r--r--src/nv_type.h1
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, &reg, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0);
REGION_TRANSLATE(0, &reg, 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, &reg);
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;