[mutter/wip/texture-purge-on-nvidia: 46/66] wayland: Create EGLStream-backed buffers through wl_eglstream_controller



commit 2376756b8b1540d7317f97d26191bff069cba329
Author: Miguel A. Vico <mvicomoya nvidia com>
Date:   Tue Jun 27 16:37:30 2017 -0700

    wayland: Create EGLStream-backed buffers through wl_eglstream_controller
    
    One of the current limitations of EGLStreams is that there's no way to
    resize a surface consumer without re-creating the entire stream.
    
    Therefore, while resizing, clients will send wl_surface::attach requests
    so the compositor can re-create its endpoint of the stream, but no
    buffer will be available actually. If we proceed with the rest of the
    attach operation we'll be presenting an empty buffer.
    
    In order to fix this, a separate wl_eglstream_controller protocol has
    been introduced that clients can use to request a stream re-creation
    without overloading wl_surface::attach for that purpose.
    
    This change adds the required logic to create the corresponding
    wl_eglstream_controller global interface that clients can bind to.
    
    Whenever a client requests a stream to be created, we just need to
    create and realize the new EGLStream buffer. The same buffer resource
    will be given at a later time to wl_surface::attach, whenever new
    content is made available by the application, so we can proceed to
    acquire the stream buffer and update the surface state.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=782575
    
    (cherry picked from commit 435b3c4bdb62edcbb4b400223ddf7e44613efa54)

 configure.ac                          | 12 +++++
 src/Makefile.am                       |  8 +++
 src/wayland/meta-wayland-egl-stream.c | 98 +++++++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-egl-stream.h |  2 +
 src/wayland/meta-wayland.c            |  4 ++
 5 files changed, 124 insertions(+)
---
diff --git a/configure.ac b/configure.ac
index 9adb14b5b..2aa9c4352 100644
--- a/configure.ac
+++ b/configure.ac
@@ -290,13 +290,24 @@ AS_IF([test "$have_native_backend" = "yes"], [
 ])
 AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"])
 
+MUTTER_WAYLAND_EGLSTREAM_MODULES="wayland-eglstream-protocols"
+
 AC_ARG_ENABLE(egl-device,
   AS_HELP_STRING([--enable-egl-device], [enable support for EGLDevice on top of KMS]),,
   enable_egl_device=no
+  have_wayland_eglstream=no
 )
 AS_IF([test "$enable_egl_device" = "yes"], [
   AC_DEFINE([HAVE_EGL_DEVICE],[1], [Defined if EGLDevice support is enabled])
+  PKG_CHECK_EXISTS([$MUTTER_WAYLAND_EGLSTREAM_MODULES], [have_wayland_eglstream=yes], 
[have_wayland_eglstream=no])
+])
+AS_IF([test "$have_wayland_eglstream" = "yes"], [
+  AC_DEFINE([HAVE_WAYLAND_EGLSTREAM],[1],[Defined if Wayland EGLStream protocols are available])
+  PKG_CHECK_MODULES(WAYLAND_EGLSTREAM, [$MUTTER_WAYLAND_EGLSTREAM_MODULES],
+                    [ac_wayland_eglstream_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir 
$MUTTER_WAYLAND_EGLSTREAM_MODULES`])
+  AC_SUBST(WAYLAND_EGLSTREAM_DATADIR, $ac_wayland_eglstream_pkgdatadir)
 ])
+AM_CONDITIONAL([HAVE_WAYLAND_EGLSTREAM],[test "$have_wayland_eglstream" = "yes"])
 
 MUTTER_WAYLAND_MODULES="wayland-server >= 1.13.0"
 
@@ -549,6 +560,7 @@ mutter-$VERSION
        Introspection:            ${found_introspection}
        Session management:       ${found_sm}
        Wayland:                  ${have_wayland}
+       Wayland EGLStream:        ${have_wayland_eglstream}
        Native (KMS) backend:     ${have_native_backend}
        EGLDevice:                ${enable_egl_device}
        Remote desktop:           ${enable_remote_desktop}
diff --git a/src/Makefile.am b/src/Makefile.am
index aaf7c9c80..bd879f203 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -91,6 +91,12 @@ mutter_built_sources += \
        gtk-text-input-protocol.c                                       \
        gtk-text-input-server-protocol.h                                \
        $(NULL)
+
+if HAVE_WAYLAND_EGLSTREAM
+mutter_built_sources += \
+       wayland-eglstream-controller-server-protocol.h \
+       $(NULL)
+endif
 endif
 
 wayland_protocols =                            \
@@ -770,3 +776,5 @@ endef
        $(AM_V_GEN)$(WAYLAND_SCANNER) code $< $@
 %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
        $(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
+%-server-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/%.xml
+       $(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
diff --git a/src/wayland/meta-wayland-egl-stream.c b/src/wayland/meta-wayland-egl-stream.c
index 39ff93433..0d7ce2304 100644
--- a/src/wayland/meta-wayland-egl-stream.c
+++ b/src/wayland/meta-wayland-egl-stream.c
@@ -32,6 +32,104 @@
 #include "backends/meta-egl-ext.h"
 #include "meta/meta-backend.h"
 #include "wayland/meta-wayland-buffer.h"
+#include "wayland/meta-wayland-private.h"
+
+#ifdef HAVE_WAYLAND_EGLSTREAM
+
+#include "wayland-eglstream-controller-server-protocol.h"
+#include <dlfcn.h>
+
+static struct wl_interface *wl_eglstream_controller_interface_ptr = NULL;
+
+static void
+attach_eglstream_consumer (struct wl_client   *client,
+                           struct wl_resource *resource,
+                           struct wl_resource *wl_surface,
+                           struct wl_resource *wl_eglstream)
+{
+  MetaWaylandBuffer *buffer = meta_wayland_buffer_from_resource (wl_eglstream);
+
+  if (!meta_wayland_buffer_is_realized (buffer))
+    meta_wayland_buffer_realize (buffer);
+}
+
+static const struct wl_eglstream_controller_interface
+meta_eglstream_controller_interface = {
+  attach_eglstream_consumer
+};
+
+static void
+bind_eglstream_controller (struct wl_client *client,
+                           void             *data,
+                           uint32_t          version,
+                           uint32_t          id)
+{
+  struct wl_resource *resource;
+
+  g_assert (wl_eglstream_controller_interface_ptr != NULL);
+
+  resource = wl_resource_create (client,
+                                 wl_eglstream_controller_interface_ptr,
+                                 version,
+                                 id);
+
+  if (resource == NULL)
+    {
+      wl_client_post_no_memory(client);
+      return;
+    }
+
+  wl_resource_set_implementation (resource,
+                                  &meta_eglstream_controller_interface,
+                                  data,
+                                  NULL);
+}
+
+#endif /* HAVE_WAYLAND_EGLSTREAM */
+
+gboolean
+meta_wayland_eglstream_controller_init (MetaWaylandCompositor *compositor)
+{
+#ifdef HAVE_WAYLAND_EGLSTREAM
+  /*
+   * wl_eglstream_controller_interface is provided by
+   * libnvidia-egl-wayland.so.1
+   *
+   * Since it might not be available on the
+   * system, dynamically load it at runtime and resolve the needed
+   * symbols. If available, it should be found under any of the search
+   * directories of dlopen()
+   *
+   * Failure to initialize wl_eglstream_controller is non-fatal
+   */
+
+  void *lib = dlopen ("libnvidia-egl-wayland.so.1", RTLD_NOW | RTLD_LAZY);
+  if (!lib)
+    goto fail;
+
+  wl_eglstream_controller_interface_ptr =
+    dlsym (lib, "wl_eglstream_controller_interface");
+
+  if (!wl_eglstream_controller_interface_ptr)
+    goto fail;
+
+  if (wl_global_create (compositor->wayland_display,
+                        wl_eglstream_controller_interface_ptr, 1,
+                        NULL,
+                        bind_eglstream_controller) == NULL)
+    goto fail;
+
+  return TRUE;
+
+fail:
+  if (lib)
+    dlclose(lib);
+
+  g_debug ("WL: Unable to initialize wl_eglstream_controller.");
+#endif
+
+  return FALSE;
+}
 
 struct _MetaWaylandEglStream
 {
diff --git a/src/wayland/meta-wayland-egl-stream.h b/src/wayland/meta-wayland-egl-stream.h
index 12a011f78..fe488ed54 100644
--- a/src/wayland/meta-wayland-egl-stream.h
+++ b/src/wayland/meta-wayland-egl-stream.h
@@ -31,6 +31,8 @@
 #include "cogl/cogl.h"
 #include "wayland/meta-wayland-types.h"
 
+gboolean meta_wayland_eglstream_controller_init (MetaWaylandCompositor *compositor);
+
 #define META_TYPE_WAYLAND_EGL_STREAM (meta_wayland_egl_stream_get_type ())
 G_DECLARE_FINAL_TYPE (MetaWaylandEglStream, meta_wayland_egl_stream,
                       META, WAYLAND_EGL_STREAM, GObject);
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index bab6b4ac4..9d416b20e 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -46,6 +46,8 @@
 #include "meta-wayland-inhibit-shortcuts.h"
 #include "meta-wayland-inhibit-shortcuts-dialog.h"
 #include "meta-xwayland-grab-keyboard.h"
+#include "meta-xwayland.h"
+#include "meta-wayland-egl-stream.h"
 
 static MetaWaylandCompositor _meta_wayland_compositor;
 static char *_display_name_override;
@@ -394,6 +396,8 @@ meta_wayland_init (void)
                                   meta_xwayland_global_filter,
                                   compositor);
 
+  meta_wayland_eglstream_controller_init (compositor);
+
   if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
     g_error ("Failed to start X Wayland");
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]