xf86-video-intel: 2 commits - configure.ac src/sna/sna_accel.c src/sna/sna_display.c src/sna/sna.h

Chris Wilson ickle at kemper.freedesktop.org
Sun May 6 13:58:55 PDT 2012


 configure.ac          |    2 
 src/sna/sna.h         |    4 
 src/sna/sna_accel.c   |  294 +++++++++++++++++++-------------------------------
 src/sna/sna_display.c |    4 
 4 files changed, 120 insertions(+), 184 deletions(-)

New commits:
commit 2c801c45dbad58d18f2673e17723825dda0c4e55
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun May 6 17:23:11 2012 +0100

    sna: Replace timerfd with OsTimer
    
    As timerfd is linux-specific, and OsTimer an OS-agnostic abraction,
    replace the former with the later. Arguably this has slightly better
    performance characteristics in select-bound loops.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index 3770983..c031a26 100644
--- a/configure.ac
+++ b/configure.ac
@@ -265,8 +265,6 @@ if test "x$DEBUG" = xfull; then
         CFLAGS="$CFLAGS -O0 -ggdb3"
 fi
 
-AC_CHECK_HEADERS([sys/timerfd.h])
-
 DRIVER_NAME=intel
 AC_SUBST([DRIVER_NAME])
 AC_SUBST([moduledir])
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 3e4b8ec..d7a20b9 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -225,7 +225,9 @@ struct sna {
 	unsigned watch_flush;
 	unsigned flush;
 
-	int timer[NUM_TIMERS];
+	uint32_t time;
+	OsTimerPtr timer;
+	uint32_t timer_expire[NUM_TIMERS];
 	uint16_t timer_active;
 	uint16_t timer_ready;
 
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 3e03934..3280490 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -11964,165 +11964,123 @@ static struct sna_pixmap *sna_accel_scanout(struct sna *sna)
 	return priv && priv->gpu_bo ? priv : NULL;
 }
 
-#if HAVE_SYS_TIMERFD_H && !FORCE_FLUSH
-#include <sys/timerfd.h>
-#include <errno.h>
-
-static uint64_t read_timer(int fd)
-{
-	uint64_t count = 0;
-	int ret = read(fd, &count, sizeof(count));
-	return count;
-	(void)ret;
-}
-
-static void sna_accel_drain_timer(struct sna *sna, int id)
+static void sna_accel_disarm_timer(struct sna *sna, int id)
 {
-	if (sna->timer_active & (1<<id))
-		read_timer(sna->timer[id]);
-}
-
-static void _sna_accel_disarm_timer(struct sna *sna, int id)
-{
-	struct itimerspec to;
-
-	DBG(("%s[%d] (time=%ld)\n", __FUNCTION__, id, (long)GetTimeInMillis()));
-
-	memset(&to, 0, sizeof(to));
-	timerfd_settime(sna->timer[id], 0, &to, NULL);
+	DBG(("%s[%d] (time=%ld)\n", __FUNCTION__, id, (long)sna->time));
 	sna->timer_active &= ~(1<<id);
+	sna->timer_ready &= ~(1<<id);
 }
 
-#define return_if_timer_active(id) do {					\
-	if (sna->timer_active & (1<<(id)))				\
-		return (sna->timer_ready & (1<<(id))) && read_timer(sna->timer[id]) > 0;			\
-} while (0)
-
-static Bool sna_accel_do_flush(struct sna *sna)
+static bool sna_accel_do_flush(struct sna *sna)
 {
-	struct itimerspec to;
 	struct sna_pixmap *priv;
 
 	priv = sna_accel_scanout(sna);
 	if (priv == NULL) {
 		DBG(("%s -- no scanout attached\n", __FUNCTION__));
-		return FALSE;
-	}
-
-	if (sna->kgem.flush_now) {
-		sna->kgem.flush_now = 0;
-		if (priv->gpu_bo->exec) {
-			DBG(("%s -- forcing flush\n", __FUNCTION__));
-			sna_accel_drain_timer(sna, FLUSH_TIMER);
-			return TRUE;
-		}
-	}
-
-	return_if_timer_active(FLUSH_TIMER);
-
-	if (priv->cpu_damage == NULL && priv->gpu_bo->exec == NULL) {
-		DBG(("%s -- no pending write to scanout\n", __FUNCTION__));
-		return FALSE;
+		sna_accel_disarm_timer(sna, FLUSH_TIMER);
+		return false;
 	}
 
 	if (sna->flags & SNA_NO_DELAYED_FLUSH)
-		return TRUE;
-
-	if (sna->timer[FLUSH_TIMER] == -1)
-		return TRUE;
-
-	DBG(("%s, starting flush timer, at time=%ld\n",
-	     __FUNCTION__, (long)GetTimeInMillis()));
+		return true;
 
-	/* Initial redraw hopefully before this vblank */
-	to.it_value.tv_sec = 0;
-	to.it_value.tv_nsec = sna->vblank_interval / 2;
+	if (sna->timer_active & (1<<(FLUSH_TIMER))) {
+		if (sna->kgem.flush_now) {
+			sna->kgem.flush_now = 0;
+			if (priv->gpu_bo->exec) {
+				DBG(("%s -- forcing flush\n", __FUNCTION__));
+				sna->timer_ready |= 1 << FLUSH_TIMER;
+			}
+		}
 
-	/* Then periodic updates for every vblank */
-	to.it_interval.tv_sec = 0;
-	to.it_interval.tv_nsec = sna->vblank_interval;
-	timerfd_settime(sna->timer[FLUSH_TIMER], 0, &to, NULL);
+		if (sna->timer_ready & (1<<(FLUSH_TIMER))) {
+			sna->timer_expire[FLUSH_TIMER] =
+				sna->time + sna->vblank_interval;
+			return true;
+		}
+	} else {
+		if (priv->cpu_damage == NULL && priv->gpu_bo->exec == NULL) {
+			DBG(("%s -- no pending write to scanout\n", __FUNCTION__));
+		} else {
+			sna->timer_active |= 1 << FLUSH_TIMER;
+			sna->timer_ready |= 1 << FLUSH_TIMER;
+			sna->timer_expire[FLUSH_TIMER] =
+				sna->time + sna->vblank_interval / 2;
+		}
+	}
 
-	sna->timer_active |= 1 << FLUSH_TIMER;
-	return FALSE;
+	return false;
 }
 
-static Bool sna_accel_do_expire(struct sna *sna)
+static bool sna_accel_do_expire(struct sna *sna)
 {
-	struct itimerspec to;
-
-	return_if_timer_active(EXPIRE_TIMER);
-
-	if (!sna->kgem.need_expire)
-		return FALSE;
-
-	if (sna->timer[EXPIRE_TIMER] == -1)
-		return TRUE;
-
-	to.it_interval.tv_sec = MAX_INACTIVE_TIME;
-	to.it_interval.tv_nsec = 0;
-	to.it_value = to.it_interval;
-	timerfd_settime(sna->timer[EXPIRE_TIMER], 0, &to, NULL);
+	if (sna->timer_active & (1<<(EXPIRE_TIMER))) {
+		if (sna->timer_ready & (1<<(EXPIRE_TIMER))) {
+			sna->timer_expire[EXPIRE_TIMER] =
+				sna->time + MAX_INACTIVE_TIME * 1000;
+			return true;
+		}
+	} else {
+		if (sna->kgem.need_expire) {
+			sna->timer_active |= 1 << EXPIRE_TIMER;
+			sna->timer_ready |= 1 << EXPIRE_TIMER;
+			sna->timer_expire[EXPIRE_TIMER] =
+				sna->time + MAX_INACTIVE_TIME * 1000;
+		}
+	}
 
-	sna->timer_active |= 1 << EXPIRE_TIMER;
-	return FALSE;
+	return false;
 }
 
-static Bool sna_accel_do_inactive(struct sna *sna)
+static bool sna_accel_do_inactive(struct sna *sna)
 {
-	struct itimerspec to;
-
-	return_if_timer_active(INACTIVE_TIMER);
-
-	if (list_is_empty(&sna->active_pixmaps))
-		return FALSE;
-
-	if (sna->timer[INACTIVE_TIMER] == -1)
-		return FALSE;
-
-	/* Periodic expiration after every 2 minutes. */
-	to.it_interval.tv_sec = 120;
-	to.it_interval.tv_nsec = 0;
-	to.it_value = to.it_interval;
-	timerfd_settime(sna->timer[INACTIVE_TIMER], 0, &to, NULL);
+	if (sna->timer_active & (1<<(INACTIVE_TIMER))) {
+		if (sna->timer_ready & (1<<(INACTIVE_TIMER))) {
+			sna->timer_expire[INACTIVE_TIMER] =
+				sna->time + 120 * 1000;
+			return true;
+		}
+	} else {
+		if (!list_is_empty(&sna->active_pixmaps)) {
+			sna->timer_active |= 1 << INACTIVE_TIMER;
+			sna->timer_ready |= 1 << INACTIVE_TIMER;
+			sna->timer_expire[INACTIVE_TIMER] =
+				sna->time + 120 * 1000;
+		}
+	}
 
-	sna->timer_active |= 1 << INACTIVE_TIMER;
-	return FALSE;
+	return false;
 }
 
-static void sna_accel_create_timers(struct sna *sna)
+static CARD32 sna_timeout(OsTimerPtr timer, CARD32 now, pointer arg)
 {
-	int id;
+	struct sna *sna = arg;
+	CARD32 next = UINT32_MAX;
+	uint32_t active;
+	int i;
 
-	/* XXX Can we replace this with OSTimer provided by dix? */
+	active = sna->timer_active & ~sna->timer_ready;
+	if (active == 0)
+		return 0;
 
-#ifdef CLOCK_MONOTONIC_COARSE
-	for (id = 0; id < NUM_FINE_TIMERS; id++)
-		sna->timer[id] = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
-	for (; id < NUM_TIMERS; id++) {
-		sna->timer[id] = timerfd_create(CLOCK_MONOTONIC_COARSE, TFD_NONBLOCK);
-		if (sna->timer[id] == -1)
-			sna->timer[id] = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
+	for (i = 0; i < NUM_TIMERS; i++) {
+		if (active & (1 << i)) {
+			if (now > sna->timer_expire[i]) {
+				sna->timer_ready |= 1 << i;
+			} else {
+				if (sna->timer_expire[i] < next)
+					next = sna->timer_expire[i];
+			}
+		}
 	}
-#else
-	for (id = 0; id < NUM_TIMERS; id++)
-		sna->timer[id] = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
-#endif
-}
-#else
-static void sna_accel_create_timers(struct sna *sna)
-{
-	int id;
 
-	for (id = 0; id < NUM_TIMERS; id++)
-		sna->timer[id] = -1;
+	if ((sna->timer_active & ~sna->timer_ready) == 0)
+		return 0;
+
+	assert(next != UINT32_MAX);
+	return next - now;
 }
-static Bool sna_accel_do_flush(struct sna *sna) { return sna_accel_scanout(sna) != NULL; }
-static Bool sna_accel_do_expire(struct sna *sna) { return sna->kgem.need_expire; }
-static Bool sna_accel_do_inactive(struct sna *sna) { return FALSE; }
-static void sna_accel_drain_timer(struct sna *sna, int id) { }
-static void _sna_accel_disarm_timer(struct sna *sna, int id) { }
-#endif
 
 static bool sna_accel_flush(struct sna *sna)
 {
@@ -12131,14 +12089,14 @@ static bool sna_accel_flush(struct sna *sna)
 	bool busy = priv->cpu_damage || need_throttle;
 
 	DBG(("%s (time=%ld), cpu damage? %p, exec? %d nbatch=%d, busy? %d, need_throttle=%d\n",
-	     __FUNCTION__, (long)GetTimeInMillis(),
+	     __FUNCTION__, (long)sna->time,
 	     priv->cpu_damage,
 	     priv->gpu_bo->exec != NULL,
 	     sna->kgem.nbatch,
 	     sna->kgem.busy, need_throttle));
 
 	if (!sna->kgem.busy && !busy)
-		_sna_accel_disarm_timer(sna, FLUSH_TIMER);
+		sna_accel_disarm_timer(sna, FLUSH_TIMER);
 	sna->kgem.busy = busy;
 
 	if (priv->cpu_damage)
@@ -12152,10 +12110,10 @@ static bool sna_accel_flush(struct sna *sna)
 
 static void sna_accel_expire(struct sna *sna)
 {
-	DBG(("%s (time=%ld)\n", __FUNCTION__, (long)GetTimeInMillis()));
+	DBG(("%s (time=%ld)\n", __FUNCTION__, (long)sna->time));
 
 	if (!kgem_expire_cache(&sna->kgem))
-		_sna_accel_disarm_timer(sna, EXPIRE_TIMER);
+		sna_accel_disarm_timer(sna, EXPIRE_TIMER);
 }
 
 static void sna_accel_inactive(struct sna *sna)
@@ -12163,7 +12121,7 @@ static void sna_accel_inactive(struct sna *sna)
 	struct sna_pixmap *priv;
 	struct list preserve;
 
-	DBG(("%s (time=%ld)\n", __FUNCTION__, (long)GetTimeInMillis()));
+	DBG(("%s (time=%ld)\n", __FUNCTION__, (long)sna->time));
 
 #if DEBUG_ACCEL
 	{
@@ -12252,22 +12210,12 @@ static void sna_accel_inactive(struct sna *sna)
 	if (list_is_empty(&sna->inactive_clock[1]) &&
 	    list_is_empty(&sna->inactive_clock[0]) &&
 	    list_is_empty(&sna->active_pixmaps))
-		_sna_accel_disarm_timer(sna, INACTIVE_TIMER);
-}
-
-static void sna_accel_install_timers(struct sna *sna)
-{
-	int n;
-
-	for (n = 0; n < NUM_TIMERS; n++) {
-		if (sna->timer[n] != -1)
-			AddGeneralSocket(sna->timer[n]);
-	}
+		sna_accel_disarm_timer(sna, INACTIVE_TIMER);
 }
 
 Bool sna_accel_pre_init(struct sna *sna)
 {
-	sna_accel_create_timers(sna);
+	sna->timer = TimerSet(NULL, 0, 0, sna_timeout, sna);
 	return TRUE;
 }
 
@@ -12287,7 +12235,6 @@ Bool sna_accel_init(ScreenPtr screen, struct sna *sna)
 	list_init(&sna->inactive_clock[1]);
 
 	AddGeneralSocket(sna->kgem.fd);
-	sna_accel_install_timers(sna);
 
 	screen->CreateGC = sna_create_gc;
 	screen->GetImage = sna_get_image;
@@ -12413,17 +12360,17 @@ static void sna_accel_throttle(struct sna *sna)
 	if (sna->flags & SNA_NO_THROTTLE)
 		return;
 
-	DBG(("%s (time=%ld)\n", __FUNCTION__, (long)GetTimeInMillis()));
+	DBG(("%s (time=%ld)\n", __FUNCTION__, (long)sna->time));
 
 	kgem_throttle(&sna->kgem);
 }
 
 void sna_accel_block_handler(struct sna *sna)
 {
-	if (sna_accel_do_flush(sna)) {
-		if (sna_accel_flush(sna))
-			sna_accel_throttle(sna);
-	}
+	sna->time = GetTimeInMillis();
+
+	if (sna_accel_do_flush(sna) && sna_accel_flush(sna))
+		sna_accel_throttle(sna);
 
 	if (sna_accel_do_expire(sna))
 		sna_accel_expire(sna);
@@ -12437,31 +12384,20 @@ void sna_accel_block_handler(struct sna *sna)
 		sna->watch_flush = 0;
 	}
 
-	sna->timer_ready = 0;
+	if (sna->timer_ready) {
+		sna->timer_ready = 0;
+		TimerForce(sna->timer);
+	}
 }
 
 void sna_accel_wakeup_handler(struct sna *sna, fd_set *ready)
 {
-	int id, active;
-
 	if (sna->kgem.need_retire)
 		kgem_retire(&sna->kgem);
 	if (sna->kgem.need_purge)
 		kgem_purge_cache(&sna->kgem);
-
-	active = sna->timer_active & ~sna->timer_ready;
-	for (id = 0; id < NUM_TIMERS; id++)
-		if (active & (1 << id) && FD_ISSET(sna->timer[id], ready))
-			sna->timer_ready |= 1 << id;
 }
 
 void sna_accel_free(struct sna *sna)
 {
-	int id;
-
-	for (id = 0; id < NUM_TIMERS; id++)
-		if (sna->timer[id] != -1) {
-			close(sna->timer[id]);
-			sna->timer[id] = -1;
-		}
 }
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 6287cd9..65d1992 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -643,8 +643,8 @@ static void update_flush_interval(struct sna *sna)
 	if (max_vrefresh == 0)
 		max_vrefresh = 40;
 
-	sna->vblank_interval = 1000 * 1000 * 1000 / max_vrefresh; /* Hz -> ns */
-	DBG(("max_vrefresh=%d, vblank_interval=%d ns\n",
+	sna->vblank_interval = 1000 / max_vrefresh; /* Hz -> ms */
+	DBG(("max_vrefresh=%d, vblank_interval=%d ms\n",
 	       max_vrefresh, sna->vblank_interval));
 }
 
commit 74d2707de4a0f94d2143f1e9c60762e4167b1ea6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun May 6 21:51:27 2012 +0100

    sna: Remove short-circuiting for large font fallbacks
    
    Unlike the fallback for an unhandled depth, we need to ensure that the
    pixmaps are mapped to the CPU before calling the fb routines.
    
    Reported-by: Toralf Förster <toralf.foerster at gmx.de>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=49558
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 1bc34dc..3e03934 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -10796,9 +10796,6 @@ sna_poly_text8(DrawablePtr drawable, GCPtr gc,
 	if (drawable->depth < 8)
 		goto fallback;
 
-	if (sna_font_too_large(gc->font))
-		goto fallback;
-
 	for (i = n = 0; i < count; i++) {
 		if (sna_get_glyph8(gc->font, priv, chars[i], &info[n]))
 			n++;
@@ -10828,8 +10825,11 @@ sna_poly_text8(DrawablePtr drawable, GCPtr gc,
 	if (!ACCEL_POLY_TEXT8)
 		goto force_fallback;
 
+	if (sna_font_too_large(gc->font))
+		goto force_fallback;
+
 	if (!PM_IS_SOLID(drawable, gc->planemask))
-		return false;
+		goto force_fallback;
 
 	if (!gc_is_solid(gc, &fg))
 		goto force_fallback;
@@ -10888,9 +10888,6 @@ sna_poly_text16(DrawablePtr drawable, GCPtr gc,
 	if (drawable->depth < 8)
 		goto fallback;
 
-	if (sna_font_too_large(gc->font))
-		goto fallback;
-
 	for (i = n = 0; i < count; i++) {
 		if (sna_get_glyph16(gc->font, priv, chars[i], &info[n]))
 			n++;
@@ -10920,8 +10917,11 @@ sna_poly_text16(DrawablePtr drawable, GCPtr gc,
 	if (!ACCEL_POLY_TEXT16)
 		goto force_fallback;
 
+	if (sna_font_too_large(gc->font))
+		goto force_fallback;
+
 	if (!PM_IS_SOLID(drawable, gc->planemask))
-		return false;
+		goto force_fallback;
 
 	if (!gc_is_solid(gc, &fg))
 		goto force_fallback;
@@ -10980,9 +10980,6 @@ sna_image_text8(DrawablePtr drawable, GCPtr gc,
 	if (drawable->depth < 8)
 		goto fallback;
 
-	if (sna_font_too_large(gc->font))
-		goto fallback;
-
 	for (i = n = 0; i < count; i++) {
 		if (sna_get_glyph8(gc->font, priv, chars[i], &info[n]))
 			n++;
@@ -11024,6 +11021,9 @@ sna_image_text8(DrawablePtr drawable, GCPtr gc,
 	if (!ACCEL_IMAGE_TEXT8)
 		goto force_fallback;
 
+	if (sna_font_too_large(gc->font))
+		goto force_fallback;
+
 	if (!PM_IS_SOLID(drawable, gc->planemask))
 		goto force_fallback;
 
@@ -11074,9 +11074,6 @@ sna_image_text16(DrawablePtr drawable, GCPtr gc,
 	if (drawable->depth < 8)
 		goto fallback;
 
-	if (sna_font_too_large(gc->font))
-		goto fallback;
-
 	for (i = n = 0; i < count; i++) {
 		if (sna_get_glyph16(gc->font, priv, chars[i], &info[n]))
 			n++;
@@ -11118,6 +11115,9 @@ sna_image_text16(DrawablePtr drawable, GCPtr gc,
 	if (!ACCEL_IMAGE_TEXT16)
 		goto force_fallback;
 
+	if (sna_font_too_large(gc->font))
+		goto force_fallback;
+
 	if (!PM_IS_SOLID(drawable, gc->planemask))
 		goto force_fallback;
 


More information about the xorg-commit mailing list