All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI
@ 2021-06-24  4:10 Vivek Kasireddy
  2021-06-24  4:10 ` [RFC v1 1/1] ui: Add a plain " Vivek Kasireddy
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Vivek Kasireddy @ 2021-06-24  4:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Dongwon Kim, Tina Zhang, Vivek Kasireddy,
	Gerd Hoffmann

Why does Qemu need a new Wayland UI backend?
The main reason why there needs to be a plain and simple Wayland backend
for Qemu UI is to eliminate the Blit (aka GPU copy) that happens if using
a toolkit like GTK or SDL (because they use EGL). The Blit can be eliminated
by sharing the dmabuf fd -- associated with the Guest scanout buffer --
directly with the Host compositor via the linux-dmabuf (unstable) protocol.
Once properly integrated, it would be potentially possible to have the
scanout buffer created by the Guest compositor be placed directly on a
hardware plane on the Host thereby improving performance. Only Guest 
compositors that use multiple back buffers (at-least 1 front and 1 back)
and virtio-gpu would benefit from this work.

The patch(es) are still WIP and the only reason why I am sending them now
is to get feedback and see if anyone thinks this work is interesting. And,
even after this work is complete, it is not meant to be merged and can be
used for performance testing purposes. Given Qemu UI's new direction, the
proper way to add new backends is to create a separate UI/display module
that is part of the dbus/pipewire infrastructure that Marc-Andre is
working on:
https://lists.nongnu.org/archive/html/qemu-devel/2021-03/msg04331.html

Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Cc: Dongwon Kim <dongwon.kim@intel.com>
Cc: Tina Zhang <tina.zhang@intel.com>

Vivek Kasireddy (1):
  ui: Add a plain Wayland backend for Qemu UI

 configure         |  17 ++
 meson.build       |  25 +++
 meson_options.txt |   2 +
 qapi/ui.json      |  19 ++-
 ui/meson.build    |  52 ++++++
 ui/wayland.c      | 402 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 516 insertions(+), 1 deletion(-)
 create mode 100644 ui/wayland.c

-- 
2.30.2



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC v1 1/1] ui: Add a plain Wayland backend for Qemu UI
  2021-06-24  4:10 [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI Vivek Kasireddy
@ 2021-06-24  4:10 ` Vivek Kasireddy
  2021-06-24  8:07   ` Philippe Mathieu-Daudé
  2021-06-24  8:31   ` Thomas Huth
  2021-06-24  4:30 ` [RFC v1 0/1] ui: Add a " no-reply
  2021-06-24  8:28 ` Gerd Hoffmann
  2 siblings, 2 replies; 7+ messages in thread
From: Vivek Kasireddy @ 2021-06-24  4:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vivek Kasireddy, Gerd Hoffmann

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
 configure         |  17 ++
 meson.build       |  25 +++
 meson_options.txt |   2 +
 qapi/ui.json      |  19 ++-
 ui/meson.build    |  52 ++++++
 ui/wayland.c      | 402 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 516 insertions(+), 1 deletion(-)
 create mode 100644 ui/wayland.c

diff --git a/configure b/configure
index 8dcb9965b2..f6caaa6329 100755
--- a/configure
+++ b/configure
@@ -403,6 +403,7 @@ cfi_debug="false"
 seccomp="auto"
 glusterfs="auto"
 gtk="auto"
+wayland="auto"
 tls_priority="NORMAL"
 gnutls="$default_feature"
 nettle="$default_feature"
@@ -1372,6 +1373,10 @@ for opt do
   ;;
   --enable-gtk) gtk="enabled"
   ;;
+  --disable-wayland) wayland="disabled"
+  ;;
+  --enable-wayland) wayland="enabled"
+  ;;
   --tls-priority=*) tls_priority="$optarg"
   ;;
   --disable-gnutls) gnutls="no"
@@ -1845,6 +1850,7 @@ disabled with --disable-FEATURE, default is enabled if available
   sdl             SDL UI
   sdl-image       SDL Image support for icons
   gtk             gtk UI
+  wayland         Wayland UI
   vte             vte support for the gtk UI
   curses          curses UI
   iconv           font glyph conversion support
@@ -3616,6 +3622,11 @@ if $pkg_config gbm; then
     gbm="yes"
 fi
 
+if $pkg_config wayland-client; then
+    wayland_cflags="$($pkg_config --cflags wayland-client)"
+    wayland_libs="$($pkg_config --libs wayland-client)"
+fi
+
 if test "$opengl" != "no" ; then
   epoxy=no
   if $pkg_config epoxy; then
@@ -5870,6 +5881,11 @@ if test "$gbm" = "yes" ; then
     echo "GBM_CFLAGS=$gbm_cflags" >> $config_host_mak
 fi
 
+if test "$wayland" = "enabled" ; then
+    echo "CONFIG_WAYLAND=y" >> $config_host_mak
+    echo "WAYLAND_LIBS=$wayland_libs" >> $config_host_mak
+    echo "WAYLAND_CFLAGS=$wayland_cflags" >> $config_host_mak
+fi
 
 if test "$avx2_opt" = "yes" ; then
   echo "CONFIG_AVX2_OPT=y" >> $config_host_mak
@@ -6436,6 +6452,7 @@ if test "$skip_meson" = no; then
         -Dkvm=$kvm -Dhax=$hax -Dwhpx=$whpx -Dhvf=$hvf -Dnvmm=$nvmm \
         -Dxen=$xen -Dxen_pci_passthrough=$xen_pci_passthrough -Dtcg=$tcg \
         -Dcocoa=$cocoa -Dgtk=$gtk -Dmpath=$mpath -Dsdl=$sdl -Dsdl_image=$sdl_image \
+        -Dwayland=$wayland \
         -Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \
         -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f -Dvirtiofsd=$virtiofsd \
         -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt -Dbrlapi=$brlapi \
diff --git a/meson.build b/meson.build
index 626cf932c1..dbafe4a5d4 100644
--- a/meson.build
+++ b/meson.build
@@ -855,6 +855,29 @@ if gtkx11.found()
   x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
                    kwargs: static_kwargs)
 endif
+
+wayland = not_found
+if not get_option('wayland').auto()
+  wlclientdep = dependency('wayland-client', version: '>= 1.18.90',
+                           method: 'pkg-config',
+                           required: get_option('wayland'),
+                           kwargs: static_kwargs)
+  wlprotocolsdep = dependency('wayland-protocols', version: '>= 1.14.91',
+                              method: 'pkg-config',
+                              required: get_option('wayland'),
+                              kwargs: static_kwargs)
+
+  if not wlprotocolsdep.found()
+    wlproto_dir = subproject('wayland-protocols').get_variable('wayland_protocols_srcdir')
+  else
+    wlproto_dir = wlprotocolsdep.get_pkgconfig_variable('pkgdatadir')
+  endif
+
+  wayland = declare_dependency(dependencies: [wlclientdep, wlprotocolsdep],
+                               compile_args: config_host['WAYLAND_CFLAGS'].split(),
+                               link_args: config_host['WAYLAND_LIBS'].split())
+endif
+
 vnc = not_found
 png = not_found
 jpeg = not_found
@@ -1146,6 +1169,7 @@ if glusterfs.found()
   config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
 endif
 config_host_data.set('CONFIG_GTK', gtk.found())
+config_host_data.set('CONFIG_WAYLAND', wayland.found())
 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
 config_host_data.set('CONFIG_EBPF', libbpf.found())
@@ -2695,6 +2719,7 @@ summary_info += {'SDL support':       sdl.found()}
 summary_info += {'SDL image support': sdl_image.found()}
 # TODO: add back version
 summary_info += {'GTK support':       gtk.found()}
+summary_info += {'Wayland support':   wayland.found()}
 summary_info += {'pixman':            pixman.found()}
 # TODO: add back version
 summary_info += {'VTE support':       config_host.has_key('CONFIG_VTE')}
diff --git a/meson_options.txt b/meson_options.txt
index 3d304cac96..86066c63c9 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -86,6 +86,8 @@ option('rbd', type : 'feature', value : 'auto',
        description: 'Ceph block device driver')
 option('gtk', type : 'feature', value : 'auto',
        description: 'GTK+ user interface')
+option('wayland', type : 'feature', value : 'auto',
+       description: 'Wayland user interface')
 option('sdl', type : 'feature', value : 'auto',
        description: 'SDL user interface')
 option('sdl_image', type : 'feature', value : 'auto',
diff --git a/qapi/ui.json b/qapi/ui.json
index 1052ca9c38..55e5967889 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1057,6 +1057,20 @@
 { 'struct'  : 'DisplayEGLHeadless',
   'data'    : { '*rendernode' : 'str' } }
 
+##
+# @DisplayWayland:
+#
+# Wayland display options.
+#
+# @rendernode: Which DRM render node should be used. Default is the first
+#              available node on the host.
+#
+# Since: 3.1
+#
+##
+{ 'struct'  : 'DisplayWayland',
+  'data'    : { '*rendernode' : 'str' } }
+
  ##
  # @DisplayGLMode:
  #
@@ -1108,6 +1122,8 @@
 #                DRI device. Graphical display need to be paired with
 #                VNC or Spice. (Since 3.1)
 #
+# @wayland: The Wayland user interface.
+#
 # @curses: Display video output via curses.  For graphics device
 #          models which support a text mode, QEMU can display this
 #          output using a curses/ncurses interface. Nothing is
@@ -1128,7 +1144,7 @@
 { 'enum'    : 'DisplayType',
   'data'    : [ 'default', 'none', 'gtk', 'sdl',
                 'egl-headless', 'curses', 'cocoa',
-                'spice-app'] }
+                'wayland', 'spice-app'] }
 
 ##
 # @DisplayOptions:
@@ -1154,6 +1170,7 @@
   'discriminator' : 'type',
   'data'    : { 'gtk'            : 'DisplayGTK',
                 'curses'         : 'DisplayCurses',
+                'wayland'        : 'DisplayWayland',
                 'egl-headless'   : 'DisplayEGLHeadless'} }
 
 ##
diff --git a/ui/meson.build b/ui/meson.build
index a3a187d633..fe255aec04 100644
--- a/ui/meson.build
+++ b/ui/meson.build
@@ -62,6 +62,58 @@ if config_host.has_key('CONFIG_OPENGL') and gbm.found()
   ui_modules += {'egl-headless' : egl_headless_ss}
 endif
 
+wayland_scanner = find_program('wayland-scanner')
+proto_sources = [
+  ['xdg-shell', 'stable', ],
+  ['fullscreen-shell', 'unstable', 'v1', ],
+  ['linux-dmabuf', 'unstable', 'v1', ],
+]
+wayland_headers = []
+wayland_proto_sources = []
+
+if wayland.found()
+  foreach p: proto_sources
+    proto_name = p.get(0)
+    proto_stability = p.get(1)
+
+    if proto_stability == 'stable'
+      output_base = proto_name
+      input = files(join_paths(wlproto_dir, '@0@/@1@/@2@.xml'.format(proto_stability, proto_name, output_base)))
+    else
+      proto_version = p.get(2)
+      output_base = '@0@-@1@-@2@'.format(proto_name, proto_stability, proto_version)
+      input = files(join_paths(wlproto_dir, '@0@/@1@/@2@.xml'.format(proto_stability, proto_name, output_base)))
+    endif
+
+    wayland_headers += custom_target('@0@ client header'.format(output_base),
+      input: input,
+      output: '@0@-client-protocol.h'.format(output_base),
+      command: [
+        wayland_scanner,
+        'client-header',
+        '@INPUT@', '@OUTPUT@',
+      ], build_by_default: true
+    )
+
+    wayland_proto_sources += custom_target('@0@ source'.format(output_base),
+      input: input,
+      output: '@0@-protocol.c'.format(output_base),
+      command: [
+        wayland_scanner,
+        'private-code',
+        '@INPUT@', '@OUTPUT@',
+      ], build_by_default: true
+    )
+  endforeach
+endif
+
+if wayland.found()
+  wayland_ss = ss.source_set()
+  wayland_ss.add(when: wayland, if_true: files('wayland.c', 'xdg-shell-protocol.c', 'fullscreen-shell-unstable-v1-protocol.c','linux-dmabuf-unstable-v1-protocol.c'))
+  #wayland_ss.add(when: wayland, if_true: files('wayland.c'), [wayland_proto_sources])
+  ui_modules += {'wayland' : wayland_ss}
+endif
+
 if gtk.found()
   softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('win32-kbd-hook.c'))
 
diff --git a/ui/wayland.c b/ui/wayland.c
new file mode 100644
index 0000000000..351d7e1146
--- /dev/null
+++ b/ui/wayland.c
@@ -0,0 +1,402 @@
+/*
+ * Wayland UI -- A simple Qemu UI backend to share buffers with Wayland compositors
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Mostly (boilerplate) based on cgit.freedesktop.org/wayland/weston/tree/clients/simple-dmabuf-egl.c
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
+#include "ui/console.h"
+#include <wayland-client.h>
+#include "xdg-shell-client-protocol.h"
+#include "fullscreen-shell-unstable-v1-client-protocol.h"
+#include "linux-dmabuf-unstable-v1-client-protocol.h"
+
+#define MAX_BUFFERS 3
+
+typedef struct wayland_display {
+    struct wl_display *display;
+    struct wl_registry *registry;
+    struct wl_compositor *compositor;
+    struct xdg_wm_base *wm_base;
+    struct zwp_fullscreen_shell_v1 *fshell;
+    struct zwp_linux_dmabuf_v1 *dmabuf;
+} wayland_display;
+
+typedef struct wayland_buffer {
+    QemuConsole *con;
+    QemuDmaBuf *dmabuf;
+    struct wl_buffer *buffer;
+    bool busy;
+} wayland_buffer;
+
+typedef struct wayland_window {
+    wayland_display *display;
+    DisplayChangeListener dcl;
+    struct wl_surface *surface;
+    struct xdg_surface *xdg_surface;
+    struct xdg_toplevel *xdg_toplevel;
+    struct wl_callback *callback;
+    wayland_buffer buffers[MAX_BUFFERS];
+    wayland_buffer *new_buffer;
+    bool redraw;
+} wayland_window;
+
+static const struct wl_callback_listener frame_listener;
+
+static void
+xdg_surface_handle_configure(void *data, struct xdg_surface *surface,
+			     uint32_t serial)
+{
+    xdg_surface_ack_configure(surface, serial);
+}
+
+static const struct xdg_surface_listener xdg_surface_listener = {
+    xdg_surface_handle_configure,
+};
+
+static void
+xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *toplevel,
+			      int32_t width, int32_t height,
+			      struct wl_array *states)
+{
+}
+
+static void
+xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel)
+{
+}
+
+static const struct xdg_toplevel_listener xdg_toplevel_listener = {
+    xdg_toplevel_handle_configure,
+    xdg_toplevel_handle_close,
+};
+
+static void wayland_refresh(DisplayChangeListener *dcl)
+{
+    graphic_hw_update(dcl->con);
+}
+
+static QEMUGLContext wayland_create_context(DisplayChangeListener *dcl,
+                                            QEMUGLParams *params)
+{
+    return NULL;
+}
+
+static void wayland_destroy_context(DisplayChangeListener *dcl,
+                                    QEMUGLContext ctx)
+{
+}
+
+static int wayland_make_context_current(DisplayChangeListener *dcl,
+                                        QEMUGLContext ctx)
+{
+    return 0;
+}
+
+static void wayland_scanout_disable(DisplayChangeListener *dcl)
+{
+}
+
+static void wayland_scanout_texture(DisplayChangeListener *dcl,
+                                    uint32_t backing_id,
+                                    bool backing_y_0_top,
+                                    uint32_t backing_width,
+                                    uint32_t backing_height,
+                                    uint32_t x, uint32_t y,
+                                    uint32_t w, uint32_t h)
+{
+}
+
+static void wayland_release_dmabuf(DisplayChangeListener *dcl,
+                                   QemuDmaBuf *dmabuf)
+{
+}
+
+static void wayland_dispatch_handler(void *opaque)
+{
+    wayland_display *wldpy = opaque;
+
+    wl_display_prepare_read(wldpy->display);
+    wl_display_read_events(wldpy->display);
+    wl_display_dispatch_pending(wldpy->display);
+    wl_display_flush(wldpy->display);
+}
+
+static void wayland_window_redraw(void *data, struct wl_callback *callback,
+                                  uint32_t time)
+{
+    wayland_window *window = data;
+    QemuDmaBuf *dmabuf = window->new_buffer->dmabuf;
+
+    if (callback) {
+        wl_callback_destroy(callback);
+        window->callback = NULL;
+    }
+    if (!window->redraw) {
+        return;
+    }
+    window->callback = wl_surface_frame(window->surface);
+    wl_callback_add_listener(window->callback, &frame_listener, window);
+
+    wl_surface_attach(window->surface, window->new_buffer->buffer, 0, 0);
+    wl_surface_damage(window->surface, 0, 0, dmabuf->width, dmabuf->height);
+    wl_surface_commit(window->surface);
+    wl_display_flush(window->display->display);
+    window->redraw = false;
+}
+
+static const struct wl_callback_listener frame_listener = {
+    wayland_window_redraw
+};
+
+static void buffer_release(void *data, struct wl_buffer *buf)
+{
+    wayland_buffer *buffer = data;
+    QemuDmaBuf *dmabuf = buffer->dmabuf;
+
+    dmabuf->fence_fd = -1;
+    graphic_hw_gl_block(buffer->con, false);
+    graphic_hw_gl_flushed(buffer->con);
+    buffer->busy = false;
+    wl_buffer_destroy(buf);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+    buffer_release
+};
+
+static wayland_buffer *window_next_buffer(wayland_window *window)
+{
+    int i;
+
+    for (i = 0; i < MAX_BUFFERS; i++) {
+        if (!window->buffers[i].busy) {
+            return &window->buffers[i];
+        }
+    }
+    return NULL;
+}
+
+static void wayland_scanout_dmabuf(DisplayChangeListener *dcl,
+                                   QemuDmaBuf *dmabuf)
+{
+    wayland_window *window = container_of(dcl, wayland_window, dcl);
+    wayland_display *display = window->display;
+    wayland_buffer *buffer = window_next_buffer(window);
+    struct zwp_linux_buffer_params_v1 *params;
+
+    if (!buffer) {
+	error_report("Can't find free buffer\n");
+        exit(1);
+    }
+    params = zwp_linux_dmabuf_v1_create_params(display->dmabuf);
+    zwp_linux_buffer_params_v1_add(params, dmabuf->fd, 0, 0, dmabuf->stride,
+                                   0, 0);
+    buffer->buffer = zwp_linux_buffer_params_v1_create_immed(params,
+                                                             dmabuf->width,
+                                                             dmabuf->height,
+                                                             dmabuf->fourcc,
+                                                             0);
+    zwp_linux_buffer_params_v1_destroy(params);
+    buffer->dmabuf = dmabuf;
+    buffer->con = window->dcl.con;
+    window->new_buffer = buffer;
+    dmabuf->fence_fd = 1;
+    wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
+}
+
+static void wayland_scanout_flush(DisplayChangeListener *dcl,
+                                  uint32_t x, uint32_t y,
+                                  uint32_t w, uint32_t h)
+{
+    wayland_window *window = container_of(dcl, wayland_window, dcl);
+    static bool first = true;
+
+    if (!window->new_buffer->busy && !first) {
+        graphic_hw_gl_block(window->new_buffer->con, true);
+    }
+
+    window->redraw = true;
+    if (first || !window->callback) {
+        wayland_window_redraw(window, NULL, 0);
+    }
+    window->new_buffer->busy = true;
+    first = false;
+}
+
+static const DisplayChangeListenerOps wayland_ops = {
+    .dpy_name                = "wayland",
+    .dpy_refresh             = wayland_refresh,
+
+    .dpy_gl_ctx_create       = wayland_create_context,
+    .dpy_gl_ctx_destroy      = wayland_destroy_context,
+    .dpy_gl_ctx_make_current = wayland_make_context_current,
+
+    .dpy_gl_scanout_disable  = wayland_scanout_disable,
+    .dpy_gl_scanout_texture  = wayland_scanout_texture,
+    .dpy_gl_scanout_dmabuf   = wayland_scanout_dmabuf,
+    .dpy_gl_release_dmabuf   = wayland_release_dmabuf,
+    .dpy_gl_update           = wayland_scanout_flush,
+};
+
+static void early_wayland_init(DisplayOptions *opts)
+{
+    display_opengl = 1;
+}
+
+static void
+dmabuf_modifier(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
+		 uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
+{
+}
+
+static void
+dmabuf_format(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
+              uint32_t format)
+{
+}
+
+static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
+    dmabuf_format,
+    dmabuf_modifier
+};
+
+static void
+xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
+{
+    xdg_wm_base_pong(shell, serial);
+}
+
+static const struct xdg_wm_base_listener wm_base_listener = {
+    xdg_wm_base_ping,
+};
+
+static void
+registry_handle_global(void *data, struct wl_registry *registry,
+                       uint32_t id, const char *interface, uint32_t version)
+{
+    wayland_display *d = data;
+
+    if (strcmp(interface, "wl_compositor") == 0) {
+        d->compositor = wl_registry_bind(registry,
+			                 id, &wl_compositor_interface, 1);
+    } else if (strcmp(interface, "xdg_wm_base") == 0) {
+	d->wm_base = wl_registry_bind(registry,
+				      id, &xdg_wm_base_interface, 1);
+	xdg_wm_base_add_listener(d->wm_base, &wm_base_listener, d);
+    } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
+	d->fshell = wl_registry_bind(registry,
+	                             id, &zwp_fullscreen_shell_v1_interface,
+	                             1);
+    } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
+	d->dmabuf = wl_registry_bind(registry,
+	                             id, &zwp_linux_dmabuf_v1_interface, 3);
+	zwp_linux_dmabuf_v1_add_listener(d->dmabuf, &dmabuf_listener,
+	                                 d);
+    }
+}
+
+static void
+registry_handle_global_remove(void *data, struct wl_registry *registry,
+                              uint32_t name)
+{
+}
+
+static const struct wl_registry_listener registry_listener = {
+    registry_handle_global,
+    registry_handle_global_remove
+};
+
+static wayland_display *create_display(void)
+{
+    wayland_display *display;
+
+    display = g_new0(wayland_display, 1);
+    display->display = wl_display_connect(NULL);
+    assert(display->display);
+
+    display->registry = wl_display_get_registry(display->display);
+    wl_registry_add_listener(display->registry,
+                             &registry_listener, display);
+    wl_display_roundtrip(display->display);
+    if (display->dmabuf == NULL) {
+	error_report("No zwp_linux_dmabuf global\n");
+	exit(1);
+    }
+    return display;
+}
+
+static wayland_window *create_window(wayland_display *display)
+{
+    wayland_window *window;
+
+    window = g_new0(wayland_window, 1);
+    window->display = display;
+    window->surface = wl_compositor_create_surface(display->compositor);
+
+    if (display->wm_base) {
+        window->xdg_surface = xdg_wm_base_get_xdg_surface(display->wm_base,
+	                                                  window->surface);
+        assert(window->xdg_surface);
+        xdg_surface_add_listener(window->xdg_surface,
+                                 &xdg_surface_listener, window);
+        window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
+        assert(window->xdg_toplevel);
+        xdg_toplevel_add_listener(window->xdg_toplevel,
+                                  &xdg_toplevel_listener, window);
+        xdg_toplevel_set_title(window->xdg_toplevel, "qemu-wayland");
+        wl_surface_commit(window->surface);
+    } else if (display->fshell) {
+        zwp_fullscreen_shell_v1_present_surface(display->fshell,
+	                                        window->surface,
+		                                ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT,
+		                                NULL);
+    } else {
+         assert(0);
+    }
+
+    return window;
+}
+
+static void wayland_init(DisplayState *ds, DisplayOptions *opts)
+{
+    QemuConsole *con;
+    wayland_display *wldpy;
+    wayland_window *wlwdw;
+    int idx;
+
+    wldpy = create_display();
+    for (idx = 0;; idx++) {
+        con = qemu_console_lookup_by_index(idx);
+        if (!con || !qemu_console_is_graphic(con)) {
+            break;
+        }
+
+        wlwdw = create_window(wldpy);
+        wlwdw->dcl.con = con;
+        wlwdw->dcl.ops = &wayland_ops;
+        register_displaychangelistener(&wlwdw->dcl);
+    }
+    wl_display_roundtrip(wldpy->display);
+    qemu_set_fd_handler(wl_display_get_fd(wldpy->display),
+                        wayland_dispatch_handler, NULL, wldpy);
+}
+
+static QemuDisplay qemu_display_wayland = {
+    .type       = DISPLAY_TYPE_WAYLAND,
+    .early_init = early_wayland_init,
+    .init       = wayland_init,
+};
+
+static void register_wayland(void)
+{
+    qemu_display_register(&qemu_display_wayland);
+}
+
+type_init(register_wayland);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI
  2021-06-24  4:10 [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI Vivek Kasireddy
  2021-06-24  4:10 ` [RFC v1 1/1] ui: Add a plain " Vivek Kasireddy
@ 2021-06-24  4:30 ` no-reply
  2021-06-24  8:28 ` Gerd Hoffmann
  2 siblings, 0 replies; 7+ messages in thread
From: no-reply @ 2021-06-24  4:30 UTC (permalink / raw)
  To: vivek.kasireddy
  Cc: dongwon.kim, qemu-devel, vivek.kasireddy, tina.zhang, kraxel,
	marcandre.lureau

Patchew URL: https://patchew.org/QEMU/20210624041040.1250631-1-vivek.kasireddy@intel.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210624041040.1250631-1-vivek.kasireddy@intel.com
Subject: [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/20210624041040.1250631-1-vivek.kasireddy@intel.com -> patchew/20210624041040.1250631-1-vivek.kasireddy@intel.com
Switched to a new branch 'test'
547ce45 ui: Add a plain Wayland backend for Qemu UI

=== OUTPUT BEGIN ===
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#260: 
new file mode 100644

WARNING: line over 80 characters
#266: FILE: ui/wayland.c:2:
+ * Wayland UI -- A simple Qemu UI backend to share buffers with Wayland compositors

ERROR: use QEMU instead of Qemu or QEmu
#266: FILE: ui/wayland.c:2:
+ * Wayland UI -- A simple Qemu UI backend to share buffers with Wayland compositors

ERROR: line over 90 characters
#271: FILE: ui/wayland.c:7:
+ * Mostly (boilerplate) based on cgit.freedesktop.org/wayland/weston/tree/clients/simple-dmabuf-egl.c

ERROR: code indent should never use tabs
#318: FILE: ui/wayland.c:54:
+^I^I^I     uint32_t serial)$

ERROR: code indent should never use tabs
#329: FILE: ui/wayland.c:65:
+^I^I^I      int32_t width, int32_t height,$

ERROR: code indent should never use tabs
#330: FILE: ui/wayland.c:66:
+^I^I^I      struct wl_array *states)$

ERROR: code indent should never use tabs
#459: FILE: ui/wayland.c:195:
+^Ierror_report("Can't find free buffer\n");$

ERROR: Error messages should not contain newlines
#459: FILE: ui/wayland.c:195:
+       error_report("Can't find free buffer\n");

ERROR: code indent should never use tabs
#519: FILE: ui/wayland.c:255:
+^I^I uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)$

ERROR: code indent should never use tabs
#552: FILE: ui/wayland.c:288:
+^I^I^I                 id, &wl_compositor_interface, 1);$

ERROR: code indent should never use tabs
#554: FILE: ui/wayland.c:290:
+^Id->wm_base = wl_registry_bind(registry,$

ERROR: code indent should never use tabs
#555: FILE: ui/wayland.c:291:
+^I^I^I^I      id, &xdg_wm_base_interface, 1);$

ERROR: code indent should never use tabs
#556: FILE: ui/wayland.c:292:
+^Ixdg_wm_base_add_listener(d->wm_base, &wm_base_listener, d);$

ERROR: code indent should never use tabs
#558: FILE: ui/wayland.c:294:
+^Id->fshell = wl_registry_bind(registry,$

ERROR: code indent should never use tabs
#559: FILE: ui/wayland.c:295:
+^I                             id, &zwp_fullscreen_shell_v1_interface,$

ERROR: code indent should never use tabs
#560: FILE: ui/wayland.c:296:
+^I                             1);$

ERROR: code indent should never use tabs
#562: FILE: ui/wayland.c:298:
+^Id->dmabuf = wl_registry_bind(registry,$

ERROR: code indent should never use tabs
#563: FILE: ui/wayland.c:299:
+^I                             id, &zwp_linux_dmabuf_v1_interface, 3);$

ERROR: code indent should never use tabs
#564: FILE: ui/wayland.c:300:
+^Izwp_linux_dmabuf_v1_add_listener(d->dmabuf, &dmabuf_listener,$

ERROR: code indent should never use tabs
#565: FILE: ui/wayland.c:301:
+^I                                 d);$

ERROR: code indent should never use tabs
#593: FILE: ui/wayland.c:329:
+^Ierror_report("No zwp_linux_dmabuf global\n");$

ERROR: Error messages should not contain newlines
#593: FILE: ui/wayland.c:329:
+       error_report("No zwp_linux_dmabuf global\n");

ERROR: code indent should never use tabs
#594: FILE: ui/wayland.c:330:
+^Iexit(1);$

ERROR: code indent should never use tabs
#609: FILE: ui/wayland.c:345:
+^I                                                  window->surface);$

ERROR: code indent should never use tabs
#621: FILE: ui/wayland.c:357:
+^I                                        window->surface,$

ERROR: line over 90 characters
#622: FILE: ui/wayland.c:358:
+                                               ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT,

ERROR: code indent should never use tabs
#622: FILE: ui/wayland.c:358:
+^I^I                                ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT,$

ERROR: code indent should never use tabs
#623: FILE: ui/wayland.c:359:
+^I^I                                NULL);$

total: 27 errors, 2 warnings, 607 lines checked

Commit 547ce45b800d (ui: Add a plain Wayland backend for Qemu UI) has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210624041040.1250631-1-vivek.kasireddy@intel.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC v1 1/1] ui: Add a plain Wayland backend for Qemu UI
  2021-06-24  4:10 ` [RFC v1 1/1] ui: Add a plain " Vivek Kasireddy
@ 2021-06-24  8:07   ` Philippe Mathieu-Daudé
  2021-06-24  8:31   ` Thomas Huth
  1 sibling, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-06-24  8:07 UTC (permalink / raw)
  To: Vivek Kasireddy, qemu-devel; +Cc: Gerd Hoffmann

On 6/24/21 6:10 AM, Vivek Kasireddy wrote:
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
>  configure         |  17 ++
>  meson.build       |  25 +++
>  meson_options.txt |   2 +
>  qapi/ui.json      |  19 ++-
>  ui/meson.build    |  52 ++++++
>  ui/wayland.c      | 402 ++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 516 insertions(+), 1 deletion(-)
>  create mode 100644 ui/wayland.c

> diff --git a/qapi/ui.json b/qapi/ui.json
> index 1052ca9c38..55e5967889 100644
> --- a/qapi/ui.json
> +++ b/qapi/ui.json
> @@ -1057,6 +1057,20 @@
>  { 'struct'  : 'DisplayEGLHeadless',
>    'data'    : { '*rendernode' : 'str' } }
>  
> +##
> +# @DisplayWayland:
> +#
> +# Wayland display options.
> +#
> +# @rendernode: Which DRM render node should be used. Default is the first
> +#              available node on the host.
> +#
> +# Since: 3.1

Likely 6.1 :)

(no need to respin for this single comment).



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI
  2021-06-24  4:10 [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI Vivek Kasireddy
  2021-06-24  4:10 ` [RFC v1 1/1] ui: Add a plain " Vivek Kasireddy
  2021-06-24  4:30 ` [RFC v1 0/1] ui: Add a " no-reply
@ 2021-06-24  8:28 ` Gerd Hoffmann
  2021-06-24 18:17   ` Kasireddy, Vivek
  2 siblings, 1 reply; 7+ messages in thread
From: Gerd Hoffmann @ 2021-06-24  8:28 UTC (permalink / raw)
  To: Vivek Kasireddy
  Cc: Marc-André Lureau, Tina Zhang, qemu-devel, Dongwon Kim

On Wed, Jun 23, 2021 at 09:10:39PM -0700, Vivek Kasireddy wrote:
> Why does Qemu need a new Wayland UI backend?
> The main reason why there needs to be a plain and simple Wayland backend
> for Qemu UI is to eliminate the Blit (aka GPU copy) that happens if using
> a toolkit like GTK or SDL (because they use EGL). The Blit can be eliminated
> by sharing the dmabuf fd -- associated with the Guest scanout buffer --
> directly with the Host compositor via the linux-dmabuf (unstable) protocol.

Hmm, that probably means no window decorations (and other UI elements),
right?  Also the code seems to not (yet?) handle mouse and kbd input.

> The patch(es) are still WIP and the only reason why I am sending them now
> is to get feedback and see if anyone thinks this work is interesting. And,
> even after this work is complete, it is not meant to be merged and can be
> used for performance testing purposes. Given Qemu UI's new direction, the
> proper way to add new backends is to create a separate UI/display module
> that is part of the dbus/pipewire infrastructure that Marc-Andre is
> working on:
> https://lists.nongnu.org/archive/html/qemu-devel/2021-03/msg04331.html

Separating emulation and UI has the big advantage that the guest
lifecycle is decoupled from the desktop session lifecycle, i.e.
the guest can continue to run when the desktop session ends.

Works today with spice (when using unix socket to connect it can pass
dma-buf handles from qemu to spice client).

Using dbus instead certainly makes sense.  Whenever we'll just go send
dma-buf handles over dbus or integrate with pipewire for display/sound
not clear yet.  Marc-André thinks using pipewire doesn't bring benefits
and I havn't found the time yet to learn more about pipewire ...

take care,
  Gerd



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC v1 1/1] ui: Add a plain Wayland backend for Qemu UI
  2021-06-24  4:10 ` [RFC v1 1/1] ui: Add a plain " Vivek Kasireddy
  2021-06-24  8:07   ` Philippe Mathieu-Daudé
@ 2021-06-24  8:31   ` Thomas Huth
  1 sibling, 0 replies; 7+ messages in thread
From: Thomas Huth @ 2021-06-24  8:31 UTC (permalink / raw)
  To: Vivek Kasireddy, qemu-devel; +Cc: Paolo Bonzini, Gerd Hoffmann

On 24/06/2021 06.10, Vivek Kasireddy wrote:
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
> ---
>   configure         |  17 ++
>   meson.build       |  25 +++
>   meson_options.txt |   2 +
>   qapi/ui.json      |  19 ++-
>   ui/meson.build    |  52 ++++++
>   ui/wayland.c      | 402 ++++++++++++++++++++++++++++++++++++++++++++++
>   6 files changed, 516 insertions(+), 1 deletion(-)
>   create mode 100644 ui/wayland.c
> 
> diff --git a/configure b/configure
> index 8dcb9965b2..f6caaa6329 100755
> --- a/configure
> +++ b/configure
> @@ -403,6 +403,7 @@ cfi_debug="false"
>   seccomp="auto"
>   glusterfs="auto"
>   gtk="auto"
> +wayland="auto"
>   tls_priority="NORMAL"
>   gnutls="$default_feature"
>   nettle="$default_feature"
> @@ -1372,6 +1373,10 @@ for opt do
>     ;;
>     --enable-gtk) gtk="enabled"
>     ;;
> +  --disable-wayland) wayland="disabled"
> +  ;;
> +  --enable-wayland) wayland="enabled"
> +  ;;
>     --tls-priority=*) tls_priority="$optarg"
>     ;;
>     --disable-gnutls) gnutls="no"
> @@ -1845,6 +1850,7 @@ disabled with --disable-FEATURE, default is enabled if available
>     sdl             SDL UI
>     sdl-image       SDL Image support for icons
>     gtk             gtk UI
> +  wayland         Wayland UI
>     vte             vte support for the gtk UI
>     curses          curses UI
>     iconv           font glyph conversion support
> @@ -3616,6 +3622,11 @@ if $pkg_config gbm; then
>       gbm="yes"
>   fi
>   
> +if $pkg_config wayland-client; then
> +    wayland_cflags="$($pkg_config --cflags wayland-client)"
> +    wayland_libs="$($pkg_config --libs wayland-client)"
> +fi
> +
>   if test "$opengl" != "no" ; then
>     epoxy=no
>     if $pkg_config epoxy; then
> @@ -5870,6 +5881,11 @@ if test "$gbm" = "yes" ; then
>       echo "GBM_CFLAGS=$gbm_cflags" >> $config_host_mak
>   fi
>   
> +if test "$wayland" = "enabled" ; then
> +    echo "CONFIG_WAYLAND=y" >> $config_host_mak
> +    echo "WAYLAND_LIBS=$wayland_libs" >> $config_host_mak
> +    echo "WAYLAND_CFLAGS=$wayland_cflags" >> $config_host_mak
> +fi

I think you don't really need the above two hunks in the configure script - 
this could be handled in the meson.build file instead. See e.g. commit 
1b6954713fee4945207 where the gtk detection has been moved from configure to 
Meson.

  Thomas



^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI
  2021-06-24  8:28 ` Gerd Hoffmann
@ 2021-06-24 18:17   ` Kasireddy, Vivek
  0 siblings, 0 replies; 7+ messages in thread
From: Kasireddy, Vivek @ 2021-06-24 18:17 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: Marc-André Lureau, Zhang, Tina, qemu-devel, Kim, Dongwon

Hi Gerd,

> > Why does Qemu need a new Wayland UI backend?
> > The main reason why there needs to be a plain and simple Wayland backend
> > for Qemu UI is to eliminate the Blit (aka GPU copy) that happens if using
> > a toolkit like GTK or SDL (because they use EGL). The Blit can be eliminated
> > by sharing the dmabuf fd -- associated with the Guest scanout buffer --
> > directly with the Host compositor via the linux-dmabuf (unstable) protocol.
> 
> Hmm, that probably means no window decorations (and other UI elements),
[Kasireddy, Vivek] Right, unfortunately, no decorations or other UI elements. For
that we can use GTK. 
> right?  Also the code seems to not (yet?) handle mouse and kbd input.
[Kasireddy, Vivek] Yes, kbd and mouse support not added yet and that is why I
tagged it as WIP. But it should not be too hard to add that.

> 
> > The patch(es) are still WIP and the only reason why I am sending them now
> > is to get feedback and see if anyone thinks this work is interesting. And,
> > even after this work is complete, it is not meant to be merged and can be
> > used for performance testing purposes. Given Qemu UI's new direction, the
> > proper way to add new backends is to create a separate UI/display module
> > that is part of the dbus/pipewire infrastructure that Marc-Andre is
> > working on:
> > https://lists.nongnu.org/archive/html/qemu-devel/2021-03/msg04331.html
> 
> Separating emulation and UI has the big advantage that the guest
> lifecycle is decoupled from the desktop session lifecycle, i.e.
> the guest can continue to run when the desktop session ends.
> 
> Works today with spice (when using unix socket to connect it can pass
> dma-buf handles from qemu to spice client).
> 
> Using dbus instead certainly makes sense.  Whenever we'll just go send
> dma-buf handles over dbus or integrate with pipewire for display/sound
> not clear yet.  Marc-André thinks using pipewire doesn't bring benefits
> and I havn't found the time yet to learn more about pipewire ...
[Kasireddy, Vivek] On our side, we'll also try to learn how dbus and pipewire
fit in and work. Having said that, can Marc-Andre's work be merged in 
stages -- first only dbus and no pipewire?

Thanks,
Vivek
> 
> take care,
>   Gerd



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-06-24 18:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-24  4:10 [RFC v1 0/1] ui: Add a Wayland backend for Qemu UI Vivek Kasireddy
2021-06-24  4:10 ` [RFC v1 1/1] ui: Add a plain " Vivek Kasireddy
2021-06-24  8:07   ` Philippe Mathieu-Daudé
2021-06-24  8:31   ` Thomas Huth
2021-06-24  4:30 ` [RFC v1 0/1] ui: Add a " no-reply
2021-06-24  8:28 ` Gerd Hoffmann
2021-06-24 18:17   ` Kasireddy, Vivek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.