xf86-video-intel: 4 commits - src/sna/gen3_render.c src/sna/kgem.h src/sna/sna_display.c src/sna/sna_dri.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Jul 8 02:01:00 PDT 2011


 src/sna/gen3_render.c |    5 -
 src/sna/kgem.h        |    5 +
 src/sna/sna_display.c |    6 +
 src/sna/sna_dri.c     |  179 ++++++++++++++++++++++++++++++++++++++------------
 4 files changed, 151 insertions(+), 44 deletions(-)

New commits:
commit 1e2cae0ab339e477929e429f8ff31b11fcaf2cbf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jul 8 09:54:43 2011 +0100

    sna/gen3: Restore disabling the use of stencil/fog in the invariant
    
    One cleanup too far causing spurious results after rebooting. We also
    need to ensure that the writemask is fully enabled (ie not disabled)
    as well.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 4b59f40..464e87b 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -1082,12 +1082,13 @@ static void gen3_emit_invariant(struct sna *sna)
 		  CSB_TCB(6, 6) |
 		  CSB_TCB(7, 7));
 
-	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | 1);
-	OUT_BATCH(0x00000000);	/* Disable texture coordinate wrap-shortest */
+	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 1);
+	OUT_BATCH(0); /* Disable texture coordinate wrap-shortest */
 	OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) |
 		  S4_LINE_WIDTH_ONE |
 		  S4_CULLMODE_NONE |
 		  S4_VFMT_XY);
+	OUT_BATCH(0); /* Disable fog/stencil. *Enable* write mask. */
 
 	OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
 	OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE);
commit ec3dd64e739c4c2bbd8141de5275fe8a90f24a57
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jul 8 00:17:27 2011 +0100

    sna/dri: Enable chaining of page-flips
    
    Trade off extra frames of latency for extra frames of anti-jitter
    buffering and loss of completion information; compiz users rejoice.
    
    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 c89a7d2..2a8a865 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -76,11 +76,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NDEBUG 1
 #endif
 
+#define NO_TRIPPLE_BUFFER 0
+
 enum frame_event_type {
 	DRI2_SWAP,
 	DRI2_SWAP_THROTTLE,
 	DRI2_ASYNC_FLIP,
 	DRI2_FLIP,
+	DRI2_FLIP_THROTTLE,
 	DRI2_WAITMSC,
 };
 
@@ -113,6 +116,8 @@ struct sna_dri_frame_event {
 	PixmapPtr old_front;
 	PixmapPtr next_front;
 	uint32_t old_fb;
+
+	struct sna_dri_frame_event *chain;
 };
 
 static inline struct sna_dri_frame_event *
@@ -833,10 +838,69 @@ done:
 	sna_dri_frame_event_info_free(info);
 }
 
+static int
+sna_dri_flip(struct sna *sna, DrawablePtr draw, struct sna_dri_frame_event *info)
+{
+	struct sna_dri_private *front_priv = info->front->driverPrivate;
+	struct sna_dri_frame_event *pending;
+	ScreenPtr screen = draw->pScreen;
+	PixmapPtr pixmap;
+
+	if (NO_TRIPPLE_BUFFER)
+		return sna_dri_schedule_flip(sna, draw, info);
+
+	info->type = DRI2_FLIP_THROTTLE;
+
+	pending = sna->dri.flip_pending[info->pipe];
+	if (pending) {
+		if (pending->type != DRI2_FLIP_THROTTLE) {
+			/* We need to first wait (one vblank) for the
+			 * async flips to complete beofore this client can
+			 * take over.
+			 */
+			info->type = DRI2_FLIP;
+			return sna_dri_schedule_flip(sna, draw, info);
+		}
+
+		DBG(("%s: chaining flip\n", __FUNCION__));
+		assert(pending->chain == NULL);
+		pending->chain = info;
+		return TRUE;
+	}
+
+	if (!sna_dri_schedule_flip(sna, draw, info))
+		return FALSE;
+
+	info->old_front =
+		sna_set_screen_pixmap(sna, get_pixmap(info->back));
+	sna->dri.flip_pending[info->pipe] = info;
+
+	if ((pixmap = screen->CreatePixmap(screen,
+					   draw->width,
+					   draw->height,
+					   draw->depth,
+					   SNA_CREATE_FB))) {
+		DBG(("%s: new back buffer\n", __FUNCTION__));
+		front_priv->pixmap->refcnt--;
+		front_priv->pixmap = pixmap;
+		front_priv->bo = sna_pixmap_set_dri(sna, pixmap);
+		info->front->name = kgem_bo_flink(&sna->kgem, front_priv->bo);
+		info->front->pitch = front_priv->bo->pitch;
+	}
+
+	sna_dri_exchange_buffers(draw, info->front, info->back);
+	DRI2SwapComplete(info->client, draw, 0, 0, 0,
+			 DRI2_EXCHANGE_COMPLETE,
+			 info->event_complete,
+			 info->event_data);
+	return TRUE;
+}
+
 static void sna_dri_flip_event(struct sna *sna,
 			       struct sna_dri_frame_event *flip)
 {
 	DrawablePtr drawable;
+	struct sna_dri_frame_event *chain;
 	int status;
 
 	DBG(("%s(frame=%d, tv=%d.%06d, type=%d)\n",
@@ -854,45 +918,76 @@ static void sna_dri_flip_event(struct sna *sna,
 		 * into account. This usually means some defective kms pageflip completion,
 		 * causing wrong (msc, ust) return values and possible visual corruption.
 		 */
-		if (!flip->drawable_id)
-			return;
-
-		status = dixLookupDrawable(&drawable,
-					   flip->drawable_id,
-					   serverClient,
-					   M_ANY, DixWriteAccess);
-		if (status != Success)
-			return;
-
-		if ((flip->fe_frame < flip->frame) &&
-		    (flip->frame - flip->fe_frame < 5)) {
-			static int limit = 5;
-
-			/* XXX we are currently hitting this path with older
-			 * kernels, so make it quieter.
-			 */
-			if (limit) {
-				xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
-					   "%s: Pageflip completion has impossible msc %d < target_msc %d\n",
-					   __func__, flip->fe_frame, flip->frame);
-				limit--;
+		if (flip->drawable_id) {
+			status = dixLookupDrawable(&drawable,
+						   flip->drawable_id,
+						   serverClient,
+						   M_ANY, DixWriteAccess);
+			if (status == Success) {
+				if ((flip->fe_frame < flip->frame) &&
+				    (flip->frame - flip->fe_frame < 5)) {
+					static int limit = 5;
+
+					/* XXX we are currently hitting this path with older
+					 * kernels, so make it quieter.
+					 */
+					if (limit) {
+						xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
+							   "%s: Pageflip completion has impossible msc %d < target_msc %d\n",
+							   __func__, flip->fe_frame, flip->frame);
+						limit--;
+					}
+
+					/* All-0 values signal timestamping failure. */
+					flip->fe_frame = flip->fe_tv_sec = flip->fe_tv_usec = 0;
+				}
+
+				DBG(("%s: flip complete\n", __FUNCTION__));
+				DRI2SwapComplete(flip->client, drawable,
+						 flip->fe_frame,
+						 flip->fe_tv_sec,
+						 flip->fe_tv_usec,
+						 DRI2_FLIP_COMPLETE,
+						 flip->client ? flip->event_complete : NULL,
+						 flip->event_data);
 			}
-
-			/* All-0 values signal timestamping failure. */
-			flip->fe_frame = flip->fe_tv_sec = flip->fe_tv_usec = 0;
 		}
 
-		DBG(("%s: flip complete\n", __FUNCTION__));
-		DRI2SwapComplete(flip->client, drawable,
-				 flip->fe_frame,
-				 flip->fe_tv_sec,
-				 flip->fe_tv_usec,
-				 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_FLIP_THROTTLE:
+		assert(sna->dri.flip_pending[flip->pipe] == flip);
+		sna->dri.flip_pending[flip->pipe] = NULL;
+
+		chain = flip->chain;
 
 		sna_mode_delete_fb(flip->sna, flip->old_front, flip->old_fb);
 		sna_dri_frame_event_info_free(flip);
+
+		if (chain) {
+			status = dixLookupDrawable(&drawable,
+						   chain->drawable_id,
+						   serverClient,
+						   M_ANY, DixWriteAccess);
+			if (status == Success) {
+				if (!(can_flip(chain->sna, drawable,
+					       chain->front, chain->back) &&
+				      sna_dri_flip(chain->sna, drawable, chain))) {
+					sna_dri_copy(sna, drawable, NULL,
+						     chain->front, chain->back, true);
+					DRI2SwapComplete(chain->client,
+							 drawable,
+							 0, 0, 0,
+							 DRI2_BLIT_COMPLETE,
+							 chain->client ? chain->event_complete : NULL,
+							 chain->event_data);
+					sna_dri_frame_event_info_free(chain);
+				}
+			} else
+				sna_dri_frame_event_info_free(chain);
+		}
 		break;
 
 	case DRI2_ASYNC_FLIP:
@@ -1052,12 +1147,8 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	info->type = swap_type;
 	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);
+		if (flip && sna_dri_flip(sna, draw, info))
 			return TRUE;
-		}
 
 		DBG(("%s: emitting immediate vsync'ed blit, throttling client\n",
 		     __FUNCTION__));
@@ -1200,6 +1291,7 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 	DBG(("%s()\n", __FUNCTION__));
 
 	if (!can_flip(sna, draw, front, back)) {
+blit:
 		sna_dri_copy(sna, draw, NULL, front, back, false);
 		DRI2SwapComplete(client, draw, 0, 0, 0,
 				 DRI2_BLIT_COMPLETE, func, data);
@@ -1259,6 +1351,11 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 			front->name = kgem_bo_flink(&sna->kgem, front_priv->bo);
 			front->pitch = front_priv->bo->pitch;
 		}
+	} else if (info->type != DRI2_ASYNC_FLIP) {
+		/* A normal vsync'ed client is finishing, wait for it
+		 * to unpin the old framebuffer before taking* pver.
+		 */
+		goto blit;
 	}
 
 	if (front_priv->pixmap == info->next_front &&
commit a32694b0f07e35c22dd83bcfb828196d5d86628e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jul 7 23:11:39 2011 +0100

    sna/dri: Remove redundant NULL check in reference
    
    The buffer has already been dereferenced by this point...
    
    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 b75c46e..c89a7d2 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -316,10 +316,8 @@ static void sna_dri_destroy_buffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer)
 
 static void sna_dri_reference_buffer(DRI2Buffer2Ptr buffer)
 {
-	if (buffer) {
-		struct sna_dri_private *private = buffer->driverPrivate;
-		private->refcnt++;
-	}
+	struct sna_dri_private *private = buffer->driverPrivate;
+	private->refcnt++;
 }
 
 static void damage(DrawablePtr drawable, PixmapPtr pixmap, RegionPtr region)
commit d180c5f5f781f4fa7f747dd7bb8073a20771cd79
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 6 20:19:00 2011 +0100

    sna: Take advantage of the needs_flush tracking on the front buffer
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 6c1f656..2ad975a 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -181,8 +181,13 @@ static inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo)
 void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo);
 static inline void kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo)
 {
+	if (!bo->needs_flush)
+		return;
+
 	kgem_bo_submit(kgem, bo);
 	__kgem_flush(kgem, bo);
+
+	bo->needs_flush = false;
 }
 
 static inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo)
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 1586884..b3b3185 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1787,6 +1787,12 @@ sna_do_pageflip(struct sna *sna,
 		sna->mode.fb_pixmap = pixmap->drawable.serialNumber;
 		bo->cpu_read = bo->cpu_write = false;
 		bo->gpu = true;
+
+		/* Although the kernel performs an implicit flush upon
+		 * page-flipping, marking the bo as requiring a flush
+		 * here ensures that the buffer goes into the active cache
+		 * upon release.
+		 */
 		bo->needs_flush = true;
 	} else {
 		drmModeRmFB(sna->kgem.fd, mode->fb_id);


More information about the xorg-commit mailing list