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.
This commit is contained in:
Derek Foreman 2016-06-15 12:27:46 -05:00
parent d96c52bc30
commit 47e9d11f74
3 changed files with 36 additions and 8 deletions

View File

@ -27,6 +27,7 @@ struct _Evas_Engine_Info_Wayland_Shm
/* non-blocking or blocking mode */
Evas_Engine_Render_Mode render_mode;
Evas *evas;
};
#endif

View File

@ -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;
ERR("Fallback from dmabuf to shm attempted and failed.");
abort();
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);
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

View File

@ -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;