wayland_shm: Don't use a fixed number of buffers
authorDerek Foreman <derekf@osg.samsung.com>
Fri, 17 Nov 2017 20:32:30 +0000 (14:32 -0600)
committerDerek Foreman <derekf@osg.samsung.com>
Fri, 17 Nov 2017 20:33:36 +0000 (14:33 -0600)
We no longer allocate 3 buffers at startup, we now allocate only as needed.

Trimming the queue will come later, as there are some situations where we
might need 3 buffers and later drop down to 2 (when on a hardware plane)

Most clients will only ever need 2 buffers, so this is a reasonable RAM
savings.

src/lib/ecore_wl2/Ecore_Wl2.h
src/modules/evas/engines/wayland_shm/evas_dmabuf.c
src/modules/evas/engines/wayland_shm/evas_engine.h
src/modules/evas/engines/wayland_shm/evas_outbuf.c

index 1f58cd4..88fbeda 100644 (file)
@@ -376,7 +376,6 @@ struct _Ecore_Wl2_Buffer
    int index;
    Eina_Bool locked : 1;
    Eina_Bool busy : 1;
-   Eina_Bool used : 1;
    Eina_Bool orphaned : 1;
    Eina_Bool alpha : 1;
 };
index b137c27..350ec59 100644 (file)
@@ -13,8 +13,7 @@ struct _Dmabuf_Surface
    Surface *surface;
 
    Ecore_Wl2_Buffer *current;
-   Ecore_Wl2_Buffer **buffer;
-   int nbuf;
+   Eina_List *buffers;
 
    Eina_Bool alpha : 1;
 };
@@ -25,31 +24,24 @@ static void _evas_dmabuf_surface_destroy(Surface *s);
 static void
 _evas_dmabuf_surface_reconfigure(Surface *s, int w, int h, uint32_t flags EINA_UNUSED, Eina_Bool force)
 {
-   Ecore_Wl2_Buffer *buf;
+   Ecore_Wl2_Buffer *b;
+   Eina_List *l, *tmp;
    Dmabuf_Surface *surface;
-   int i;
 
    if ((!w) || (!h)) return;
    surface = s->surf.dmabuf;
-   for (i = 0; i < surface->nbuf; i++)
+   EINA_LIST_FOREACH_SAFE(surface->buffers, l, tmp, b)
      {
-        if (surface->buffer[i])
-          {
-             Ecore_Wl2_Buffer *b = surface->buffer[i];
-             int stride = b->stride;
+        int stride = b->stride;
 
-             /* If stride is a little bigger than width we still fit */
-             if (!force && (w >= b->w) && (w <= stride / 4) && (h == b->h))
-               {
-                  b->w = w;
-                  continue;
-               }
-
-             ecore_wl2_buffer_destroy(b);
+        /* If stride is a little bigger than width we still fit */
+        if (!force && (w >= b->w) && (w <= stride / 4) && (h == b->h))
+          {
+             b->w = w;
+             continue;
           }
-        buf = ecore_wl2_buffer_create(s->ob->ewd, w, h, surface->alpha);
-        if (!buf)  return;
-        surface->buffer[i] = buf;
+        ecore_wl2_buffer_destroy(b);
+        surface->buffers = eina_list_remove_list(surface->buffers, l);
      }
 }
 
@@ -83,39 +75,48 @@ _evas_dmabuf_surface_data_get(Surface *s, int *w, int *h)
 static Ecore_Wl2_Buffer *
 _evas_dmabuf_surface_wait(Dmabuf_Surface *s)
 {
-   int i = 0, best = -1, best_age = -1;
+   Ecore_Wl2_Buffer *b, *best = NULL;
+   Eina_List *l;
+   int best_age = -1;
 
-   for (i = 0; i < s->nbuf; i++)
+   EINA_LIST_FOREACH(s->buffers, l, b)
      {
-        if (s->buffer[i]->locked || s->buffer[i]->busy) continue;
-        if (s->buffer[i]->age > best_age)
+        if (b->locked || b->busy) continue;
+        if (b->age > best_age)
           {
-             best = i;
-             best_age = s->buffer[i]->age;
+             best = b;
+             best_age = b->age;
           }
      }
 
-   if (best >= 0) return s->buffer[best];
-   return NULL;
+   if (!best && (eina_list_count(s->buffers) < MAX_BUFFERS))
+     {
+        Outbuf *ob;
+        ob = s->surface->ob;
+        best = ecore_wl2_buffer_create(ob->ewd, ob->w, ob->h, s->alpha);
+        s->buffers = eina_list_append(s->buffers, best);
+     }
+   return best;
 }
 
 static int
 _evas_dmabuf_surface_assign(Surface *s)
 {
+   Ecore_Wl2_Buffer *b;
+   Eina_List *l;
    Dmabuf_Surface *surface;
-   int i;
 
    surface = s->surf.dmabuf;
    surface->current = _evas_dmabuf_surface_wait(surface);
    if (!surface->current)
      {
         WRN("No free DMAbuf buffers, dropping a frame");
-        for (i = 0; i < surface->nbuf; i++)
-          surface->buffer[i]->age = 0;
+        EINA_LIST_FOREACH(surface->buffers, l, b)
+          b->age = 0;
         return 0;
      }
-   for (i = 0; i < surface->nbuf; i++)
-     if (surface->buffer[i]->used) surface->buffer[i]->age++;
+   EINA_LIST_FOREACH(surface->buffers, l, b)
+     if (b->age) b->age++;
 
    return surface->current->age;
 }
@@ -135,7 +136,6 @@ _evas_dmabuf_surface_post(Surface *s, Eina_Rectangle *rects, unsigned int count)
 
    surface->current = NULL;
    b->busy = EINA_TRUE;
-   b->used = EINA_TRUE;
    b->age = 0;
 
    win = s->info->info.wl2_win;
@@ -149,14 +149,11 @@ _evas_dmabuf_surface_post(Surface *s, Eina_Rectangle *rects, unsigned int count)
 static void
 _internal_evas_dmabuf_surface_destroy(Dmabuf_Surface *surface)
 {
-   int i;
+   Ecore_Wl2_Buffer *b;
 
-   for (i = 0; i < surface->nbuf; i++)
-      ecore_wl2_buffer_destroy(surface->buffer[i]);
+   EINA_LIST_FREE(surface->buffers, b)
+     ecore_wl2_buffer_destroy(b);
 
-   free(surface->buffer);
-   surface->buffer = NULL;
-   surface->nbuf = 0;
    free(surface);
 }
 
@@ -169,12 +166,11 @@ _evas_dmabuf_surface_destroy(Surface *s)
 }
 
 Eina_Bool
-_evas_dmabuf_surface_create(Surface *s, int w, int h, int num_buff)
+_evas_dmabuf_surface_create(Surface *s)
 {
    Ecore_Wl2_Display *ewd;
    Ecore_Wl2_Buffer_Type types = 0;
    Dmabuf_Surface *surf = NULL;
-   int i = 0;
 
    ewd = s->info->info.wl2_display;
    if (ecore_wl2_display_shm_get(ewd))
@@ -189,27 +185,8 @@ _evas_dmabuf_surface_create(Surface *s, int w, int h, int num_buff)
    surf->alpha = s->info->info.destination_alpha;
 
    /* create surface buffers */
-   surf->nbuf = num_buff;
-   surf->buffer = calloc(surf->nbuf, sizeof(Ecore_Wl2_Buffer *));
-   if (!surf->buffer) goto err;
-
    if (!ecore_wl2_buffer_init(ewd, types)) goto err;
 
-   if (w && h)
-     {
-        for (i = 0; i < num_buff; i++)
-          {
-             surf->buffer[i] = ecore_wl2_buffer_create(s->ob->ewd,
-                                                       w, h, surf->alpha);
-             if (!surf->buffer[i])
-               {
-                  DBG("Could not create buffers");
-                  /* _init() handled surface cleanup when it failed */
-                  return EINA_FALSE;
-               }
-          }
-     }
-
    s->funcs.destroy = _evas_dmabuf_surface_destroy;
    s->funcs.reconfigure = _evas_dmabuf_surface_reconfigure;
    s->funcs.data_get = _evas_dmabuf_surface_data_get;
@@ -219,7 +196,6 @@ _evas_dmabuf_surface_create(Surface *s, int w, int h, int num_buff)
    return EINA_TRUE;
 
 err:
-   free(surf->buffer);
    free(surf);
    return EINA_FALSE;
 }
index 726f424..79a76ce 100644 (file)
@@ -100,7 +100,6 @@ struct _Outbuf
    int w, h;
    int rotation;
    int onebuf;
-   int num_buff;
    Outbuf_Depth depth;
 
    Ecore_Wl2_Display *ewd;
@@ -130,8 +129,7 @@ struct _Outbuf
    Eina_Bool dirty : 1;
 };
 
-Eina_Bool _evas_dmabuf_surface_create(Surface *s, int w, int h, int num_buff);
-Eina_Bool _evas_shm_surface_create(Surface *s, int w, int h, int num_buff);
+Eina_Bool _evas_dmabuf_surface_create(Surface *s);
 
 Outbuf *_evas_outbuf_setup(int w, int h, Evas_Engine_Info_Wayland *info);
 void _evas_outbuf_free(Outbuf *ob);
index 6732fb2..fdcaf21 100644 (file)
@@ -10,7 +10,7 @@
 #define BLUE_MASK 0x0000ff
 
 static Surface *
-_evas_surface_create(Evas_Engine_Info_Wayland *info, int w, int h, Outbuf *ob)
+_evas_surface_create(Evas_Engine_Info_Wayland *info, Outbuf *ob)
 {
    Surface *out;
 
@@ -19,7 +19,7 @@ _evas_surface_create(Evas_Engine_Info_Wayland *info, int w, int h, Outbuf *ob)
    out->info = info;
    out->ob = ob;
 
-   if (_evas_dmabuf_surface_create(out, w, h, ob->num_buff)) return out;
+   if (_evas_dmabuf_surface_create(out)) return out;
 
    free(out);
    return NULL;
@@ -29,8 +29,6 @@ Outbuf *
 _evas_outbuf_setup(int w, int h, Evas_Engine_Info_Wayland *info)
 {
    Outbuf *ob = NULL;
-   char *num;
-   int sw, sh;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
@@ -46,39 +44,9 @@ _evas_outbuf_setup(int w, int h, Evas_Engine_Info_Wayland *info)
    ob->priv.destination_alpha = info->info.destination_alpha;
    ob->ewd = info->info.wl2_display;
 
-   /* default to triple buffer */
-   ob->num_buff = 3;
-
-   /* check for any 'number of buffers' override in the environment */
-   if ((num = getenv("EVAS_WAYLAND_SHM_BUFFERS")))
-     {
-        int n = 0;
-
-        n = atoi(num);
-        if (n <= 0) n = 1;
-        if (n > MAX_BUFFERS) n = MAX_BUFFERS;
-
-        ob->num_buff = n;
-     }
-
-   /* try to create the outbuf surface */
-   if ((ob->rotation == 0) || (ob->rotation == 180))
-     {
-        sw = w;
-        sh = h;
-     }
-   else if ((ob->rotation == 90) || (ob->rotation == 270))
-     {
-        sw = h;
-        sh = w;
-     }
-   else
-     goto unhandled_rotation;
-
-   ob->surface = _evas_surface_create(info, sw, sh, ob);
+   ob->surface = _evas_surface_create(info, ob);
    if (!ob->surface) goto surf_err;
 
-unhandled_rotation:
    eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8);
 
    return ob;
@@ -295,7 +263,6 @@ _evas_outbuf_swap_mode_get(Outbuf *ob)
    age = ob->surface->funcs.assign(ob->surface);
    if (!age) return MODE_FULL;
 
-   if (age > ob->num_buff) return MODE_FULL;
    else if (age == 1) return MODE_COPY;
    else if (age == 2) return MODE_DOUBLE;
    else if (age == 3) return MODE_TRIPLE;