xf86-video-intel: 2 commits - src/sna/sna_display.c src/sna/sna_dri.c src/sna/sna.h src/sna/sna_video_sprite.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Nov 12 06:40:04 PST 2012


 src/sna/sna.h              |    4 -
 src/sna/sna_display.c      |   11 +++--
 src/sna/sna_dri.c          |   96 +++++++++++++++++++++++++++++++++++----------
 src/sna/sna_video_sprite.c |   14 +++++-
 4 files changed, 96 insertions(+), 29 deletions(-)

New commits:
commit b27ecf3059bc066ef59f2a71c1d8d8f0ffec7191
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Nov 12 14:06:06 2012 +0000

    sna/dri: Prevent scheduling a swap on stale buffers
    
    If the screen has been reconfigured and the DRI client tries to swap the
    old buffers (having not processed the invalidate event and retrieved the
    current names), quietly drop the request. If we try to obey the request,
    we will end up attaching a back buffer that is the wrong size to the
    scanout...
    
    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 23d9572..17e3db1 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -98,9 +98,10 @@ struct sna_dri_frame_event {
 };
 
 struct sna_dri_private {
-	int refcnt;
 	PixmapPtr pixmap;
 	struct kgem_bo *bo;
+	unsigned long serial;
+	int refcnt;
 };
 
 static inline struct sna_dri_frame_event *
@@ -259,6 +260,8 @@ sna_dri_create_buffer(DrawablePtr draw,
 			assert(private->pixmap == pixmap);
 			assert(sna_pixmap(pixmap)->gpu_bo == private->bo);
 			assert(kgem_bo_flink(&sna->kgem, private->bo) == buffer->name);
+			assert(8*private->bo->pitch >= pixmap->drawable.width * pixmap->drawable.bitsPerPixel);
+			assert(private->bo->pitch * pixmap->drawable.height <= kgem_bo_size(private->bo));
 
 			private->refcnt++;
 			return buffer;
@@ -353,6 +356,7 @@ sna_dri_create_buffer(DrawablePtr draw,
 	private->refcnt = 1;
 	private->bo = bo;
 	private->pixmap = pixmap;
+	private->serial = get_drawable_pixmap(draw)->drawable.serialNumber;
 
 	if (buffer->name == 0)
 		goto err;
@@ -1064,6 +1068,15 @@ can_flip(struct sna * sna,
 	}
 
 	assert(get_private(front)->pixmap == sna->front);
+	assert(get_private(front)->serial == pixmap->drawable.serialNumber);
+
+	if (get_private(back)->serial != pixmap->drawable.serialNumber) {
+		DBG(("%s: no, DRI2 drawable has a stale reference to the pixmap (DRI2 pixmap=%ld, X pixmap=%ld)\n",
+		     __FUNCTION__,
+		     get_private(back)->serial,
+		     pixmap->drawable.serialNumber));
+		return false;
+	}
 
 	DBG(("%s: window size: %dx%d, clip=(%d, %d), (%d, %d) x %d\n",
 	     __FUNCTION__,
@@ -1154,9 +1167,34 @@ can_exchange(struct sna * sna,
 		return false;
 	}
 
+	assert(get_private(front)->serial == pixmap->drawable.serialNumber);
+	if (get_private(back)->serial != pixmap->drawable.serialNumber) {
+		DBG(("%s: no, DRI2 drawable has a stale reference to the pixmap (DRI2 pixmap=%ld, X pixmap=%ld)\n",
+		     __FUNCTION__,
+		     get_private(back)->serial,
+		     pixmap->drawable.serialNumber));
+		return false;
+	}
+
 	return true;
 }
 
+static bool
+can_blit(struct sna * sna,
+	 DrawablePtr draw,
+	 DRI2BufferPtr front,
+	 DRI2BufferPtr back)
+{
+	PixmapPtr pixmap;
+
+	if (draw->type == DRAWABLE_PIXMAP)
+		return true;
+
+	pixmap = get_drawable_pixmap(draw);
+	return (get_private(front)->serial == pixmap->drawable.serialNumber &&
+		get_private(back)->serial  == pixmap->drawable.serialNumber);
+}
+
 inline static uint32_t pipe_select(int pipe)
 {
 	/* The third pipe was introduced with IvyBridge long after
@@ -1236,7 +1274,7 @@ static void chain_swap(struct sna *sna,
 		DBG(("%s: performing chained exchange\n", __FUNCTION__));
 		sna_dri_exchange_buffers(draw, chain->front, chain->back);
 		type = DRI2_EXCHANGE_COMPLETE;
-	} else {
+	} else if (can_blit(sna, draw, chain->front, chain->back)) {
 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
 
 		chain->bo = sna_dri_copy_to_front(sna, draw, NULL,
@@ -1245,6 +1283,12 @@ static void chain_swap(struct sna *sna,
 						  true);
 
 		type = DRI2_BLIT_COMPLETE;
+	} else {
+		DRI2SwapComplete(chain->client, draw,
+				 0, 0, 0, DRI2_BLIT_COMPLETE,
+				 chain->client ? chain->event_complete : NULL, chain->event_data);
+		sna_dri_frame_event_info_free(sna, draw, chain);
+		return;
 	}
 
 	DRI2SwapComplete(chain->client, draw,
@@ -1309,10 +1353,11 @@ void sna_dri_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
 		}
 		/* else fall through to blit */
 	case DRI2_SWAP:
-		info->bo = sna_dri_copy_to_front(sna, draw, NULL,
-						 get_private(info->front)->bo,
-						 get_private(info->back)->bo,
-						 true);
+		if (can_blit(sna, draw, info->front, info->back))
+			info->bo = sna_dri_copy_to_front(sna, draw, NULL,
+							 get_private(info->front)->bo,
+							 get_private(info->back)->bo,
+							 true);
 		info->type = DRI2_SWAP_WAIT;
 		/* fall through to SwapComplete */
 	case DRI2_SWAP_WAIT:
@@ -1411,12 +1456,14 @@ static void chain_flip(struct sna *sna)
 		} else
 			sna->dri.flip_pending = chain;
 	} else {
-		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
+		if (can_blit(sna, chain->draw, chain->front, chain->back)) {
+			DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
 
-		chain->bo = sna_dri_copy_to_front(sna, chain->draw, NULL,
-						  get_private(chain->front)->bo,
-						  get_private(chain->back)->bo,
-						  true);
+			chain->bo = sna_dri_copy_to_front(sna, chain->draw, NULL,
+							  get_private(chain->front)->bo,
+							  get_private(chain->back)->bo,
+							  true);
+		}
 		DRI2SwapComplete(chain->client, chain->draw, 0, 0, 0,
 				 DRI2_BLIT_COMPLETE, chain->client ? chain->event_complete : NULL, chain->event_data);
 		sna_dri_frame_event_info_free(sna, chain->draw, chain);
@@ -1494,10 +1541,12 @@ static void sna_dri_flip_event(struct sna *sna,
 			DBG(("%s: no longer able to flip\n", __FUNCTION__));
 
 			if (flip->draw) {
-				flip->bo = sna_dri_copy_to_front(sna, flip->draw, NULL,
-								 get_private(flip->front)->bo,
-								 get_private(flip->back)->bo,
-								 false);
+				if (can_blit(sna, flip->draw, flip->front, flip->back)) {
+					flip->bo = sna_dri_copy_to_front(sna, flip->draw, NULL,
+									 get_private(flip->front)->bo,
+									 get_private(flip->back)->bo,
+									 false);
+				}
 				DRI2SwapComplete(flip->client, flip->draw,
 						 0, 0, 0,
 						 DRI2_BLIT_COMPLETE,
@@ -1966,10 +2015,15 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 	info->type = swap_type;
 	if (divisor == 0) {
-		if (can_exchange(sna, draw, front, back))
+		if (can_exchange(sna, draw, front, back)) {
 			sna_dri_immediate_xchg(sna, draw, info);
-		else
+		} else if (can_blit(sna, draw, front, back)) {
 			sna_dri_immediate_blit(sna, draw, info);
+		} else {
+			DRI2SwapComplete(client, draw, 0, 0, 0,
+					 DRI2_BLIT_COMPLETE, func, data);
+			sna_dri_frame_event_info_free(sna, draw, info);
+		}
 		return TRUE;
 	}
 
@@ -2044,17 +2098,17 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	return TRUE;
 
 blit_fallback:
+	pipe = DRI2_BLIT_COMPLETE;
 	if (can_exchange(sna, draw, front, back)) {
 		DBG(("%s -- xchg\n", __FUNCTION__));
 		sna_dri_exchange_buffers(draw, front, back);
 		pipe = DRI2_EXCHANGE_COMPLETE;
-	} else {
+	} else if (can_blit(sna, draw, front, back)) {
 		DBG(("%s -- blit\n", __FUNCTION__));
 		sna_dri_copy_to_front(sna, draw, NULL,
 				      get_private(front)->bo,
 				      get_private(back)->bo,
 				      false);
-		pipe = DRI2_BLIT_COMPLETE;
 	}
 	if (info)
 		sna_dri_frame_event_info_free(sna, draw, info);
@@ -2078,17 +2132,17 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 
 	if (!can_flip(sna, draw, front, back)) {
 blit:
+		name = DRI2_BLIT_COMPLETE;
 		if (can_exchange(sna, draw, front, back)) {
 			DBG(("%s: unable to flip, so xchg\n", __FUNCTION__));
 			sna_dri_exchange_buffers(draw, front, back);
 			name = DRI2_EXCHANGE_COMPLETE;
-		} else {
+		} else if (can_blit(sna, draw, front, back)) {
 			DBG(("%s: unable to flip, so blit\n", __FUNCTION__));
 			sna_dri_copy_to_front(sna, draw, NULL,
 					      get_private(front)->bo,
 					      get_private(back)->bo,
 					      false);
-			name = DRI2_BLIT_COMPLETE;
 		}
 
 		DRI2SwapComplete(client, draw, 0, 0, 0, name, func, data);
commit 34aa1e3b2702a55799a5655a3ba10bce4cc2065a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Nov 12 11:22:53 2012 +0000

    sna: Compile against ancient libdrm
    
    We need to trim the sprite video overlays if the prototypes are not
    known.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 45cfebe..f1b3beb 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -371,8 +371,8 @@ static inline void sna_dri_close(struct sna *sna, ScreenPtr pScreen) { }
 void sna_dri_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap);
 
 extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
-extern int sna_crtc_to_plane(xf86CrtcPtr crtc);
-extern int sna_crtc_id(xf86CrtcPtr crtc);
+extern uint32_t sna_crtc_to_plane(xf86CrtcPtr crtc);
+extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
 
 CARD32 sna_format_for_depth(int depth);
 CARD32 sna_render_format_for_depth(int depth);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index d384bb2..aefb6f7 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -113,7 +113,7 @@ static inline uint32_t fb_id(struct kgem_bo *bo)
 	return bo->delta;
 }
 
-int sna_crtc_id(xf86CrtcPtr crtc)
+uint32_t sna_crtc_id(xf86CrtcPtr crtc)
 {
 	return to_sna_crtc(crtc)->id;
 }
@@ -123,7 +123,7 @@ int sna_crtc_to_pipe(xf86CrtcPtr crtc)
 	return to_sna_crtc(crtc)->pipe;
 }
 
-int sna_crtc_to_plane(xf86CrtcPtr crtc)
+uint32_t sna_crtc_to_plane(xf86CrtcPtr crtc)
 {
 	return to_sna_crtc(crtc)->plane;
 }
@@ -1458,9 +1458,10 @@ static const xf86CrtcFuncsRec sna_crtc_funcs = {
 #endif
 };
 
-static uint32_t
+static int
 sna_crtc_find_plane(struct sna *sna, int pipe)
 {
+#ifdef DRM_IOCTL_MODE_GETPLANERESOURCES
 	struct drm_mode_get_plane_res r;
 	uint32_t *planes, id = 0;
 	int i;
@@ -1496,7 +1497,11 @@ sna_crtc_find_plane(struct sna *sna, int pipe)
 	}
 	free(planes);
 
+	assert(id);
 	return id;
+#else
+	return 0;
+#endif
 }
 
 static void
diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
index ff3b4b3..d4eae91 100644
--- a/src/sna/sna_video_sprite.c
+++ b/src/sna/sna_video_sprite.c
@@ -37,9 +37,11 @@
 #include <xf86xv.h>
 #include <X11/extensions/Xv.h>
 #include <fourcc.h>
-#include <drm_fourcc.h>
 #include <i915_drm.h>
 
+#ifdef  DRM_IOCTL_MODE_GETPLANERESOURCES
+#include <drm_fourcc.h>
+
 #define IMAGE_MAX_WIDTH		2048
 #define IMAGE_MAX_HEIGHT	2048
 
@@ -181,7 +183,7 @@ sna_video_sprite_show(struct sna *sna,
 		      xf86CrtcPtr crtc,
 		      BoxPtr dstBox)
 {
-	int plane = sna_crtc_to_plane(crtc);
+	uint32_t plane = sna_crtc_to_plane(crtc);
 
 	update_dst_box_to_crtc_coords(sna, crtc, dstBox);
 	if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
@@ -286,7 +288,7 @@ static int sna_video_sprite_put_image(ScrnInfoPtr scrn,
 				   clip))
 		return Success;
 
-	if (!crtc || !sna_crtc_to_plane(crtc)) {
+	if (!crtc || sna_crtc_to_plane(crtc) == 0) {
 		/* If the video isn't visible on any CRTC, turn it off */
 		sna_video_sprite_off(sna, video);
 		return Success;
@@ -441,3 +443,9 @@ XF86VideoAdaptorPtr sna_video_sprite_setup(struct sna *sna,
 
 	return adaptor;
 }
+#else
+XF86VideoAdaptorPtr sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
+{
+	return NULL;
+}
+#endif


More information about the xorg-commit mailing list