derekf pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=7fa02c89946a3583249b0574ae1db43acfcad147

commit 7fa02c89946a3583249b0574ae1db43acfcad147
Author: Derek Foreman <der...@osg.samsung.com>
Date:   Tue Dec 6 16:16:10 2016 -0600

    wayland_shm: Refcount the dmabuf buffer manager
    
    Because we async render into buffers before the compositor has told us
    we can use them, we can end up kicking over to fallback while still
    rendering into a buffer.
    
    Refcount the manager to let us clean up properly without crashing when
    this happens.
---
 src/modules/evas/engines/wayland_shm/evas_dmabuf.c | 75 ++++++++++++++++++----
 1 file changed, 63 insertions(+), 12 deletions(-)

diff --git a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c 
b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
index acd434d..41073e0 100644
--- a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
+++ b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
@@ -42,6 +42,8 @@ struct _Buffer_Manager
    void (*manager_destroy)(void);
    void *priv;
    void *dl_handle;
+   int refcount;
+   Eina_Bool destroyed;
 };
 
 Buffer_Manager *buffer_manager = NULL;
@@ -316,6 +318,7 @@ _buffer_manager_get(void)
    if (!success) goto err_bm;
 
    drm_fd = fd;
+   buffer_manager->refcount = 1;
    return buffer_manager;
 
 err_bm:
@@ -328,9 +331,16 @@ err_alloc:
 }
 
 static void
-_buffer_manager_destroy(void)
+_buffer_manager_ref(void)
+{
+   buffer_manager->refcount++;
+}
+
+static void
+_buffer_manager_deref(void)
 {
-   if (!buffer_manager) return;
+   buffer_manager->refcount--;
+   if (buffer_manager->refcount || !buffer_manager->destroyed) return;
 
    if (buffer_manager->manager_destroy) buffer_manager->manager_destroy();
    free(buffer_manager);
@@ -339,6 +349,50 @@ _buffer_manager_destroy(void)
 }
 
 static void
+_buffer_manager_destroy(void)
+{
+   if (buffer_manager->destroyed) return;
+   buffer_manager->destroyed = EINA_TRUE;
+   _buffer_manager_deref();
+}
+
+
+static Buffer_Handle *
+_buffer_manager_alloc(const char *name, int w, int h, unsigned long *stride, 
int32_t *fd)
+{
+   Buffer_Handle *out;
+
+   _buffer_manager_ref();
+   out = buffer_manager->alloc(buffer_manager, name, w, h, stride, fd);
+   if (!out) _buffer_manager_deref();
+   return out;
+}
+
+static void *
+_buffer_manager_map(Dmabuf_Buffer *buf)
+{
+   void *out;
+
+   _buffer_manager_ref();
+   out = buffer_manager->map(buf);
+   if (!out) _buffer_manager_deref();
+   return out;
+}
+
+static void
+_buffer_manager_unmap(Dmabuf_Buffer *buf)
+{
+   buffer_manager->unmap(buf);
+   _buffer_manager_deref();
+}
+static void
+_buffer_manager_discard(Dmabuf_Buffer *buf)
+{
+   buffer_manager->discard(buf);
+   _buffer_manager_deref();
+}
+
+static void
 buffer_release(void *data, struct wl_buffer *buffer EINA_UNUSED)
 {
    Dmabuf_Buffer *b = data;
@@ -379,7 +433,7 @@ _fallback(Dmabuf_Surface *s, int w, int h)
    if (!b) b = s->current;
    if (!b) goto out;
 
-   if (!b->mapping) b->mapping = buffer_manager->map(b);
+   if (!b->mapping) b->mapping = _buffer_manager_map(b);
 
    b->busy = EINA_FALSE;
 
@@ -394,7 +448,7 @@ _fallback(Dmabuf_Surface *s, int w, int h)
    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, EINA_FALSE);
-   buffer_manager->unmap(b);
+   _buffer_manager_unmap(b);
 
 out:
    _internal_evas_dmabuf_surface_destroy(s);
@@ -471,7 +525,7 @@ static const struct zwp_linux_buffer_params_v1_listener 
params_listener =
 static void
 _evas_dmabuf_buffer_unlock(Dmabuf_Buffer *b)
 {
-   buffer_manager->unmap(b);
+   _buffer_manager_unmap(b);
    b->mapping = NULL;
    b->locked = EINA_FALSE;
 }
@@ -488,9 +542,7 @@ _evas_dmabuf_buffer_destroy(Dmabuf_Buffer *b)
         return;
      }
    if (b->fd != -1) close(b->fd);
-   /* The buffer manager may have been destroyed already if we're
-    * doing fallback */
-   if (buffer_manager) buffer_manager->discard(b);
+   _buffer_manager_discard(b);
    if (b->wl_buffer) wl_buffer_destroy(b->wl_buffer);
    b->wl_buffer = NULL;
    free(b);
@@ -545,7 +597,7 @@ _evas_dmabuf_surface_data_get(Surface *s, int *w, int *h)
    if (h) *h = b->h;
    if (b->locked) return b->mapping;
 
-   ptr = buffer_manager->map(b);
+   ptr = _buffer_manager_map(b);
    if (!ptr)
      return NULL;
 
@@ -648,17 +700,16 @@ _evas_dmabuf_buffer_init(Dmabuf_Surface *s, int w, int h)
 {
    Dmabuf_Buffer *out;
    struct zwp_linux_buffer_params_v1 *dp;
-   Buffer_Manager *bm = _buffer_manager_get();
    uint32_t flags = 0;
 
-   if (!bm) return NULL;
+   if (!_buffer_manager_get()) return NULL;
 
    out = calloc(1, sizeof(Dmabuf_Buffer));
    if (!out) return NULL;
 
    out->fd = -1;
    out->surface = s;
-   out->bh = bm->alloc(bm, "name", w, h, &out->stride, &out->fd);
+   out->bh = _buffer_manager_alloc("name", w, h, &out->stride, &out->fd);
    if (!out->bh)
      {
         free(out);

-- 


Reply via email to