mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-11-23 22:50:24 +00:00
Library Forwarding/wayland: Avoid using global state to substitute callback tables
The pointer tracked internally by Wayland can be queried via wl_proxy_get_listener, so we don't need our own bookkeeping. This also changes the callback table's element type to a fixed-size uint64_t, which makes it work for 32-bit guests.
This commit is contained in:
parent
3c0b041c44
commit
b9f2389d74
@ -33,7 +33,6 @@ extern "C" const wl_interface wl_callback_interface {};
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/Guest.h"
|
||||
|
||||
@ -51,27 +50,21 @@ template<> struct ArgType<'f'> { using type = wl_fixed_t; };
|
||||
template<> struct ArgType<'h'> { using type = int32_t; }; // fd?
|
||||
|
||||
template<char... Signature>
|
||||
static void* WaylandAllocateHostTrampolineForGuestListener(void (*callback)()) {
|
||||
static uint64_t WaylandAllocateHostTrampolineForGuestListener(void (*callback)()) {
|
||||
using cb = void(void*, wl_proxy*, typename ArgType<Signature>::type...);
|
||||
return (void*)AllocateHostTrampolineForGuestFunction((cb*)callback);
|
||||
return (uint64_t)(uintptr_t)(void*)AllocateHostTrampolineForGuestFunction((cb*)callback);
|
||||
}
|
||||
|
||||
#define WL_CLOSURE_MAX_ARGS 20
|
||||
|
||||
// Per-proxy list of callbacks set up via wl_proxy_add_listener.
|
||||
// These tables store the host-callable trampolines to the actual listener
|
||||
// callbacks provided by the guest application.
|
||||
// NOTE: There can only be one listener per proxy. Wayland will return an error
|
||||
// if wl_proxy_add_listener is called twice.
|
||||
// NOTE: Entries should be removed in wl_destroy_proxy. Since proxy wrappers do
|
||||
// not use their own listeners, wl_proxy_wrapper_destroy does not need to
|
||||
// be customized.
|
||||
static std::unordered_map<wl_proxy*, std::array<void*, WL_CLOSURE_MAX_ARGS>> proxy_listeners;
|
||||
|
||||
extern "C" int wl_proxy_add_listener(wl_proxy *proxy,
|
||||
void (**callback)(void), void *data) {
|
||||
// NOTE: This table must remain valid past the return of this function.
|
||||
auto& host_callbacks = proxy_listeners[proxy];
|
||||
// Replace guest-provided callback table with host-callable function pointers
|
||||
// NOTE: A reference to this table is stored in the wl_proxy, so the data
|
||||
// must remain valid until the proxy is destroyed (or another listener
|
||||
// is added)
|
||||
delete[] (uint64_t*)wl_proxy_get_listener(proxy); // Delete previous substitute, if any
|
||||
auto host_callbacks = new uint64_t[WL_CLOSURE_MAX_ARGS];
|
||||
|
||||
for (int i = 0; i < fex_wl_get_interface_event_count(proxy); ++i) {
|
||||
char event_signature[16];
|
||||
@ -185,12 +178,13 @@ extern "C" int wl_proxy_add_listener(wl_proxy *proxy,
|
||||
}
|
||||
}
|
||||
|
||||
return fexfn_pack_wl_proxy_add_listener(proxy, (void(**)())host_callbacks.data(), data);
|
||||
return fexfn_pack_wl_proxy_add_listener(proxy, (void(**)())host_callbacks, data);
|
||||
}
|
||||
|
||||
extern "C" void wl_proxy_destroy(struct wl_proxy *proxy) {
|
||||
proxy_listeners.erase(proxy);
|
||||
return fexfn_pack_wl_proxy_destroy(proxy);
|
||||
extern "C" void wl_proxy_destroy(wl_proxy *proxy) {
|
||||
// Delete substitute callback table (if any), then the proxy itself
|
||||
delete[] (uint64_t*)wl_proxy_get_listener(proxy);
|
||||
fexfn_pack_wl_proxy_destroy(proxy);
|
||||
}
|
||||
|
||||
// Adapted from the Wayland sources
|
||||
|
@ -51,6 +51,7 @@ template<> struct fex_gen_param<wl_proxy_add_listener, 1, void(**)()> : fexgen::
|
||||
template<> struct fex_gen_param<wl_proxy_add_listener, 2, void*> : fexgen::assume_compatible_data_layout {};
|
||||
template<> struct fex_gen_config<wl_proxy_create> {};
|
||||
template<> struct fex_gen_config<wl_proxy_create_wrapper> {};
|
||||
template<> struct fex_gen_config<wl_proxy_get_listener> {};
|
||||
template<> struct fex_gen_config<wl_proxy_get_tag> {};
|
||||
template<> struct fex_gen_config<wl_proxy_get_user_data> {};
|
||||
template<> struct fex_gen_config<wl_proxy_get_version> {};
|
||||
|
Loading…
Reference in New Issue
Block a user