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;