The API enables to use the frame event and the buffer event. Signed-off-by: Axel Davy <axel.d...@ens.fr> --- v2: fix indentation + move a call from patch 1 to here + add a missing call hw/xfree86/xwayland/Makefile.am | 1 + hw/xfree86/xwayland/xwayland-events.c | 216 +++++++++++++++++++++++++++++++++ hw/xfree86/xwayland/xwayland-private.h | 8 ++ hw/xfree86/xwayland/xwayland-window.c | 6 + hw/xfree86/xwayland/xwayland.h | 14 +++ 5 files changed, 245 insertions(+) create mode 100644 hw/xfree86/xwayland/xwayland-events.c
diff --git a/hw/xfree86/xwayland/Makefile.am b/hw/xfree86/xwayland/Makefile.am index 22ab154..cc45444 100644 --- a/hw/xfree86/xwayland/Makefile.am +++ b/hw/xfree86/xwayland/Makefile.am @@ -21,6 +21,7 @@ libxwayland_la_SOURCES = \ xwayland-output.c \ xwayland-cursor.c \ xwayland-window.c \ + xwayland-events.c \ xwayland-private.h \ drm-client-protocol.h \ drm-protocol.c \ diff --git a/hw/xfree86/xwayland/xwayland-events.c b/hw/xfree86/xwayland/xwayland-events.c new file mode 100644 index 0000000..3a986bf --- /dev/null +++ b/hw/xfree86/xwayland/xwayland-events.c @@ -0,0 +1,216 @@ +/* + * Copyright © 2014 Axel Davy + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +#include <unistd.h> + +#include <wayland-util.h> +#include <wayland-client.h> + +#include <xf86Crtc.h> +#include "xwayland.h" +#include "xwayland-private.h" + + +/* + * Handling of frame events and buffer events. + * API to use them + */ + +struct _todo +{ + union + { + todo_func_frame tff; + todo_func_buffer tfb; + } tocall; + void *args; + struct wl_list link; +}; + +static void +event_todo_free(struct wl_list *todo_list) +{ + struct _todo *pos, *tmp; + wl_list_for_each_safe(pos, tmp, todo_list, link) { + wl_list_remove(&pos->link); + free(pos); + } +} + +static const struct wl_callback_listener frame_listener; + +static void +frame_listener_callback(void *data, + struct wl_callback *callback, uint32_t time) +{ + struct xwl_window *xwl_window = data; + struct wl_list todo_list; + struct _todo *todo; + + wl_callback_destroy(xwl_window->frame_callback); + xwl_window->frame_callback = wl_surface_frame(xwl_window->surface); + wl_callback_add_listener(xwl_window->frame_callback, + &frame_listener, xwl_window); + + if (wl_list_empty(&xwl_window->frame_todo)) + return; + + /* todo funcs are able to ask to be recalled */ + + wl_list_init(&todo_list); + wl_list_insert_list(&todo_list, &xwl_window->frame_todo); + wl_list_init(&xwl_window->frame_todo); + wl_list_for_each(todo, &todo_list, link) + todo->tocall.tff(0, time, todo->args); + event_todo_free(&todo_list); + + /* We need to commit to let the compositor know the new frame callback */ + if (!wl_list_empty(&xwl_window->frame_todo)) { + /* reverse the list. It is useful to keep the order between two + * waiting functions that keep adding themselves to the todo list */ + wl_list_init(&todo_list); + wl_list_insert_list(&todo_list, &xwl_window->frame_todo); + wl_list_init(&xwl_window->frame_todo); + wl_list_for_each(todo, &todo_list, link) + wl_list_insert(&xwl_window->frame_todo, &todo->link); + wl_surface_commit(xwl_window->surface); + } +} + + + +static const struct wl_callback_listener frame_listener = { + frame_listener_callback +}; + + +static void +wl_buffer_release_event(void *data, struct wl_buffer *buffer) +{ + struct xwl_pixmap *xwl_pixmap = data; + struct wl_list todo_list; + struct _todo *todo; + + if (wl_list_empty(&xwl_pixmap->buffer_todo)) + return; + wl_list_init(&todo_list); + wl_list_insert_list(&todo_list, &xwl_pixmap->buffer_todo); + wl_list_init(&xwl_pixmap->buffer_todo); + wl_list_for_each(todo, &todo_list, link) + todo->tocall.tfb(0, todo->args); + event_todo_free(&todo_list); +} + +static struct wl_buffer_listener wl_buffer_listener = { + wl_buffer_release_event +}; + +void +create_frame_listener(struct xwl_window *xwl_window) +{ + wl_list_init(&xwl_window->frame_todo); + xwl_window->frame_callback = wl_surface_frame(xwl_window->surface); + wl_callback_add_listener(xwl_window->frame_callback, + &frame_listener, xwl_window); + wl_surface_commit(xwl_window->surface); +} + +void +destroy_frame_listener(struct xwl_window *xwl_window) +{ + struct _todo *pos, *tmp; + if (!xwl_window->frame_callback) + return; + wl_callback_destroy(xwl_window->frame_callback); + xwl_window->frame_callback = NULL; + + wl_list_for_each_safe(pos, tmp, &xwl_window->frame_todo, link) { + pos->tocall.tff(XWL_TODO_OBJECT_DESTRUCTION, 0, pos->args); + wl_list_remove(&pos->link); + free(pos); + } +} + +void +create_buffer_listener(struct xwl_pixmap *xwl_pixmap) +{ + wl_list_init(&xwl_pixmap->buffer_todo); + wl_buffer_add_listener(xwl_pixmap->buffer, &wl_buffer_listener, + xwl_pixmap); +} + +void +destroy_buffer_listener(struct xwl_pixmap *xwl_pixmap) +{ + struct _todo *pos, *tmp; + wl_list_for_each_safe(pos, tmp, &xwl_pixmap->buffer_todo, link) { + pos->tocall.tfb(XWL_TODO_OBJECT_DESTRUCTION, pos->args); + wl_list_remove(&pos->link); + free(pos); + } +} + +Bool +xwl_add_frame_todo(WindowPtr window, todo_func_frame tocall, void *arg) +{ + struct xwl_window *xwl_window = get_xwl_window(window); + struct _todo *todo; + + if (!xwl_window) + return FALSE; + if (!xwl_window->frame_callback) + create_frame_listener(xwl_window); + if (!xwl_window->frame_callback) + return FALSE; + if (wl_list_empty(&xwl_window->frame_todo)) + wl_surface_commit(xwl_window->surface); + todo = calloc(sizeof(struct _todo), 1); + if (!todo) + return FALSE; + todo->tocall.tff = tocall; + todo->args = arg; + wl_list_insert(&xwl_window->frame_todo, &todo->link); + return TRUE; +} + +Bool +xwl_add_buffer_release_todo(WindowPtr window, + todo_func_buffer tocall, void *arg) +{ + struct xwl_window *xwl_window = get_xwl_window(window); + struct xwl_pixmap *xwl_pixmap; + struct _todo *todo; + if (!xwl_window) + return FALSE; + xwl_pixmap = xwl_window_get_buffer(xwl_window); + todo = calloc(sizeof(struct _todo), 1); + if (!todo) + return FALSE; + todo->tocall.tfb = tocall; + todo->args = arg; + wl_list_insert(&xwl_pixmap->buffer_todo, &todo->link); + return TRUE; +} diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h index 3131dac..3731f43 100644 --- a/hw/xfree86/xwayland/xwayland-private.h +++ b/hw/xfree86/xwayland/xwayland-private.h @@ -33,10 +33,13 @@ struct xwl_window { DamagePtr damage; struct xorg_list link; struct xorg_list link_damage; + struct wl_callback *frame_callback; + struct wl_list frame_todo; }; struct xwl_pixmap { struct wl_buffer *buffer; + struct wl_list buffer_todo; }; struct xwl_output; @@ -144,6 +147,11 @@ void xwl_pixmap_attach_buffer(PixmapPtr pixmap, struct wl_buffer *buffer); struct xwl_pixmap *xwl_window_get_buffer(struct xwl_window *xwl_window); struct xwl_window *get_xwl_window(WindowPtr window); +void create_frame_listener(struct xwl_window* xwl_window); +void destroy_frame_listener(struct xwl_window* xwl_window); +void create_buffer_listener(struct xwl_pixmap *xwl_pixmap); +void destroy_buffer_listener(struct xwl_pixmap* xwl_pixmap); + extern const struct xserver_listener xwl_server_listener; #endif /* _XWAYLAND_PRIVATE_H_ */ diff --git a/hw/xfree86/xwayland/xwayland-window.c b/hw/xfree86/xwayland/xwayland-window.c index 1e6c09b..b9fdbbb 100644 --- a/hw/xfree86/xwayland/xwayland-window.c +++ b/hw/xfree86/xwayland/xwayland-window.c @@ -72,6 +72,7 @@ xwl_pixmap_attach_buffer(PixmapPtr pixmap, struct wl_buffer *buffer) return; } xwl_pixmap->buffer = buffer; + create_buffer_listener(xwl_pixmap); dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap); } @@ -221,6 +222,10 @@ xwl_unrealize_window(WindowPtr window) if (!xwl_window) return ret; + /* The frame listener is created automatically when needed. + * Clean it if needed. */ + destroy_frame_listener(xwl_window); + wl_surface_destroy(xwl_window->surface); xorg_list_del(&xwl_window->link); if (RegionNotEmpty(DamageRegion(xwl_window->damage))) @@ -262,6 +267,7 @@ xwl_destroy_pixmap(PixmapPtr pixmap) struct xwl_pixmap *xwl_pixmap = dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); if (xwl_pixmap) { + destroy_buffer_listener(xwl_pixmap); wl_buffer_destroy(xwl_pixmap->buffer); dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, NULL); diff --git a/hw/xfree86/xwayland/xwayland.h b/hw/xfree86/xwayland/xwayland.h index c380618..daf87f6 100644 --- a/hw/xfree86/xwayland/xwayland.h +++ b/hw/xfree86/xwayland/xwayland.h @@ -38,6 +38,13 @@ struct xwl_driver { PixmapPtr pixmap); }; +/* This flag indicated the todo_func is called because the object + * is beeing destroyed */ +#define XWL_TODO_OBJECT_DESTRUCTION 0x01 + +typedef void (*todo_func_buffer)(int flags, void *arg); +typedef void (*todo_func_frame)(int flags, uint32_t time, void *arg); + #define XWL_FLAGS_ROOTLESS 0x01 extern _X_EXPORT int @@ -90,4 +97,11 @@ extern _X_EXPORT int xwl_create_window_buffer_shm(struct xwl_window *xwl_window, PixmapPtr pixmap, int fd); +extern _X_EXPORT Bool +xwl_add_frame_todo(WindowPtr window, todo_func_frame tocall, void *arg); + +extern _X_EXPORT Bool +xwl_add_buffer_release_todo(WindowPtr window, + todo_func_buffer tocall, void *arg); + #endif /* _XWAYLAND_H_ */ -- 1.8.3.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel