diff options
author | Chad Versace <chad.versace@intel.com> | 2015-03-27 11:31:09 -0700 |
---|---|---|
committer | Chad Versace <chad.versace@intel.com> | 2015-03-27 11:31:13 -0700 |
commit | 8b5766929bfc717acc4ef6feb22126e694ea5474 (patch) | |
tree | 72da74d232a5d9de1dd9d7a482f43fa9ed521d7d | |
parent | 3b9b8f5f6d1b99af43e95ec0868404e552a85b73 (diff) | |
parent | bd32a55d927766205de97c857e317425a9124281 (diff) | |
download | waffle-8b5766929bfc717acc4ef6feb22126e694ea5474.tar.gz |
Merge branch 'evelikov/no-libwayland'
* evelikov/no-libwayland:
wayland: resolve wayland-client symbols at runtime (via libdl)
wayland: do not link against wayland-egl
wayland: fetch wl_egl_* function pointers at wayland_platform_create
wayland: fix indentation
-rw-r--r-- | cmake/Modules/WafflePrintConfigurationSummary.cmake | 2 | ||||
-rw-r--r-- | src/waffle/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/waffle/wayland/wayland_display.c | 2 | ||||
-rw-r--r-- | src/waffle/wayland/wayland_platform.c | 43 | ||||
-rw-r--r-- | src/waffle/wayland/wayland_platform.h | 18 | ||||
-rw-r--r-- | src/waffle/wayland/wayland_window.c | 47 | ||||
-rw-r--r-- | src/waffle/wayland/wayland_wrapper.c | 115 | ||||
-rw-r--r-- | src/waffle/wayland/wayland_wrapper.h | 94 |
8 files changed, 301 insertions, 27 deletions
diff --git a/cmake/Modules/WafflePrintConfigurationSummary.cmake b/cmake/Modules/WafflePrintConfigurationSummary.cmake index 1f38db5..1199ea3 100644 --- a/cmake/Modules/WafflePrintConfigurationSummary.cmake +++ b/cmake/Modules/WafflePrintConfigurationSummary.cmake @@ -60,9 +60,7 @@ 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}") - message(" wayland-egl_LDFLAGS: ${wayland-egl_LDFLAGS}") endif() if(waffle_has_x11) message(" x11-xcb_INCLUDE_DIRS: ${x11-xcb_INCLUDE_DIRS}") diff --git a/src/waffle/CMakeLists.txt b/src/waffle/CMakeLists.txt index ac9b415..4f1d5c7 100644 --- a/src/waffle/CMakeLists.txt +++ b/src/waffle/CMakeLists.txt @@ -41,12 +41,6 @@ list(APPEND waffle_libdeps ) if(waffle_on_linux) - if(waffle_has_wayland) - list(APPEND waffle_libdeps - ${wayland-client_LDFLAGS} - ${wayland-egl_LDFLAGS} - ) - endif() if(waffle_has_x11) list(APPEND waffle_libdeps ${x11-xcb_LDFLAGS} @@ -138,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 63cfdc2..2746ca1 100644 --- a/src/waffle/wayland/wayland_platform.c +++ b/src/waffle/wayland/wayland_platform.c @@ -27,6 +27,7 @@ #define _POSIX_C_SOURCE 200112 // glib feature macro for unsetenv() #include <stdlib.h> +#include <dlfcn.h> #include "waffle_wayland.h" @@ -42,6 +43,9 @@ #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"; static const struct wcore_platform_vtbl wayland_platform_vtbl; @@ -50,6 +54,7 @@ wayland_platform_destroy(struct wcore_platform *wc_self) { struct wayland_platform *self = wayland_platform(wegl_platform(wc_self)); bool ok = true; + int error; if (!self) return true; @@ -59,6 +64,17 @@ wayland_platform_destroy(struct wcore_platform *wc_self) if (self->linux) ok &= linux_platform_destroy(self->linux); + if (self->dl_wl_egl) { + error = dlclose(self->dl_wl_egl); + if (error) { + ok &= false; + wcore_errorf(WAFFLE_ERROR_UNKNOWN, + "dlclose(\"%s\") failed: %s", + libwl_egl_filename, dlerror()); + } + } + + ok &= wayland_wrapper_teardown(); ok &= wegl_platform_teardown(&self->wegl); free(self); return ok; @@ -78,6 +94,33 @@ 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, + "dlopen(\"%s\") failed: %s", + libwl_egl_filename, dlerror()); + goto error; + } + +#define RETRIEVE_WL_EGL_SYMBOL(function) \ + self->function = dlsym(self->dl_wl_egl, #function); \ + if (!self->function) { \ + wcore_errorf(WAFFLE_ERROR_FATAL, \ + "dlsym(\"%s\", \"" #function "\") failed: %s", \ + libwl_egl_filename, dlerror()); \ + goto error; \ + } + + RETRIEVE_WL_EGL_SYMBOL(wl_egl_window_create); + RETRIEVE_WL_EGL_SYMBOL(wl_egl_window_destroy); + RETRIEVE_WL_EGL_SYMBOL(wl_egl_window_resize); + +#undef RETRIEVE_WL_EGL_SYMBOL + self->linux = linux_platform_create(); if (!self->linux) goto error; diff --git a/src/waffle/wayland/wayland_platform.h b/src/waffle/wayland/wayland_platform.h index c4e870f..574a306 100644 --- a/src/waffle/wayland/wayland_platform.h +++ b/src/waffle/wayland/wayland_platform.h @@ -36,10 +36,28 @@ #include "wcore_util.h" struct linux_platform; +struct wl_egl_window; +struct wl_surface; struct wayland_platform { struct wegl_platform wegl; struct linux_platform *linux; + + + void *dl_wl_egl; + + struct wl_egl_window * + (*wl_egl_window_create)(struct wl_surface *surface, + int width, int height); + + void + (*wl_egl_window_destroy)(struct wl_egl_window *egl_window); + + void + (*wl_egl_window_resize)(struct wl_egl_window *egl_window, + int width, int height, + int dx, int dy); + }; DEFINE_CONTAINER_CAST_FUNC(wayland_platform, diff --git a/src/waffle/wayland/wayland_window.c b/src/waffle/wayland/wayland_window.c index 4ac9c16..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 @@ -39,11 +41,14 @@ #include "wegl_config.h" #include "wayland_display.h" +#include "wayland_platform.h" #include "wayland_window.h" bool wayland_window_destroy(struct wcore_window *wc_self) { + struct wcore_platform *wc_plat = wc_self->display->platform; + struct wayland_platform *plat = wayland_platform(wegl_platform(wc_plat)); struct wayland_window *self = wayland_window(wc_self); bool ok = true; @@ -53,7 +58,7 @@ wayland_window_destroy(struct wcore_window *wc_self) ok &= wegl_window_teardown(&self->wegl); if (self->wl_window) - wl_egl_window_destroy(self->wl_window); + plat->wl_egl_window_destroy(self->wl_window); if (self->wl_shell_surface) wl_shell_surface_destroy(self->wl_shell_surface); @@ -102,6 +107,7 @@ wayland_window_create(struct wcore_platform *wc_plat, const intptr_t attrib_list[]) { struct wayland_window *self; + struct wayland_platform *plat = wayland_platform(wegl_platform(wc_plat)); struct wayland_display *dpy = wayland_display(wc_config->display); bool ok = true; @@ -142,7 +148,8 @@ wayland_window_create(struct wcore_platform *wc_plat, &shell_surface_listener, NULL); - self->wl_window = wl_egl_window_create(self->wl_surface, width, height); + self->wl_window = plat->wl_egl_window_create(self->wl_surface, + width, height); if (!self->wl_window) { wcore_errorf(WAFFLE_ERROR_UNKNOWN, "wl_egl_window_create failed"); goto error; @@ -184,35 +191,37 @@ wayland_window_show(struct wcore_window *wc_self) bool wayland_window_swap_buffers(struct wcore_window *wc_self) { - struct wayland_display *dpy = wayland_display(wc_self->display); - bool ok; + struct wayland_display *dpy = wayland_display(wc_self->display); + bool ok; - ok = wegl_window_swap_buffers(wc_self); - if (!ok) - return false; + ok = wegl_window_swap_buffers(wc_self); + if (!ok) + return false; - ok = wayland_display_sync(dpy); - if (!ok) - return false; + ok = wayland_display_sync(dpy); + if (!ok) + return false; - return true; + return true; } bool wayland_window_resize(struct wcore_window *wc_self, int32_t width, int32_t height) { - struct wayland_window *self = wayland_window(wc_self); - struct wayland_display *dpy = wayland_display(self->wegl.wcore.display); + struct wayland_window *self = wayland_window(wc_self); + struct wcore_platform *wc_plat = wc_self->display->platform; + struct wayland_platform *plat = wayland_platform(wegl_platform(wc_plat)); + struct wayland_display *dpy = wayland_display(self->wegl.wcore.display); - wl_egl_window_resize(wayland_window(wc_self)->wl_window, - width, height, 0, 0); + plat->wl_egl_window_resize(wayland_window(wc_self)->wl_window, + width, height, 0, 0); - if (!wayland_display_sync(dpy)) - return false; + if (!wayland_display_sync(dpy)) + return false; - // FIXME: How to detect if the resize failed? - return true; + // FIXME: How to detect if the resize failed? + return true; } union waffle_native_window* 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) |