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