raster pushed a commit to branch master. http://git.enlightenment.org/core/enlightenment.git/commit/?id=d96c75b8d59a72b19d99930144dc833b7634c778
commit d96c75b8d59a72b19d99930144dc833b7634c778 Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com> Date: Fri Apr 16 03:18:41 2021 +0000 e - wl - fix buffer referencing to not have junk on surface del we were losing refs to buffers when clients quit and surface were deleted thus causing junk and errors in binding these now deleted buffers as fds now were invalid. keep them around longer until hide anim is done. this is callback-hell... @fix --- src/bin/e_comp_wl.c | 6 +++--- src/bin/e_comp_wl_dmabuf.c | 20 ++++++++++++++++-- src/bin/e_comp_wl_dmabuf.h | 4 ++++ src/bin/e_pixmap.c | 52 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index a606c150b..c21dcc971 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -2651,14 +2651,14 @@ _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec) if (ec->comp_data->surface) wl_resource_set_user_data(ec->comp_data->surface, NULL); + if (ec->internal_elm_win) + evas_object_hide(ec->frame); + /* WL clients take an extra ref at startup so they don't get deleted while * visible. Since we drop that in the render loop we need to make sure * it's dropped here if the client isn't going to be rendered. */ if (!evas_object_visible_get(ec->frame)) e_object_unref(E_OBJECT(ec)); - - if (ec->internal_elm_win) - evas_object_hide(ec->frame); } static void diff --git a/src/bin/e_comp_wl_dmabuf.c b/src/bin/e_comp_wl_dmabuf.c index 799a81033..95bb10ed7 100644 --- a/src/bin/e_comp_wl_dmabuf.c +++ b/src/bin/e_comp_wl_dmabuf.c @@ -44,11 +44,20 @@ # define DRM_FORMAT_MOD_LINEAR 0 #endif -static void -linux_dmabuf_buffer_destroy(struct linux_dmabuf_buffer *buffer) +void +linux_dmabuf_buffer_ref(struct linux_dmabuf_buffer *buffer) +{ + buffer->refs++; +} + +void +linux_dmabuf_buffer_unref(struct linux_dmabuf_buffer *buffer) { int i; + buffer->refs--; + if (buffer->refs > 0) return; + for (i = 0; i < buffer->attributes.n_planes; i++) { close(buffer->attributes.fd[i]); @@ -59,6 +68,12 @@ linux_dmabuf_buffer_destroy(struct linux_dmabuf_buffer *buffer) free(buffer); } +static void +linux_dmabuf_buffer_destroy(struct linux_dmabuf_buffer *buffer) +{ + linux_dmabuf_buffer_unref(buffer); +} + static void destroy_params(struct wl_resource *params_resource) { @@ -369,6 +384,7 @@ linux_dmabuf_create_params(struct wl_client *client, buffer = calloc(1, sizeof *buffer); if (!buffer) goto err_out; + buffer->refs = 1; for (i = 0; i < MAX_DMABUF_PLANES; i++) buffer->attributes.fd[i] = -1; diff --git a/src/bin/e_comp_wl_dmabuf.h b/src/bin/e_comp_wl_dmabuf.h index 945490f38..2114d15cb 100644 --- a/src/bin/e_comp_wl_dmabuf.h +++ b/src/bin/e_comp_wl_dmabuf.h @@ -58,6 +58,7 @@ struct linux_dmabuf_buffer { void *user_data; dmabuf_user_data_destroy_func user_data_destroy_func; + int refs; // a refcount to keep this alive for just a bit longer... /* XXX: * @@ -75,6 +76,9 @@ struct linux_dmabuf_buffer { */ }; +void linux_dmabuf_buffer_ref(struct linux_dmabuf_buffer *buffer); +void linux_dmabuf_buffer_unref(struct linux_dmabuf_buffer *buffer); + int linux_dmabuf_setup(struct wl_display *display); diff --git a/src/bin/e_pixmap.c b/src/bin/e_pixmap.c index 3d1e4e6d5..7a6d1cbe0 100644 --- a/src/bin/e_pixmap.c +++ b/src/bin/e_pixmap.c @@ -53,6 +53,7 @@ struct _E_Pixmap void *data; Eina_Rectangle opaque; Eina_List *free_buffers; + Eina_List *busy_list; #endif Eina_Bool usable E_BITFIELD; @@ -136,6 +137,8 @@ static void _e_pixmap_wl_resource_release(E_Comp_Wl_Buffer *buffer) { buffer->busy--; + if (buffer->dmabuf_buffer) + linux_dmabuf_buffer_unref(buffer->dmabuf_buffer); if (buffer->busy) return; if (buffer->pool) @@ -171,6 +174,11 @@ _e_pixmap_wayland_buffer_release(E_Pixmap *cp, E_Comp_Wl_Buffer *buffer) return; } + if (buffer->busy == 1) + { + // we are at busy 1 abut about to go to 0 below, so remove now + cp->busy_list = eina_list_remove(cp->busy_list, buffer); + } _e_pixmap_wl_resource_release(buffer); } @@ -193,6 +201,18 @@ _e_pixmap_wayland_image_clear(E_Pixmap *cp) { EINA_SAFETY_ON_NULL_RETURN(cp); + if (cp->busy_list) + { + E_Comp_Wl_Buffer *buffer; + + EINA_LIST_FREE(cp->busy_list, buffer) + { + buffer->busy--; + if (buffer->dmabuf_buffer) + linux_dmabuf_buffer_unref(buffer->dmabuf_buffer); + } + } + if (!cp->held_buffer) return; if (!cp->held_buffer->pool) return; @@ -703,7 +723,17 @@ e_pixmap_resource_set(E_Pixmap *cp, void *resource) if (cp->buffer == resource) return; if (cp->buffer) - _e_pixmap_wl_resource_release(cp->buffer); + { + if (resource) + { + if (cp->buffer->busy == 1) + { + // about to go to busy 0, so remove from list + cp->busy_list = eina_list_remove(cp->busy_list, cp->buffer); + } + _e_pixmap_wl_resource_release(cp->buffer); + } + } if (cp->buffer_destroy_listener.notify) { @@ -716,7 +746,14 @@ e_pixmap_resource_set(E_Pixmap *cp, void *resource) wl_signal_add(&cp->buffer->destroy_signal, &cp->buffer_destroy_listener); + if (cp->buffer->dmabuf_buffer) + linux_dmabuf_buffer_ref(cp->buffer->dmabuf_buffer); cp->buffer->busy++; + if (cp->buffer->busy > 0) + { + cp->busy_list = eina_list_remove(cp->busy_list, cp->buffer); + cp->busy_list = eina_list_append(cp->busy_list, cp->buffer); + } #else (void)resource; #endif @@ -751,23 +788,32 @@ e_pixmap_is_pixels(E_Pixmap *cp) static void _e_pixmap_scanout_handler(void *data, Evas_Native_Surface_Status status) { - E_Comp_Wl_Buffer *buffer; + E_Comp_Wl_Buffer *buffer = data; printf("EWL: %s, Status: %d\n", __FUNCTION__, status); - buffer = data; switch (status) { case EVAS_NATIVE_SURFACE_STATUS_SCANOUT_ON: + if (buffer->dmabuf_buffer) + linux_dmabuf_buffer_ref(buffer->dmabuf_buffer); buffer->busy++; + // XXX: fixme - handle cp->busy_list break; case EVAS_NATIVE_SURFACE_STATUS_SCANOUT_OFF: + // busy-- + // XXX: fixme - handle cp->busy_list _e_pixmap_wl_resource_release(buffer); break; case EVAS_NATIVE_SURFACE_STATUS_PLANE_ASSIGN: + if (buffer->dmabuf_buffer) + linux_dmabuf_buffer_ref(buffer->dmabuf_buffer); + // XXX: fixme - handle cp->busy_list buffer->busy++; break; case EVAS_NATIVE_SURFACE_STATUS_PLANE_RELEASE: + // busy-- + // XXX: fixme - handle cp->busy_list _e_pixmap_wl_resource_release(buffer); break; } --