Library Forwarding: Support GL forwarding with guest-libX11

This commit is contained in:
Tony Wasserka committed 2024-05-02 17:59:28 +02:00
1 parent 997d1bf04b
commit a114850c2a
5 files changed
+261 -28

No files matched your search

+186 -5
View File
@@ -6,7 +6,8 @@ $end_info$
*/
#include <cstdio>
#include <dlfcn.h>
#include <cstdlib>
#include <string_view>
#define GL_GLEXT_PROTOTYPES 1
#define GLX_GLXEXT_PROTOTYPES 1
@@ -17,15 +18,195 @@ $end_info$
#include <GL/glxext.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <cstdlib>
#include <xcb/xcb.h>
#include "common/Host.h"
#include "common/X11Manager.h"
template<>
struct host_layout<_XDisplay*> {
_XDisplay* data;
_XDisplay* guest_display;
host_layout(guest_layout<_XDisplay*>&);
~host_layout();
};
static X11Manager x11_manager;
static void* (*GuestMalloc)(size_t) = nullptr;
host_layout<_XDisplay*>::host_layout(guest_layout<_XDisplay*>& guest)
: guest_display(guest.force_get_host_pointer()) {
data = x11_manager.GuestToHostDisplay(guest_display);
}
host_layout<_XDisplay*>::~host_layout() {
// Flush host-side event queue to make effects of the guest-side connection visible
x11_manager.HostXFlush(data);
}
static void fexfn_impl_libGL_SetGuestMalloc(uintptr_t GuestTarget, uintptr_t GuestUnpacker) {
MakeHostTrampolineForGuestFunctionAt(GuestTarget, GuestUnpacker, &GuestMalloc);
}
static void fexfn_impl_libGL_SetGuestXGetVisualInfo(uintptr_t GuestTarget, uintptr_t GuestUnpacker) {
MakeHostTrampolineForGuestFunctionAt(GuestTarget, GuestUnpacker, &x11_manager.GuestXGetVisualInfo);
}
static void fexfn_impl_libGL_SetGuestXSync(uintptr_t GuestTarget, uintptr_t GuestUnpacker) {
MakeHostTrampolineForGuestFunctionAt(GuestTarget, GuestUnpacker, &x11_manager.GuestXSync);
}
static void fexfn_impl_libGL_SetGuestXDisplayString(uintptr_t GuestTarget, uintptr_t GuestUnpacker) {
MakeHostTrampolineForGuestFunctionAt(GuestTarget, GuestUnpacker, &x11_manager.GuestXDisplayString);
}
#include "thunkgen_host_libGL.inl"
void* symbolFromGlXGetProcAddr(void*, const char* name) {
return (void*)glXGetProcAddress((const GLubyte*)name);
auto fexfn_impl_libGL_glXGetProcAddress(const GLubyte* name) -> void (*)() {
using VoidFn = void (*)();
std::string_view name_sv {reinterpret_cast<const char*>(name)};
if (name_sv == "glXChooseFBConfig") {
return (VoidFn)fexfn_impl_libGL_glXChooseFBConfig;
} else if (name_sv == "glXChooseFBConfigSGIX") {
return (VoidFn)fexfn_impl_libGL_glXChooseFBConfigSGIX;
} else if (name_sv == "glXGetFBConfigs") {
return (VoidFn)fexfn_impl_libGL_glXGetFBConfigs;
} else if (name_sv == "glXGetFBConfigFromVisualSGIX") {
return (VoidFn)fexfn_impl_libGL_glXGetFBConfigFromVisualSGIX;
} else if (name_sv == "glXGetVisualFromFBConfigSGIX") {
return (VoidFn)fexfn_impl_libGL_glXGetVisualFromFBConfigSGIX;
} else if (name_sv == "glXChooseVisual") {
return (VoidFn)fexfn_impl_libGL_glXChooseVisual;
} else if (name_sv == "glXCreateContext") {
return (VoidFn)fexfn_impl_libGL_glXCreateContext;
} else if (name_sv == "glXCreateGLXPixmap") {
return (VoidFn)fexfn_impl_libGL_glXCreateGLXPixmap;
} else if (name_sv == "glXCreateGLXPixmapMESA") {
return (VoidFn)fexfn_impl_libGL_glXCreateGLXPixmapMESA;
} else if (name_sv == "glXGetConfig") {
return (VoidFn)fexfn_impl_libGL_glXGetConfig;
} else if (name_sv == "glXGetVisualFromFBConfig") {
return (VoidFn)fexfn_impl_libGL_glXGetVisualFromFBConfig;
}
return (VoidFn)glXGetProcAddress((const GLubyte*)name);
}
// Relocate data to guest heap so it can be called with XFree.
// The memory at the given host location will be de-allocated.
template<typename T>
T* RelocateArrayToGuestHeap(T* Data, int NumItems) {
if (!Data) {
return nullptr;
}
guest_layout<T*> GuestData;
GuestData.data = reinterpret_cast<uintptr_t>(GuestMalloc(sizeof(guest_layout<T>) * NumItems));
for (int Index = 0; Index < NumItems; ++Index) {
GuestData.get_pointer()[Index] = to_guest(to_host_layout(Data[Index]));
}
x11_manager.HostXFree(Data);
return GuestData.force_get_host_pointer();
}
// Maps to a host-side XVisualInfo, which must be XFree'ed by the caller.
static XVisualInfo* LookupHostVisualInfo(Display* HostDisplay, guest_layout<XVisualInfo*> GuestInfo) {
if (!GuestInfo.data) {
return nullptr;
}
int num_matches;
auto ret = x11_manager.HostXGetVisualInfo(HostDisplay, VisualScreenMask | VisualIDMask, GuestInfo.force_get_host_pointer(), &num_matches);
if (num_matches != 1) {
fprintf(stderr, "ERROR: Did not find unique host XVisualInfo\n");
std::abort();
}
return ret;
}
// Maps to a guest-side XVisualInfo and destroys the host argument.
static guest_layout<XVisualInfo*> MapToGuestVisualInfo(Display* HostDisplay, XVisualInfo* HostInfo) {
if (!HostInfo) {
return guest_layout<XVisualInfo*> {.data = 0};
}
int num_matches;
auto guest_display = x11_manager.HostToGuestDisplay(HostDisplay);
auto ret = x11_manager.GuestXGetVisualInfo(guest_display.get_pointer(), VisualScreenMask | VisualIDMask, HostInfo, &num_matches);
if (num_matches != 1) {
fprintf(stderr, "ERROR: Did not find unique guest XVisualInfo\n");
std::abort();
}
// We effectively relocated the VisualInfo, so free the original one now
x11_manager.HostXFree(HostInfo);
guest_layout<XVisualInfo*> GuestRet;
GuestRet.data = reinterpret_cast<uintptr_t>(ret);
return GuestRet;
}
GLXFBConfig* fexfn_impl_libGL_glXChooseFBConfig(Display* Display, int Screen, const int* Attributes, int* NumItems) {
auto ret = fexldr_ptr_libGL_glXChooseFBConfig(Display, Screen, Attributes, NumItems);
return RelocateArrayToGuestHeap(ret, *NumItems);
}
GLXFBConfigSGIX* fexfn_impl_libGL_glXChooseFBConfigSGIX(Display* Display, int Screen, int* Attributes, int* NumItems) {
auto ret = fexldr_ptr_libGL_glXChooseFBConfigSGIX(Display, Screen, Attributes, NumItems);
return RelocateArrayToGuestHeap(ret, *NumItems);
}
GLXFBConfig* fexfn_impl_libGL_glXGetFBConfigs(Display* Display, int Screen, int* NumItems) {
auto ret = fexldr_ptr_libGL_glXGetFBConfigs(Display, Screen, NumItems);
return RelocateArrayToGuestHeap(ret, *NumItems);
}
GLXFBConfigSGIX fexfn_impl_libGL_glXGetFBConfigFromVisualSGIX(Display* Display, guest_layout<XVisualInfo*> Info) {
auto HostInfo = LookupHostVisualInfo(Display, Info);
auto ret = fexldr_ptr_libGL_glXGetFBConfigFromVisualSGIX(Display, HostInfo);
x11_manager.HostXFree(HostInfo);
return ret;
}
guest_layout<XVisualInfo*> fexfn_impl_libGL_glXGetVisualFromFBConfigSGIX(Display* Display, GLXFBConfigSGIX Config) {
return MapToGuestVisualInfo(Display, fexldr_ptr_libGL_glXGetVisualFromFBConfigSGIX(Display, Config));
}
guest_layout<XVisualInfo*> fexfn_impl_libGL_glXChooseVisual(Display* Display, int Screen, int* Attributes) {
return MapToGuestVisualInfo(Display, fexldr_ptr_libGL_glXChooseVisual(Display, Screen, Attributes));
}
GLXContext fexfn_impl_libGL_glXCreateContext(Display* Display, guest_layout<XVisualInfo*> Info, GLXContext ShareList, Bool Direct) {
auto HostInfo = LookupHostVisualInfo(Display, Info);
auto ret = fexldr_ptr_libGL_glXCreateContext(Display, HostInfo, ShareList, Direct);
x11_manager.HostXFree(HostInfo);
return ret;
}
GLXPixmap fexfn_impl_libGL_glXCreateGLXPixmap(Display* Display, guest_layout<XVisualInfo*> Info, Pixmap Pixmap) {
auto HostInfo = LookupHostVisualInfo(Display, Info);
auto ret = fexldr_ptr_libGL_glXCreateGLXPixmap(Display, HostInfo, Pixmap);
x11_manager.HostXFree(HostInfo);
return ret;
}
GLXPixmap fexfn_impl_libGL_glXCreateGLXPixmapMESA(Display* Display, guest_layout<XVisualInfo*> Info, Pixmap Pixmap, Colormap Colormap) {
auto HostInfo = LookupHostVisualInfo(Display, Info);
auto ret = fexldr_ptr_libGL_glXCreateGLXPixmapMESA(Display, HostInfo, Pixmap, Colormap);
x11_manager.HostXFree(HostInfo);
return ret;
}
int fexfn_impl_libGL_glXGetConfig(Display* Display, guest_layout<XVisualInfo*> Info, int Attribute, int* Value) {
auto HostInfo = LookupHostVisualInfo(Display, Info);
auto ret = fexldr_ptr_libGL_glXGetConfig(Display, HostInfo, Attribute, Value);
x11_manager.HostXFree(HostInfo);
return ret;
}
guest_layout<XVisualInfo*> fexfn_impl_libGL_glXGetVisualFromFBConfig(Display* Display, GLXFBConfig Config) {
return MapToGuestVisualInfo(Display, fexldr_ptr_libGL_glXGetVisualFromFBConfig(Display, Config));
}
EXPORTS(libGL)