summaryrefslogtreecommitdiff
path: root/src/sna/sna_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sna/sna_accel.c')
-rw-r--r--src/sna/sna_accel.c93
1 files changed, 88 insertions, 5 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e1905d1d..cffac538 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -171,6 +171,8 @@ static void sna_pixmap_destroy_gpu_bo(struct sna *sna, struct sna_pixmap *priv)
priv->gpu_bo = NULL;
}
+ list_del(&priv->inactive);
+
/* and reset the upload counter */
priv->source_count = SOURCE_BIAS;
}
@@ -180,6 +182,7 @@ static Bool sna_destroy_private(PixmapPtr pixmap, struct sna_pixmap *priv)
struct sna *sna = to_sna_from_pixmap(pixmap);
list_del(&priv->list);
+ list_del(&priv->inactive);
sna_damage_destroy(&priv->gpu_damage);
sna_damage_destroy(&priv->cpu_damage);
@@ -301,6 +304,7 @@ static struct sna_pixmap *_sna_pixmap_attach(PixmapPtr pixmap)
return NULL;
list_init(&priv->list);
+ list_init(&priv->inactive);
priv->pixmap = pixmap;
sna_set_pixmap(pixmap, priv);
@@ -386,6 +390,7 @@ sna_pixmap_create_scratch(ScreenPtr screen,
priv = sna_pixmap(pixmap);
memset(priv, 0, sizeof(*priv));
list_init(&priv->list);
+ list_init(&priv->inactive);
priv->pixmap = pixmap;
} else {
pixmap = create_pixmap(sna, screen, 0, 0, depth,
@@ -818,6 +823,8 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box)
done:
if (priv->cpu_damage == NULL)
list_del(&priv->list);
+ if (!priv->gpu_only && !priv->pinned)
+ list_move(&priv->inactive, &sna->active_pixmaps);
}
static inline Bool
@@ -993,6 +1000,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
priv->pinned = 0;
priv->mapped = 0;
list_init(&priv->list);
+ list_init(&priv->inactive);
priv->pixmap = pixmap;
sna_set_pixmap(pixmap, priv);
@@ -1128,6 +1136,8 @@ done:
sna_damage_reduce_all(&priv->gpu_damage,
pixmap->drawable.width, pixmap->drawable.height);
list_del(&priv->list);
+ if (!priv->gpu_only && !priv->pinned)
+ list_move(&priv->inactive, &sna->active_pixmaps);
priv->gpu = true;
return priv;
}
@@ -8477,6 +8487,28 @@ static Bool sna_accel_do_expire(struct sna *sna)
return FALSE;
}
+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 60s. */
+ to.it_interval.tv_sec = 60;
+ to.it_interval.tv_nsec = 0;
+ to.it_value = to.it_interval;
+ timerfd_settime(sna->timer[INACTIVE_TIMER], 0, &to, NULL);
+
+ sna->timer_active |= 1 << INACTIVE_TIMER;
+ return FALSE;
+}
+
static void sna_accel_create_timers(struct sna *sna)
{
int id;
@@ -8494,6 +8526,7 @@ static void sna_accel_create_timers(struct sna *sna)
}
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
@@ -8526,13 +8559,57 @@ static void sna_accel_expire(struct sna *sna)
_sna_accel_disarm_timer(sna, EXPIRE_TIMER);
}
+static void sna_accel_inactive(struct sna *sna)
+{
+ DBG(("%s (time=%ld)\n", __FUNCTION__, (long)GetTimeInMillis()));
+
+ /* clear out the oldest inactive pixmaps */
+ while (!list_is_empty(&sna->inactive_clock[1])) {
+ struct sna_pixmap *priv;
+
+ priv = list_first_entry(&sna->inactive_clock[1],
+ struct sna_pixmap,
+ inactive);
+ if (priv->pinned) {
+ list_del(&priv->inactive);
+ } else {
+ DBG(("%s: discarding GPU bo handle=%d\n",
+ __FUNCTION__, priv->gpu_bo->handle));
+ sna_pixmap_move_to_cpu(priv->pixmap, true);
+ }
+
+ /* XXX Rather than discarding the GPU buffer here, we
+ * could mark it purgeable and allow the shrinker to
+ * reap its storage only under memory pressure.
+ */
+ }
+
+ /* Age the current inactive pixmaps */
+ sna->inactive_clock[1].next = sna->inactive_clock[0].next;
+ sna->inactive_clock[0].next->prev = &sna->inactive_clock[1];
+ sna->inactive_clock[0].prev->next = &sna->inactive_clock[1];
+ sna->inactive_clock[1].prev = sna->inactive_clock[0].prev;
+
+ sna->inactive_clock[0].next = sna->active_pixmaps.next;
+ sna->active_pixmaps.next->prev = &sna->inactive_clock[0];
+ sna->active_pixmaps.prev->next = &sna->inactive_clock[0];
+ sna->inactive_clock[0].prev = sna->active_pixmaps.prev;
+
+ list_init(&sna->active_pixmaps);
+
+ if (list_is_empty(&sna->inactive_clock[1]) &&
+ list_is_empty(&sna->inactive_clock[0]))
+ _sna_accel_disarm_timer(sna, INACTIVE_TIMER);
+}
+
static void sna_accel_install_timers(struct sna *sna)
{
- if (sna->timer[FLUSH_TIMER] != -1)
- AddGeneralSocket(sna->timer[FLUSH_TIMER]);
+ int n;
- if (sna->timer[EXPIRE_TIMER] != -1)
- AddGeneralSocket(sna->timer[EXPIRE_TIMER]);
+ for (n = 0; n < NUM_TIMERS; n++) {
+ if (sna->timer[n] != -1)
+ AddGeneralSocket(sna->timer[n]);
+ }
}
Bool sna_accel_pre_init(struct sna *sna)
@@ -8552,8 +8629,11 @@ Bool sna_accel_init(ScreenPtr screen, struct sna *sna)
screen->RealizeFont = sna_realize_font;
screen->UnrealizeFont = sna_unrealize_font;
- list_init(&sna->dirty_pixmaps);
list_init(&sna->deferred_free);
+ list_init(&sna->dirty_pixmaps);
+ list_init(&sna->active_pixmaps);
+ list_init(&sna->inactive_clock[0]);
+ list_init(&sna->inactive_clock[1]);
AddGeneralSocket(sna->kgem.fd);
sna_accel_install_timers(sna);
@@ -8673,6 +8753,9 @@ void sna_accel_block_handler(struct sna *sna)
if (sna_accel_do_expire(sna))
sna_accel_expire(sna);
+
+ if (sna_accel_do_inactive(sna))
+ sna_accel_inactive(sna);
}
void sna_accel_wakeup_handler(struct sna *sna)