xf86-video-intel: 3 commits - src/sna/gen4_render.c src/sna/kgem.c src/sna/sna_display.c src/sna/sna_dri.c src/sna/sna.h test/Makefile.am

Chris Wilson ickle at kemper.freedesktop.org
Mon Jun 13 14:36:45 PDT 2011


 src/sna/gen4_render.c |    2 
 src/sna/kgem.c        |   23 ++++----
 src/sna/sna.h         |    4 -
 src/sna/sna_display.c |   99 ++++++++++++++++++++++++++----------
 src/sna/sna_dri.c     |  134 ++++++++++++++++++++++++++++++++------------------
 test/Makefile.am      |    4 -
 6 files changed, 176 insertions(+), 90 deletions(-)

New commits:
commit 12b8a62652e219de255fdd8b3c801c23274130e9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 13 20:51:56 2011 +0100

    test: Exclude the long running stress tests from make distcheck
    
    tinderbox complains when it is left running for days on end...
    
    Reported-by: Jeremy Huddleston <jeremyhu at apple.com>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/Makefile.am b/test/Makefile.am
index 8cacc9e..752e997 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,4 @@
-TESTS = \
+stress_TESTS = \
 	basic-fillrect \
 	basic-copyarea \
 	basic-copyarea-size \
@@ -14,7 +14,7 @@ TESTS = \
 	mixed-stress \
 	$(NULL)
 
-check_PROGRAMS = $(TESTS)
+check_PROGRAMS = $(stress_TESTS)
 
 AM_CFLAGS = @CWARNFLAGS@ @X11_CFLAGS@
 LDADD = libtest.la @X11_LIBS@
commit 4173ca344bb7d3fb7c03ebdce0e31aa82dba1192
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 13 22:31:55 2011 +0100

    sna: Invalidate the mode if the front pixmap was swapped whilst blanked
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 3a38027..d186f2c 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -205,6 +205,7 @@ struct sna {
 
 	struct sna_mode {
 		uint32_t fb_id;
+		uint32_t fb_pixmap;
 		drmModeResPtr mode_res;
 		int cpp;
 
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 0e1a122..4b7fc3f 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -49,6 +49,7 @@
 #endif
 
 struct sna_crtc {
+	struct sna *sna;
 	drmModeModeInfo kmode;
 	drmModeCrtcPtr mode_crtc;
 	PixmapPtr shadow;
@@ -337,15 +338,6 @@ mode_to_kmode(ScrnInfoPtr scrn,
 	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
 }
 
-static void
-sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
-{
-	struct sna_crtc *sna_crtc = crtc->driver_private;
-	DBG(("%s(pipe %d, dpms mode -> %d):= active=%d\n",
-	     __FUNCTION__, sna_crtc->pipe, mode, mode == DPMSModeOn));
-	sna_crtc->active = mode == DPMSModeOn;
-}
-
 static Bool
 sna_crtc_apply(xf86CrtcPtr crtc)
 {
@@ -417,6 +409,60 @@ sna_crtc_apply(xf86CrtcPtr crtc)
 	return ret;
 }
 
+static void
+sna_crtc_restore(struct sna *sna)
+{
+	ScrnInfoPtr scrn = sna->scrn;
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	struct kgem_bo *bo;
+	int i;
+
+	bo = sna_pixmap_pin(sna->front);
+	if (!bo)
+		return;
+
+	assert(bo->tiling != I915_TILING_Y);
+	if (drmModeAddFB(sna->kgem.fd,
+			 sna->front->drawable.width,
+			 sna->front->drawable.height,
+			 scrn->depth, scrn->bitsPerPixel,
+			 bo->pitch, bo->handle,
+			 &sna->mode.fb_id))
+		return;
+
+	DBG(("%s: handle %d attached to fb %d\n",
+	     __FUNCTION__, bo->handle, mode->fb_id));
+
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+		if (!crtc->enabled)
+			continue;
+
+		if (!sna_crtc_apply(crtc))
+			return;
+	}
+
+	scrn->displayWidth = bo->pitch / sna->mode.cpp;
+	sna->mode.fb_pixmap = sna->front->drawable.serialNumber;
+}
+
+static void
+sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+	struct sna_crtc *sna_crtc = crtc->driver_private;
+
+	DBG(("%s(pipe %d, dpms mode -> %d):= active=%d\n",
+	     __FUNCTION__, sna_crtc->pipe, mode, mode == DPMSModeOn));
+
+	sna_crtc->active = mode == DPMSModeOn;
+	if (mode == DPMSModeOn) {
+		struct sna *sna = sna_crtc->sna;
+		if (sna->front->drawable.serialNumber != sna->mode.fb_pixmap)
+			sna_crtc_restore(sna);
+	}
+}
+
 static Bool
 sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 			  Rotation rotation, int x, int y)
@@ -434,6 +480,9 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	     __FUNCTION__, rotation, x, y,
 	     mode->HDisplay, mode->VDisplay, mode->Clock));
 
+	if (sna_mode->fb_pixmap != sna->front->drawable.serialNumber)
+		sna_mode_remove_fb(sna);
+
 	if (sna_mode->fb_id == 0) {
 		struct kgem_bo *bo = sna_pixmap_pin(sna->front);
 		if (!bo)
@@ -455,6 +504,7 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
 		DBG(("%s: handle %d attached to fb %d\n",
 		     __FUNCTION__, bo->handle, sna_mode->fb_id));
+		sna_mode->fb_pixmap = sna->front->drawable.serialNumber;
 	}
 
 	saved_mode = crtc->mode;
@@ -662,6 +712,7 @@ sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
 
 	sna_crtc->cursor = gem_create(sna->kgem.fd, 64*64*4);
 
+	sna_crtc->sna = sna;
 	sna_crtc->crtc = crtc;
 	list_add(&sna_crtc->link, &mode->crtcs);
 }
@@ -1448,6 +1499,7 @@ sna_crtc_resize(ScrnInfoPtr scrn, int width, int height)
 	scrn->virtualY = height;
 	scrn->displayWidth = bo->pitch / sna->mode.cpp;
 
+	sna->mode.fb_pixmap = sna->front->drawable.serialNumber;
 	sna_redirect_screen_pixmap(scrn, old_front, sna->front);
 	assert(scrn->pScreen->GetScreenPixmap(scrn->pScreen) == sna->front);
 	assert(scrn->pScreen->GetWindowPixmap(scrn->pScreen->root) == sna->front);
@@ -1589,6 +1641,7 @@ sna_do_pageflip(struct sna *sna,
 	count = do_page_flip(sna, data, ref_crtc_hw_id);
 	DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count));
 	if (count) {
+		sna->mode.fb_pixmap = pixmap->drawable.serialNumber;
 		bo->cpu_read = bo->cpu_write = false;
 		bo->gpu = true;
 		bo->needs_flush = true;
@@ -1653,14 +1706,13 @@ sna_mode_remove_fb(struct sna *sna)
 	if (mode->fb_id) {
 		drmModeRmFB(sna->kgem.fd, mode->fb_id);
 		mode->fb_id = 0;
+		mode->fb_pixmap = 0;
 	}
 }
 
 void
 sna_mode_fini(struct sna *sna)
 {
-	struct sna_mode *mode = &sna->mode;
-
 #if 0
 	while (!list_is_empty(&mode->crtcs)) {
 		xf86CrtcDestroy(list_first_entry(&mode->crtcs,
@@ -1675,10 +1727,7 @@ sna_mode_fini(struct sna *sna)
 	}
 #endif
 
-	if (mode->fb_id) {
-		drmModeRmFB(sna->kgem.fd, mode->fb_id);
-		mode->fb_id = 0;
-	}
+	sna_mode_remove_fb(sna);
 
 	/* mode->shadow_fb_id should have been destroyed already */
 }
commit 2158534421f26bcd1eca9ad74ab7a30f27e47a75
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 13 15:27:23 2011 +0100

    sna/dri: Accurately track front and pending front for async flips
    
    By not tracking the front buffer correctly, i.e. performing the exchange
    on every swap, GL_FRONT was no longer pointing at the updated buffer and
    neither was the root pixmap. So both X and GL would read the wrong
    buffer was the flip was pending.
    
    The other issue was that we would feed the old front buffer back to the
    application as a future back buffer (due to buffer caching) and so the
    kernel would duly insert a WAIT_EVENT for the pending flip to complete
    before allowing rendering to affect it.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index c7bc751..da2bb76 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1271,7 +1271,7 @@ gen4_emit_pipelined_pointers(struct sna *sna,
 	     __FUNCTION__, op->mask.bo != NULL,
 	     op->src.filter, op->src.repeat,
 	     op->mask.filter, op->mask.repeat,
-	     kernel, blend, op->has_component_alpha, op->dst.format));
+	     kernel, blend, op->has_component_alpha, (int)op->dst.format));
 
 	OUT_BATCH(GEN4_3DSTATE_PIPELINED_POINTERS | 5);
 	OUT_BATCH(sna->render_state.gen4.vs);
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 8a8bca2..1d5ed06 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -973,8 +973,11 @@ bool kgem_expire_cache(struct kgem *kgem)
 		}
 	}
 	if (!kgem->need_purge) {
-		if (idle)
+		if (idle) {
+			DBG(("%s: idle\n", __FUNCTION__));
+			kgem->need_expire = false;
 			return false;
+		}
 		if (expire == 0)
 			return true;
 	}
@@ -985,12 +988,11 @@ bool kgem_expire_cache(struct kgem *kgem)
 			bo = list_last_entry(&kgem->inactive[i],
 					     struct kgem_bo, list);
 
-			if (!gem_madvise(kgem->fd, bo->handle,
-					 I915_MADV_DONTNEED)) {
-				if (bo->delta > expire) {
-					idle = false;
-					break;
-				}
+			if (gem_madvise(kgem->fd, bo->handle,
+					I915_MADV_DONTNEED) &&
+			    bo->delta > expire) {
+				idle = false;
+				break;
 			}
 
 			count++;
@@ -1002,11 +1004,12 @@ bool kgem_expire_cache(struct kgem *kgem)
 		}
 	}
 
-	DBG(("%s: purge? %d -- expired %d objects, %d bytes\n", __FUNCTION__, kgem->need_purge,  count, size));
+	DBG(("%s: purge? %d -- expired %d objects, %d bytes, idle? %d\n",
+	     __FUNCTION__, kgem->need_purge,  count, size, idle));
 
-	kgem->need_expire = !idle;
 	kgem->need_purge = false;
-	return idle;
+	kgem->need_expire = !idle;
+	return !idle;
 	(void)count;
 	(void)size;
 }
diff --git a/src/sna/sna.h b/src/sna/sna.h
index ae8e554..3a38027 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -213,7 +213,7 @@ struct sna {
 	} mode;
 
 	struct sna_dri {
-		int flip_pending[2];
+		void *flip_pending[2];
 	} dri;
 
 	unsigned int tiling;
@@ -271,7 +271,6 @@ extern int sna_do_pageflip(struct sna *sna,
 			    PixmapPtr pixmap,
 			    void *data,
 			    int ref_crtc_hw_id,
-			    PixmapPtr *old_front,
 			    uint32_t *old_fb);
 
 extern PixmapPtr sna_set_screen_pixmap(struct sna *sna, PixmapPtr pixmap);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index c2347ef..0e1a122 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1528,10 +1528,12 @@ PixmapPtr sna_set_screen_pixmap(struct sna *sna, PixmapPtr pixmap)
 	PixmapPtr old = sna->front;
 	ScrnInfoPtr scrn = sna->scrn;
 
+	assert(sna->front != pixmap);
+
 	sna->front = pixmap;
 	pixmap->refcnt++;
 
-	sna_redirect_screen_pixmap(scrn, old, sna->front);
+	sna_redirect_screen_pixmap(scrn, old, pixmap);
 	scrn->displayWidth = sna_pixmap_get_bo(pixmap)->pitch / sna->mode.cpp;
 
 	return old;
@@ -1542,7 +1544,6 @@ sna_do_pageflip(struct sna *sna,
 		PixmapPtr pixmap,
 		void *data,
 		int ref_crtc_hw_id,
-		PixmapPtr *old_front,
 		uint32_t *old_fb)
 {
 	ScrnInfoPtr scrn = sna->scrn;
@@ -1550,14 +1551,11 @@ sna_do_pageflip(struct sna *sna,
 	struct kgem_bo *bo;
 	int count;
 
-	assert(pixmap != sna->front);
-
 	bo = sna_pixmap_pin(pixmap);
 	if (!bo)
 		return 0;
 
 	*old_fb = mode->fb_id;
-	*old_front = sna->front;
 
 	/*
 	 * Create a new handle for the back buffer
@@ -1577,8 +1575,6 @@ sna_do_pageflip(struct sna *sna,
 	DBG(("%s: handle %d attached to fb %d\n",
 	     __FUNCTION__, bo->handle, mode->fb_id));
 
-	if (kgem_bo_is_dirty(bo))
-		kgem_emit_flush(&sna->kgem);
 	kgem_submit(&sna->kgem);
 
 	/*
@@ -1592,12 +1588,10 @@ sna_do_pageflip(struct sna *sna,
 	 */
 	count = do_page_flip(sna, data, ref_crtc_hw_id);
 	DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count));
-	if (count > 0) {
-		sna->front = pixmap;
-		pixmap->refcnt++;
-
-		sna_redirect_screen_pixmap(scrn, *old_front, sna->front);
-		scrn->displayWidth = bo->pitch / sna->mode.cpp;
+	if (count) {
+		bo->cpu_read = bo->cpu_write = false;
+		bo->gpu = true;
+		bo->needs_flush = true;
 	} else {
 		drmModeRmFB(sna->kgem.fd, mode->fb_id);
 		mode->fb_id = *old_fb;
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 502d05b..74a7145 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -112,15 +112,23 @@ struct sna_dri_frame_event {
 	unsigned int fe_tv_usec;
 
 	PixmapPtr old_front;
+	PixmapPtr next_front;
 	uint32_t old_fb;
 };
 
-static struct sna_dri_frame_event *
+static inline struct sna_dri_frame_event *
 to_frame_event(void *data)
 {
 	 return (struct sna_dri_frame_event *)((uintptr_t)data & ~1);
 }
 
+static inline PixmapPtr
+get_pixmap(DRI2Buffer2Ptr buffer)
+{
+	struct sna_dri_private *priv = buffer->driverPrivate;
+	return priv->pixmap;
+}
+
 static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
 					  PixmapPtr pixmap)
 {
@@ -176,9 +184,10 @@ sna_dri_create_buffer(DrawablePtr drawable,
 		pixmap->refcnt++;
 		bo = sna_pixmap_set_dri(sna, pixmap);
 		bpp = pixmap->drawable.bitsPerPixel;
-		DBG(("%s: attaching to front buffer %dx%d\n",
+		DBG(("%s: attaching to front buffer %dx%d [%p:%d]\n",
 		     __FUNCTION__,
-		     pixmap->drawable.width, pixmap->drawable.height));
+		     pixmap->drawable.width, pixmap->drawable.height,
+		     pixmap, pixmap->refcnt));
 		break;
 
 	case DRI2BufferBackLeft:
@@ -626,8 +635,6 @@ sna_dri_exchange_buffers(DrawablePtr draw,
 	DBG(("%s(%d <--> %d)\n",
 	     __FUNCTION__, front->attachment, back->attachment));
 
-	assert(front->format == back->format);
-
 	tmp = front->attachment;
 	front->attachment = back->attachment;
 	back->attachment = tmp;
@@ -651,7 +658,6 @@ sna_dri_schedule_flip(struct sna *sna,
 	info->count = sna_do_pageflip(sna,
 				      back_priv->pixmap,
 				      info, info->pipe,
-				      &info->old_front,
 				      &info->old_fb);
 	return info->count != 0;
 }
@@ -663,9 +669,10 @@ can_flip(struct sna * sna,
 	 DRI2BufferPtr back)
 {
 	struct sna_dri_private *back_priv = back->driverPrivate;
+	struct sna_dri_private *front_priv = front->driverPrivate;
 	struct sna_pixmap *front_sna, *back_sna;
 	WindowPtr win = (WindowPtr)draw;
-	PixmapPtr front_pixmap;
+	PixmapPtr front_pixmap = front_priv->pixmap;
 	PixmapPtr back_pixmap = back_priv->pixmap;
 
 	ScreenPtr screen = draw->pScreen;
@@ -692,13 +699,17 @@ can_flip(struct sna * sna,
 		return FALSE;
 	}
 
-	front_pixmap = screen->GetWindowPixmap(win);
 	if (front_pixmap != sna->front) {
 		DBG(("%s: no, window is not on the front buffer\n",
 		     __FUNCTION__));
 		return FALSE;
 	}
 
+	DBG(("%s: window size: %dx%d, clip=(%d, %d), (%d, %d)\n",
+	     __FUNCTION__,
+	     win->drawable.width, win->drawable.height,
+	     win->clipList.extents.x1, win->clipList.extents.y1,
+	     win->clipList.extents.x2, win->clipList.extents.y2));
 	if (!RegionEqual(&win->clipList, &screen->root->winSize)) {
 		DBG(("%s: no, window is clipped: clip region=(%d, %d), (%d, %d), root size=(%d, %d), (%d, %d)\n",
 		     __FUNCTION__,
@@ -889,12 +900,40 @@ static void sna_dri_flip_event(struct sna *sna,
 				 DRI2_FLIP_COMPLETE,
 				 flip->client ? flip->event_complete : NULL,
 				 flip->event_data);
+
+		sna_mode_delete_fb(flip->sna, flip->old_front, flip->old_fb);
+		sna_dri_frame_event_info_free(flip);
 		break;
 
 	case DRI2_ASYNC_FLIP:
-		DBG(("%s: async swap flip completed on pipe %d, pending %d\n",
-		     __FUNCTION__, flip->pipe, sna->dri.flip_pending[flip->pipe]));
-		sna->dri.flip_pending[flip->pipe]--;
+		DBG(("%s: async swap flip completed on pipe %d, pending? %d, new? %d\n",
+		     __FUNCTION__, flip->pipe,
+		     sna->dri.flip_pending[flip->pipe] != NULL,
+		     flip->next_front != sna->front));
+		assert(sna->dri.flip_pending[flip->pipe] == flip);
+
+		sna_mode_delete_fb(flip->sna, flip->old_front, flip->old_fb);
+
+		if (sna->front != flip->next_front) {
+			PixmapPtr next = sna->front;
+
+			DBG(("%s: async flip continuing\n", __FUNCTION__));
+			flip->count = sna_do_pageflip(sna, next,
+						      flip, flip->pipe,
+						      &flip->old_fb);
+			if (flip->count) {
+				flip->old_front = flip->next_front;
+				flip->next_front = next;
+				flip->next_front->refcnt++;
+			} else
+				goto finish_async_flip;
+		} else {
+finish_async_flip:
+			DBG(("%s: async flip completed\n", __FUNCTION__));
+			flip->next_front->drawable.pScreen->DestroyPixmap(flip->next_front);
+			sna->dri.flip_pending[flip->pipe] = NULL;
+			sna_dri_frame_event_info_free(flip);
+		}
 		break;
 
 	default:
@@ -925,9 +964,6 @@ sna_dri_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
 		return;
 
 	sna_dri_flip_event(info->sna, info);
-
-	sna_mode_delete_fb(info->sna, info->old_front, info->old_fb);
-	sna_dri_frame_event_info_free(info);
 }
 
 /*
@@ -987,8 +1023,8 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 			goto blit_fallback;
 
 		pixmap = sna_set_screen_pixmap(sna, back_priv->pixmap);
+		assert(pixmap->refcnt > 1);
 		pixmap->refcnt--;
-		assert(pixmap->refcnt > 0);
 		sna_dri_exchange_buffers(draw, front, back);
 		DRI2SwapComplete(client, draw, 0, 0, 0,
 				 DRI2_EXCHANGE_COMPLETE, func, data);
@@ -1063,6 +1099,8 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 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;
 		}
@@ -1160,11 +1198,11 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 		   DRI2SwapEventPtr func, void *data)
 {
 	ScreenPtr screen = draw->pScreen;
-	ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-	struct sna *sna = to_sna(scrn);
+	struct sna *sna = to_sna_from_screen(screen);
 	int type = DRI2_EXCHANGE_COMPLETE;
 	struct sna_dri_private *back_priv = back->driverPrivate;
 	struct sna_dri_private *front_priv = front->driverPrivate;
+	struct sna_dri_frame_event *info;
 	PixmapPtr pixmap;
 	int pipe;
 
@@ -1207,43 +1245,30 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 		return;
 	}
 
+	assert(front_priv->pixmap == sna->front);
+
 	pipe = sna_dri_get_pipe(draw);
 	if (pipe == -1) {
 		/* Drawable not displayed... just complete the swap */
-		pixmap = sna_set_screen_pixmap(sna, back_priv->pixmap);
-		pixmap->refcnt--;
-		assert(pixmap->refcnt > 0);
 		goto exchange;
 	}
 
-	DBG(("%s: flip pending on pipe %d? %d\n",
-	     __FUNCTION__, pipe, sna->dri.flip_pending[pipe]));
-	if (!sna->dri.flip_pending[pipe]) {
-		struct sna_dri_frame_event *info;
-		DRI2BufferPtr t;
-
+	info = sna->dri.flip_pending[pipe];
+	if (info == NULL) {
 		DBG(("%s: no pending flip on pipe %d, so updating scanout\n",
 		     __FUNCTION__, pipe));
 
 		info = calloc(1, sizeof(struct sna_dri_frame_event));
-		if (!info) {
+		if (!info)
 			goto exchange;
-		}
 
 		info->sna = sna;
-		info->drawable_id = draw->id;
-		info->client = client;
 		info->type = DRI2_ASYNC_FLIP;
 		info->pipe = pipe;
 
-		if (!sna_dri_add_frame_event(info)) {
-			free(info);
-			goto exchange;
-		}
-
 		info->count = sna_do_pageflip(sna, back_priv->pixmap,
 					      info, pipe,
-					      &info->old_front, &info->old_fb);
+					      &info->old_fb);
 
 		if (info->count == 0) {
 			DBG(("%s: pageflip failed\n", __FUNCTION__));
@@ -1251,26 +1276,39 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 			goto exchange;
 		}
 
-		type = DRI2_FLIP_COMPLETE;
-		sna->dri.flip_pending[pipe]++;
+		info->old_front = sna->front;
+		info->old_front->refcnt++;
 
-		/* and flip the pointers */
-		t = front;
-		front = back;
-		back = t;
+		info->next_front = back_priv->pixmap;
+		info->next_front->refcnt++;
 
-		front_priv = front->driverPrivate;
-		back_priv = back->driverPrivate;
+		type = DRI2_FLIP_COMPLETE;
+		sna->dri.flip_pending[pipe] = info;
+
+		if ((pixmap = screen->CreatePixmap(screen,
+						   draw->width,
+						   draw->height,
+						   draw->depth,
+						   SNA_CREATE_FB))) {
+			DBG(("%s: new back buffer\n", __FUNCTION__));
+			assert(front_priv->pixmap->refcnt > 1);
+			front_priv->pixmap->refcnt--;
+			front_priv->pixmap = pixmap;
+			front_priv->bo = sna_pixmap_set_dri(sna, pixmap);
+			front->name = kgem_bo_flink(&sna->kgem, front_priv->bo);
+			front->pitch = front_priv->bo->pitch;
+		}
 	}
 
-	if (front_priv->pixmap == sna->front &&
+	if (front_priv->pixmap == info->next_front &&
 	    (pixmap = screen->CreatePixmap(screen,
 					   draw->width,
 					   draw->height,
 					   draw->depth,
 					   SNA_CREATE_FB))) {
 		DBG(("%s: new back buffer\n", __FUNCTION__));
-		screen->DestroyPixmap(front_priv->pixmap);
+		assert(front_priv->pixmap->refcnt > 1);
+		front_priv->pixmap->refcnt--;
 		front_priv->pixmap = pixmap;
 		front_priv->bo = sna_pixmap_set_dri(sna, pixmap);
 		front->name = kgem_bo_flink(&sna->kgem, front_priv->bo);
@@ -1278,8 +1316,10 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 	}
 
 exchange:
+	pixmap = sna_set_screen_pixmap(sna, back_priv->pixmap);
+	screen->DestroyPixmap(pixmap);
+
 	sna_dri_exchange_buffers(draw, front, back);
-	assert(((struct sna_dri_private *)front->driverPrivate)->pixmap != sna->front);
 	DRI2SwapComplete(client, draw, 0, 0, 0, type, func, data);
 }
 #endif


More information about the xorg-commit mailing list