wayland_shm: Fix another dmabuf corner case
authorDerek Foreman <derekf@osg.samsung.com>
Wed, 15 Jun 2016 17:27:46 +0000 (12:27 -0500)
committerDerek Foreman <derekf@osg.samsung.com>
Wed, 15 Jun 2016 17:40:36 +0000 (12:40 -0500)
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.

src/modules/evas/engines/wayland_shm/Evas_Engine_Wayland_Shm.h
src/modules/evas/engines/wayland_shm/evas_dmabuf.c
src/modules/evas/engines/wayland_shm/evas_engine.c

index d25eb04..8e3e326 100644 (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
index 2b26dd9..3050f99 100644 (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;
+
+   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
index fe2f4ab..edfc24e 100644 (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;