forked from enlightenment/efl
wayland_shm: Don't use a fixed number of buffers
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.
This commit is contained in:
parent
04ce069cba
commit
796de8cb86
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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])
|
||||
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))
|
||||
{
|
||||
Ecore_Wl2_Buffer *b = surface->buffer[i];
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue