summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Foreman <derekf@osg.samsung.com>2016-12-06 12:40:35 -0600
committerDerek Foreman <derekf@osg.samsung.com>2016-12-06 12:40:35 -0600
commitbb5f2e32ab18af3a261b0e076adda3c1190d3593 (patch)
tree0849cc162e28053406944fb7aa48966708eb4320
parentdada6b6d1d9832638c2148e0d2c0a62ff64898b2 (diff)
downloadefl-devs/derekf/dmabuf.tar.gz
wayland_shm: Refcount the dmabuf buffer managerdevs/derekf/dmabuf
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.
-rw-r--r--src/modules/evas/engines/wayland_shm/evas_dmabuf.c77
1 files changed, 64 insertions, 13 deletions
diff --git a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
index df04b5e57b..9511e09ff6 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,17 +331,68 @@ err_alloc:
}
static void
-_buffer_manager_destroy(void)
+_buffer_manager_ref(void)
{
- if (!buffer_manager) return;
+ buffer_manager->refcount++;
+}
+
+static void
+_buffer_manager_deref(void)
+{
+ buffer_manager->refcount--;
+ if (buffer_manager->refcount || !buffer_manager->destroyed) return;
- if (buffer_manager->manager_destroy) buffer_manager->manager_destroy();
free(buffer_manager);
buffer_manager = NULL;
close(drm_fd);
}
static void
+_buffer_manager_destroy(void)
+{
+ if (buffer_manager->manager_destroy) buffer_manager->manager_destroy();
+ buffer_manager->destroyed = EINA_TRUE;
+ _buffer_manager_deref();
+ close(drm_fd);
+}
+
+
+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);
if (!b->mapping) goto out;
epd = efl_data_scope_get(surf->info->evas, EVAS_CANVAS_CLASS);
@@ -391,7 +445,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);
@@ -468,7 +522,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;
}
@@ -485,9 +539,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);
@@ -542,7 +594,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;
@@ -644,17 +696,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);