xf86-video-intel: 3 commits - src/sna/sna_display.c src/sna/sna.h src/sna/sna_present.c test/present-test.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Feb 16 04:01:42 PST 2015


 src/sna/sna.h         |    1 
 src/sna/sna_display.c |    3 +
 src/sna/sna_present.c |  100 ++++++++++++++++++++++++++++++++++++++------------
 test/present-test.c   |   62 ++++++++++++++++++-------------
 4 files changed, 118 insertions(+), 48 deletions(-)

New commits:
commit 1877c8f5081f3192dd30bb1162efd6acb1957487
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 16 11:35:27 2015 +0000

    test/present: Compact flip queue checks
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-test.c b/test/present-test.c
index 55d18b1..a4cadc2 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -528,7 +528,7 @@ static int test_exhaustion(Display *dpy, void *Q)
 #define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
 	xcb_connection_t *c = XGetXCBConnection(dpy);
 	Pixmap pixmap;
-	struct dri3_fence fence;
+	struct dri3_fence fence[2];
 	Window root;
 	xcb_xfixes_region_t region;
 	unsigned int width, height;
@@ -539,7 +539,8 @@ static int test_exhaustion(Display *dpy, void *Q)
 	XGetGeometry(dpy, DefaultRootWindow(dpy),
 		     &root, &x, &y, &width, &height, &border, &depth);
 
-	if (dri3_create_fence(dpy, root, &fence))
+	if (dri3_create_fence(dpy, root, &fence[0]) ||
+	    dri3_create_fence(dpy, root, &fence[1]))
 		return 0;
 
 	printf("Testing whole screen flips with long vblank queues: %dx%d\n", width, height);
@@ -548,9 +549,10 @@ static int test_exhaustion(Display *dpy, void *Q)
 	region = xcb_generate_id(c);
 	xcb_xfixes_create_region(c, region, 0, NULL);
 
-	target = check_msc(dpy, root, Q, 0, NULL);
 	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	xshmfence_reset(fence.addr);
+	xshmfence_reset(fence[0].addr);
+	xshmfence_reset(fence[1].addr);
+	target = check_msc(dpy, root, Q, 0, NULL);
 	for (n = N_VBLANKS; n--; )
 		xcb_present_pixmap(c, root, pixmap, 0,
 				   0, /* valid */
@@ -572,29 +574,26 @@ static int test_exhaustion(Display *dpy, void *Q)
 			   0, /* y_off */
 			   None,
 			   None, /* wait fence */
-			   fence.xid,
+			   fence[0].xid,
 			   XCB_PRESENT_OPTION_NONE,
 			   target, /* target msc */
 			   0, /* divisor */
 			   0, /* remainder */
 			   0, NULL);
-	xcb_flush(c);
-
-	XSync(dpy, True);
-	ret += !!xshmfence_await(fence.addr);
-
-	final = check_msc(dpy, root, Q, 0, NULL);
-	if (final < target) {
-		printf("\tFirst flip too early, MSC was %llu, expected %llu\n",
-		       (long long)final, (long long)target);
-		ret++;
-	} else if (final > target + 1) {
-		printf("\tFirst flip too late, MSC was %llu, expected %llu\n",
-		       (long long)final, (long long)target);
-		ret++;
-	}
-
-	xshmfence_reset(fence.addr);
+	for (n = 1; n < N_VBLANKS; n++)
+		xcb_present_pixmap(c, root, pixmap, 0,
+				   region, /* valid */
+				   region, /* update */
+				   0, /* x_off */
+				   0, /* y_off */
+				   None,
+				   None, /* wait fence */
+				   None,
+				   XCB_PRESENT_OPTION_NONE,
+				   target + n, /* target msc */
+				   0, /* divisor */
+				   0, /* remainder */
+				   0, NULL);
 	xcb_present_pixmap(c, root, pixmap, 0,
 			   region, /* valid */
 			   region, /* update */
@@ -602,15 +601,27 @@ static int test_exhaustion(Display *dpy, void *Q)
 			   0, /* y_off */
 			   None,
 			   None, /* wait fence */
-			   fence.xid,
+			   fence[1].xid,
 			   XCB_PRESENT_OPTION_NONE,
 			   target + N_VBLANKS, /* target msc */
 			   0, /* divisor */
 			   0, /* remainder */
 			   0, NULL);
 	xcb_flush(c);
-	ret += !!xshmfence_await(fence.addr);
 
+	ret += !!xshmfence_await(fence[0].addr);
+	final = check_msc(dpy, root, Q, 0, NULL);
+	if (final < target) {
+		printf("\tFirst flip too early, MSC was %llu, expected %llu\n",
+		       (long long)final, (long long)target);
+		ret++;
+	} else if (final > target + 1) {
+		printf("\tFirst flip too late, MSC was %llu, expected %llu\n",
+		       (long long)final, (long long)target);
+		ret++;
+	}
+
+	ret += !!xshmfence_await(fence[1].addr);
 	final = check_msc(dpy, root, Q, 0, NULL);
 	if (final < target + N_VBLANKS) {
 		printf("\tLast flip too early, MSC was %llu, expected %llu\n",
@@ -626,7 +637,8 @@ static int test_exhaustion(Display *dpy, void *Q)
 
 	XFreePixmap(dpy, pixmap);
 	xcb_xfixes_destroy_region(c, region);
-	dri3_fence_free(dpy, &fence);
+	dri3_fence_free(dpy, &fence[1]);
+	dri3_fence_free(dpy, &fence[0]);
 
 	XSync(dpy, True);
 	ret += !!_x_error_occurred;
commit 1c16a91aafa2dff3b41dafa31f233316b595f124
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 16 11:22:26 2015 +0000

    sna: Skip an async flip request to the same bo
    
    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 ecbdf4b..de0cbec 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -5449,6 +5449,9 @@ sna_page_flip(struct sna *sna,
 		assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
 		assert(crtc->flip_bo == NULL);
 
+		if (data == NULL && crtc->bo == bo)
+			goto next_crtc;
+
 		arg.crtc_id = crtc->id;
 		arg.fb_id = get_fb(sna, bo, width, height);
 		if (arg.fb_id == 0) {
commit 93b94b96c6518365fc082a33b17980b018f1e378
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Feb 16 10:59:11 2015 +0000

    sna/present: Append duplicates onto queued vblanks
    
    If we have multiple events for the same vblank, append the notification
    to an existing vblank. This is particularly useful as we it ensures that
    we then report notifications in the same order as queued.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index b7ed2b3..04875b8 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -356,6 +356,7 @@ struct sna {
 		bool available;
 		bool open;
 #if HAVE_PRESENT
+		struct list vblank_queue;
 		uint64_t unflip;
 #endif
 	} present;
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index 881b18a..c96bcd2 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -40,8 +40,10 @@ static present_screen_info_rec present_info;
 struct sna_present_event {
 	xf86CrtcPtr crtc;
 	struct sna *sna;
-	uint64_t event_id;
+	struct list link;
+	uint64_t *event_id;
 	uint64_t target_msc;
+	int n_event_id;
 };
 
 static void sna_present_unflip(ScreenPtr screen, uint64_t event_id);
@@ -88,6 +90,27 @@ static uint64_t gettime_ust64(void)
 	return ust64(tv.tv_sec, tv.tv_nsec / 1000);
 }
 
+static void vblank_complete(struct sna_present_event *info,
+			    uint64_t ust, uint64_t msc)
+{
+	int n;
+
+	DBG(("%s: %d events complete\n", __FUNCTION__, info->n_event_id));
+	for (n = 0; n < info->n_event_id; n++) {
+		DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete%s\n", __FUNCTION__,
+		     sna_crtc_to_pipe(info->crtc),
+		     (int)(ust / 1000000), (int)(ust % 1000000),
+		     (long long)msc, (long long)info->target_msc,
+		     (long long)info->event_id[n],
+		     info->target_msc && msc == (uint32_t)info->target_msc ? "" : ": MISS"));
+		present_event_notify(info->event_id[n], ust, msc);
+	}
+	if (info->n_event_id > 1)
+		free(info->event_id);
+	list_del(&info->link);
+	free(info);
+}
+
 static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t target)
 {
 	const DisplayModeRec *mode = &crtc->desiredMode;
@@ -114,7 +137,7 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
 	union drm_wait_vblank vbl;
 	uint64_t msc, ust;
 
-	DBG(("%s(event=%lld, now=%d)\n", __FUNCTION__, (long long)info->event_id, now));
+	DBG(("%s(event=%lldx%d, now=%d)\n", __FUNCTION__, (long long)info->event_id[0], info->n_event_id, now));
 
 	VG_CLEAR(vbl);
 	vbl.request.type = DRM_VBLANK_RELATIVE;
@@ -137,8 +160,7 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
 		     __FUNCTION__, (long long)info->event_id, (long long)info->target_msc, (long long)msc));
 	}
 
-	present_event_notify(info->event_id, ust, msc);
-	free(info);
+	vblank_complete(info, ust, msc);
 	free(timer);
 	return 0;
 }
@@ -148,6 +170,8 @@ static bool sna_fake_vblank(struct sna_present_event *info)
 	uint64_t msc = sna_crtc_last_swap(info->crtc)->msc;
 	uint32_t delay;
 
+	assert(info->n_event_id == 1);
+
 	if (msc < info->target_msc)
 		delay = msc_to_delay(info->crtc, info->target_msc);
 	else
@@ -157,7 +181,8 @@ static bool sna_fake_vblank(struct sna_present_event *info)
 	     __FUNCTION__, (long long)info->event_id, (long long)info->target_msc, msc, delay));
 	if (delay == 0) {
 		const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
-		present_event_notify(info->event_id, swap_ust(swap), swap->msc);
+		present_event_notify(info->event_id[0], swap_ust(swap), swap->msc);
+		list_del(&info->link);
 		free(info);
 		return true;
 	}
@@ -219,22 +244,16 @@ sna_present_vblank_handler(struct drm_event_vblank *event)
 {
 	struct sna_present_event *info = to_present_event(event->user_data);
 
-	DBG(("%s: pipe=%d tv=%d.%06d msc=%d (target=%lld), event=%lld complete%s\n", __FUNCTION__,
-	     sna_crtc_to_pipe(info->crtc),
-	     event->tv_sec, event->tv_usec, event->sequence,
-	     (long long)info->target_msc, (long long)info->event_id,
-	     info->target_msc && event->sequence == (uint32_t)info->target_msc ? "" : ": MISS"));
-	present_event_notify(info->event_id,
-			     ust64(event->tv_sec, event->tv_usec),
-			     sna_crtc_record_event(info->crtc, event));
-	free(info);
+	vblank_complete(info,
+			ust64(event->tv_sec, event->tv_usec),
+			sna_crtc_record_event(info->crtc, event));
 }
 
 static int
 sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 {
 	struct sna *sna = to_sna_from_screen(crtc->pScreen);
-	struct sna_present_event *info;
+	struct sna_present_event *info, *tmp;
 	const struct ust_msc *swap;
 	union drm_wait_vblank vbl;
 
@@ -254,14 +273,44 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 		return Success;
 	}
 
-	info = malloc(sizeof(struct sna_present_event));
+	list_for_each_entry(tmp, &sna->present.vblank_queue, link) {
+		if (tmp->target_msc == msc) {
+			uint64_t *events = tmp->event_id;
+
+			if (is_power_of_two(tmp->n_event_id)) {
+				events = malloc(2*sizeof(uint64_t)*tmp->n_event_id);
+				if (events == NULL)
+					goto fail;
+
+				memcpy(events,
+				       tmp->event_id,
+				       tmp->n_event_id*sizeof(uint64_t));
+				if (tmp->n_event_id != 1)
+					free(tmp->event_id);
+				tmp->event_id = events;
+			}
+
+			DBG(("%s: appending event=%lld to vblank %lld x %d\n",
+			     __FUNCTION__, (long long)event_id, (long long)msc, tmp->n_event_id+1));
+			events[tmp->n_event_id++] = event_id;
+			return Success;
+		}
+		if ((int64_t)(tmp->target_msc - msc) > 0)
+			break;
+	}
+
+fail:
+	info = malloc(sizeof(struct sna_present_event) + sizeof(uint64_t));
 	if (info == NULL)
 		return BadAlloc;
 
 	info->crtc = crtc->devPrivate;
 	info->sna = sna;
 	info->target_msc = msc;
-	info->event_id = event_id;
+	info->event_id = (uint64_t *)(info + 1);
+	info->event_id[0] = event_id;
+	info->n_event_id = 1;
+	list_add_tail(&info->link, &tmp->link);
 
 	VG_CLEAR(vbl);
 	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
@@ -270,6 +319,7 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 	if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(info->crtc))) {
 		DBG(("%s: vblank enqueue failed\n", __FUNCTION__));
 		if (!sna_fake_vblank(info)) {
+			list_del(&info->link);
 			free(info);
 			return BadAlloc;
 		}
@@ -401,7 +451,7 @@ flip__async(struct sna *sna,
 	DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
 	     pipe_from_crtc(crtc),
 	     gettime_ust64() / 1000000, gettime_ust64() % 1000000,
-	     (long long)sna_crtc_last_swap(crtc->devPrivate)->msc,
+	     crtc ? (long long)sna_crtc_last_swap(crtc->devPrivate)->msc : 0LL,
 	     (long long)target_msc, (long long)event_id));
 	present_event_notify(event_id, gettime_ust64(), target_msc);
 	return TRUE;
@@ -413,7 +463,8 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
 	struct sna_present_event *info = data;
 	struct ust_msc swap;
 
-	DBG(("%s(sequence=%d): event=%lld\n", __FUNCTION__, event->sequence, (long long)info->event_id));
+	DBG(("%s(sequence=%d): event=%lld\n", __FUNCTION__, event->sequence, (long long)info->event_id[0]));
+	assert(info->n_event_id == 1);
 
 	if (info->crtc == NULL) {
 		swap.tv_sec = event->tv_sec;
@@ -426,9 +477,9 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
 	     info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
 	     swap.tv_sec, swap.tv_usec, (long long)swap.msc,
 	     (long long)info->target_msc,
-	     (long long)info->event_id,
+	     (long long)info->event_id[0],
 	     info->target_msc && info->target_msc == swap.msc ? "" : ": MISS"));
-	present_event_notify(info->event_id, swap_ust(&swap), swap.msc);
+	present_event_notify(info->event_id[0], swap_ust(&swap), swap.msc);
 
 	if (info->sna->present.unflip) {
 		DBG(("%s: executing queued unflip (event=%lld)\n", __FUNCTION__, info->sna->present.unflip));
@@ -454,13 +505,15 @@ flip(struct sna *sna,
 	     (long long)event_id,
 	     bo->handle));
 
-	info = malloc(sizeof(struct sna_present_event));
+	info = malloc(sizeof(struct sna_present_event)+sizeof(uint64_t));
 	if (info == NULL)
 		return FALSE;
 
 	info->crtc = crtc ? crtc->devPrivate : NULL;
 	info->sna = sna;
-	info->event_id = event_id;
+	info->event_id = (uint64_t *)(info + 1);
+	info->event_id[0] = event_id;
+	info->n_event_id = 1;
 	info->target_msc = target_msc;
 
 	if (!sna_page_flip(sna, bo, present_flip_handler, info)) {
@@ -621,6 +674,7 @@ bool sna_present_open(struct sna *sna, ScreenPtr screen)
 		return false;
 
 	sna_present_update(sna);
+	list_init(&sna->present.vblank_queue);
 
 	return present_screen_init(screen, &present_info);
 }


More information about the xorg-commit mailing list