derekf pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=4f6e7a8ab39bbac0c780ae3c8dadfe17e804674e

commit 4f6e7a8ab39bbac0c780ae3c8dadfe17e804674e
Author: Derek Foreman <der...@osg.samsung.com>
Date:   Wed Apr 27 11:41:13 2016 -0500

    wayland_shm: Fix dmabuf fallback to shm
    
    The outbuf code should free the surface structure, not the dmabuf
    abstraction or a use after free occurs on fallback.
    
    Re-organize some code to make sure we don't rely on anything that may
    have already been freed.
    
    Add a wl_surface_commit() to keep the animation timer alive through
    the fallback process.
---
 src/modules/evas/engines/wayland_shm/evas_dmabuf.c | 39 ++++++++++------------
 src/modules/evas/engines/wayland_shm/evas_outbuf.c |  1 +
 2 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c 
b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
index 81cb806..df16114 100644
--- a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
+++ b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
@@ -60,10 +60,8 @@ struct _Dmabuf_Surface
    Dmabuf_Buffer *pre;
    Dmabuf_Buffer **buffer;
    int nbuf;
-   int pending;
 
    Eina_Bool alpha : 1;
-   Eina_Bool failed : 1;
 };
 
 static void _internal_evas_dmabuf_surface_destroy(Dmabuf_Surface *surface);
@@ -121,12 +119,6 @@ buffer_release(void *data, struct wl_buffer *buffer 
EINA_UNUSED)
 {
    Dmabuf_Buffer *b = data;
 
-   if (dmabuf_totally_hosed)
-     {
-        _internal_evas_dmabuf_surface_destroy(b->surface);
-        return;
-     }
-
    b->busy = EINA_FALSE;
    if (b->orphaned) _evas_dmabuf_buffer_destroy(b);
 }
@@ -143,9 +135,10 @@ _allocation_complete(Dmabuf_Buffer *b)
    int w, h, num_buf;
    Eina_Bool recovered;
 
-   b->surface->pending--;
    b->pending = EINA_FALSE;
-   if (!b->surface->failed) return;
+   if (!dmabuf_totally_hosed) return;
+
+   if (!b->surface) return;
 
    /* Something went wrong, better try to fall back to a different
     * buffer type...
@@ -154,7 +147,11 @@ _allocation_complete(Dmabuf_Buffer *b)
    w = b->w;
    h = b->h;
    num_buf = b->surface->nbuf;
-   dmabuf_totally_hosed = EINA_TRUE;
+
+   /* Depending when things broke we may need this commit to get
+    * the frame callback to fire and keep the animator running
+    */
+   wl_surface_commit(b->surface->wl_surface);
    _evas_dmabuf_surface_destroy(b->surface->surface);
    recovered = _evas_surface_init(s, w, h, num_buf);
    if (recovered) return;
@@ -169,7 +166,6 @@ _create_succeeded(void *data,
                  struct wl_buffer *new_buffer)
 {
    Dmabuf_Buffer *b = data;
-   Eina_Bool failed;
 
    b->wl_buffer = new_buffer;
    wl_buffer_add_listener(b->wl_buffer, &buffer_listener, b);
@@ -177,16 +173,17 @@ _create_succeeded(void *data,
 
    if (b->orphaned)
      {
-        _evas_dmabuf_buffer_destroy(b);
         _allocation_complete(b);
+        _evas_dmabuf_buffer_destroy(b);
         return;
      }
+
+   _allocation_complete(b);
+   if (dmabuf_totally_hosed) return;
+
    if (!b->busy) return;
    if (b != b->surface->pre) return;
 
-   failed = b->surface->failed;
-   _allocation_complete(b);
-   if (failed) return;
    /* This buffer was drawn into before it had a handle */
    wl_surface_attach(b->surface->wl_surface, b->wl_buffer, 0, 0);
    _evas_surface_damage(b->surface->wl_surface, b->surface->compositor_version,
@@ -203,8 +200,8 @@ _create_failed(void *data, struct 
zwp_linux_buffer_params_v1 *params)
 
    zwp_linux_buffer_params_v1_destroy(params);
 
-   b->surface->failed = EINA_TRUE;
-   if (b->orphaned) _evas_dmabuf_buffer_destroy(b);
+   dmabuf_totally_hosed = EINA_TRUE;
+   _evas_dmabuf_buffer_destroy(b);
    _allocation_complete(b);
 }
 
@@ -224,12 +221,12 @@ _evas_dmabuf_buffer_unlock(Dmabuf_Buffer *b)
 static void
 _evas_dmabuf_buffer_destroy(Dmabuf_Buffer *b)
 {
-   if (b->busy || b->pending)
+   if (b->locked || b->busy || b->pending)
      {
         b->orphaned = EINA_TRUE;
+        b->surface = NULL;
         return;
      }
-   if (b->locked) _evas_dmabuf_buffer_unlock(b);
    sym_drm_intel_bo_unreference(b->bo);
    if (b->wl_buffer) wl_buffer_destroy(b->wl_buffer);
    b->wl_buffer = NULL;
@@ -393,7 +390,6 @@ _evas_dmabuf_buffer_init(Dmabuf_Surface *s, int w, int h)
    zwp_linux_buffer_params_v1_add_listener(dp, &params_listener, out);
    zwp_linux_buffer_params_v1_create(dp, out->w, out->h,
                                      DRM_FORMAT_ARGB8888, flags);
-   s->pending++;
    return out;
 err:
    _evas_dmabuf_buffer_destroy(out);
@@ -409,7 +405,6 @@ _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_outbuf.c 
b/src/modules/evas/engines/wayland_shm/evas_outbuf.c
index f66ca2a..4501e9f 100644
--- a/src/modules/evas/engines/wayland_shm/evas_outbuf.c
+++ b/src/modules/evas/engines/wayland_shm/evas_outbuf.c
@@ -125,6 +125,7 @@ _evas_outbuf_free(Outbuf *ob)
    _evas_outbuf_idle_flush(ob);
 
    if (ob->surface) ob->surface->funcs.destroy(ob->surface);
+   free(ob->surface);
 
    eina_array_flush(&ob->priv.onebuf_regions);
 

-- 


Reply via email to