[Intel-gfx] [PATCH] DRI2: handle offscreen drawables better at swap time

Jesse Barnes jbarnes at virtuousgeek.org
Thu Mar 4 18:01:00 CET 2010


If a drawable isn't visible due to DPMS or redirection, we'll just blit
it rather than schedule a swap event.  However, we didn't reset the
target_msc, so the swap target we receive from the server could get out
of sync with the vblank count of the drawable's display.  So at DPMS on
time, the swap target would be the last good vblank count plus some
large number (since the swaps won't have been throttled).

Solve this by zeroing out the swap target like we should when we fall
back to a blit.  Also make the kernel error cases more friendly by
making them fall back to blits too.

WaitMSC probably needs a similar fix, but I've only tested this so far.

Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 64aeb76..8fc6367 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -641,28 +641,14 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	int ret, pipe = I830DRI2DrawablePipe(draw), flip = 0;
 	DRI2FrameEventPtr swap_info;
 	enum DRI2FrameEventType swap_type = DRI2_SWAP;
+	BoxRec box;
+	RegionRec region;
 
 	swap_info = xcalloc(1, sizeof(DRI2FrameEventRec));
 
 	/* Drawable not displayed... just complete the swap */
-	if (pipe == -1 || !swap_info) {
-	    BoxRec	    box;
-	    RegionRec	    region;
-
-	    box.x1 = 0;
-	    box.y1 = 0;
-	    box.x2 = draw->width;
-	    box.y2 = draw->height;
-	    REGION_INIT(pScreen, &region, &box, 0);
-
-	    I830DRI2CopyRegion(draw, &region, front, back);
-
-	    DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func,
-			     data);
-	    if (swap_info)
-		xfree(swap_info);
-	    return TRUE;
-	}
+	if (pipe == -1 || !swap_info)
+	    goto blit_fallback;
 
 	swap_info->drawable_id = draw->id;
 	swap_info->client = client;
@@ -681,7 +667,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "first get vblank counter failed: %s\n",
 			   strerror(errno));
-		return FALSE;
+		goto blit_fallback;
 	}
 
 	/* Flips need to be submitted one frame before */
@@ -694,6 +680,21 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	swap_info->type = swap_type;
 
 	/*
+	 * Sanity check the target vblank count the server gave us.
+	 * Note it'll be 1 if the drawable was offscreen for its last swap,
+	 * so don't bother reporting that as it's common.
+	 */
+	if (*target_msc != 1 && vbl.reply.sequence > *target_msc)
+	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+		       "missed vblank event: cur %ld, target %ld\n",
+		       (unsigned long)vbl.reply.sequence,
+		       (unsigned long)*target_msc);
+	else if (*target_msc != 1 && *target_msc - vbl.reply.sequence > 100)
+	    ErrorF("vblank event in the distant future: cur %ld, target %ld\n",
+		   (unsigned long)vbl.reply.sequence,
+		   (unsigned long)*target_msc);
+
+	/*
 	 * If divisor is zero, we just need to make sure target_msc passes
 	 * before waking up the client.
 	 */
@@ -711,7 +712,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "divisor 0 get vblank counter failed: %s\n",
 				   strerror(errno));
-			return FALSE;
+			goto blit_fallback;
 		}
 
 		*target_msc = vbl.reply.sequence;
@@ -764,13 +765,28 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "final get vblank counter failed: %s\n",
 			   strerror(errno));
-		return FALSE;
+		goto blit_fallback;
 	}
 
 	*target_msc = vbl.reply.sequence;
 	swap_info->frame = *target_msc;
 
 	return TRUE;
+
+blit_fallback:
+	box.x1 = 0;
+	box.y1 = 0;
+	box.x2 = draw->width;
+	box.y2 = draw->height;
+	REGION_INIT(pScreen, &region, &box, 0);
+
+	I830DRI2CopyRegion(draw, &region, front, back);
+
+	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
+	if (swap_info)
+	    xfree(swap_info);
+	*target_msc = 0; /* offscreen, so zero out target vblank count */
+	return TRUE;
 }
 
 /*



More information about the Intel-gfx mailing list