From 47e9d11f746fc7117a35c2f656ce8e624f7d2514 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Wed, 15 Jun 2016 12:27:46 -0500 Subject: [PATCH] wayland_shm: Fix another dmabuf corner case When kernel support for locally mmapping buffers is unavailable and software rendering is used, dmabuf may need to fallback to shm for the very first frame rendered. We need to copy that frame to a shm buffer during the fallback to make sure it's actually displayed. --- .../engines/wayland_shm/Evas_Engine_Wayland_Shm.h | 1 + src/modules/evas/engines/wayland_shm/evas_dmabuf.c | 42 +++++++++++++++++----- src/modules/evas/engines/wayland_shm/evas_engine.c | 1 + 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/modules/evas/engines/wayland_shm/Evas_Engine_Wayland_Shm.h b/src/modules/evas/engines/wayland_shm/Evas_Engine_Wayland_Shm.h index d25eb04..8e3e326 100644 --- a/src/modules/evas/engines/wayland_shm/Evas_Engine_Wayland_Shm.h +++ b/src/modules/evas/engines/wayland_shm/Evas_Engine_Wayland_Shm.h @@ -27,6 +27,7 @@ struct _Evas_Engine_Info_Wayland_Shm /* non-blocking or blocking mode */ Evas_Engine_Render_Mode render_mode; + Evas *evas; }; #endif diff --git a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c index 2b26dd9..3050f99 100644 --- a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c +++ b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c @@ -324,21 +324,46 @@ static const struct wl_buffer_listener buffer_listener = static void _fallback(Dmabuf_Surface *s, int w, int h) { + Evas_Public_Data *epd; + Dmabuf_Buffer *b; + Surface *surf = s->surface; Eina_Bool recovered; + unsigned char *new_data, *old_data; + int y; dmabuf_totally_hosed = EINA_TRUE; + recovered = _evas_surface_init(surf, w, h, s->nbuf); + if (!recovered) + { + ERR("Fallback from dmabuf to shm attempted and failed."); + abort(); + } - /* Depending when things broke we may need this commit to get - * the frame callback to fire and keep the animator running + /* Since a buffer may have been filled before we realized we can't + * display it, we need to make sure any async render on it is finished, + * then copy the contents into one of the newly allocated shm buffers */ - wl_surface_commit(s->wl_surface); - _evas_dmabuf_surface_destroy(s->surface); - recovered = _evas_surface_init(s->surface, w, h, s->nbuf); - if (recovered) return; + b = s->pre; + if (!b) b = s->current; + if (!b) goto out; + + if (!b->mapping) b->mapping = b->bm->map(b); + if (!b->mapping) goto out; + + epd = eo_data_scope_get(surf->info->evas, EVAS_CANVAS_CLASS); + while (epd && epd->rendering) evas_async_events_process_blocking(); + + old_data = b->mapping; + surf->funcs.assign(surf); + new_data = surf->funcs.data_get(surf, NULL, NULL); + for (y = 0; y < h; y++) + memcpy(new_data + y * w * 4, old_data + y * b->stride, w * 4); + surf->funcs.post(surf, NULL, 0); + b->bm->unmap(b); - ERR("Fallback from dmabuf to shm attempted and failed."); - abort(); +out: + _internal_evas_dmabuf_surface_destroy(s); } static void @@ -616,6 +641,7 @@ _internal_evas_dmabuf_surface_destroy(Dmabuf_Surface *surface) _evas_dmabuf_buffer_destroy(surface->buffer[i]); free(surface->buffer); + free(surface); } static void diff --git a/src/modules/evas/engines/wayland_shm/evas_engine.c b/src/modules/evas/engines/wayland_shm/evas_engine.c index fe2f4ab..edfc24e 100644 --- a/src/modules/evas/engines/wayland_shm/evas_engine.c +++ b/src/modules/evas/engines/wayland_shm/evas_engine.c @@ -112,6 +112,7 @@ eng_info(Evas *eo_evas EINA_UNUSED) /* fill in engine info */ einfo->magic.magic = rand(); einfo->render_mode = EVAS_RENDER_MODE_BLOCKING; + einfo->evas = eo_evas; /* return allocated engine info */ return einfo; -- 2.7.4