| // Copyright 2022 The SwiftShader Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef libWaylandClient_hpp |
| #define libWaylandClient_hpp |
| |
| #include <wayland-client.h> |
| |
| // The Wayland protocol functions used by the WSI (wl_display_get_registry, |
| // wl_registry_bind, wl_surface_attach, wl_shm_create_pool, ...) are NOT real |
| // symbols exported by libwayland-client.so; they are `static inline` wrappers |
| // generated into <wayland-client-protocol.h> that marshal requests through the |
| // low-level wl_proxy_* primitives. SwiftShader loads libwayland-client.so |
| // 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 just returns nullptr, which would crash on first use. |
| struct LibWaylandClientExports |
| { |
| LibWaylandClientExports() {} |
| LibWaylandClientExports(void *libwl); |
| |
| // Real exported primitives: display and event-queue handling. |
| int (*wl_display_dispatch_queue)(wl_display *display, wl_event_queue *queue) = nullptr; |
| int (*wl_display_roundtrip_queue)(wl_display *display, wl_event_queue *queue) = nullptr; |
| int (*wl_display_flush)(wl_display *display) = nullptr; |
| wl_event_queue *(*wl_display_create_queue)(wl_display *display) = nullptr; |
| void (*wl_event_queue_destroy)(wl_event_queue *queue) = nullptr; |
| |
| // Real exported primitives: proxy marshalling and lifetime. |
| // 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; |
| 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; |
| |
| // Real exported data symbols: protocol interface descriptions. |
| const wl_interface *wl_registry_interface = nullptr; |
| const wl_interface *wl_shm_interface = nullptr; |
| const wl_interface *wl_shm_pool_interface = nullptr; |
| const wl_interface *wl_surface_interface = nullptr; |
| const wl_interface *wl_buffer_interface = nullptr; |
| |
| // Re-implementations of the generated static-inline protocol wrappers, built |
| // on top of the loaded primitives above. |
| wl_registry *display_get_registry(wl_display *display); |
| int registry_add_listener(wl_registry *registry, const wl_registry_listener *listener, void *data); |
| void *registry_bind(wl_registry *registry, uint32_t name, const wl_interface *interface, uint32_t version); |
| wl_shm_pool *shm_create_pool(wl_shm *shm, int32_t fd, int32_t size); |
| wl_buffer *shm_pool_create_buffer(wl_shm_pool *pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format); |
| void shm_pool_destroy(wl_shm_pool *pool); |
| int buffer_add_listener(wl_buffer *buffer, const wl_buffer_listener *listener, void *data); |
| void buffer_destroy(wl_buffer *buffer); |
| void surface_attach(wl_surface *surface, wl_buffer *buffer, int32_t x, int32_t y); |
| void surface_damage(wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height); |
| void surface_commit(wl_surface *surface); |
| |
| // True when every primitive and interface required by the WSI resolved. |
| bool loaded() const; |
| }; |
| |
| class LibWaylandClient |
| { |
| public: |
| bool isPresent() |
| { |
| return loadExports() != nullptr; |
| } |
| |
| LibWaylandClientExports *operator->(); |
| |
| private: |
| LibWaylandClientExports *loadExports(); |
| }; |
| |
| extern LibWaylandClient libWaylandClient; |
| |
| #endif // libWaylandClient_hpp |