[PATCH] Add a FreeRds backend, take 6
FreeRDS is a FreeRDP based RDP server, the server handles incoming connections and talks RDP with the peers. FreeRds cooperates with an out-service: the out-service creates the content to display, and FreeRds will take care of encoding the content in the appropriate format (bitmapUpdate, remoteFx or NsCodec). To communicate, they use a unix socket for passing commands, and a shared buffer for the screen content. A vblank signal sent by FreeRds via the command channel allows to share the framebuffer nicely. This patch adds a backend to create a FreeRDS compositor and have weston being an out-service for FreeRds. This new revision uses the refcounting of IPC shm to have the last process that shmdt() to remove the segment. It also fixes a bug with the damaged region not resetted on mode_switch() leading to invalid read accesses. --- configure.ac | 12 +- src/Makefile.am | 17 +- src/compositor-freerds.c | 1206 ++ 3 files changed, 1233 insertions(+), 2 deletions(-) create mode 100644 src/compositor-freerds.c diff --git a/configure.ac b/configure.ac index 571bf60..51f3197 100644 --- a/configure.ac +++ b/configure.ac @@ -55,7 +55,7 @@ AC_CHECK_DECL(CLOCK_MONOTONIC,[], [[#include time.h]]) AC_CHECK_HEADERS([execinfo.h]) -AC_CHECK_FUNCS([mkostemp strchrnul initgroups posix_fallocate]) +AC_CHECK_FUNCS([accept4 mkostemp strchrnul initgroups posix_fallocate]) COMPOSITOR_MODULES=wayland-server = 1.3.90 pixman-1 @@ -206,6 +206,15 @@ if test x$enable_rdp_compositor = xyes; then PKG_CHECK_MODULES(RDP_COMPOSITOR, [freerdp = 1.1.0]) fi +AC_ARG_ENABLE([freerds-compositor], [ --enable-freerds-compositor],, + enable_freerds_compositor=no) +AM_CONDITIONAL([ENABLE_FREERDS_COMPOSITOR], + [test x$enable_freerds_compositor = xyes]) +if test x$enable_freerds_compositor = xyes; then + AC_DEFINE([BUILD_FREERDS_COMPOSITOR], [1], [Build the FreeRDS compositor]) + PKG_CHECK_MODULES(FREERDS_COMPOSITOR, [freerds-backend]) +fi + AC_ARG_WITH(cairo, AS_HELP_STRING([--with-cairo=@:@image|gl|glesv2@:@] [Which Cairo renderer to use for the clients]), @@ -526,6 +535,7 @@ AC_MSG_RESULT([ RPI Compositor ${enable_rpi_compositor} FBDEV Compositor${enable_fbdev_compositor} RDP Compositor ${enable_rdp_compositor} + FreeRDS Compositor ${enable_freerds_compositor} Raspberry Pi BCM headers${have_bcm_host} diff --git a/src/Makefile.am b/src/Makefile.am index 446639c..588625e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -117,7 +117,9 @@ module_LTLIBRARIES =\ $(wayland_backend) \ $(headless_backend) \ $(fbdev_backend)\ - $(rdp_backend) + $(rdp_backend) \ + $(freerds_backend) + if INSTALL_RPI_COMPOSITOR module_LTLIBRARIES += $(rpi_backend) @@ -280,6 +282,19 @@ rdp_backend_la_CFLAGS =\ rdp_backend_la_SOURCES = compositor-rdp.c endif +if ENABLE_FREERDS_COMPOSITOR +freerds_backend = freerds-backend.la +freerds_backend_la_LDFLAGS = -module -avoid-version +freerds_backend_la_LIBADD = $(COMPOSITOR_LIBS) \ + $(FREERDS_COMPOSITOR_LIBS) \ + ../shared/libshared.la -lwinpr-input -lfreerdp-core +freerds_backend_la_CFLAGS =\ + $(COMPOSITOR_CFLAGS)\ + $(FREERDS_COMPOSITOR_CFLAGS) \ + $(GCC_CFLAGS) +freerds_backend_la_SOURCES = compositor-freerds.c +endif + if HAVE_LCMS cms_static = cms-static.la cms_static_la_LDFLAGS = -module -avoid-version diff --git a/src/compositor-freerds.c b/src/compositor-freerds.c new file mode 100644 index 000..7e23f10 --- /dev/null +++ b/src/compositor-freerds.c @@ -0,0 +1,1206 @@ +/** + * Copyright © 2013 Hardening cont...@hardening-consulting.com + * + * 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 + *
[PATCH 2/4 v2] Add support to render-nodes.
And allows to create wl_buffers from fds instead of gem names. Signed-off-by: Axel Davy axel.d...@ens.fr --- v2: fix indentation hw/xfree86/xwayland/drm.xml| 45 +- hw/xfree86/xwayland/xwayland-drm.c | 108 + hw/xfree86/xwayland/xwayland-private.h | 1 + hw/xfree86/xwayland/xwayland.h | 7 +++ 4 files changed, 147 insertions(+), 14 deletions(-) diff --git a/hw/xfree86/xwayland/drm.xml b/hw/xfree86/xwayland/drm.xml index 89fd8f0..8a3ad69 100644 --- a/hw/xfree86/xwayland/drm.xml +++ b/hw/xfree86/xwayland/drm.xml @@ -29,7 +29,7 @@ !-- drm support. This object is created by the server and published using the display's global event. -- - interface name=wl_drm version=1 + interface name=wl_drm version=2 enum name=error entry name=authenticate_fail value=0/ entry name=invalid_format value=1/ @@ -119,6 +119,38 @@ arg name=format type=uint/ /request +!-- Create a wayland buffer for the named DRM buffer. The DRM + surface must have a name using the flink ioctl -- +request name=create_planar_buffer + arg name=id type=new_id interface=wl_buffer/ + arg name=name type=uint/ + arg name=width type=int/ + arg name=height type=int/ + arg name=format type=uint/ + arg name=offset0 type=int/ + arg name=stride0 type=int/ + arg name=offset1 type=int/ + arg name=stride1 type=int/ + arg name=offset2 type=int/ + arg name=stride2 type=int/ +/request + +!-- Create a wayland buffer for the prime fd. Use for regular and planar + buffers. Pass 0 for offset and stride for unused planes. -- +request name=create_prime_buffer since=2 + arg name=id type=new_id interface=wl_buffer/ + arg name=name type=fd/ + arg name=width type=int/ + arg name=height type=int/ + arg name=format type=uint/ + arg name=offset0 type=int/ + arg name=stride0 type=int/ + arg name=offset1 type=int/ + arg name=stride1 type=int/ + arg name=offset2 type=int/ + arg name=stride2 type=int/ +/request + !-- Notification of the path of the drm device which is used by the server. The client should use this device for creating local buffers. Only buffers created from this device should @@ -134,6 +166,17 @@ !-- Raised if the authenticate request succeeded -- event name=authenticated/ + +enum name=capability since=2 + description summary=wl_drm capability bitmask +Bitmask of capabilities. + /description + entry name=prime value=1 summary=wl_drm prime available/ +/enum + +event name=capabilities + arg name=value type=uint/ +/event /interface /protocol diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c index 30ec176..076fb68 100644 --- a/hw/xfree86/xwayland/xwayland-drm.c +++ b/hw/xfree86/xwayland/xwayland-drm.c @@ -29,6 +29,7 @@ #include unistd.h #include fcntl.h +#include sys/stat.h #include xf86drm.h #include wayland-util.h @@ -99,11 +100,20 @@ drm_handle_authenticated (void *data, struct wl_drm *drm) } } +static void +drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value) +{ +struct xwl_screen *xwl_screen = data; + +xwl_screen-drm_capabilities = value; +} + static const struct wl_drm_listener xwl_drm_listener = { drm_handle_device, drm_handle_format, -drm_handle_authenticated +drm_handle_authenticated, +drm_handle_capabilities }; static void @@ -114,7 +124,7 @@ drm_handler(void *data, struct wl_registry *registry, uint32_t id, if (strcmp (interface, wl_drm) == 0) { xwl_screen-drm = wl_registry_bind(xwl_screen-registry, id, - wl_drm_interface, 1); + wl_drm_interface, 2); wl_drm_add_listener(xwl_screen-drm, xwl_drm_listener, xwl_screen); } } @@ -130,6 +140,22 @@ static const struct wl_registry_listener drm_listener = { global_remove }; +static char +is_fd_render_node(int fd) +{ +struct stat render; + +if (fstat(fd, render)) + return 0; + +if (!S_ISCHR(render.st_mode)) + return 0; + +if (render.st_rdev 0x80) + return 1; +return 0; +} + int xwl_drm_pre_init(struct xwl_screen *xwl_screen) { @@ -137,7 +163,7 @@ xwl_drm_pre_init(struct xwl_screen *xwl_screen) xwl_screen-drm_registry = wl_display_get_registry(xwl_screen-display); wl_registry_add_listener(xwl_screen-drm_registry, drm_listener, - xwl_screen); +xwl_screen); /* Ensure drm_handler has seen all the interfaces */ wl_display_roundtrip(xwl_screen-display); @@ -153,20 +179,25 @@ xwl_drm_pre_init(struct xwl_screen *xwl_screen) return BadAccess; } -if (drmGetMagic(xwl_screen-drm_fd, magic)) { -
[PATCH 4/4 v2] Add XWayland API with Present support in mind.
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 000..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
[PATCH 1/4 v2] Move the wl_buffer from xwl_window to xwl_pixmap
This change enables to change the window pixmap, and have xwayland send the correct buffer to the Wayland compositor. Signed-off-by: Axel Davy axel.d...@ens.fr --- v2: fix indentation and remove a call that had to be in patch 4 hw/xfree86/xwayland/xwayland-drm.c | 10 +++- hw/xfree86/xwayland/xwayland-private.h | 10 +++- hw/xfree86/xwayland/xwayland-window.c | 83 +- hw/xfree86/xwayland/xwayland.c | 38 ++-- 4 files changed, 113 insertions(+), 28 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c index 5250857..30ec176 100644 --- a/hw/xfree86/xwayland/xwayland-drm.c +++ b/hw/xfree86/xwayland/xwayland-drm.c @@ -217,6 +217,7 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window, VisualID visual; WindowPtr window = xwl_window-window; ScreenPtr screen = window-drawable.pScreen; +struct wl_buffer *buffer; uint32_t format; int i; @@ -238,7 +239,7 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window, break; } -xwl_window-buffer = +buffer = wl_drm_create_buffer(xwl_window-xwl_screen-drm, name, pixmap-drawable.width, @@ -246,5 +247,10 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window, pixmap-devKind, format); -return xwl_window-buffer ? Success : BadDrawable; +if (!buffer) + return BadDrawable; + +xwl_pixmap_attach_buffer(pixmap, buffer); + +return Success; } diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h index bdecf8a..853ab3b 100644 --- a/hw/xfree86/xwayland/xwayland-private.h +++ b/hw/xfree86/xwayland/xwayland-private.h @@ -29,13 +29,16 @@ struct xwl_window { struct xwl_screen *xwl_screen; struct wl_surface *surface; -struct wl_buffer *buffer; WindowPtr window; DamagePtr damage; struct xorg_listlink; struct xorg_listlink_damage; }; +struct xwl_pixmap { +struct wl_buffer *buffer; +}; + struct xwl_output; struct xwl_screen { @@ -72,6 +75,7 @@ struct xwl_screen { RealizeWindowProcPtrRealizeWindow; UnrealizeWindowProcPtr UnrealizeWindow; SetWindowPixmapProcPtr SetWindowPixmap; +DestroyPixmapProcPtrDestroyPixmap; MoveWindowProcPtr MoveWindow; miPointerSpriteFuncPtr sprite_funcs; }; @@ -135,6 +139,10 @@ void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); void xwl_output_remove(struct xwl_output *output); +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); + 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 a2a8206..1e6c09b 100644 --- a/hw/xfree86/xwayland/xwayland-window.c +++ b/hw/xfree86/xwayland/xwayland-window.c @@ -41,6 +41,13 @@ #include xserver-client-protocol.h static DevPrivateKeyRec xwl_window_private_key; +static DevPrivateKeyRec xwl_pixmap_private_key; + +struct xwl_window * +get_xwl_window(WindowPtr window) +{ +return dixLookupPrivate(window-devPrivates, xwl_window_private_key); +} static void free_pixmap(void *data, struct wl_callback *callback, uint32_t time) @@ -56,25 +63,38 @@ static const struct wl_callback_listener free_pixmap_listener = { free_pixmap, }; +void +xwl_pixmap_attach_buffer(PixmapPtr pixmap, struct wl_buffer *buffer) +{ +struct xwl_pixmap *xwl_pixmap = calloc(sizeof *xwl_pixmap, 1); +if (!xwl_pixmap) { + wl_buffer_destroy(buffer); + return; +} +xwl_pixmap-buffer = buffer; +dixSetPrivate(pixmap-devPrivates, xwl_pixmap_private_key, xwl_pixmap); +} + static void xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap) { struct xwl_screen *xwl_screen = xwl_window-xwl_screen; struct wl_callback *callback; +struct xwl_pixmap *xwl_pixmap = + dixLookupPrivate(pixmap-devPrivates, xwl_pixmap_private_key); -/* We can safely destroy the buffer because we only use one buffer - * per surface in xwayland model */ -if (xwl_window-buffer) -wl_buffer_destroy(xwl_window-buffer); - -xwl_screen-driver-create_window_buffer(xwl_window, pixmap); +if (!xwl_pixmap) { + xwl_screen-driver-create_window_buffer(xwl_window, pixmap); + xwl_pixmap = + dixLookupPrivate(pixmap-devPrivates, xwl_pixmap_private_key); -if (!xwl_window-buffer) { -ErrorF(failed to create buffer\n); - return; + if (!xwl_pixmap) { + ErrorF(failed to create buffer\n); + return; +
[PATCH 3/4 v2] Add function to get new fd of the graphic device
neccessary for dri3 Signed-off-by: Axel Davy axel.d...@ens.fr --- v2: fix indentation hw/xfree86/xwayland/xwayland-drm.c | 56 -- hw/xfree86/xwayland/xwayland.h | 3 ++ 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c index 076fb68..12011bf 100644 --- a/hw/xfree86/xwayland/xwayland-drm.c +++ b/hw/xfree86/xwayland/xwayland-drm.c @@ -157,49 +157,63 @@ is_fd_render_node(int fd) } int -xwl_drm_pre_init(struct xwl_screen *xwl_screen) +xwl_device_get_fd(struct xwl_screen *xwl_screen) { uint32_t magic; +int fd; -xwl_screen-drm_registry = wl_display_get_registry(xwl_screen-display); -wl_registry_add_listener(xwl_screen-drm_registry, drm_listener, -xwl_screen); - -/* Ensure drm_handler has seen all the interfaces */ -wl_display_roundtrip(xwl_screen-display); -/* Ensure the xwl_drm_listener has seen the drm device, if any */ -wl_display_roundtrip(xwl_screen-display); - -ErrorF(wayland_drm_screen_init, device name %s\n, - xwl_screen-device_name); - -xwl_screen-drm_fd = open(xwl_screen-device_name, O_RDWR); -if (xwl_screen-drm_fd 0) { +fd = open(xwl_screen-device_name, O_RDWR); +if (fd 0) { ErrorF(failed to open the drm fd\n); - return BadAccess; + return -1; } -if (!is_fd_render_node(xwl_screen-drm_fd)) { +if (!is_fd_render_node(fd)) { - if (drmGetMagic(xwl_screen-drm_fd, magic)) { + if (drmGetMagic(fd, magic)) { ErrorF(failed to get drm magic); - return BadAccess; + close (fd); + return -1; } wl_drm_authenticate(xwl_screen-drm, magic); wl_display_roundtrip(xwl_screen-display); - ErrorF(opened drm fd: %d\n, xwl_screen-drm_fd); + ErrorF(opened drm fd: %d\n, fd); if (!xwl_screen-authenticated) { ErrorF(Failed to auth drm fd\n); - return BadAccess; + close (fd); + return -1; } } else { xwl_screen-authenticated = 1; } +return fd; +} + +int +xwl_drm_pre_init(struct xwl_screen *xwl_screen) +{ +xwl_screen-drm_registry = wl_display_get_registry(xwl_screen-display); +wl_registry_add_listener(xwl_screen-drm_registry, drm_listener, + xwl_screen); + +/* Ensure drm_handler has seen all the interfaces */ +wl_display_roundtrip(xwl_screen-display); +/* Ensure the xwl_drm_listener has seen the drm device, if any */ +wl_display_roundtrip(xwl_screen-display); + +ErrorF(wayland_drm_screen_init, device name %s\n, + xwl_screen-device_name); + +xwl_screen-drm_fd = xwl_device_get_fd(xwl_screen); +if (xwl_screen-drm_fd 0) { + return BadAccess; +} + return Success; } diff --git a/hw/xfree86/xwayland/xwayland.h b/hw/xfree86/xwayland/xwayland.h index 8e484a1..c380618 100644 --- a/hw/xfree86/xwayland/xwayland.h +++ b/hw/xfree86/xwayland/xwayland.h @@ -76,6 +76,9 @@ xwl_drm_authenticate(ClientPtr client, struct xwl_screen *xwl_screen, uint32_t magic); extern _X_EXPORT int +xwl_device_get_fd(struct xwl_screen *xwl_screen); + +extern _X_EXPORT int xwl_create_window_buffer_drm(struct xwl_window *xwl_window, PixmapPtr pixmap, uint32_t name); -- 1.8.3.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH wayland] protocol: Clarify semantics of sub-surface placement requests
Clarify some semantics of wl_subsurface.place_below and wl_subsurface.place_below that were not specified. Signed-off-by: Jonas Ådahl jad...@gmail.com --- Hi, Implementing support for sub-surfaces in mutter we ran in to some unspecified behaviour in the subsurface placement protocol. I have documented what I understand is how the implementation in weston works (please correct me if I'm wrong). Is this the intended semantics? Jonas protocol/wayland.xml | 6 ++ 1 file changed, 6 insertions(+) diff --git a/protocol/wayland.xml b/protocol/wayland.xml index 61fde84..619567c 100644 --- a/protocol/wayland.xml +++ b/protocol/wayland.xml @@ -1952,6 +1952,12 @@ A new sub-surface is initially added as the top-most in the stack of its siblings and parent. + + Between two sub-surface parent commits, the stacking of surfaces in a + sub-surface tree are executed as operations in the same order as the + requests were made. A placement request may alter two surfaces relative + placement by placing itself in-between. A subsequent placement request + to a sub-surface replaces any previous requests. /description arg name=sibling type=object interface=wl_surface -- 1.8.3.2 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 2/2] gl-renderer: Use eglSwapBuffersWithDamageEXT when available
Signed-off-by: Jason Ekstrand ja...@jlekstrand.net --- The second version properly sets the EGL_SWAP_BEHAVIOR surface attribute to EGL_BUFFER_PRESERVED. src/gl-renderer.c | 104 +- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/src/gl-renderer.c b/src/gl-renderer.c index c8dfa4b..eddf481 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -124,6 +124,8 @@ struct gl_renderer { PFNEGLCREATEIMAGEKHRPROC create_image; PFNEGLDESTROYIMAGEKHRPROC destroy_image; + PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage; + int has_unpack_subimage; PFNEGLBINDWAYLANDDISPLAYWL bind_display; @@ -677,6 +679,17 @@ draw_output_border_texture(struct gl_output_state *go, glDisableVertexAttribArray(0); } +static int +output_has_borders(struct weston_output *output) +{ + struct gl_output_state *go = get_output_state(output); + + return go-borders[GL_RENDERER_BORDER_TOP].data || + go-borders[GL_RENDERER_BORDER_RIGHT].data || + go-borders[GL_RENDERER_BORDER_BOTTOM].data || + go-borders[GL_RENDERER_BORDER_LEFT].data; +} + static void draw_output_borders(struct weston_output *output, enum gl_border_status border_status) @@ -732,6 +745,43 @@ draw_output_borders(struct weston_output *output, } static void +output_get_border_damage(struct weston_output *output, +enum gl_border_status border_status, +pixman_region32_t *damage) +{ + struct gl_output_state *go = get_output_state(output); + struct gl_border_image *top, *bottom, *left, *right; + int full_width, full_height; + + if (border_status == BORDER_STATUS_CLEAN) + return; /* Clean. Nothing to do. */ + + top = go-borders[GL_RENDERER_BORDER_TOP]; + bottom = go-borders[GL_RENDERER_BORDER_BOTTOM]; + left = go-borders[GL_RENDERER_BORDER_LEFT]; + right = go-borders[GL_RENDERER_BORDER_RIGHT]; + + full_width = output-current_mode-width + left-width + right-width; + full_height = output-current_mode-height + top-height + bottom-height; + if (border_status BORDER_TOP_DIRTY) + pixman_region32_union_rect(damage, damage, + 0, 0, + full_width, top-height); + if (border_status BORDER_LEFT_DIRTY) + pixman_region32_union_rect(damage, damage, + 0, top-height, + left-width, output-current_mode-height); + if (border_status BORDER_RIGHT_DIRTY) + pixman_region32_union_rect(damage, damage, + full_width - right-width, top-height, + right-width, output-current_mode-height); + if (border_status BORDER_BOTTOM_DIRTY) + pixman_region32_union_rect(damage, damage, + 0, full_height - bottom-height, + full_width, bottom-height); +} + +static void output_get_damage(struct weston_output *output, pixman_region32_t *buffer_damage, uint32_t *border_damage) { @@ -802,6 +852,9 @@ gl_renderer_repaint_output(struct weston_output *output, struct gl_renderer *gr = get_renderer(compositor); EGLBoolean ret; static int errored; + int i, nrects, buffer_height; + EGLint *egl_damage, *d; + pixman_box32_t *rects; pixman_region32_t buffer_damage, total_damage; enum gl_border_status border_damage = BORDER_STATUS_CLEAN; @@ -847,7 +900,44 @@ gl_renderer_repaint_output(struct weston_output *output, pixman_region32_copy(output-previous_damage, output_damage); wl_signal_emit(output-frame_signal, output); - ret = eglSwapBuffers(gr-egl_display, go-egl_surface); + if (gr-swap_buffers_with_damage gr-has_egl_buffer_age) { + pixman_region32_init(buffer_damage); + weston_transformed_region(output-width, output-height, + output-transform, + output-current_scale, + output_damage, buffer_damage); + + if (output_has_borders(output)) { + pixman_region32_translate(buffer_damage, + go-borders[GL_RENDERER_BORDER_LEFT].width, + go-borders[GL_RENDERER_BORDER_TOP].height); + output_get_border_damage(output, go-border_status, +buffer_damage); + } + + rects = pixman_region32_rectangles(buffer_damage, nrects); + egl_damage =
Re: [PATCH 2/2] gl-renderer: Use eglSwapBuffersWithDamageEXT when available
Never mind, the first one was correct. I misunderstood buffer age. --Jason On Jan 16, 2014 10:52 PM, Jason Ekstrand ja...@jlekstrand.net wrote: Signed-off-by: Jason Ekstrand ja...@jlekstrand.net --- The second version properly sets the EGL_SWAP_BEHAVIOR surface attribute to EGL_BUFFER_PRESERVED. src/gl-renderer.c | 104 +- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/src/gl-renderer.c b/src/gl-renderer.c index c8dfa4b..eddf481 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -124,6 +124,8 @@ struct gl_renderer { PFNEGLCREATEIMAGEKHRPROC create_image; PFNEGLDESTROYIMAGEKHRPROC destroy_image; + PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage; + int has_unpack_subimage; PFNEGLBINDWAYLANDDISPLAYWL bind_display; @@ -677,6 +679,17 @@ draw_output_border_texture(struct gl_output_state *go, glDisableVertexAttribArray(0); } +static int +output_has_borders(struct weston_output *output) +{ + struct gl_output_state *go = get_output_state(output); + + return go-borders[GL_RENDERER_BORDER_TOP].data || + go-borders[GL_RENDERER_BORDER_RIGHT].data || + go-borders[GL_RENDERER_BORDER_BOTTOM].data || + go-borders[GL_RENDERER_BORDER_LEFT].data; +} + static void draw_output_borders(struct weston_output *output, enum gl_border_status border_status) @@ -732,6 +745,43 @@ draw_output_borders(struct weston_output *output, } static void +output_get_border_damage(struct weston_output *output, +enum gl_border_status border_status, +pixman_region32_t *damage) +{ + struct gl_output_state *go = get_output_state(output); + struct gl_border_image *top, *bottom, *left, *right; + int full_width, full_height; + + if (border_status == BORDER_STATUS_CLEAN) + return; /* Clean. Nothing to do. */ + + top = go-borders[GL_RENDERER_BORDER_TOP]; + bottom = go-borders[GL_RENDERER_BORDER_BOTTOM]; + left = go-borders[GL_RENDERER_BORDER_LEFT]; + right = go-borders[GL_RENDERER_BORDER_RIGHT]; + + full_width = output-current_mode-width + left-width + right-width; + full_height = output-current_mode-height + top-height + bottom-height; + if (border_status BORDER_TOP_DIRTY) + pixman_region32_union_rect(damage, damage, + 0, 0, + full_width, top-height); + if (border_status BORDER_LEFT_DIRTY) + pixman_region32_union_rect(damage, damage, + 0, top-height, + left-width, output-current_mode-height); + if (border_status BORDER_RIGHT_DIRTY) + pixman_region32_union_rect(damage, damage, + full_width - right-width, top-height, + right-width, output-current_mode-height); + if (border_status BORDER_BOTTOM_DIRTY) + pixman_region32_union_rect(damage, damage, + 0, full_height - bottom-height, + full_width, bottom-height); +} + +static void output_get_damage(struct weston_output *output, pixman_region32_t *buffer_damage, uint32_t *border_damage) { @@ -802,6 +852,9 @@ gl_renderer_repaint_output(struct weston_output *output, struct gl_renderer *gr = get_renderer(compositor); EGLBoolean ret; static int errored; + int i, nrects, buffer_height; + EGLint *egl_damage, *d; + pixman_box32_t *rects; pixman_region32_t buffer_damage, total_damage; enum gl_border_status border_damage = BORDER_STATUS_CLEAN; @@ -847,7 +900,44 @@ gl_renderer_repaint_output(struct weston_output *output, pixman_region32_copy(output-previous_damage, output_damage); wl_signal_emit(output-frame_signal, output); - ret = eglSwapBuffers(gr-egl_display, go-egl_surface); + if (gr-swap_buffers_with_damage gr-has_egl_buffer_age) { + pixman_region32_init(buffer_damage); + weston_transformed_region(output-width, output-height, + output-transform, + output-current_scale, + output_damage, buffer_damage); + + if (output_has_borders(output)) { + pixman_region32_translate(buffer_damage, + go-borders[GL_RENDERER_BORDER_LEFT].width, + go-borders[GL_RENDERER_BORDER_TOP].height); + output_get_border_damage(output, go-border_status, +