xf86-video-intel: 2 commits - src/sna/sna_dri2.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Jun 8 00:58:46 PDT 2014


 src/sna/sna_dri2.c |   69 +++++++++++++++++++++++++++++++++++------------------
 1 file changed, 46 insertions(+), 23 deletions(-)

New commits:
commit 22cd7c873edd0b641e54e81d643ec6b0ea921f88
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jun 8 08:46:27 2014 +0100

    sna/dri2: Explicitly drain the pending event queue before swapping
    
    As there may be some latency between the wakeup and the queue, do a
    final check if there is a pending vblank event before we decide whether
    to chain up or perform an immediate flip.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index a6f1013..314651e 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -40,6 +40,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <time.h>
 #include <string.h>
 #include <unistd.h>
+#include <poll.h>
 
 #include "sna.h"
 #include "intel_options.h"
@@ -209,13 +210,14 @@ struct dri2_window {
 
 static struct dri2_window *dri2_window(WindowPtr win)
 {
+	assert(win->drawable.type != DRAWABLE_PIXMAP);
 	return ((void **)__get_private(win, sna_window_key))[1];
 }
 
 static struct sna_dri2_event *
-sna_dri2_window_get_chain(WindowPtr win)
+dri2_chain(DrawablePtr d)
 {
-	struct dri2_window *priv = dri2_window(win);
+	struct dri2_window *priv = dri2_window((WindowPtr)d);
 	assert(priv != NULL);
 	return priv->chain;
 }
@@ -246,8 +248,7 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
 	if (buffer->attachment == DRI2BufferBackLeft &&
 	    draw->type != DRAWABLE_PIXMAP) {
 		DBG(("%s: replacing back buffer\n", __FUNCTION__));
-		sna_dri2_get_back(to_sna_from_drawable(draw), buffer,
-				  sna_dri2_window_get_chain((WindowPtr)draw));
+		sna_dri2_get_back(to_sna_from_drawable(draw), buffer, dri2_chain(draw));
 
 		assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
 		assert(get_private(buffer)->bo->active_scanout == 0);
@@ -1615,7 +1616,7 @@ static void chain_swap(struct sna *sna, struct sna_dri2_event *chain)
 	if (chain->queued) /* too early! */
 		return;
 
-	assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw));
+	assert(chain == dri2_chain((WindowPtr)chain->draw));
 	DBG(("%s: chaining draw=%ld, type=%d\n",
 	     __FUNCTION__, (long)chain->draw->id, chain->type));
 	chain->queued = true;
@@ -1826,11 +1827,11 @@ sna_dri2_immediate_blit(struct sna *sna,
 		sync = false;
 
 	DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, send-event? %d\n",
-	     __FUNCTION__, sync, sna_dri2_window_get_chain((WindowPtr)draw) != info,
+	     __FUNCTION__, sync, dri2_chain(draw) != info,
 	     event));
 
 	info->type = SWAP_THROTTLE;
-	if (!sync || sna_dri2_window_get_chain((WindowPtr)draw) == info) {
+	if (!sync || dri2_chain(draw) == info) {
 		DBG(("%s: no pending blit, starting chain\n",
 		     __FUNCTION__));
 
@@ -1923,7 +1924,7 @@ static void chain_flip(struct sna *sna)
 		return;
 	}
 
-	assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw));
+	assert(chain == dri2_chain(chain->draw));
 	chain->queued = true;
 
 	if (can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) &&
@@ -2266,7 +2267,7 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 		return false;
 
 	sync = current_msc < *target_msc;
-	event = sna_dri2_window_get_chain((WindowPtr)draw) == NULL;
+	event = dri2_chain(draw) == NULL;
 	if (!sync || event) {
 		DBG(("%s: performing immediate xchg on pipe %d\n",
 		     __FUNCTION__, sna_crtc_to_pipe(crtc)));
@@ -2313,6 +2314,14 @@ complete:
 	return true;
 }
 
+static bool has_pending_events(struct sna *sna)
+{
+	struct pollfd pfd;
+	pfd.fd = sna->kgem.fd;
+	pfd.events = POLLIN;
+	return poll(&pfd, 1, 0) == 1;
+}
+
 /*
  * ScheduleSwap is responsible for requesting a DRM vblank event for the
  * appropriate frame.
@@ -2386,6 +2395,13 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		goto blit;
 	}
 
+	assert(draw->type != DRAWABLE_PIXMAP);
+
+	while (dri2_chain(draw) && has_pending_events(sna)) {
+		DBG(("%s: flushing pending events\n", __FUNCTIONS__));
+		sna_mode_wakeup(sna);
+	}
+
 	if (can_xchg(sna, draw, front, back) &&
 	    sna_dri2_schedule_xchg(client, draw, crtc, front, back,
 				   target_msc, divisor, remainder,
commit 258e0cda1d69f74736d0e0be014996173e275543
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jun 8 08:21:38 2014 +0100

    sna/dri2: Mark frames under construction
    
    As we may recurse into the vblank handler whilst waiting for the
    TearFree shadow, we need to be careful that we do not queue the frame
    from the vblank handler that we are in the process of constructing.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index f49bd19..a6f1013 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1612,9 +1612,14 @@ static void chain_swap(struct sna *sna, struct sna_dri2_event *chain)
 		return;
 	}
 
+	if (chain->queued) /* too early! */
+		return;
+
 	assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw));
 	DBG(("%s: chaining draw=%ld, type=%d\n",
 	     __FUNCTION__, (long)chain->draw->id, chain->type));
+	chain->queued = true;
+
 	switch (chain->type) {
 	case SWAP_THROTTLE:
 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
@@ -1628,10 +1633,8 @@ static void chain_swap(struct sna *sna, struct sna_dri2_event *chain)
 			vbl.request.sequence = 1;
 			vbl.request.signal = (uintptr_t)chain;
 
-			if (!sna_wait_vblank(sna, &vbl, chain->pipe)) {
-				chain->queued = true;
+			if (!sna_wait_vblank(sna, &vbl, chain->pipe))
 				return;
-			}
 
 			DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
 		}
@@ -1639,6 +1642,7 @@ static void chain_swap(struct sna *sna, struct sna_dri2_event *chain)
 		if (can_xchg(sna, chain->draw, chain->front, chain->back)) {
 			sna_dri2_exchange_buffers(chain->draw, chain->front, chain->back);
 		} else {
+			assert(chain->queued);
 			chain->bo = __sna_dri2_copy_region(sna, chain->draw, NULL,
 							   chain->back, chain->front,
 							   true);
@@ -1655,7 +1659,6 @@ static void chain_swap(struct sna *sna, struct sna_dri2_event *chain)
 		DRM_VBLANK_EVENT;
 	vbl.request.sequence = 1;
 	vbl.request.signal = (uintptr_t)chain;
-	chain->queued = true;
 	if (sna_wait_vblank(sna, &vbl, chain->pipe)) {
 		DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__));
 		frame_swap_complete(sna, chain, DRI2_BLIT_COMPLETE);
@@ -1736,6 +1739,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
 
 		/* else fall through to blit */
 	case SWAP:
+		assert(info->queued);
 		if (sna->mode.shadow && !sna->mode.shadow_damage) {
 			/* recursed from wait_for_shadow(), simply requeue */
 			DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
@@ -1744,6 +1748,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
 			sna_dri2_exchange_buffers(draw, info->front, info->back);
 			info->type = SWAP_WAIT;
 		}  else {
+			assert(info->queued);
 			info->bo = __sna_dri2_copy_region(sna, draw, NULL,
 							  info->back, info->front, true);
 			info->type = SWAP_WAIT;
@@ -1829,6 +1834,7 @@ sna_dri2_immediate_blit(struct sna *sna,
 		DBG(("%s: no pending blit, starting chain\n",
 		     __FUNCTION__));
 
+		info->queued = true;
 		info->bo = __sna_dri2_copy_region(sna, draw, NULL,
 						  info->back,
 						  info->front,
@@ -1844,10 +1850,8 @@ sna_dri2_immediate_blit(struct sna *sna,
 				vbl.request.sequence = 1;
 				vbl.request.signal = (uintptr_t)info;
 				ret = !sna_wait_vblank(sna, &vbl, info->pipe);
-				if (ret) {
-					info->queued = true;
+				if (ret)
 					event = !swap_limit(draw, 2);
-				}
 			}
 			if (event) {
 				DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
@@ -1920,12 +1924,14 @@ static void chain_flip(struct sna *sna)
 	}
 
 	assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw));
+	chain->queued = true;
 
 	if (can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) &&
 	    sna_dri2_flip(sna, chain)) {
 		DBG(("%s: performing chained flip\n", __FUNCTION__));
 	} else {
 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
+		assert(chain->queued);
 		chain->bo = __sna_dri2_copy_region(sna, chain->draw, NULL,
 						  chain->back, chain->front,
 						  true);
@@ -1942,10 +1948,9 @@ static void chain_flip(struct sna *sna)
 			vbl.request.sequence = 1;
 			vbl.request.signal = (uintptr_t)chain;
 
-			if (!sna_wait_vblank(sna, &vbl, chain->pipe)) {
-				chain->queued = true;
+			assert(chain->queued);
+			if (!sna_wait_vblank(sna, &vbl, chain->pipe))
 				return;
-			}
 		}
 
 		DBG(("%s: fake triple buffering (or vblank wait failed), unblocking client\n", __FUNCTION__));
@@ -2235,6 +2240,7 @@ out:
 		vbl.reply.sequence = draw_target_seq(draw, *target_msc - 1);
 		vbl.request.signal = (uintptr_t)info;
 
+		info->queued = true;
 		if (sna_wait_vblank(sna, &vbl, info->pipe)) {
 			sna_dri2_event_free(sna, draw, info);
 			return false;
@@ -2242,7 +2248,6 @@ out:
 	}
 
 	DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc));
-	info->queued = true;
 	swap_limit(draw, 1);
 	return true;
 }
@@ -2291,12 +2296,12 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 			vbl.request.sequence = 1;
 			vbl.request.signal = (uintptr_t)info;
 
+			info->queued = true;
 			if (sna_wait_vblank(sna, &vbl, info->pipe)) {
 				sna_dri2_event_free(sna, draw, info);
 				goto complete;
 			}
 
-			info->queued = true;
 			swap_limit(draw, 2);
 		}
 	} else {
@@ -2425,6 +2430,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	 * the swap.
 	 */
 	info->type = SWAP;
+	info->queued = true;
 	if (divisor && current_msc >= *target_msc) {
 		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
 		     __FUNCTION__,
@@ -2440,6 +2446,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	vbl.request.sequence = draw_target_seq(draw, *target_msc - 1);
 	if (*target_msc <= current_msc + 1) {
 		DBG(("%s: performing blit before queueing\n", __FUNCTION__));
+		assert(info->queued);
 		info->bo = __sna_dri2_copy_region(sna, draw, NULL,
 						  back, front,
 						  true);
@@ -2452,11 +2459,11 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		*target_msc = current_msc + 1;
 	}
 
+	assert(info->queued);
 	if (sna_wait_vblank(sna, &vbl, info->pipe))
 		goto blit;
 
 	DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc));
-	info->queued = true;
 	swap_limit(draw, 1 + (info->type == SWAP_WAIT));
 	return TRUE;
 
@@ -2585,10 +2592,10 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
 	}
 	vbl.request.sequence = draw_target_seq(draw, target_msc);
 
+	info->queued = true;
 	if (sna_wait_vblank(sna, &vbl, pipe))
 		goto out_free_info;
 
-	info->queued = true;
 	DRI2BlockClient(client, draw);
 	return TRUE;
 


More information about the xorg-commit mailing list