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

Chris Wilson ickle at kemper.freedesktop.org
Mon May 5 01:35:37 PDT 2014


 src/sna/sna.h         |    3 +
 src/sna/sna_display.c |   93 ++++++++++++++++++++++++-------------------
 src/sna/sna_dri.c     |  107 +++++++++++++++++++++++++-------------------------
 3 files changed, 111 insertions(+), 92 deletions(-)

New commits:
commit 8fd13a52072c2f8f12f934deaba1ef9ddb16d5f9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon May 5 09:32:59 2014 +0100

    sna: Reorder connector initialisation to avoid leak
    
    If the output was ignored, we would leak the allocations. However, we
    can check the output name after the first GETCONNECTOR/GETENCODER
    request before any allocations.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index ed3b9b0..e46f5d1 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -2723,7 +2723,7 @@ sna_output_add(struct sna *sna, int id, drmModeResPtr res, int serial)
 	xf86OutputPtr *outputs, output;
 	const char *output_name;
 	char name[32];
-	int len, i, ret = -1;
+	int len, i;
 
 	DBG(("%s(%d)\n", __FUNCTION__, id));
 
@@ -2750,11 +2750,41 @@ sna_output_add(struct sna *sna, int id, drmModeResPtr res, int serial)
 		return 0;
 	}
 
+	if (compat_conn.conn.connector_type < ARRAY_SIZE(output_names))
+		output_name = output_names[compat_conn.conn.connector_type];
+	else
+		output_name = "UNKNOWN";
+	len = snprintf(name, 32, "%s%d", output_name, compat_conn.conn.connector_type_id);
+	if (output_ignored(scrn, name))
+		return 0;
+
 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc)) {
 		DBG(("%s: GETENCODER failed, ret=%d\n", __FUNCTION__, errno));
 		return 0;
 	}
 
+	if (xf86IsEntityShared(scrn->entityList[0])) {
+		const char *str;
+
+		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
+		if (str && !sna_zaphod_match(str, name)) {
+			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
+			return 0;
+		}
+
+		if ((enc.possible_crtcs & (1 << scrn->confScreen->device->screen)) == 0) {
+			if (str) {
+				xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+					   "%s is an invalid output for screen (pipe) %d\n",
+					   name, scrn->confScreen->device->screen);
+				return -1;
+			} else
+				return 0;
+		}
+
+		enc.possible_crtcs = 1;
+	}
+
 	sna_output = calloc(sizeof(struct sna_output), 1);
 	if (!sna_output)
 		return -1;
@@ -2783,36 +2813,6 @@ sna_output_add(struct sna *sna, int id, drmModeResPtr res, int serial)
 	VG(VALGRIND_MAKE_MEM_DEFINED(sna_output->prop_ids, sizeof(uint32_t)*sna_output->num_props));
 	VG(VALGRIND_MAKE_MEM_DEFINED(sna_output->prop_values, sizeof(uint64_t)*sna_output->num_props));
 
-	if (compat_conn.conn.connector_type < ARRAY_SIZE(output_names))
-		output_name = output_names[compat_conn.conn.connector_type];
-	else
-		output_name = "UNKNOWN";
-	len = snprintf(name, 32, "%s%d", output_name, compat_conn.conn.connector_type_id);
-	if (output_ignored(scrn, name))
-		return 0;
-
-	if (xf86IsEntityShared(scrn->entityList[0])) {
-		const char *str;
-
-		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
-		if (str && !sna_zaphod_match(str, name)) {
-			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
-			ret = 0;
-			goto cleanup;
-		}
-
-		if ((enc.possible_crtcs & (1 << scrn->confScreen->device->screen)) == 0) {
-			if (str) {
-				xf86DrvMsg(scrn->scrnIndex, X_ERROR,
-					   "%s is an invalid output for screen (pipe) %d\n",
-					   name, scrn->confScreen->device->screen);
-			}
-			goto cleanup;
-		}
-
-		enc.possible_crtcs = 1;
-	}
-
 	output = calloc(1, sizeof(*output) + len + 1);
 	if (!output)
 		goto cleanup;
@@ -2889,7 +2889,7 @@ cleanup:
 	free(sna_output->prop_ids);
 	free(sna_output->prop_values);
 	free(sna_output);
-	return ret;
+	return -1;
 }
 
 static void sna_output_del(xf86OutputPtr output)
commit 55f567f9d8dd1bbc21acf30f02d394e54ddc8157
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun May 4 12:13:25 2014 +0100

    sna/dri: Report the last known MSC whilst the pipe is off
    
    From OML_sync_control:
    "The graphics MSC value is incremented once for each screen refresh.
    For a non-interlaced display, this means that the graphics MSC value
    is incremented for each frame."
    
    When the pipe is disabled, return the last known MSC such that the
    reported value is always monotonic and consistent with the pipe when it
    is active again. That also is consistent with OML_sync_control which
    says that the MSC is a vertical refresh counter, and by implication does
    not increase whilst the pipe is off.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index cc086d7..06ddaab 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -72,6 +72,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <signal.h>
 #include <setjmp.h>
 
+#define MAX_PIPES 4
+
 #include "compiler.h"
 
 #if HAS_DEBUG_FULL
@@ -307,6 +309,7 @@ struct sna {
 
 	struct sna_dri {
 		void *flip_pending;
+		unsigned int last_msc[MAX_PIPES];
 	} dri;
 
 	struct sna_xv {
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index dc1ceaa..89d707a 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -851,10 +851,37 @@ sna_dri_copy_region(DrawablePtr draw,
 	__sna_dri_copy_region(sna, draw, region, src, dst, false);
 }
 
-static inline int sna_wait_vblank(struct sna *sna, drmVBlank *vbl)
+inline static uint32_t pipe_select(int pipe)
+{
+	/* The third pipe was introduced with IvyBridge long after
+	 * multiple pipe support was added to the kernel, hence
+	 * we can safely ignore the capability check - if we have more
+	 * than two pipes, we can assume that they are fully supported.
+	 */
+	if (pipe > 1)
+		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
+	else if (pipe > 0)
+		return DRM_VBLANK_SECONDARY;
+	else
+		return 0;
+}
+
+static inline int sna_wait_vblank(struct sna *sna, drmVBlank *vbl, int pipe)
 {
-	DBG(("%s\n", __FUNCTION__));
-	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+	int ret;
+
+	DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe));
+
+	vbl->request.type |= pipe_select(pipe);
+	ret = drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+	if (ret)
+		return ret;
+
+	assert(pipe < MAX_PIPES);
+	DBG(("%s: last_msc[%d] = %u\n", __FUNCTION__, pipe, vbl->request.sequence));
+	sna->dri.last_msc[pipe] = vbl->request.sequence;
+
+	return 0;
 }
 
 #if DRI2INFOREC_VERSION >= 4
@@ -1223,21 +1250,6 @@ can_flip(struct sna * sna,
 	return true;
 }
 
-inline static uint32_t pipe_select(int pipe)
-{
-	/* The third pipe was introduced with IvyBridge long after
-	 * multiple pipe support was added to the kernel, hence
-	 * we can safely ignore the capability check - if we have more
-	 * than two pipes, we can assume that they are fully supported.
-	 */
-	if (pipe > 1)
-		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
-	else if (pipe > 0)
-		return DRM_VBLANK_SECONDARY;
-	else
-		return 0;
-}
-
 static void
 sna_dri_exchange_buffers(DrawablePtr draw,
 			 DRI2BufferPtr front,
@@ -1307,12 +1319,11 @@ static void chain_swap(struct sna *sna,
 		VG_CLEAR(vbl);
 		vbl.request.type =
 			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT |
-			pipe_select(chain->pipe);
+			DRM_VBLANK_EVENT;
 		vbl.request.sequence = 1;
 		vbl.request.signal = (unsigned long)chain;
 
-		if (!sna_wait_vblank(sna, &vbl))
+		if (!sna_wait_vblank(sna, &vbl, chain->pipe))
 			return;
 
 		DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
@@ -1330,11 +1341,10 @@ static void chain_swap(struct sna *sna,
 	vbl.request.type =
 		DRM_VBLANK_RELATIVE |
 		DRM_VBLANK_NEXTONMISS |
-		DRM_VBLANK_EVENT |
-		pipe_select(chain->pipe);
+		DRM_VBLANK_EVENT;
 	vbl.request.sequence = 0;
 	vbl.request.signal = (unsigned long)chain;
-	if (sna_wait_vblank(sna, &vbl))
+	if (sna_wait_vblank(sna, &vbl, chain->pipe))
 		sna_dri_frame_event_info_free(sna, draw, chain);
 }
 
@@ -1350,11 +1360,10 @@ static bool sna_dri_blit_complete(struct sna *sna,
 		VG_CLEAR(vbl);
 		vbl.request.type =
 			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT |
-			pipe_select(info->pipe);
+			DRM_VBLANK_EVENT;
 		vbl.request.sequence = 1;
 		vbl.request.signal = (unsigned long)info;
-		if (!sna_wait_vblank(sna, &vbl))
+		if (!sna_wait_vblank(sna, &vbl, info->pipe))
 			return false;
 	}
 
@@ -1393,12 +1402,11 @@ void sna_dri_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
 			VG_CLEAR(vbl);
 			vbl.request.type =
 				DRM_VBLANK_RELATIVE |
-				DRM_VBLANK_EVENT |
-				pipe_select(info->pipe);
+				DRM_VBLANK_EVENT;
 			vbl.request.sequence = 1;
 			vbl.request.signal = (unsigned long)info;
 
-			if (!sna_wait_vblank(sna, &vbl))
+			if (!sna_wait_vblank(sna, &vbl, info->pipe))
 				return;
 
 			DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
@@ -1488,11 +1496,10 @@ sna_dri_immediate_blit(struct sna *sna,
 				vbl.request.type =
 					DRM_VBLANK_RELATIVE |
 					DRM_VBLANK_NEXTONMISS |
-					DRM_VBLANK_EVENT |
-					pipe_select(info->pipe);
+					DRM_VBLANK_EVENT;
 				vbl.request.sequence = 0;
 				vbl.request.signal = (unsigned long)info;
-				ret = !sna_wait_vblank(sna, &vbl);
+				ret = !sna_wait_vblank(sna, &vbl, info->pipe);
 			}
 		} else {
 			DBG(("%s: pending blit, chained\n", __FUNCTION__));
@@ -1790,7 +1797,7 @@ get_current_msc_for_target(struct sna *sna, CARD64 target_msc, int pipe)
 		VG_CLEAR(vbl);
 		vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe);
 		vbl.request.sequence = 0;
-		if (sna_wait_vblank(sna, &vbl) == 0)
+		if (sna_wait_vblank(sna, &vbl, pipe) == 0)
 			ret = vbl.reply.sequence;
 	}
 
@@ -1951,8 +1958,7 @@ out:
 
 	vbl.request.type =
 		DRM_VBLANK_ABSOLUTE |
-		DRM_VBLANK_EVENT |
-		pipe_select(pipe);
+		DRM_VBLANK_EVENT;
 
 	/*
 	 * If divisor is zero, or current_msc is smaller than target_msc
@@ -1999,7 +2005,7 @@ out:
 	/* Account for 1 frame extra pageflip delay */
 	vbl.request.sequence -= 1;
 	vbl.request.signal = (unsigned long)info;
-	if (sna_wait_vblank(sna, &vbl)) {
+	if (sna_wait_vblank(sna, &vbl, pipe)) {
 		sna_dri_frame_event_info_free(sna, draw, info);
 		return false;
 	}
@@ -2142,11 +2148,10 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 		vbl.request.type =
 			DRM_VBLANK_ABSOLUTE |
-			DRM_VBLANK_EVENT |
-			pipe_select(pipe);
+			DRM_VBLANK_EVENT;
 		vbl.request.sequence = *target_msc;
 		vbl.request.signal = (unsigned long)info;
-		if (sna_wait_vblank(sna, &vbl))
+		if (sna_wait_vblank(sna, &vbl, pipe))
 			goto blit;
 
 		return TRUE;
@@ -2169,8 +2174,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	vbl.request.type =
 		DRM_VBLANK_ABSOLUTE |
 		DRM_VBLANK_EVENT |
-		DRM_VBLANK_NEXTONMISS |
-		pipe_select(pipe);
+		DRM_VBLANK_NEXTONMISS;
 
 	vbl.request.sequence = current_msc - current_msc % divisor + remainder;
 	/*
@@ -2186,7 +2190,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 	vbl.request.sequence -= 1;
 	vbl.request.signal = (unsigned long)info;
-	if (sna_wait_vblank(sna, &vbl))
+	if (sna_wait_vblank(sna, &vbl, pipe))
 		goto blit;
 
 	return TRUE;
@@ -2223,21 +2227,21 @@ sna_dri_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
 	drmVBlank vbl;
 	int pipe;
 
-
 	pipe = sna_dri_get_pipe(draw);
 	DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe));
 	if (pipe == -1) {
 fail:
 		/* Drawable not displayed, make up a *monotonic* value */
+		assert(pipe < MAX_PIPES);
 		*ust = gettime_us();
-		*msc = 0;
+		*msc = sna->dri.last_msc[pipe < 0 ? 0 : pipe];
 		return TRUE;
 	}
 
 	VG_CLEAR(vbl);
-	vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe);
+	vbl.request.type = DRM_VBLANK_RELATIVE;
 	vbl.request.sequence = 0;
-	if (sna_wait_vblank(sna, &vbl) == 0) {
+	if (sna_wait_vblank(sna, &vbl, pipe) == 0) {
 		*ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
 		*msc = vbl.reply.sequence;
 		DBG(("%s: msc=%llu, ust=%llu\n", __FUNCTION__,
@@ -2286,9 +2290,9 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
 	VG_CLEAR(vbl);
 
 	/* Get current count */
-	vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe);
+	vbl.request.type = DRM_VBLANK_RELATIVE;
 	vbl.request.sequence = 0;
-	if (sna_wait_vblank(sna, &vbl))
+	if (sna_wait_vblank(sna, &vbl, pipe))
 		goto out_complete;
 
 	current_msc = vbl.reply.sequence;
@@ -2315,8 +2319,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
 	sna_dri_add_frame_event(draw, info);
 
 	vbl.request.signal = (unsigned long)info;
-	vbl.request.type =
-		DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
+	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
 	/*
 	 * 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
@@ -2342,7 +2345,7 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
 			vbl.request.sequence += divisor;
 	}
 
-	if (sna_wait_vblank(sna, &vbl))
+	if (sna_wait_vblank(sna, &vbl, pipe))
 		goto out_free_info;
 
 	DBG(("%s: waiting until MSC=%llu\n", __FUNCTION__, (long long)vbl.request.sequence));
commit 080e9f99857081bca063c67afb7c98854d1f61f4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun May 4 11:59:40 2014 +0100

    sna: Prefer PrimaryOutput for timing signals
    
    If the drawable is even partially on the PrimaryOutput, use that pipe
    for determining synchronisation counters and synchronised updates.
    
    OML_sync_control:
    	"For a multi-monitor system, the monitor used to
    	 determine MSC is screen 0 of <display>."
    
    The PrimaryOutput is the nearest approximation we have to "screen 0". We
    also deviate in handling what hapens when that screen is off, which is
    not mentioned at all in OML_sync_control.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 70fbc8d..ed3b9b0 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -4523,15 +4523,33 @@ sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
 	DBG(("%s for box=(%d, %d), (%d, %d)\n",
 	     __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
 
+	if (desired == NULL) {
+		rrScrPrivPtr rr = rrGetScrPriv(xf86ScrnToScreen(sna->scrn));
+		if (rr && rr->primaryOutput) {
+			xf86OutputPtr output = rr->primaryOutput->devPrivate;
+			DBG(("%s: have PrimaryOutput? %d marking as desired\n", __FUNCTION__, output->crtc != NULL));
+			desired = output->crtc;
+		}
+	}
+	if (desired && to_sna_crtc(desired) && to_sna_crtc(desired)->bo) {
+		BoxRec cover_box;
+		if (sna_box_intersect(&cover_box, &desired->bounds, box)) {
+			DBG(("%s: box overlaps desired crtc: (%d, %d), (%d, %d)\n",
+			     __FUNCTION__,
+			     cover_box.x1, cover_box.y1,
+			     cover_box.x2, cover_box.y2));
+			return desired;
+		}
+	}
+
 	best_crtc = NULL;
 	best_coverage = 0;
-	for (c = 0; c < config->num_crtc; c++) {
+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
 		xf86CrtcPtr crtc = config->crtc[c];
 		BoxRec cover_box;
 		int coverage;
 
-		if (to_sna_crtc(crtc) == NULL)
-			break;
+		assert(to_sna_crtc(crtc));
 
 		/* If the CRTC is off, treat it as not covering */
 		if (to_sna_crtc(crtc)->bo == NULL) {
@@ -4557,11 +4575,6 @@ sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
 		     cover_box.x1, cover_box.y1,
 		     cover_box.x2, cover_box.y2,
 		     c));
-		if (crtc == desired) {
-			DBG(("%s: box is on desired crtc [%p]\n",
-			     __FUNCTION__, crtc));
-			return crtc;
-		}
 
 		coverage = sna_box_area(&cover_box);
 		DBG(("%s: box covers %d of crtc %d\n",


More information about the xorg-commit mailing list