By doing so one can use waffle's other platforms, without having wayland installed/available on their system.
This patch is based on a similar work by the SDL devs. v2: - Remove implementation details from commit message. - Follow SDL's approach. v3: - Include wayland-client.h only when needed (in the C files). Signed-off-by: Emil Velikov <[email protected]> --- .../Modules/WafflePrintConfigurationSummary.cmake | 1 - src/waffle/CMakeLists.txt | 6 +- src/waffle/wayland/wayland_display.c | 2 + src/waffle/wayland/wayland_platform.c | 6 ++ src/waffle/wayland/wayland_window.c | 2 + src/waffle/wayland/wayland_wrapper.c | 115 +++++++++++++++++++++ src/waffle/wayland/wayland_wrapper.h | 94 +++++++++++++++++ 7 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 src/waffle/wayland/wayland_wrapper.c create mode 100644 src/waffle/wayland/wayland_wrapper.h diff --git a/cmake/Modules/WafflePrintConfigurationSummary.cmake b/cmake/Modules/WafflePrintConfigurationSummary.cmake index 27aa8dc..1199ea3 100644 --- a/cmake/Modules/WafflePrintConfigurationSummary.cmake +++ b/cmake/Modules/WafflePrintConfigurationSummary.cmake @@ -60,7 +60,6 @@ if(waffle_has_glx) endif() if(waffle_has_wayland) message(" wayland-client_INCLUDE_DIRS: ${wayland-client_INCLUDE_DIRS}") - message(" wayland-client_LDFLAGS: ${wayland-client_LDFLAGS}") message(" wayland-egl_INCLUDE_DIRS: ${wayland-egl_INCLUDE_DIRS}") endif() if(waffle_has_x11) diff --git a/src/waffle/CMakeLists.txt b/src/waffle/CMakeLists.txt index 4a473be..4f1d5c7 100644 --- a/src/waffle/CMakeLists.txt +++ b/src/waffle/CMakeLists.txt @@ -41,11 +41,6 @@ list(APPEND waffle_libdeps ) if(waffle_on_linux) - if(waffle_has_wayland) - list(APPEND waffle_libdeps - ${wayland-client_LDFLAGS} - ) - endif() if(waffle_has_x11) list(APPEND waffle_libdeps ${x11-xcb_LDFLAGS} @@ -137,6 +132,7 @@ if(waffle_has_wayland) wayland/wayland_display.c wayland/wayland_platform.c wayland/wayland_window.c + wayland/wayland_wrapper.c ) endif() diff --git a/src/waffle/wayland/wayland_display.c b/src/waffle/wayland/wayland_display.c index e7c6e94..e2d59a8 100644 --- a/src/waffle/wayland/wayland_display.c +++ b/src/waffle/wayland/wayland_display.c @@ -28,6 +28,8 @@ #include <stdlib.h> #include <string.h> +// The wrapper must be included before wayland-client.h +#include "wayland_wrapper.h" #include <wayland-client.h> #undef container_of diff --git a/src/waffle/wayland/wayland_platform.c b/src/waffle/wayland/wayland_platform.c index 94c0010..2746ca1 100644 --- a/src/waffle/wayland/wayland_platform.c +++ b/src/waffle/wayland/wayland_platform.c @@ -43,6 +43,7 @@ #include "wayland_display.h" #include "wayland_platform.h" #include "wayland_window.h" +#include "wayland_wrapper.h" static const char *libwl_egl_filename = "libwayland-egl.so.1"; @@ -73,6 +74,7 @@ wayland_platform_destroy(struct wcore_platform *wc_self) } } + ok &= wayland_wrapper_teardown(); ok &= wegl_platform_teardown(&self->wegl); free(self); return ok; @@ -92,6 +94,10 @@ wayland_platform_create(void) if (!ok) goto error; + ok = wayland_wrapper_init(); + if (!ok) + goto error; + self->dl_wl_egl = dlopen(libwl_egl_filename, RTLD_LAZY | RTLD_LOCAL); if (!self->dl_wl_egl) { wcore_errorf(WAFFLE_ERROR_FATAL, diff --git a/src/waffle/wayland/wayland_window.c b/src/waffle/wayland/wayland_window.c index 2cdf8e6..b5eeaa3 100644 --- a/src/waffle/wayland/wayland_window.c +++ b/src/waffle/wayland/wayland_window.c @@ -28,6 +28,8 @@ #include <stdlib.h> #include <string.h> +// The wrapper must be included before wayland-(client|egl).h +#include "wayland_wrapper.h" #include <wayland-egl.h> #undef container_of diff --git a/src/waffle/wayland/wayland_wrapper.c b/src/waffle/wayland/wayland_wrapper.c new file mode 100644 index 0000000..6ffd5a9 --- /dev/null +++ b/src/waffle/wayland/wayland_wrapper.c @@ -0,0 +1,115 @@ +// Copyright 2015 Emil Velikov +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// @file +/// @brief Wrappers for Wayland-client functions +/// +/// Many of the wayland functions are defined as static inline within the +/// public headers. In order to avoid the static(link-time) dependency, we +/// provide the required symbols with this file. +/// +/// This is achieved by declaring wrapper functions, around which we define the +/// needed (base) wayland ones. After that we include the public header, at +/// which point the pre-processor/compiler will use our defines. +/// +/// Each wrapper is initialised via dlsym to retrieve the relevant symbol from +/// the library libwayland-client.so.0 + + +#include <stdbool.h> +#include <dlfcn.h> + +#include "wcore_error.h" + +#include "wayland_wrapper.h" + +// dlopen handle for libwayland-client.so.0 +static void *dl_wl_client; + +static const char *libwl_client_filename = "libwayland-client.so.0"; + +bool +wayland_wrapper_teardown(void) +{ + bool ok = true; + int error; + + if (dl_wl_client) { + error = dlclose(dl_wl_client); + if (error) { + ok &= false; + wcore_errorf(WAFFLE_ERROR_UNKNOWN, + "dlclose(\"%s\") failed: %s", + libwl_client_filename, dlerror()); + } + } + + return ok; +} + +bool +wayland_wrapper_init(void) +{ + bool ok = true; + + dl_wl_client = dlopen(libwl_client_filename, RTLD_LAZY | RTLD_LOCAL); + if (!dl_wl_client) { + wcore_errorf(WAFFLE_ERROR_FATAL, + "dlopen(\"%s\") failed: %s", + libwl_client_filename, dlerror()); + ok = false; + goto error; + } + +#define RETRIEVE_WL_CLIENT_SYMBOL(S) \ + wfl_##S = (__typeof__(wfl_##S))dlsym(dl_wl_client, #S); \ + if (!wfl_##S) { \ + wcore_errorf(WAFFLE_ERROR_FATAL, \ + "dlsym(\"%s\", \"" #S "\") failed: %s", \ + libwl_client_filename, dlerror()); \ + ok = false; \ + goto error; \ + } + + RETRIEVE_WL_CLIENT_SYMBOL(wl_compositor_interface); + RETRIEVE_WL_CLIENT_SYMBOL(wl_registry_interface); + RETRIEVE_WL_CLIENT_SYMBOL(wl_shell_interface); + RETRIEVE_WL_CLIENT_SYMBOL(wl_shell_surface_interface); + RETRIEVE_WL_CLIENT_SYMBOL(wl_surface_interface); + + RETRIEVE_WL_CLIENT_SYMBOL(wl_display_connect); + RETRIEVE_WL_CLIENT_SYMBOL(wl_display_disconnect); + RETRIEVE_WL_CLIENT_SYMBOL(wl_display_roundtrip); + RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_destroy); + RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_add_listener); + RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_marshal); + RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_marshal_constructor); +#undef RETRIEVE_WL_CLIENT_SYMBOL + +error: + // On failure the caller of wayland_wrapper_init will trigger it's own + // destruction which will execute wayland_wrapper_teardown. + return ok; +} diff --git a/src/waffle/wayland/wayland_wrapper.h b/src/waffle/wayland/wayland_wrapper.h new file mode 100644 index 0000000..40a581a --- /dev/null +++ b/src/waffle/wayland/wayland_wrapper.h @@ -0,0 +1,94 @@ +// Copyright 2015 Emil Velikov +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#include <stdbool.h> +#include "wayland-util.h" + +bool +wayland_wrapper_init(void); + +bool +wayland_wrapper_teardown(void); + + +// Data symbols +const struct wl_interface *wfl_wl_compositor_interface; +const struct wl_interface *wfl_wl_registry_interface; +const struct wl_interface *wfl_wl_shell_interface; +const struct wl_interface *wfl_wl_shell_surface_interface; +const struct wl_interface *wfl_wl_surface_interface; + + +// Forward declaration of the structs required by the functions +struct wl_proxy; +struct wl_display; + + +// Functions +struct wl_display * +(*wfl_wl_display_connect)(const char *name); + +void +(*wfl_wl_display_disconnect)(struct wl_display *display); + +int +(*wfl_wl_display_roundtrip)(struct wl_display *display); + + +void +(*wfl_wl_proxy_destroy)(struct wl_proxy *proxy); + +int +(*wfl_wl_proxy_add_listener)(struct wl_proxy *proxy, + void (**implementation)(void), void *data); + +void +(*wfl_wl_proxy_marshal)(struct wl_proxy *p, uint32_t opcode, ...); + +struct wl_proxy * +(*wfl_wl_proxy_marshal_constructor)(struct wl_proxy *proxy, + uint32_t opcode, + const struct wl_interface *interface, + ...); + +#ifdef _WAYLAND_CLIENT_H +#error Do not include wayland-client.h ahead of wayland_wrapper.h +#endif + +#define wl_compositor_interface (*wfl_wl_compositor_interface) +#define wl_registry_interface (*wfl_wl_registry_interface) +#define wl_shell_interface (*wfl_wl_shell_interface) +#define wl_shell_surface_interface (*wfl_wl_shell_surface_interface) +#define wl_surface_interface (*wfl_wl_surface_interface) + +#define wl_display_connect (*wfl_wl_display_connect) +#define wl_display_disconnect (*wfl_wl_display_disconnect) +#define wl_display_roundtrip (*wfl_wl_display_roundtrip) +#define wl_proxy_destroy (*wfl_wl_proxy_destroy) +#define wl_proxy_add_listener (*wfl_wl_proxy_add_listener) +#define wl_proxy_marshal (*wfl_wl_proxy_marshal) +#define wl_proxy_marshal_constructor (*wfl_wl_proxy_marshal_constructor) -- 2.3.1 _______________________________________________ waffle mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/waffle

