diff mbox

DRI2: handle offscreen drawables better at swap time

Message ID 20100304090100.6896412e@jbarnes-piketon (mailing list archive)
State Accepted
Headers show

Commit Message

Jesse Barnes March 4, 2010, 5:01 p.m. UTC
None
diff mbox

Patch

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;
 }
 
 /*