xf86-video-intel: 3 commits - src/sna/sna_dri.c src/sna/sna_driver.c

Chris Wilson ickle at kemper.freedesktop.org
Sat Jun 11 01:28:11 PDT 2011


 src/sna/sna_dri.c    |  120 ++++++++++++++++++++++++++++-----------------------
 src/sna/sna_driver.c |    4 -
 2 files changed, 70 insertions(+), 54 deletions(-)

New commits:
commit 5f4dbcc8bde3690668bde739ac61178037612475
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 11 09:06:50 2011 +0100

    sna/dri: Queue page-flips immediately for next vblank
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 9b86e29..72962ed 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -66,7 +66,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "dri2.h"
 
-#if DRI2INFOREC_VERSION < 2
+#if DRI2INFOREC_VERSION <= 2
 #error DRI2 version supported by the Xserver is too old
 #endif
 
@@ -975,14 +975,15 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
 	struct sna *sna = to_sna(scrn);
 	drmVBlank vbl;
-	int ret, pipe = sna_dri_get_pipe(draw), flip = 0;
-	struct sna_dri_frame_event *swap_info = NULL;
+	int ret, pipe, flip = 0;
+	struct sna_dri_frame_event *info;
 	enum DRI2FrameEventType swap_type = DRI2_SWAP;
 	CARD64 current_msc;
 
 	DBG(("%s(target_msc=%llu)\n", __FUNCTION__, (long long)*target_msc));
 
 	/* Drawable not displayed... just complete the swap */
+	pipe = sna_dri_get_pipe(draw);
 	if (pipe == -1)
 		goto xchg_fallback;
 
@@ -992,22 +993,21 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	divisor &= 0xffffffff;
 	remainder &= 0xffffffff;
 
-	swap_info = calloc(1, sizeof(struct sna_dri_frame_event));
-	if (!swap_info)
-		goto blit_fallback;
+	info = calloc(1, sizeof(struct sna_dri_frame_event));
+	if (!info)
+		goto xchg_fallback;
 
-	swap_info->sna = sna;
-	swap_info->drawable_id = draw->id;
-	swap_info->client = client;
-	swap_info->event_complete = func;
-	swap_info->event_data = data;
-	swap_info->front = front;
-	swap_info->back = back;
-
-	if (!sna_dri_add_frame_event(swap_info)) {
-		free(swap_info);
-		swap_info = NULL;
-		goto blit_fallback;
+	info->sna = sna;
+	info->drawable_id = draw->id;
+	info->client = client;
+	info->event_complete = func;
+	info->event_data = data;
+	info->front = front;
+	info->back = back;
+
+	if (!sna_dri_add_frame_event(info)) {
+		free(info);
+		goto xchg_fallback;
 	}
 
 	sna_dri_reference_buffer(front);
@@ -1035,14 +1035,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		flip = 1;
 	}
 
-	swap_info->type = swap_type;
-
-	/* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
-	 * Do it early, so handling of different timing constraints
-	 * for divisor, remainder and msc vs. target_msc works.
-	 */
-	if (*target_msc > 0)
-		*target_msc -= flip;
+	info->type = swap_type;
 
 	/*
 	 * If divisor is zero, or current_msc is smaller than target_msc
@@ -1050,6 +1043,25 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	 * the swap.
 	 */
 	if (divisor == 0 || current_msc < *target_msc) {
+		/* If target_msc already reached or passed, set it to
+		 * current_msc to ensure we return a reasonable value back
+		 * to the caller. This makes swap_interval logic more robust.
+		 */
+		if (current_msc >= *target_msc)
+			*target_msc = current_msc;
+
+		info->frame = *target_msc;
+		if (flip && sna_dri_schedule_flip(sna, draw, info)) {
+			sna_dri_exchange_buffers(draw, front, back);
+			return TRUE;
+		}
+
+		DBG(("%s: waiting before swapping: current=%d, target=%d,  divisor=%d\n",
+		     __FUNCTION__,
+		     (int)current_msc,
+		     (int)*target_msc,
+		     (int)divisor));
+
 		vbl.request.type =  DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
 		if (pipe > 0)
 			vbl.request.type |= DRM_VBLANK_SECONDARY;
@@ -1063,28 +1075,30 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		if (pipe > 0)
 			vbl.request.type |= DRM_VBLANK_SECONDARY;
 
-		/* If target_msc already reached or passed, set it to
-		 * current_msc to ensure we return a reasonable value back
-		 * to the caller. This makes swap_interval logic more robust.
-		 */
-		if (current_msc >= *target_msc)
-			*target_msc = current_msc;
-
 		vbl.request.sequence = *target_msc;
-		vbl.request.signal = (unsigned long)swap_info;
-		ret = drmWaitVBlank(sna->kgem.fd, &vbl);
-		if (ret) {
+		vbl.request.signal = (unsigned long)info;
+		if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "divisor 0 get vblank counter failed: %s\n",
 				   strerror(errno));
 			goto blit_fallback;
 		}
-
-		*target_msc = vbl.reply.sequence + flip;
-		swap_info->frame = *target_msc;
 		return TRUE;
 	}
 
+	/* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
+	 * Do it early, so handling of different timing constraints
+	 * for divisor, remainder and msc vs. target_msc works.
+	 */
+	if (flip && *target_msc > 0)
+		--*target_msc;
+
+	DBG(("%s: missed target, queueing event for next: current=%d, target=%d,  divisor=%d\n",
+		     __FUNCTION__,
+		     (int)current_msc,
+		     (int)*target_msc,
+		     (int)divisor));
+
 	/*
 	 * If we get here, target_msc has already passed or we don't have one,
 	 * and we need to queue an event that will satisfy the divisor/remainder
@@ -1096,8 +1110,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	if (pipe > 0)
 		vbl.request.type |= DRM_VBLANK_SECONDARY;
 
-	vbl.request.sequence = current_msc - (current_msc % divisor) +
-		remainder;
+	vbl.request.sequence = current_msc - current_msc % divisor + remainder;
 
 	/*
 	 * If the calculated deadline vbl.request.sequence is smaller than
@@ -1116,9 +1129,8 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	/* Account for 1 frame extra pageflip delay if flip > 0 */
 	vbl.request.sequence -= flip;
 
-	vbl.request.signal = (unsigned long)swap_info;
-	ret = drmWaitVBlank(sna->kgem.fd, &vbl);
-	if (ret) {
+	vbl.request.signal = (unsigned long)info;
+	if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "final get vblank counter failed: %s\n",
 			   strerror(errno));
@@ -1127,22 +1139,20 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 	/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
 	*target_msc = vbl.reply.sequence + flip;
-	swap_info->frame = *target_msc;
+	info->frame = *target_msc;
 	return TRUE;
 
 blit_fallback:
 	DBG(("%s -- blit\n", __FUNCTION__));
 	sna_dri_copy_region(draw, NULL, front, back);
-
-	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
-	if (swap_info)
-		sna_dri_frame_event_info(swap_info);
-	*target_msc = 0; /* offscreen, so zero out target vblank count */
-	return TRUE;
-
+	sna_dri_frame_event_info(info);
+	swap_type = DRI2_BLIT_COMPLETE;
+	goto fallback;
 xchg_fallback:
+	swap_type = DRI2_EXCHANGE_COMPLETE;
 	sna_dri_exchange_buffers(draw, front, back);
-	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_EXCHANGE_COMPLETE, func, data);
+fallback:
+	DRI2SwapComplete(client, draw, 0, 0, 0, swap_type, func, data);
 	*target_msc = 0; /* offscreen, so zero out target vblank count */
 	return TRUE;
 }
commit 00e8b4bec6dc5bb46e6f073af9c1fa34f4a2c2c9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 11 09:00:16 2011 +0100

    sna/dri: For offscreen, swaps just exchange the buffers
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index c90545e..9b86e29 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -980,11 +980,11 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	enum DRI2FrameEventType swap_type = DRI2_SWAP;
 	CARD64 current_msc;
 
-	DBG(("%s()\n", __FUNCTION__));
+	DBG(("%s(target_msc=%llu)\n", __FUNCTION__, (long long)*target_msc));
 
 	/* Drawable not displayed... just complete the swap */
 	if (pipe == -1)
-		goto blit_fallback;
+		goto xchg_fallback;
 
 	/* Truncate to match kernel interfaces; means occasional overflow
 	 * misses, but that's generally not a big deal */
@@ -1139,6 +1139,12 @@ blit_fallback:
 		sna_dri_frame_event_info(swap_info);
 	*target_msc = 0; /* offscreen, so zero out target vblank count */
 	return TRUE;
+
+xchg_fallback:
+	sna_dri_exchange_buffers(draw, front, back);
+	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_EXCHANGE_COMPLETE, func, data);
+	*target_msc = 0; /* offscreen, so zero out target vblank count */
+	return TRUE;
 }
 
 #if DRI2INFOREC_VERSION >= 6
commit e9397b28eff5be4cd5e8a2ceca80333424f24391
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 11 08:54:04 2011 +0100

    sna: Process dri wakeups first
    
    The goal is to minimise the latency in receiving the event from the
    kernel and acting upon it.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 2c9cae9..b9402e7 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -594,10 +594,10 @@ sna_wakeup_handler(int i, pointer data, unsigned long result, pointer read_mask)
 	if ((int)result < 0)
 		return;
 
-	sna_accel_wakeup_handler(sna);
-
 	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask))
 		sna_dri_wakeup(sna);
+
+	sna_accel_wakeup_handler(sna);
 }
 
 #if HAVE_UDEV


More information about the xorg-commit mailing list