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; }