xf86-video-intel: src/sna/sna_dri.c
Chris Wilson
ickle at kemper.freedesktop.org
Sun Jun 26 04:10:56 PDT 2011
src/sna/sna_dri.c | 149 ++++++++++++++++++++++++++++--------------------------
1 file changed, 78 insertions(+), 71 deletions(-)
New commits:
commit 130350111720a0e4ae825bb9d21a8c481cd2b548
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sat Jun 25 23:21:20 2011 +0100
sna/dri: Reorganise schedule_swap to not confuse immediate and wait paths
Eeek, the wait-for-target-msc was using the immediate swap path, meaning
that for copy-swaps the copy was submitting immediately but the client
throttled waiting upon the target vblank. What is actually intended is
for the presentation to be delayed until the target_msc.
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 510ddd1..de5312b 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -177,7 +177,8 @@ sna_dri_create_buffer(DrawablePtr drawable,
int bpp, usage;
DBG(("%s(attachment=%d, format=%d, drawable=%dx%d)\n",
- __FUNCTION__, attachment, format,drawable->width,drawable->height));
+ __FUNCTION__, attachment, format,
+ drawable->width, drawable->height));
buffer = calloc(1, sizeof *buffer + sizeof *private);
if (buffer == NULL)
@@ -793,6 +794,8 @@ static void sna_dri_vblank_handle(int fd,
case DRI2_SWAP:
sna_dri_copy(sna, draw, NULL, info->front, info->back, true);
case DRI2_SWAP_THROTTLE:
+ DBG(("%s: %d complete, frame=%d tv=%d.%06d\n",
+ __FUNCTION__, info->type, frame, tv_sec, tv_usec));
DRI2SwapComplete(info->client,
draw, frame,
tv_sec, tv_usec,
@@ -1034,8 +1037,36 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
sna_dri_reference_buffer(back);
info->type = swap_type;
- if (divisor == 0)
- goto immediate;
+ if (divisor == 0) {
+ DBG(("%s: performing immediate swap\n", __FUNCTION__));
+ if (flip && sna_dri_schedule_flip(sna, draw, info)) {
+ info->old_front =
+ sna_set_screen_pixmap(sna, get_pixmap(back));
+ sna_dri_exchange_buffers(draw, front, back);
+ return TRUE;
+ }
+
+ DBG(("%s: emitting immediate vsync'ed blit, throttling client\n",
+ __FUNCTION__));
+
+ info->type = DRI2_SWAP_THROTTLE;
+
+ vbl.request.type =
+ DRM_VBLANK_RELATIVE |
+ DRM_VBLANK_EVENT |
+ DRM_VBLANK_NEXTONMISS;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 0;
+ vbl.request.signal = (unsigned long)info;
+ if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
+ sna_dri_frame_event_info_free(info);
+ DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
+ }
+
+ sna_dri_copy(sna, draw, NULL, front, back, true);
+ return TRUE;
+ }
/* Get current count */
vbl.request.type = DRM_VBLANK_RELATIVE;
@@ -1057,66 +1088,39 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
* the swap.
*/
if (current_msc < *target_msc) {
- DBG(("%s: performing immediate swap: current=%d, target=%d, divisor=%d\n",
+ DBG(("%s: waiting for swap: current=%d, target=%d, divisor=%d\n",
__FUNCTION__,
(int)current_msc,
(int)*target_msc,
(int)divisor));
- /* 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;
-
-immediate:
info->frame = *target_msc;
- if (flip && sna_dri_schedule_flip(sna, draw, info)) {
- info->old_front =
- sna_set_screen_pixmap(sna, get_pixmap(back));
- sna_dri_exchange_buffers(draw, front, back);
- return TRUE;
- }
-
- DBG(("%s: emitting immediate vsync'ed blit, throttling client\n",
- __FUNCTION__));
-
- info->type = DRI2_SWAP_THROTTLE;
+ info->type = flip ? DRI2_FLIP : DRI2_SWAP;
vbl.request.type =
- DRM_VBLANK_RELATIVE |
- DRM_VBLANK_EVENT |
- DRM_VBLANK_NEXTONMISS;
+ DRM_VBLANK_ABSOLUTE |
+ DRM_VBLANK_EVENT;
if (pipe > 0)
vbl.request.type |= DRM_VBLANK_SECONDARY;
- vbl.request.sequence = 0;
+ vbl.request.sequence = *target_msc - flip;
vbl.request.signal = (unsigned long)info;
if (drmWaitVBlank(sna->kgem.fd, &vbl))
- sna_dri_frame_event_info_free(info);
+ goto blit_fallback;
- sna_dri_copy(sna, draw, NULL, front, back, true);
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 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
+ * equation.
*/
- 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
- * equation.
- */
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
if (flip == 0)
vbl.request.type |= DRM_VBLANK_NEXTONMISS;
@@ -1131,7 +1135,7 @@ immediate:
* when effective onset frame seq could satisfy
* seq % divisor == remainder, so we need to wait for the next time
* this will happen.
-
+ *
* This comparison takes the 1 frame swap delay in pageflipping mode
* into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
* if we are blitting/exchanging instead of flipping.
@@ -1279,7 +1283,7 @@ sna_dri_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
drmVBlank vbl;
int pipe = sna_dri_get_pipe(draw);
- DBG(("%s()\n", __FUNCTION__));
+ DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe));
/* Drawable not displayed, make up a value */
if (pipe == -1) {
@@ -1308,6 +1312,8 @@ sna_dri_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
*ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
*msc = vbl.reply.sequence;
+ DBG(("%s: msc=%llu, ust=%llu\n", __FUNCTION__,
+ (long long)*msc, (long long)*ust));
return TRUE;
}
@@ -1321,16 +1327,14 @@ static int
sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
CARD64 divisor, CARD64 remainder)
{
- ScreenPtr screen = draw->pScreen;
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- struct sna *sna = to_sna(scrn);
- struct sna_dri_frame_event *info;
- drmVBlank vbl;
+ struct sna *sna = to_sna_from_drawable(draw);
+ struct sna_dri_frame_event *info = NULL;
int pipe = sna_dri_get_pipe(draw);
CARD64 current_msc;
+ drmVBlank vbl;
- DBG(("%s(target_msc=%llu, divisor=%llu, rem=%llu)\n",
- __FUNCTION__,
+ DBG(("%s(pipe=%d, target_msc=%llu, divisor=%llu, rem=%llu)\n",
+ __FUNCTION__, pipe,
(long long)target_msc,
(long long)divisor,
(long long)remainder));
@@ -1345,15 +1349,6 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
if (pipe == -1)
goto out_complete;
- info = calloc(1, sizeof(struct sna_dri_frame_event));
- if (!info)
- goto out_complete;
-
- info->sna = sna;
- info->drawable_id = draw->id;
- info->client = client;
- info->type = DRI2_WAITMSC;
-
/* Get current count */
vbl.request.type = DRM_VBLANK_RELATIVE;
if (pipe > 0)
@@ -1362,7 +1357,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
static int limit = 5;
if (limit) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
"%s:%d get vblank counter failed: %s\n",
__FUNCTION__, __LINE__,
strerror(errno));
@@ -1373,20 +1368,32 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
current_msc = vbl.reply.sequence;
+ /* If target_msc already reached or passed, set it to
+ * current_msc to ensure we return a reasonable value back
+ * to the caller. This keeps the client from continually
+ * sending us MSC targets from the past by forcibly updating
+ * their count on this call.
+ */
+ if (divisor == 0 && current_msc >= target_msc) {
+ target_msc = current_msc;
+ goto out_complete;
+ }
+
+ info = calloc(1, sizeof(struct sna_dri_frame_event));
+ if (!info)
+ goto out_complete;
+
+ info->sna = sna;
+ info->drawable_id = draw->id;
+ info->client = client;
+ info->type = DRI2_WAITMSC;
+
/*
* If divisor is zero, or current_msc is smaller than target_msc,
- * we just need to make sure target_msc passes before waking up the
+ * we just need to make sure target_msc passes before waking up the
* client.
*/
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 keeps the client from continually
- * sending us MSC targets from the past by forcibly updating
- * their count on this call.
- */
- if (current_msc >= target_msc)
- target_msc = current_msc;
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
if (pipe > 0)
vbl.request.type |= DRM_VBLANK_SECONDARY;
@@ -1395,7 +1402,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
static int limit = 5;
if (limit) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
"%s:%d get vblank counter failed: %s\n",
__FUNCTION__, __LINE__,
strerror(errno));
@@ -1432,7 +1439,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
if (drmWaitVBlank(sna->kgem.fd, &vbl)) {
static int limit = 5;
if (limit) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
"%s:%d get vblank counter failed: %s\n",
__FUNCTION__, __LINE__,
strerror(errno));
@@ -1443,10 +1450,10 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
info->frame = vbl.reply.sequence;
DRI2BlockClient(client, draw);
-
return TRUE;
out_complete:
+ free(info);
DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
return TRUE;
}
More information about the xorg-commit
mailing list