blob: 4d22dfe3897a62f1725e9ce1ecb1ebfad3b1bf94 [file]
// 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