diff options
Diffstat (limited to '0007-compositor-Process-stream-attach-requests-with-wl_eg.patch')
-rw-r--r-- | 0007-compositor-Process-stream-attach-requests-with-wl_eg.patch | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/0007-compositor-Process-stream-attach-requests-with-wl_eg.patch b/0007-compositor-Process-stream-attach-requests-with-wl_eg.patch new file mode 100644 index 000000000000..247fd1c11607 --- /dev/null +++ b/0007-compositor-Process-stream-attach-requests-with-wl_eg.patch @@ -0,0 +1,459 @@ +From 5076208fd90be98deff790f0f4429cfe54f1457a Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Thu, 18 May 2017 14:35:36 -0700 +Subject: [PATCH 7/8] compositor: Process stream attach requests with + wl_eglstream_controller +X-NVConfidentiality: public + +So far, the EGLStream implementation of the Wayland client-side driver +has been using wl_surface_attach + commit in order to make the server +create its stream endpoint and attach a consumer to it. + +However, no actual buffer would be actually shared between client and +server, which goes against many of the assumptions behind +wl_surface_attach + commit. + +This has caused different interaction issues in the past. + +In order to properly resolve this once and for all, a new +wl_eglstream_controller protocol has been added which will let clients +request the compositor to create its stream. + +This change adds the required code for weston to create a +wl_eglstream_controller global and process attach_eglstream_consumer +requests. + +[mvicomoya: - Dynamically load libnvidia-egl-wayland.so.1 instead linking + against it + - Add wayland-eglstream-protocols package dependency and + generate server header for wayland-eglstream-controller at + build time] + +Signed-off-by: Ashutosh Agarwal <asagarwal@nvidia.com> +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +--- + Makefile.am | 14 ++++ + compositor/meson.build | 1 + + configure.ac | 4 ++ + libweston/compositor.c | 78 +++++++++++++++++++++ + libweston/compositor.h | 4 ++ + libweston/gl-renderer.c | 147 +++++++++++++++++++++++++--------------- + protocol/meson.build | 7 ++ + 7 files changed, 201 insertions(+), 54 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 5407b593..0bad6976 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -192,6 +192,11 @@ nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ + + BUILT_SOURCES += $(nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES) + ++nodist_libweston_eglstreams_@LIBWESTON_MAJOR@_la_SOURCES = \ ++ protocol/wayland-eglstream-controller-server-protocol.h ++ ++BUILT_SOURCES += $(nodist_libweston_eglstreams_@LIBWESTON_MAJOR@_la_SOURCES) ++ + bin_PROGRAMS += weston + + weston_LDFLAGS = -export-dynamic +@@ -1736,6 +1741,15 @@ protocol/%-server-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostabili + protocol/%-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostability,$$*)/$$(call protoname,$$*)/$$*.xml + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) client-header < $< > $@ + ++protocol/%-protocol.c : $(WAYLAND_EGLSTREAM_PROTOCOLS_DATADIR)/%.xml ++ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) code < $< > $@ ++ ++protocol/%-server-protocol.h : $(WAYLAND_EGLSTREAM_PROTOCOLS_DATADIR)/%.xml ++ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) server-header < $< > $@ ++ ++protocol/%-client-protocol.h : $(WAYLAND_EGLSTREAM_PROTOCOLS_DATADIR)/%.xml ++ $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) client-header < $< > $@ ++ + protocol/%-protocol.c : $(top_srcdir)/protocol/%.xml + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(wayland_scanner) code < $< > $@ + +diff --git a/compositor/meson.build b/compositor/meson.build +index d5d7282f..7655ef5a 100644 +--- a/compositor/meson.build ++++ b/compositor/meson.build +@@ -9,6 +9,7 @@ srcs_weston = [ + input_method_unstable_v1_protocol_c, + weston_screenshooter_server_protocol_h, + weston_screenshooter_protocol_c, ++ wayland_eglstream_controller_server_protocol_h, + ] + deps_weston = [ + dep_libshared, +diff --git a/configure.ac b/configure.ac +index 425ba238..5c1932bc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -261,6 +261,10 @@ PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.17], + [ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`]) + AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir) + ++PKG_CHECK_MODULES(WAYLAND_EGLSTREAM_PROTOCOLS, [wayland-eglstream-protocols], ++ [ac_wayland_eglstream_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-eglstream-protocols`]) ++AC_SUBST(WAYLAND_EGLSTREAM_PROTOCOLS_DATADIR, $ac_wayland_eglstream_protocols_pkgdatadir) ++ + AC_ARG_ENABLE(wayland-compositor, [ --enable-wayland-compositor],, + enable_wayland_compositor=yes) + AM_CONDITIONAL(ENABLE_WAYLAND_COMPOSITOR, +diff --git a/libweston/compositor.c b/libweston/compositor.c +index d87522e7..947739f8 100644 +--- a/libweston/compositor.c ++++ b/libweston/compositor.c +@@ -3,6 +3,7 @@ + * Copyright © 2008-2011 Kristian Høgsberg + * Copyright © 2012-2018 Collabora, Ltd. + * Copyright © 2017, 2018 General Electric Company ++ * Copyright © 2017-2018 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the +@@ -71,6 +72,7 @@ + #include "version.h" + #include "plugin-registry.h" + #include "pixel-formats.h" ++#include "wayland-eglstream-controller-server-protocol.h" + + #define DEFAULT_REPAINT_WINDOW 7 /* milliseconds */ + +@@ -6473,6 +6475,80 @@ bind_presentation(struct wl_client *client, + wp_presentation_send_clock_id(resource, compositor->presentation_clock); + } + ++static struct wl_interface *eglstream_controller_interface = NULL; ++ ++static void ++attach_eglstream_consumer(struct wl_client *client, ++ struct wl_resource *resource, ++ struct wl_resource *wl_surface, ++ struct wl_resource *wl_eglstream) ++{ ++ struct weston_surface *surface = ++ wl_resource_get_user_data(wl_surface); ++ ++ surface->compositor->renderer->attach_eglstream_consumer(surface, ++ wl_eglstream); ++} ++ ++static const struct wl_eglstream_controller_interface ++eglstream_controller_implementation = { ++ attach_eglstream_consumer ++}; ++ ++static void ++bind_eglstream_controller(struct wl_client *client, ++ void *data, uint32_t version, uint32_t id) ++{ ++ struct wl_resource *resource; ++ ++ resource = wl_resource_create(client, eglstream_controller_interface, ++ version, id); ++ ++ if (resource == NULL) { ++ wl_client_post_no_memory(client); ++ return; ++ } ++ wl_resource_set_implementation(resource, ++ &eglstream_controller_implementation, ++ data, ++ NULL); ++} ++ ++static void ++init_eglstream_controller(struct wl_display *display) ++{ ++ /* ++ * 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; ++ ++ eglstream_controller_interface = ++ dlsym(lib, "wl_eglstream_controller_interface"); ++ ++ if (!eglstream_controller_interface) ++ goto fail; ++ ++ if (wl_global_create(display, ++ eglstream_controller_interface, 1, ++ NULL, bind_eglstream_controller)) ++ return; /* success */ ++fail: ++ if (lib) ++ dlclose(lib); ++ weston_log("warning: Unable to initialize wl_eglstream_controller.\n"); ++} ++ + static void + compositor_bind(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +@@ -6836,6 +6912,8 @@ weston_compositor_create(struct wl_display *display, void *user_data) + ec, bind_presentation)) + goto fail; + ++ init_eglstream_controller(ec->wl_display); ++ + if (weston_debug_compositor_create(ec) < 0) + goto fail; + +diff --git a/libweston/compositor.h b/libweston/compositor.h +index a5223c28..1c39c50c 100644 +--- a/libweston/compositor.h ++++ b/libweston/compositor.h +@@ -925,6 +925,10 @@ struct weston_renderer { + void (*query_dmabuf_modifiers)(struct weston_compositor *ec, + int format, uint64_t **modifiers, + int *num_modifiers); ++ ++ /** Create weston endpoint of an EGLStream & attach a consumer to it */ ++ bool (*attach_eglstream_consumer)(struct weston_surface *es, ++ struct wl_resource *wl_eglstream); + }; + + enum weston_capability { +diff --git a/libweston/gl-renderer.c b/libweston/gl-renderer.c +index 5e594535..8265a712 100644 +--- a/libweston/gl-renderer.c ++++ b/libweston/gl-renderer.c +@@ -1,7 +1,7 @@ + /* + * Copyright © 2012 Intel Corporation + * Copyright © 2015 Collabora, Ltd. +- * Copyright © 2016 NVIDIA Corporation ++ * Copyright © 2016-2017 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the +@@ -2537,18 +2537,9 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface, + surface->is_opaque = dmabuf_is_opaque(dmabuf); + } + +-/* +- * gl_renderer_attach_stream_texture +- * +- * Try to bind given <buffer> to an EGLStream. If the given buffer was already +- * bound, it will acquire next frame on the stream. +- * +- * Return true if the given <buffer> corresponds to an EGLStream; otherwise, +- * return false (if might be another kind of buffer). +- */ +-static bool +-gl_renderer_attach_stream_texture(struct weston_surface *es, +- struct weston_buffer *buffer) ++static EGLint ++gl_renderer_attach_eglstream_consumer_common(struct weston_surface *es, ++ struct wl_resource *wl_eglstream) + { + #ifdef EGL_NV_stream_attrib + struct weston_compositor *ec = es->compositor; +@@ -2557,65 +2548,111 @@ gl_renderer_attach_stream_texture(struct weston_surface *es, + EGLStreamKHR stream = EGL_NO_STREAM_KHR; + EGLAttrib stream_attribs[] = { + #ifdef EGL_WL_wayland_eglstream +- EGL_WAYLAND_EGLSTREAM_WL, (EGLAttrib)buffer->resource, ++ EGL_WAYLAND_EGLSTREAM_WL, (EGLAttrib)wl_eglstream, + #endif + EGL_NONE + }; +- EGLint stream_state = EGL_STREAM_STATE_EMPTY_KHR; + + /* Check for required extensions. If they arent supported, there's no +- * way the given buffer corresponds to an EGLStream */ ++ * way the given resource corresponds to an EGLStream */ + if (!gr->has_egl_stream_attrib || + !gr->has_egl_stream_consumer_gltexture || + !gr->has_egl_wayland_eglstream) +- return false; ++ return EGL_BAD_ACCESS; + + stream = gr->create_stream_attrib(gr->egl_display, stream_attribs); +- if (stream == EGL_NO_STREAM_KHR) { ++ ++ if (stream == EGL_NO_STREAM_KHR) ++ return eglGetError(); ++ ++ if (gs->egl_stream != EGL_NO_STREAM_KHR) ++ gr->destroy_stream(gr->egl_display, gs->egl_stream); ++ ++ gs->egl_stream = stream; ++ gs->shader = &gr->texture_shader_egl_external; ++ gs->target = GL_TEXTURE_EXTERNAL_OES; ++ ++ glActiveTexture(GL_TEXTURE0); ++ ensure_textures(gs, 2); ++ glBindTexture(gs->target, gs->textures[1]); ++ ++ gs->new_stream = (gr->stream_consumer_gltexture( ++ gr->egl_display, ++ gs->egl_stream) == EGL_TRUE); ++ ++ if (!gs->new_stream) { + EGLint err = eglGetError(); + +- switch (err) { +- case EGL_BAD_ACCESS: +- /* EGL_BAD_ACCESS is generated whenever buffer->resource +- * does not corresponds to a stream */ +- return false; ++ weston_log("failed to set stream consumer\n"); ++ weston_log("EGL error state: %s (0x%04lx)\n", ++ egl_error_string(err), (long)err); + +- case EGL_BAD_STREAM_KHR: +- /* EGL_BAD_STREAM_KHR is generated whenever +- * buffer->resource corresponds to a previously created +- * stream so we must have a valid stream handle already +- * we can use to acquire next frame */ +- break; ++ gr->destroy_stream(gr->egl_display, gs->egl_stream); ++ gs->egl_stream = EGL_NO_STREAM_KHR; ++ return err; ++ } + +- default: +- /* An unknown error was generated */ +- assert(0); +- return false; +- } +- } else { +- /* Clean up current stream resources if needed */ +- if (gs->egl_stream != EGL_NO_STREAM_KHR) +- gr->destroy_stream(gr->egl_display, gs->egl_stream); ++ return EGL_SUCCESS; ++#else ++ return EGL_BAD_ACCESS; ++#endif ++} + +- gs->egl_stream = stream; +- gs->shader = &gr->texture_shader_egl_external; +- gs->target = GL_TEXTURE_EXTERNAL_OES; ++static bool ++gl_renderer_attach_eglstream_consumer(struct weston_surface *es, ++ struct wl_resource *stream) ++{ ++ EGLint err = gl_renderer_attach_eglstream_consumer_common(es, stream); ++ return (err == EGL_SUCCESS); ++} ++ ++/* ++ * gl_renderer_attach_stream_texture ++ * ++ * Try to bind given <buffer> to an EGLStream. If the given buffer was already ++ * bound, it will acquire next frame on the stream. ++ * ++ * Return true if the given <buffer> corresponds to an EGLStream; otherwise, ++ * return false (if might be another kind of buffer). ++ */ ++static bool ++gl_renderer_attach_stream_texture(struct weston_surface *es, ++ struct weston_buffer *buffer) ++{ ++#ifdef EGL_NV_stream_attrib ++ struct weston_compositor *ec = es->compositor; ++ struct gl_renderer *gr = get_renderer(ec); ++ struct gl_surface_state *gs = get_surface_state(es); ++ EGLint stream_state = EGL_STREAM_STATE_EMPTY_KHR; + +- glActiveTexture(GL_TEXTURE0); +- ensure_textures(gs, 2); +- glBindTexture(gs->target, gs->textures[1]); ++ EGLint err; + +- gs->new_stream = (gr->stream_consumer_gltexture( +- gr->egl_display, +- gs->egl_stream) == EGL_TRUE); ++ err = gl_renderer_attach_eglstream_consumer_common(es, buffer->resource); + +- if (!gs->new_stream) { +- weston_log("failed to set stream consumer\n"); +- gl_renderer_print_egl_error_state(); +- gr->destroy_stream(gr->egl_display, gs->egl_stream); +- gs->egl_stream = EGL_NO_STREAM_KHR; +- return true; /* buffer->resource is EGLStream */ +- } ++ switch (err) { ++ case EGL_BAD_ACCESS: ++ /* EGL_BAD_ACCESS is generated whenever buffer->resource ++ * does not corresponds to a stream */ ++ return false; ++ ++ case EGL_BAD_STREAM_KHR: ++ /* EGL_BAD_STREAM_KHR is generated whenever ++ * buffer->resource corresponds to a previously created ++ * stream so we must have a valid stream handle already ++ * we can use to acquire next frame */ ++ break; ++ ++ case EGL_SUCCESS: ++ /* EGL_SUCCESS is returned when the server stream endpoint is ++ * created and a consumer is attached successfully. This path is ++ * hit with old drivers which use wl_surface::attach + commit to ++ * request stream creation. */ ++ return true; /* buffer->resource is EGLStream */ ++ ++ default: ++ /* An unknown error was generated */ ++ assert(0); ++ return false; + } + + /* At this point we should have a valid stream handle */ +@@ -4041,6 +4078,8 @@ gl_renderer_display_create(struct weston_compositor *ec, EGLenum platform, + gr->base.surface_get_content_size = + gl_renderer_surface_get_content_size; + gr->base.surface_copy_content = gl_renderer_surface_copy_content; ++ gr->base.attach_eglstream_consumer = ++ gl_renderer_attach_eglstream_consumer; + gr->egl_display = NULL; + + /* extension_suffix is supported */ +diff --git a/protocol/meson.build b/protocol/meson.build +index 34026ff9..37642298 100644 +--- a/protocol/meson.build ++++ b/protocol/meson.build +@@ -7,6 +7,9 @@ prog_scanner = find_program(dep_scanner.get_pkgconfig_variable('wayland_scanner' + dep_wp = dependency('wayland-protocols', version: '>= 1.17') + dir_wp_base = dep_wp.get_pkgconfig_variable('pkgdatadir') + ++dep_wep = dependency('wayland-eglstream-protocols') ++dir_wep_base = dep_wep.get_pkgconfig_variable('pkgdatadir') ++ + install_data( + [ + 'weston-debug.xml', +@@ -37,6 +40,7 @@ generated_protocols = [ + [ 'xdg-output', 'v1' ], + [ 'xdg-shell', 'v6' ], + [ 'xdg-shell', 'stable' ], ++ [ 'wayland-eglstream-controller', '3rdparty', dir_wep_base ], + ] + + foreach proto: generated_protocols +@@ -44,6 +48,9 @@ foreach proto: generated_protocols + if proto[1] == 'internal' + base_file = proto_name + xml_path = '@0@.xml'.format(proto_name) ++ elif proto[1] == '3rdparty' ++ base_file = proto_name ++ xml_path = '@0@/@1@.xml'.format(proto[2], base_file) + elif proto[1] == 'stable' + base_file = proto_name + xml_path = '@0@/stable/@1@/@1@.xml'.format(dir_wp_base, base_file) +-- +2.21.0 + |