xwayland: Add buffer release callback
The API `wl_buffer_add_listener` is misleading in the sense that there can be only one `wl_buffer` release callback, and trying to add a new listener when once is already in place will lead to a protocol error. The Xwayland EGL backends may need to set up their own `wl_buffer` release listener, meaning that there is no way to our own `wl_buffer` release callback. To avoid the problem, add our own callback API to be notified when the `wl_buffer` associated with an `xwl_pixmap` is released, triggered from the different `xwl_pixmap` implementations. Also update the Present code to use the new buffer release callback API. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
This commit is contained in:
parent
8d4be7f6c4
commit
7765874186
|
@ -305,9 +305,10 @@ xwl_glamor_eglstream_destroy_pixmap(PixmapPtr pixmap)
|
|||
{
|
||||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
if (xwl_pixmap && pixmap->refcnt == 1)
|
||||
if (xwl_pixmap && pixmap->refcnt == 1) {
|
||||
xwl_pixmap_del_buffer_release_cb(pixmap);
|
||||
xwl_eglstream_unref_pixmap_stream(xwl_pixmap);
|
||||
|
||||
}
|
||||
return glamor_destroy_pixmap(pixmap);
|
||||
}
|
||||
|
||||
|
@ -475,7 +476,10 @@ xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
|
|||
static void
|
||||
xwl_eglstream_buffer_release_callback(void *data, struct wl_buffer *wl_buffer)
|
||||
{
|
||||
xwl_eglstream_unref_pixmap_stream(data);
|
||||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(data);
|
||||
|
||||
xwl_pixmap_buffer_release_cb(data, wl_buffer);
|
||||
xwl_eglstream_unref_pixmap_stream(xwl_pixmap);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener xwl_eglstream_buffer_release_listener = {
|
||||
|
@ -517,7 +521,7 @@ xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
|
|||
|
||||
wl_buffer_add_listener(xwl_pixmap->buffer,
|
||||
&xwl_eglstream_buffer_release_listener,
|
||||
xwl_pixmap);
|
||||
pixmap);
|
||||
|
||||
wl_eglstream_controller_attach_eglstream_consumer(
|
||||
xwl_eglstream->controller, xwl_window->surface, xwl_pixmap->buffer);
|
||||
|
|
|
@ -260,6 +260,7 @@ xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap)
|
|||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
if (xwl_pixmap && pixmap->refcnt == 1) {
|
||||
xwl_pixmap_del_buffer_release_cb(pixmap);
|
||||
if (xwl_pixmap->buffer)
|
||||
wl_buffer_destroy(xwl_pixmap->buffer);
|
||||
|
||||
|
@ -272,6 +273,10 @@ xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap)
|
|||
return glamor_destroy_pixmap(pixmap);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener xwl_glamor_gbm_buffer_listener = {
|
||||
xwl_pixmap_buffer_release_cb,
|
||||
};
|
||||
|
||||
static struct wl_buffer *
|
||||
xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap,
|
||||
Bool *created)
|
||||
|
@ -348,6 +353,11 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap,
|
|||
}
|
||||
|
||||
close(prime_fd);
|
||||
|
||||
/* Add our listener now */
|
||||
wl_buffer_add_listener(xwl_pixmap->buffer,
|
||||
&xwl_glamor_gbm_buffer_listener, pixmap);
|
||||
|
||||
return xwl_pixmap->buffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,13 +169,14 @@ xwl_present_free_event(struct xwl_present_event *event)
|
|||
}
|
||||
|
||||
static void
|
||||
xwl_present_buffer_release(void *data, struct wl_buffer *buffer)
|
||||
xwl_present_buffer_release(PixmapPtr pixmap, void *data)
|
||||
{
|
||||
struct xwl_present_event *event = data;
|
||||
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
wl_buffer_set_user_data(buffer, NULL);
|
||||
xwl_pixmap_del_buffer_release_cb(pixmap);
|
||||
event->buffer_released = TRUE;
|
||||
|
||||
if (event->abort) {
|
||||
|
@ -193,10 +194,6 @@ xwl_present_buffer_release(void *data, struct wl_buffer *buffer)
|
|||
}
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener xwl_present_release_listener = {
|
||||
xwl_present_buffer_release
|
||||
};
|
||||
|
||||
static void
|
||||
xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
|
@ -452,7 +449,6 @@ xwl_present_flip(WindowPtr present_window,
|
|||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window);
|
||||
BoxPtr damage_box;
|
||||
Bool buffer_created;
|
||||
struct wl_buffer *buffer;
|
||||
struct xwl_present_event *event;
|
||||
|
||||
|
@ -465,7 +461,7 @@ xwl_present_flip(WindowPtr present_window,
|
|||
if (!event)
|
||||
return FALSE;
|
||||
|
||||
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, &buffer_created);
|
||||
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, NULL);
|
||||
|
||||
event->event_id = event_id;
|
||||
event->xwl_present_window = xwl_present_window;
|
||||
|
@ -482,9 +478,7 @@ xwl_present_flip(WindowPtr present_window,
|
|||
xorg_list_add(&event->list, &xwl_present_window->release_queue);
|
||||
}
|
||||
|
||||
if (buffer_created)
|
||||
wl_buffer_add_listener(buffer, &xwl_present_release_listener, NULL);
|
||||
wl_buffer_set_user_data(buffer, event);
|
||||
xwl_pixmap_set_buffer_release_cb(pixmap, xwl_present_buffer_release, event);
|
||||
|
||||
/* We can flip directly to the main surface (full screen window without clips) */
|
||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
||||
|
|
|
@ -189,6 +189,10 @@ shm_format_for_depth(int depth)
|
|||
}
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener xwl_shm_buffer_listener = {
|
||||
xwl_pixmap_buffer_release_cb,
|
||||
};
|
||||
|
||||
PixmapPtr
|
||||
xwl_shm_create_pixmap(ScreenPtr screen,
|
||||
int width, int height, int depth, unsigned int hint)
|
||||
|
@ -241,6 +245,9 @@ xwl_shm_create_pixmap(ScreenPtr screen,
|
|||
wl_shm_pool_destroy(pool);
|
||||
close(fd);
|
||||
|
||||
wl_buffer_add_listener(xwl_pixmap->buffer,
|
||||
&xwl_shm_buffer_listener, pixmap);
|
||||
|
||||
xwl_pixmap_set_private(pixmap, xwl_pixmap);
|
||||
|
||||
return pixmap;
|
||||
|
@ -263,6 +270,7 @@ xwl_shm_destroy_pixmap(PixmapPtr pixmap)
|
|||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
if (xwl_pixmap && pixmap->refcnt == 1) {
|
||||
xwl_pixmap_del_buffer_release_cb(pixmap);
|
||||
if (xwl_pixmap->buffer)
|
||||
wl_buffer_destroy(xwl_pixmap->buffer);
|
||||
munmap(xwl_pixmap->data, xwl_pixmap->size);
|
||||
|
|
|
@ -169,6 +169,7 @@ static DevPrivateKeyRec xwl_client_private_key;
|
|||
static DevPrivateKeyRec xwl_window_private_key;
|
||||
static DevPrivateKeyRec xwl_screen_private_key;
|
||||
static DevPrivateKeyRec xwl_pixmap_private_key;
|
||||
static DevPrivateKeyRec xwl_pixmap_cb_private_key;
|
||||
static DevPrivateKeyRec xwl_damage_private_key;
|
||||
|
||||
struct xwl_client *
|
||||
|
@ -298,6 +299,64 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
|||
xwl_window_property_allow_commits(xwl_window, rec);
|
||||
}
|
||||
|
||||
struct xwl_pixmap_buffer_release_cb {
|
||||
xwl_pixmap_cb callback;
|
||||
void *data;
|
||||
};
|
||||
|
||||
Bool
|
||||
xwl_pixmap_set_buffer_release_cb(PixmapPtr pixmap,
|
||||
xwl_pixmap_cb func, void *data)
|
||||
{
|
||||
struct xwl_pixmap_buffer_release_cb *xwl_pixmap_buffer_release_cb;
|
||||
|
||||
xwl_pixmap_buffer_release_cb = dixLookupPrivate(&pixmap->devPrivates,
|
||||
&xwl_pixmap_cb_private_key);
|
||||
|
||||
if (xwl_pixmap_buffer_release_cb == NULL) {
|
||||
xwl_pixmap_buffer_release_cb =
|
||||
calloc(1, sizeof (struct xwl_pixmap_buffer_release_cb));
|
||||
|
||||
if (xwl_pixmap_buffer_release_cb == NULL) {
|
||||
ErrorF("Failed to allocate pixmap callback data\n");
|
||||
return FALSE;
|
||||
}
|
||||
dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_cb_private_key,
|
||||
xwl_pixmap_buffer_release_cb);
|
||||
}
|
||||
|
||||
xwl_pixmap_buffer_release_cb->callback = func;
|
||||
xwl_pixmap_buffer_release_cb->data = data;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_pixmap_del_buffer_release_cb(PixmapPtr pixmap)
|
||||
{
|
||||
struct xwl_pixmap_buffer_release_cb *xwl_pixmap_buffer_release_cb;
|
||||
|
||||
xwl_pixmap_buffer_release_cb = dixLookupPrivate(&pixmap->devPrivates,
|
||||
&xwl_pixmap_cb_private_key);
|
||||
if (xwl_pixmap_buffer_release_cb) {
|
||||
dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_cb_private_key, NULL);
|
||||
free(xwl_pixmap_buffer_release_cb);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xwl_pixmap_buffer_release_cb(void *data, struct wl_buffer *wl_buffer)
|
||||
{
|
||||
PixmapPtr pixmap = data;
|
||||
struct xwl_pixmap_buffer_release_cb *xwl_pixmap_buffer_release_cb;
|
||||
|
||||
xwl_pixmap_buffer_release_cb = dixLookupPrivate(&pixmap->devPrivates,
|
||||
&xwl_pixmap_cb_private_key);
|
||||
if (xwl_pixmap_buffer_release_cb)
|
||||
(*xwl_pixmap_buffer_release_cb->callback)
|
||||
(pixmap, xwl_pixmap_buffer_release_cb->data);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_close_screen(ScreenPtr screen)
|
||||
{
|
||||
|
@ -1348,6 +1407,8 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
return FALSE;
|
||||
if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0))
|
||||
return FALSE;
|
||||
if (!dixRegisterPrivateKey(&xwl_pixmap_cb_private_key, PRIVATE_PIXMAP, 0))
|
||||
return FALSE;
|
||||
if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0))
|
||||
return FALSE;
|
||||
/* There are no easy to use new / delete client hooks, we could use a
|
||||
|
|
|
@ -60,6 +60,8 @@ struct xwl_pixmap;
|
|||
struct xwl_window;
|
||||
struct xwl_screen;
|
||||
|
||||
typedef void (*xwl_pixmap_cb) (PixmapPtr pixmap, void *data);
|
||||
|
||||
struct xwl_egl_backend {
|
||||
/* Set by the backend if available */
|
||||
Bool is_available;
|
||||
|
@ -461,6 +463,10 @@ RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
|
|||
|
||||
void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap);
|
||||
struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap);
|
||||
Bool xwl_pixmap_set_buffer_release_cb(PixmapPtr pixmap,
|
||||
xwl_pixmap_cb func, void *data);
|
||||
void xwl_pixmap_del_buffer_release_cb(PixmapPtr pixmap);
|
||||
void xwl_pixmap_buffer_release_cb(void *data, struct wl_buffer *wl_buffer);
|
||||
|
||||
struct xwl_window *xwl_window_from_window(WindowPtr window);
|
||||
|
||||
|
|
Loading…
Reference in New Issue