From 90fecc7485b2cb8c4ac2d0a4a79f9dc761c51067 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 30 Jan 2018 17:06:48 -0600 Subject: [PATCH] wl2_surface_dmabuf: Trim the buffer queue after a while If we have more buffers than we need for 100 frames then drop the oldest. This can happen if we're on a hardware plane and then removed from it, or really whenever the compositor feels like holding onto a few frames. Trimming the queue too soon could result in having to do a costly full frame redraw, so we wait a while to make sure we don't need one again. Having more frames than we need costs us a little every draw since we always use the oldest available. It also wastes memory. --- .../ecore_wl2_surface_module_dmabuf.c | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/lib/ecore_wl2/ecore_wl2_surface_module_dmabuf.c b/src/lib/ecore_wl2/ecore_wl2_surface_module_dmabuf.c index 2be8ded399..6cc7123c04 100644 --- a/src/lib/ecore_wl2/ecore_wl2_surface_module_dmabuf.c +++ b/src/lib/ecore_wl2/ecore_wl2_surface_module_dmabuf.c @@ -10,6 +10,7 @@ #include "linux-dmabuf-unstable-v1-client-protocol.h" #define MAX_BUFFERS 4 +#define QUEUE_TRIM_DURATION 100 int ECORE_WL2_SURFACE_DMABUF = 0; @@ -17,6 +18,7 @@ typedef struct _Ecore_Wl2_Dmabuf_Private { Ecore_Wl2_Buffer *current; Eina_List *buffers; + int unused_duration; } Ecore_Wl2_Dmabuf_Private; static void * @@ -95,10 +97,16 @@ _evas_dmabuf_surface_wait(Ecore_Wl2_Surface *s, Ecore_Wl2_Dmabuf_Private *p) Eina_List *l; int best_age = -1; int age; + int num_required = 1, num_allocated = 0; EINA_LIST_FOREACH(p->buffers, l, b) { - if (ecore_wl2_buffer_busy_get(b)) continue; + num_allocated++; + if (ecore_wl2_buffer_busy_get(b)) + { + num_required++; + continue; + } age = ecore_wl2_buffer_age_get(b); if (age > best_age) { @@ -107,6 +115,23 @@ _evas_dmabuf_surface_wait(Ecore_Wl2_Surface *s, Ecore_Wl2_Dmabuf_Private *p) } } + if (num_required < num_allocated) + p->unused_duration++; + else + p->unused_duration = 0; + + /* If we've had unused buffers for longer than QUEUE_TRIM_DURATION, then + * destroy the oldest buffer (currently in best) and recursively call + * ourself to get the next oldest. + */ + if (best && (p->unused_duration > QUEUE_TRIM_DURATION)) + { + p->unused_duration = 0; + p->buffers = eina_list_remove(p->buffers, best); + ecore_wl2_buffer_destroy(best); + best = _evas_dmabuf_surface_wait(s, p); + } + if (!best && (eina_list_count(p->buffers) < MAX_BUFFERS)) { best = ecore_wl2_surface_buffer_create(s);