Merge branch 'devs/devilhorns/wip'

This push merges some changes to the evas wayland shm engine. These
changes help to reduce dropped frames, fix max buffer age, provide
a better next buffer selection algorithm, and move buffer flipping out
of the render thread. In total, these provide better wayland_shm
engine performance. These patches are based on previous drm engine work
by Derek Foreman.
This commit is contained in:
Chris Michael 2016-10-26 12:21:53 -04:00
commit c759ec6362
5 changed files with 47 additions and 29 deletions

View File

@ -649,11 +649,11 @@ _evas_dmabuf_buffer_init(Dmabuf_Surface *s, int w, int h)
out->surface = s;
out->bh = bm->alloc(bm, "name", w, h, &out->stride, &out->fd);
if (!out->bh)
{
free(out);
_fallback(s, w, h);
return NULL;
}
{
free(out);
_fallback(s, w, h);
return NULL;
}
out->w = w;
out->h = h;

View File

@ -55,7 +55,7 @@ _render_engine_swapbuf_setup(int w, int h, Evas_Engine_Info_Wayland_Shm *einfo)
_evas_outbuf_update_region_free,
_evas_outbuf_idle_flush,
_evas_outbuf_flush,
NULL,
_evas_outbuf_redraws_clear,
_evas_outbuf_free,
w, h))
goto err;

View File

@ -125,6 +125,9 @@ struct _Outbuf
/* list of previous frame pending regions to write out */
Eina_List *prev_pending_writes;
Eina_Rectangle *rects;
unsigned int rect_count;
/* Eina_Bool redraw : 1; */
Eina_Bool destination_alpha : 1;
} priv;
@ -145,6 +148,7 @@ void *_evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int
void _evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
void _evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
void _evas_surface_damage(struct wl_surface *s, int compositor_version, int w, int h, Eina_Rectangle *rects, unsigned int count);
void _evas_outbuf_redraws_clear(Outbuf *ob);
Eina_Bool _evas_surface_init(Surface *s, int w, int h, int num_buf);

View File

@ -56,8 +56,8 @@ _evas_outbuf_setup(int w, int h, Evas_Engine_Info_Wayland_Shm *info)
ob->depth = info->info.depth;
ob->priv.destination_alpha = info->info.destination_alpha;
/* default to double buffer */
ob->num_buff = 2;
/* 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")))
@ -199,12 +199,14 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf
{
Eina_Rectangle *result;
RGBA_Image *img;
unsigned int n = 0, i = 0;
unsigned int i = 0;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
if (ob->priv.rect_count) free(ob->priv.rects);
/* check for pending writes */
if (!ob->priv.pending_writes)
{
@ -212,11 +214,13 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf
Eina_Array_Iterator it;
/* get number of buffer regions */
n = eina_array_count_get(&ob->priv.onebuf_regions);
if (n == 0) return;
ob->priv.rect_count = eina_array_count_get(&ob->priv.onebuf_regions);
if (ob->priv.rect_count == 0) return;
/* allocate rectangles */
if (!(result = alloca(n * sizeof(Eina_Rectangle)))) return;
ob->priv.rects = malloc(ob->priv.rect_count * sizeof(Eina_Rectangle));
if (!ob->priv.rects) return;
result = ob->priv.rects;
/* loop the buffer regions and assign to result */
EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
@ -225,8 +229,6 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf
eina_rectangle_free(rect);
}
ob->surface->funcs.post(ob->surface, result, n);
/* clean array */
eina_array_clean(&ob->priv.onebuf_regions);
@ -245,11 +247,12 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf
else
{
/* get number of pending writes */
n = eina_list_count(ob->priv.pending_writes);
if (n == 0) return;
ob->priv.rect_count = eina_list_count(ob->priv.pending_writes);
if (ob->priv.rect_count == 0) return;
/* allocate rectangles */
if (!(result = alloca(n * sizeof(Eina_Rectangle)))) return;
ob->priv.rects = malloc(ob->priv.rect_count * sizeof(Eina_Rectangle));
if (!ob->priv.rects) return;
result = ob->priv.rects;
/* loop the pending writes */
EINA_LIST_FREE(ob->priv.pending_writes, img)
@ -306,8 +309,6 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf
i++;
}
ob->surface->funcs.post(ob->surface, result, n);
}
}
@ -319,7 +320,10 @@ _evas_outbuf_swap_mode_get(Outbuf *ob)
LOGFN(__FILE__, __LINE__, __FUNCTION__);
age = ob->surface->funcs.assign(ob->surface);
if (age == 1) return MODE_COPY;
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;
else if (age == 4) return MODE_QUADRUPLE;
@ -616,3 +620,12 @@ _evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
}
void
_evas_outbuf_redraws_clear(Outbuf *ob)
{
if (!ob->priv.rect_count) return;
ob->surface->funcs.post(ob->surface, ob->priv.rects, ob->priv.rect_count);
free(ob->priv.rects);
ob->priv.rect_count = 0;
}

View File

@ -461,18 +461,19 @@ _evas_shm_surface_reconfigure(Surface *s, int w, int h, uint32_t flags)
static Shm_Leaf *
_evas_shm_surface_wait(Shm_Surface *surface)
{
int iterations = 0, i;
int i = 0, best = -1, best_age = -1;
while (iterations++ < 10)
for (i = 0; i < surface->num_buff; i++)
{
for (i = 0; i < surface->num_buff; i++)
if (surface->leaf[i].busy) continue;
if ((surface->leaf[i].valid) && (surface->leaf[i].age > best_age))
{
if (surface->leaf[i].busy) continue;
if (surface->leaf[i].valid) return &surface->leaf[i];
best = i;
best_age = surface->leaf[i].age;
}
wl_display_dispatch_pending(surface->disp);
}
if (best >= 0) return &surface->leaf[best];
return NULL;
}
@ -506,7 +507,7 @@ _evas_shm_surface_assign(Surface *s)
if (surface->leaf[i].valid && surface->leaf[i].drawn)
{
surface->leaf[i].age++;
if (surface->leaf[i].age > surface->num_buff)
if (surface->leaf[i].age > 4)
{
surface->leaf[i].age = 0;
surface->leaf[i].drawn = EINA_FALSE;