Vulkan: Build Wayland WSI against libwayland older than 1.20 The Wayland WSI marshalled requests via wl_proxy_marshal_flags and used WL_MARSHAL_FLAG_DESTROY, both introduced in libwayland 1.20 (1.19.91). SwiftShader's bundled headers are 1.21 so the standalone build compiled, but embedded builds that use the host's Wayland headers fail where those are older: rolling into Dawn on Debian 11 (Bullseye, Wayland 1.18) broke with "error: use of undeclared identifier 'WL_MARSHAL_FLAG_DESTROY'". Marshal requests through the older wl_proxy_marshal / wl_proxy_marshal_constructor / wl_proxy_marshal_constructor_versioned primitives instead. These have existed since libwayland 1.2 and are exactly what the generated static-inline wrappers used prior to 1.20, so this needs neither the 1.20-only wl_proxy_marshal_flags symbol at runtime nor the WL_MARSHAL_FLAG_DESTROY macro at compile time, and introduces no new minimum libwayland version. Change-Id: I965424d33c9420a8d6832009099190e1174c46cb Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/77608 Tested-by: Yuly Novikov <ynovikov@chromium.org> Reviewed-by: Yuly Novikov <ynovikov@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@google.com> Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
diff --git a/src/WSI/libWaylandClient.cpp b/src/WSI/libWaylandClient.cpp index a0926b7..3a06215 100644 --- a/src/WSI/libWaylandClient.cpp +++ b/src/WSI/libWaylandClient.cpp
@@ -26,10 +26,11 @@ getFuncAddress(libwl, "wl_display_create_queue", &wl_display_create_queue); getFuncAddress(libwl, "wl_event_queue_destroy", &wl_event_queue_destroy); - getFuncAddress(libwl, "wl_proxy_marshal_flags", &wl_proxy_marshal_flags); + getFuncAddress(libwl, "wl_proxy_marshal", &wl_proxy_marshal); + getFuncAddress(libwl, "wl_proxy_marshal_constructor", &wl_proxy_marshal_constructor); + getFuncAddress(libwl, "wl_proxy_marshal_constructor_versioned", &wl_proxy_marshal_constructor_versioned); getFuncAddress(libwl, "wl_proxy_add_listener", &wl_proxy_add_listener); getFuncAddress(libwl, "wl_proxy_destroy", &wl_proxy_destroy); - getFuncAddress(libwl, "wl_proxy_get_version", &wl_proxy_get_version); getFuncAddress(libwl, "wl_proxy_set_queue", &wl_proxy_set_queue); getFuncAddress(libwl, "wl_proxy_create_wrapper", &wl_proxy_create_wrapper); getFuncAddress(libwl, "wl_proxy_wrapper_destroy", &wl_proxy_wrapper_destroy); @@ -45,25 +46,26 @@ { return wl_display_dispatch_queue && wl_display_roundtrip_queue && wl_display_flush && wl_display_create_queue && wl_event_queue_destroy && - wl_proxy_marshal_flags && wl_proxy_add_listener && wl_proxy_destroy && - wl_proxy_get_version && wl_proxy_set_queue && wl_proxy_create_wrapper && - wl_proxy_wrapper_destroy && + wl_proxy_marshal && wl_proxy_marshal_constructor && wl_proxy_marshal_constructor_versioned && + wl_proxy_add_listener && wl_proxy_destroy && wl_proxy_set_queue && + wl_proxy_create_wrapper && wl_proxy_wrapper_destroy && wl_registry_interface && wl_shm_interface && wl_shm_pool_interface && wl_surface_interface && wl_buffer_interface; } // The following re-implement the static-inline wrappers from -// <wayland-client-protocol.h>, mirroring exactly the wl_proxy_marshal_flags() -// calls they generate (opcodes and WL_MARSHAL_FLAG_DESTROY come from that -// header). They marshal through the dynamically-loaded primitives instead of -// referencing libwayland-client symbols at link time. +// <wayland-client-protocol.h>, marshalling through the dynamically-loaded +// wl_proxy_marshal[_constructor[_versioned]] primitives instead of referencing +// libwayland-client symbols at link time. Opcodes come from that header. Object- +// creating requests pass a null new-id placeholder and let the created proxy +// inherit its parent's version (registry_bind is the exception: it binds an +// explicit version). wl_registry *LibWaylandClientExports::display_get_registry(wl_display *display) { - wl_proxy *proxy = reinterpret_cast<wl_proxy *>(display); - return reinterpret_cast<wl_registry *>(wl_proxy_marshal_flags( - proxy, WL_DISPLAY_GET_REGISTRY, wl_registry_interface, - wl_proxy_get_version(proxy), 0, static_cast<void *>(nullptr))); + return reinterpret_cast<wl_registry *>(wl_proxy_marshal_constructor( + reinterpret_cast<wl_proxy *>(display), WL_DISPLAY_GET_REGISTRY, + wl_registry_interface, static_cast<void *>(nullptr))); } int LibWaylandClientExports::registry_add_listener(wl_registry *registry, const wl_registry_listener *listener, void *data) @@ -74,33 +76,30 @@ void *LibWaylandClientExports::registry_bind(wl_registry *registry, uint32_t name, const wl_interface *interface, uint32_t version) { - wl_proxy *proxy = reinterpret_cast<wl_proxy *>(registry); - return reinterpret_cast<void *>(wl_proxy_marshal_flags( - proxy, WL_REGISTRY_BIND, interface, version, 0, + return reinterpret_cast<void *>(wl_proxy_marshal_constructor_versioned( + reinterpret_cast<wl_proxy *>(registry), WL_REGISTRY_BIND, interface, version, name, interface->name, version, static_cast<void *>(nullptr))); } wl_shm_pool *LibWaylandClientExports::shm_create_pool(wl_shm *shm, int32_t fd, int32_t size) { - wl_proxy *proxy = reinterpret_cast<wl_proxy *>(shm); - return reinterpret_cast<wl_shm_pool *>(wl_proxy_marshal_flags( - proxy, WL_SHM_CREATE_POOL, wl_shm_pool_interface, - wl_proxy_get_version(proxy), 0, static_cast<void *>(nullptr), fd, size)); + return reinterpret_cast<wl_shm_pool *>(wl_proxy_marshal_constructor( + reinterpret_cast<wl_proxy *>(shm), WL_SHM_CREATE_POOL, + wl_shm_pool_interface, static_cast<void *>(nullptr), fd, size)); } wl_buffer *LibWaylandClientExports::shm_pool_create_buffer(wl_shm_pool *pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format) { - wl_proxy *proxy = reinterpret_cast<wl_proxy *>(pool); - return reinterpret_cast<wl_buffer *>(wl_proxy_marshal_flags( - proxy, WL_SHM_POOL_CREATE_BUFFER, wl_buffer_interface, - wl_proxy_get_version(proxy), 0, static_cast<void *>(nullptr), offset, width, height, stride, format)); + return reinterpret_cast<wl_buffer *>(wl_proxy_marshal_constructor( + reinterpret_cast<wl_proxy *>(pool), WL_SHM_POOL_CREATE_BUFFER, + wl_buffer_interface, static_cast<void *>(nullptr), offset, width, height, stride, format)); } void LibWaylandClientExports::shm_pool_destroy(wl_shm_pool *pool) { wl_proxy *proxy = reinterpret_cast<wl_proxy *>(pool); - wl_proxy_marshal_flags(proxy, WL_SHM_POOL_DESTROY, nullptr, - wl_proxy_get_version(proxy), WL_MARSHAL_FLAG_DESTROY); + wl_proxy_marshal(proxy, WL_SHM_POOL_DESTROY); + wl_proxy_destroy(proxy); } int LibWaylandClientExports::buffer_add_listener(wl_buffer *buffer, const wl_buffer_listener *listener, void *data) @@ -112,29 +111,23 @@ void LibWaylandClientExports::buffer_destroy(wl_buffer *buffer) { wl_proxy *proxy = reinterpret_cast<wl_proxy *>(buffer); - wl_proxy_marshal_flags(proxy, WL_BUFFER_DESTROY, nullptr, - wl_proxy_get_version(proxy), WL_MARSHAL_FLAG_DESTROY); + wl_proxy_marshal(proxy, WL_BUFFER_DESTROY); + wl_proxy_destroy(proxy); } void LibWaylandClientExports::surface_attach(wl_surface *surface, wl_buffer *buffer, int32_t x, int32_t y) { - wl_proxy *proxy = reinterpret_cast<wl_proxy *>(surface); - wl_proxy_marshal_flags(proxy, WL_SURFACE_ATTACH, nullptr, - wl_proxy_get_version(proxy), 0, buffer, x, y); + wl_proxy_marshal(reinterpret_cast<wl_proxy *>(surface), WL_SURFACE_ATTACH, buffer, x, y); } void LibWaylandClientExports::surface_damage(wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height) { - wl_proxy *proxy = reinterpret_cast<wl_proxy *>(surface); - wl_proxy_marshal_flags(proxy, WL_SURFACE_DAMAGE, nullptr, - wl_proxy_get_version(proxy), 0, x, y, width, height); + wl_proxy_marshal(reinterpret_cast<wl_proxy *>(surface), WL_SURFACE_DAMAGE, x, y, width, height); } void LibWaylandClientExports::surface_commit(wl_surface *surface) { - wl_proxy *proxy = reinterpret_cast<wl_proxy *>(surface); - wl_proxy_marshal_flags(proxy, WL_SURFACE_COMMIT, nullptr, - wl_proxy_get_version(proxy), 0); + wl_proxy_marshal(reinterpret_cast<wl_proxy *>(surface), WL_SURFACE_COMMIT); } LibWaylandClientExports *LibWaylandClient::operator->() @@ -147,7 +140,9 @@ static LibWaylandClientExports exports = [] { void *libwl = nullptr; - if(getProcAddress(RTLD_DEFAULT, "wl_proxy_marshal_flags")) // Search the global scope for pre-loaded Wayland client library. + // wl_proxy_marshal is present in every libwayland version, so it reliably + // detects a pre-loaded Wayland client library in the global scope. + if(getProcAddress(RTLD_DEFAULT, "wl_proxy_marshal")) { libwl = RTLD_DEFAULT; }
diff --git a/src/WSI/libWaylandClient.hpp b/src/WSI/libWaylandClient.hpp index 0e69710..4d22dfe 100644 --- a/src/WSI/libWaylandClient.hpp +++ b/src/WSI/libWaylandClient.hpp
@@ -25,8 +25,7 @@ // dynamically (so it remains a self-contained ICD that also works where Wayland // is absent), therefore it can only dlsym the real exported primitives and must // re-implement those inline wrappers on top of them. dlsym'ing the wrapper names -// directly returns nullptr, so the surface previously crashed on first use (as -// seen when running ANGLE's EGLWaylandTest with SwiftShader). +// directly just returns nullptr, which would crash on first use. struct LibWaylandClientExports { LibWaylandClientExports() {} @@ -40,10 +39,16 @@ void (*wl_event_queue_destroy)(wl_event_queue *queue) = nullptr; // Real exported primitives: proxy marshalling and lifetime. - wl_proxy *(*wl_proxy_marshal_flags)(wl_proxy *proxy, uint32_t opcode, const wl_interface *interface, uint32_t version, uint32_t flags, ...) = nullptr; + // Requests are marshalled with the wl_proxy_marshal[_constructor[_versioned]] + // trio (available since libwayland 1.2) rather than the newer + // wl_proxy_marshal_flags (1.20 / 1.19.91), so this builds and runs against + // older libwayland too. These are exactly the primitives the generated + // static-inline wrappers used prior to 1.20. + void (*wl_proxy_marshal)(wl_proxy *proxy, uint32_t opcode, ...) = nullptr; + wl_proxy *(*wl_proxy_marshal_constructor)(wl_proxy *proxy, uint32_t opcode, const wl_interface *interface, ...) = nullptr; + wl_proxy *(*wl_proxy_marshal_constructor_versioned)(wl_proxy *proxy, uint32_t opcode, const wl_interface *interface, uint32_t version, ...) = nullptr; int (*wl_proxy_add_listener)(wl_proxy *proxy, void (**implementation)(void), void *data) = nullptr; void (*wl_proxy_destroy)(wl_proxy *proxy) = nullptr; - uint32_t (*wl_proxy_get_version)(wl_proxy *proxy) = nullptr; void (*wl_proxy_set_queue)(wl_proxy *proxy, wl_event_queue *queue) = nullptr; void *(*wl_proxy_create_wrapper)(void *proxy) = nullptr; void (*wl_proxy_wrapper_destroy)(void *proxy_wrapper) = nullptr;