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
This commit is contained in:
Carsten Haitzler 2021-04-16 03:18:41 +00:00
parent 92695f10fc
commit d96c75b8d5
4 changed files with 74 additions and 8 deletions

View File

@ -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

View File

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

View File

@ -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);

View File

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