forked from enlightenment/enlightenment
Rework wayland buffer handling
We need to keep wayland buffers around even if they'll never be written to again. This is part of Buffer_Reference's task in weston, but we already have our pixmap abstraction which can serve mostly the same purpose. Remove the "buffer reference" stuff from e_pixmap and replace it with a kept buffer for the last commit. Add shared memory pool references to keep pools from going away on us.
This commit is contained in:
parent
b98e78d464
commit
dfc7c26ce4
|
@ -1696,7 +1696,6 @@ _e_comp_wl_subsurface_destroy(struct wl_resource *resource)
|
|||
}
|
||||
|
||||
_e_comp_wl_surface_state_finish(&sdata->cached);
|
||||
e_comp_wl_buffer_reference(&sdata->cached_buffer_ref, NULL);
|
||||
|
||||
/* the client is getting deleted, which means the pixmap will be getting
|
||||
* freed. We need to unset the surface user data */
|
||||
|
@ -1743,8 +1742,9 @@ _e_comp_wl_subsurface_commit_to_cache(E_Client *ec)
|
|||
sdata->cached.new_attach = EINA_TRUE;
|
||||
_e_comp_wl_surface_state_buffer_set(&sdata->cached,
|
||||
cdata->pending.buffer);
|
||||
e_comp_wl_buffer_reference(&sdata->cached_buffer_ref,
|
||||
cdata->pending.buffer);
|
||||
e_pixmap_resource_set(ec->pixmap, cdata->pending.buffer);
|
||||
e_pixmap_dirty(ec->pixmap);
|
||||
e_pixmap_refresh(ec->pixmap);
|
||||
}
|
||||
|
||||
sdata->cached.sx = cdata->pending.sx;
|
||||
|
|
|
@ -56,7 +56,10 @@ struct _E_Comp_Wl_Buffer
|
|||
struct wl_resource *resource;
|
||||
struct wl_signal destroy_signal;
|
||||
struct wl_listener destroy_listener;
|
||||
struct wl_listener deferred_destroy_listener;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
struct wl_shm_pool *pool;
|
||||
E_Pixmap *discarding_pixmap;
|
||||
int32_t w, h;
|
||||
uint32_t busy;
|
||||
};
|
||||
|
|
|
@ -42,11 +42,13 @@ struct _E_Pixmap
|
|||
|
||||
#ifdef HAVE_WAYLAND
|
||||
E_Comp_Wl_Buffer *buffer;
|
||||
E_Comp_Wl_Buffer_Ref buffer_ref;
|
||||
E_Comp_Wl_Buffer *held_buffer;
|
||||
struct wl_listener buffer_destroy_listener;
|
||||
struct wl_listener held_buffer_destroy_listener;
|
||||
void *data;
|
||||
Eina_Rectangle opaque;
|
||||
uuid_t uuid;
|
||||
Eina_List *free_buffers;
|
||||
#endif
|
||||
|
||||
Eina_Bool usable : 1;
|
||||
|
@ -55,15 +57,36 @@ struct _E_Pixmap
|
|||
};
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
|
||||
static void
|
||||
_e_pixmap_cb_deferred_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
|
||||
{
|
||||
E_Comp_Wl_Buffer *buffer;
|
||||
|
||||
buffer = container_of(listener, E_Comp_Wl_Buffer, deferred_destroy_listener);
|
||||
buffer->discarding_pixmap->free_buffers = eina_list_remove(buffer->discarding_pixmap->free_buffers, buffer);
|
||||
buffer->discarding_pixmap = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_e_pixmap_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
|
||||
{
|
||||
E_Pixmap *cp;
|
||||
|
||||
cp = container_of(listener, E_Pixmap, buffer_destroy_listener);
|
||||
cp->data = NULL;
|
||||
cp->buffer = NULL;
|
||||
cp->buffer_destroy_listener.notify = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_e_pixmap_cb_held_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
|
||||
{
|
||||
E_Pixmap *cp;
|
||||
|
||||
cp = container_of(listener, E_Pixmap, held_buffer_destroy_listener);
|
||||
cp->held_buffer = NULL;
|
||||
cp->held_buffer_destroy_listener.notify = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
|
@ -102,6 +125,67 @@ _e_pixmap_image_clear_x(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_U
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
static void
|
||||
_e_pixmap_wayland_buffer_release(E_Pixmap *cp, E_Comp_Wl_Buffer *buffer)
|
||||
{
|
||||
if (!buffer) return;
|
||||
|
||||
if (e_comp->rendering)
|
||||
{
|
||||
if (buffer->discarding_pixmap) return;
|
||||
|
||||
buffer->discarding_pixmap = cp;
|
||||
buffer->deferred_destroy_listener.notify = _e_pixmap_cb_deferred_buffer_destroy;
|
||||
wl_signal_add(&buffer->destroy_signal, &buffer->deferred_destroy_listener);
|
||||
cp->free_buffers = eina_list_append(cp->free_buffers, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->busy--;
|
||||
if (buffer->busy) return;
|
||||
|
||||
wl_resource_queue_event(buffer->resource, WL_BUFFER_RELEASE);
|
||||
wl_shm_pool_unref(buffer->pool);
|
||||
buffer->pool = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_e_pixmap_wl_buffers_free(E_Pixmap *cp)
|
||||
{
|
||||
E_Comp_Wl_Buffer *b;
|
||||
|
||||
if (e_comp->rendering) return;
|
||||
|
||||
EINA_LIST_FREE(cp->free_buffers, b)
|
||||
{
|
||||
wl_list_remove(&b->deferred_destroy_listener.link);
|
||||
b->deferred_destroy_listener.notify = NULL;
|
||||
_e_pixmap_wayland_buffer_release(cp, b);
|
||||
b->discarding_pixmap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_e_pixmap_wayland_image_clear(E_Pixmap *cp)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(cp);
|
||||
|
||||
if (!cp->held_buffer) return;
|
||||
if (!cp->held_buffer->pool) return;
|
||||
|
||||
_e_pixmap_wayland_buffer_release(cp, cp->held_buffer);
|
||||
if (cp->held_buffer_destroy_listener.notify)
|
||||
{
|
||||
wl_list_remove(&cp->held_buffer_destroy_listener.link);
|
||||
cp->held_buffer_destroy_listener.notify = NULL;
|
||||
}
|
||||
|
||||
cp->data = NULL;
|
||||
cp->held_buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_e_pixmap_free(E_Pixmap *cp)
|
||||
{
|
||||
|
@ -124,6 +208,7 @@ _e_pixmap_free(E_Pixmap *cp)
|
|||
break;
|
||||
case E_PIXMAP_TYPE_WL:
|
||||
#ifdef HAVE_WAYLAND
|
||||
_e_pixmap_wayland_image_clear(cp);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
|
@ -546,7 +631,25 @@ e_pixmap_resource_set(E_Pixmap *cp, void *resource)
|
|||
{
|
||||
if ((!cp) || (cp->type != E_PIXMAP_TYPE_WL)) return;
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (cp->buffer == resource) return;
|
||||
|
||||
if (cp->buffer)
|
||||
{
|
||||
cp->buffer->busy--;
|
||||
if (!cp->buffer->busy) wl_resource_queue_event(cp->buffer->resource, WL_BUFFER_RELEASE);
|
||||
}
|
||||
if (cp->buffer_destroy_listener.notify)
|
||||
{
|
||||
wl_list_remove(&cp->buffer_destroy_listener.link);
|
||||
cp->buffer_destroy_listener.notify = NULL;
|
||||
}
|
||||
cp->buffer = resource;
|
||||
if (!cp->buffer) return;
|
||||
cp->buffer_destroy_listener.notify = _e_pixmap_cb_buffer_destroy;
|
||||
wl_signal_add(&cp->buffer->destroy_signal,
|
||||
&cp->buffer_destroy_listener);
|
||||
|
||||
cp->buffer->busy++;
|
||||
#else
|
||||
(void)resource;
|
||||
#endif
|
||||
|
@ -607,7 +710,7 @@ e_pixmap_image_clear(E_Pixmap *cp, Eina_Bool cache)
|
|||
#endif
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (cp->type == E_PIXMAP_TYPE_WL)
|
||||
if (!cp->buffer_ref.buffer) return;
|
||||
if (!cp->buffer) return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -638,6 +741,8 @@ e_pixmap_image_clear(E_Pixmap *cp, Eina_Bool cache)
|
|||
struct wl_resource *cb;
|
||||
Eina_List *free_list;
|
||||
|
||||
if (!e_comp->rendering) _e_pixmap_wl_buffers_free(cp);
|
||||
|
||||
if ((!cp->client) || (!cp->client->comp_data)) return;
|
||||
cd = (E_Comp_Wl_Client_Data *)cp->client->comp_data;
|
||||
|
||||
|
@ -652,13 +757,6 @@ e_pixmap_image_clear(E_Pixmap *cp, Eina_Bool cache)
|
|||
wl_resource_destroy(cb);
|
||||
}
|
||||
}
|
||||
if (cp->buffer_destroy_listener.notify)
|
||||
{
|
||||
wl_list_remove(&cp->buffer_destroy_listener.link);
|
||||
cp->buffer_destroy_listener.notify = NULL;
|
||||
}
|
||||
e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
|
||||
cp->data = NULL;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
|
@ -696,27 +794,22 @@ e_pixmap_image_refresh(E_Pixmap *cp)
|
|||
case E_PIXMAP_TYPE_WL:
|
||||
#ifdef HAVE_WAYLAND
|
||||
{
|
||||
E_Comp_Wl_Buffer *buffer = cp->buffer;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
if (cp->held_buffer == cp->buffer) return EINA_TRUE;
|
||||
|
||||
shm_buffer = buffer->shm_buffer;
|
||||
if (cp->buffer_ref.buffer && (cp->buffer_ref.buffer != buffer))
|
||||
{
|
||||
/* FIXME: wtf? */
|
||||
}
|
||||
else if (cp->buffer_ref.buffer) return EINA_TRUE;
|
||||
e_comp_wl_buffer_reference(&cp->buffer_ref, buffer);
|
||||
if (cp->held_buffer) _e_pixmap_wayland_image_clear(cp);
|
||||
|
||||
if (cp->buffer_destroy_listener.notify)
|
||||
{
|
||||
wl_list_remove(&cp->buffer_destroy_listener.link);
|
||||
cp->buffer_destroy_listener.notify = NULL;
|
||||
}
|
||||
if (!cp->buffer->shm_buffer) return EINA_TRUE;
|
||||
|
||||
cp->buffer_destroy_listener.notify = _e_pixmap_cb_buffer_destroy;
|
||||
wl_signal_add(&buffer->destroy_signal, &cp->buffer_destroy_listener);
|
||||
if (shm_buffer)
|
||||
cp->data = wl_shm_buffer_get_data(shm_buffer);
|
||||
cp->held_buffer = cp->buffer;
|
||||
if (!cp->held_buffer) return EINA_TRUE;
|
||||
|
||||
cp->held_buffer->pool = wl_shm_buffer_ref_pool(cp->held_buffer->shm_buffer);
|
||||
cp->held_buffer->busy++;
|
||||
cp->data = wl_shm_buffer_get_data(cp->buffer->shm_buffer);
|
||||
|
||||
cp->held_buffer_destroy_listener.notify = _e_pixmap_cb_held_buffer_destroy;
|
||||
wl_signal_add(&cp->held_buffer->destroy_signal,
|
||||
&cp->held_buffer_destroy_listener);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
@ -757,7 +850,7 @@ e_pixmap_image_is_argb(const E_Pixmap *cp)
|
|||
#endif
|
||||
case E_PIXMAP_TYPE_WL:
|
||||
#ifdef HAVE_WAYLAND
|
||||
return ((cp->buffer_ref.buffer != NULL) && (cp->image_argb));
|
||||
return ((cp->buffer != NULL) && (cp->image_argb));
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
|
@ -809,14 +902,14 @@ e_pixmap_image_data_argb_convert(E_Pixmap *cp, void *pix, void *ipix, Eina_Recta
|
|||
case E_PIXMAP_TYPE_WL:
|
||||
if (cp->image_argb) return EINA_TRUE;
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (cp->buffer_ref.buffer)
|
||||
if (cp->buffer)
|
||||
{
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
uint32_t format;
|
||||
int i, x, y;
|
||||
unsigned int *src, *dst;
|
||||
|
||||
shm_buffer = cp->buffer_ref.buffer->shm_buffer;
|
||||
shm_buffer = cp->buffer->shm_buffer;
|
||||
if (!shm_buffer) return EINA_FALSE;
|
||||
|
||||
format = wl_shm_buffer_get_format(shm_buffer);
|
||||
|
|
Loading…
Reference in New Issue