diff --git a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c index 7f73047673..e777b2f798 100644 --- a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c +++ b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c @@ -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; diff --git a/src/modules/evas/engines/wayland_shm/evas_engine.c b/src/modules/evas/engines/wayland_shm/evas_engine.c index ee339c1dac..817a126db5 100644 --- a/src/modules/evas/engines/wayland_shm/evas_engine.c +++ b/src/modules/evas/engines/wayland_shm/evas_engine.c @@ -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; diff --git a/src/modules/evas/engines/wayland_shm/evas_engine.h b/src/modules/evas/engines/wayland_shm/evas_engine.h index 3cab22b1f5..467e4061c7 100644 --- a/src/modules/evas/engines/wayland_shm/evas_engine.h +++ b/src/modules/evas/engines/wayland_shm/evas_engine.h @@ -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); diff --git a/src/modules/evas/engines/wayland_shm/evas_outbuf.c b/src/modules/evas/engines/wayland_shm/evas_outbuf.c index 35f4bc997a..d1cc7bb7ce 100644 --- a/src/modules/evas/engines/wayland_shm/evas_outbuf.c +++ b/src/modules/evas/engines/wayland_shm/evas_outbuf.c @@ -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; +} diff --git a/src/modules/evas/engines/wayland_shm/evas_shm.c b/src/modules/evas/engines/wayland_shm/evas_shm.c index 492f6be509..d86d466b7c 100644 --- a/src/modules/evas/engines/wayland_shm/evas_shm.c +++ b/src/modules/evas/engines/wayland_shm/evas_shm.c @@ -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;