From 5f39331f78ecfdd9c02df5f0a6c0da970a9abe42 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 15 Nov 2019 21:43:44 +0100 Subject: [PATCH] Keep track of the update frequency of each layer Keep track of the number of layer updates per 60 page-flips. We could implement a more fine-grained tracking, for instance with a sliding window. However it's a lot more complex than the current solution and the gains are not clear. I'd prefer to keep the current solution and experiment with other solutions once we have a good test-bed. References: https://github.com/emersion/libliftoff/issues/22 --- alloc.c | 21 +++++++++++++++++++++ include/private.h | 9 +++++++++ layer.c | 18 ++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/alloc.c b/alloc.c index 34c4541..464e878 100644 --- a/alloc.c +++ b/alloc.c @@ -550,6 +550,25 @@ static void mark_layers_clean(struct liftoff_display *display) } } +static void update_layers_priority(struct liftoff_display *display) +{ + struct liftoff_output *output; + struct liftoff_layer *layer; + + display->page_flip_counter++; + bool period_elapsed = + display->page_flip_counter >= LIFTOFF_PRIORITY_PERIOD; + if (period_elapsed) { + display->page_flip_counter = 0; + } + + liftoff_list_for_each(output, &display->outputs, link) { + liftoff_list_for_each(layer, &output->layers, link) { + layer_update_priority(layer, period_elapsed); + } + } +} + bool liftoff_display_apply(struct liftoff_display *display, drmModeAtomicReq *req) { struct liftoff_output *output; @@ -560,6 +579,8 @@ bool liftoff_display_apply(struct liftoff_display *display, drmModeAtomicReq *re size_t i; bool compatible; + update_layers_priority(display); + if (reuse_previous_alloc(display, req)) { liftoff_log(LIFTOFF_DEBUG, "Re-using previous plane allocation"); return true; diff --git a/include/private.h b/include/private.h index 481e0ae..3df3b01 100644 --- a/include/private.h +++ b/include/private.h @@ -5,6 +5,10 @@ #include "list.h" #include "log.h" +/* Layer priority is assigned depending on the number of updates during a + * given number of page-flips */ +#define LIFTOFF_PRIORITY_PERIOD 60 + struct liftoff_display { int drm_fd; @@ -13,6 +17,8 @@ struct liftoff_display { uint32_t *crtcs; size_t crtcs_len; + + int page_flip_counter; }; struct liftoff_output { @@ -34,6 +40,8 @@ struct liftoff_layer { size_t props_len; struct liftoff_plane *plane; + + int current_priority, pending_priority; }; struct liftoff_layer_property { @@ -71,6 +79,7 @@ struct liftoff_layer_property *layer_get_property(struct liftoff_layer *layer, void layer_get_rect(struct liftoff_layer *layer, struct liftoff_rect *rect); bool layer_intersects(struct liftoff_layer *a, struct liftoff_layer *b); void layer_mark_clean(struct liftoff_layer *layer); +void layer_update_priority(struct liftoff_layer *layer, bool make_current); struct liftoff_plane *plane_create(struct liftoff_display *display, uint32_t id); void plane_destroy(struct liftoff_plane *plane); diff --git a/layer.c b/layer.c index 8460afa..c5f24e1 100644 --- a/layer.c +++ b/layer.c @@ -117,3 +117,21 @@ void layer_mark_clean(struct liftoff_layer *layer) layer->props[i].changed = false; } } + +void layer_update_priority(struct liftoff_layer *layer, bool make_current) { + struct liftoff_layer_property *prop; + + /* TODO: also bump priority when updating other + * properties */ + prop = layer_get_property(layer, "FB_ID"); + if (prop->changed) { + layer->pending_priority++; + } + + if (make_current) { + layer->current_priority = layer->pending_priority; + layer->pending_priority = 0; + liftoff_log(LIFTOFF_DEBUG, "Layer %p has priority %d", + (void *)layer, layer->current_priority); + } +}