diff options
author | Derek Foreman <derekf@osg.samsung.com> | 2016-12-06 12:40:35 -0600 |
---|---|---|
committer | Derek Foreman <derekf@osg.samsung.com> | 2016-12-06 12:40:35 -0600 |
commit | bb5f2e32ab18af3a261b0e076adda3c1190d3593 (patch) | |
tree | 0849cc162e28053406944fb7aa48966708eb4320 | |
parent | dada6b6d1d9832638c2148e0d2c0a62ff64898b2 (diff) | |
download | efl-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.c | 77 |
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); |