mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-11-23 14:40:14 +00:00
Library Forwarding: Support GL forwarding with guest-libX11
This commit is contained in:
parent
997d1bf04b
commit
a114850c2a
@ -2,9 +2,6 @@
|
||||
"DB": {
|
||||
"GL": {
|
||||
"Library" : "libGL-guest.so",
|
||||
"Depends": [
|
||||
"X11"
|
||||
],
|
||||
"Overlay": [
|
||||
"@PREFIX_LIB@/libGL.so",
|
||||
"@PREFIX_LIB@/libGL.so.1",
|
||||
|
@ -466,12 +466,22 @@ constexpr bool IsCompatible() {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct decaying_host_layout {
|
||||
host_layout<T> data;
|
||||
operator T() {
|
||||
return data.data;
|
||||
}
|
||||
};
|
||||
|
||||
template<ParameterAnnotations Annotation, typename HostT, typename T>
|
||||
auto Projection(guest_layout<T>& data) {
|
||||
if constexpr (Annotation.is_passthrough) {
|
||||
return data;
|
||||
} else if constexpr ((IsCompatible<T, Annotation>() && std::is_same_v<T, HostT>) || !std::is_pointer_v<T>) {
|
||||
return host_layout<HostT> {data}.data;
|
||||
// Instead of using host_layout<HostT> { data }.data, return a wrapper object.
|
||||
// This ensures that temporary lifetime extension can kick in at call-site.
|
||||
return decaying_host_layout<HostT> {.data {data}};
|
||||
} else {
|
||||
// This argument requires temporary storage for repacked data
|
||||
// *and* it needs to call custom repack functions (if any)
|
||||
|
@ -18,6 +18,7 @@ $end_info$
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
#include <dlfcn.h>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
@ -72,8 +73,20 @@ voidFunc* glXGetProcAddressARB(const GLubyte* procname) {
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper around malloc() without noexcept specifiers
|
||||
static void* malloc_wrapper(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void OnInit() {
|
||||
fexfn_pack_SetGuestMalloc((uintptr_t)malloc_wrapper, (uintptr_t)CallbackUnpack<decltype(malloc_wrapper)>::Unpack);
|
||||
fexfn_pack_SetGuestXSync((uintptr_t)XSync, (uintptr_t)CallbackUnpack<decltype(XSync)>::Unpack);
|
||||
fexfn_pack_SetGuestXGetVisualInfo((uintptr_t)XGetVisualInfo, (uintptr_t)CallbackUnpack<decltype(XGetVisualInfo)>::Unpack);
|
||||
fexfn_pack_SetGuestXDisplayString((uintptr_t)XDisplayString, (uintptr_t)CallbackUnpack<decltype(XDisplayString)>::Unpack);
|
||||
}
|
||||
|
||||
// libGL.so must pull in libX11.so as a dependency. Referencing some libX11
|
||||
// symbol here prevents the linker from optimizing away the unused dependency
|
||||
auto implicit_libx11_dependency = XSetErrorHandler;
|
||||
|
||||
LOAD_LIB(libGL)
|
||||
LOAD_LIB_INIT(libGL, OnInit)
|
||||
|
@ -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)
|
||||
|
@ -19,7 +19,21 @@ struct fex_gen_config {
|
||||
};
|
||||
|
||||
template<>
|
||||
struct fex_gen_config<glXGetProcAddress> : fexgen::custom_guest_entrypoint, fexgen::returns_guest_pointer {};
|
||||
struct fex_gen_config<glXGetProcAddress> : fexgen::custom_host_impl, fexgen::custom_guest_entrypoint, fexgen::returns_guest_pointer {};
|
||||
|
||||
// internal use
|
||||
void SetGuestMalloc(uintptr_t, uintptr_t);
|
||||
void SetGuestXSync(uintptr_t, uintptr_t);
|
||||
void SetGuestXGetVisualInfo(uintptr_t, uintptr_t);
|
||||
void SetGuestXDisplayString(uintptr_t, uintptr_t);
|
||||
template<>
|
||||
struct fex_gen_config<SetGuestMalloc> : fexgen::custom_guest_entrypoint, fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_config<SetGuestXSync> : fexgen::custom_guest_entrypoint, fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_config<SetGuestXGetVisualInfo> : fexgen::custom_guest_entrypoint, fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_config<SetGuestXDisplayString> : fexgen::custom_guest_entrypoint, fexgen::custom_host_impl {};
|
||||
|
||||
template<typename>
|
||||
struct fex_gen_type {};
|
||||
@ -37,21 +51,23 @@ struct fex_gen_type<_cl_context> : fexgen::opaque_type {};
|
||||
template<>
|
||||
struct fex_gen_type<_cl_event> : fexgen::opaque_type {};
|
||||
|
||||
// Opaque for the purpose of libGL
|
||||
// host_layout is manually customized for this. Mark as opaque to please the interface parser
|
||||
template<>
|
||||
struct fex_gen_type<_XDisplay> : fexgen::opaque_type {};
|
||||
|
||||
#ifndef IS_32BIT_THUNK
|
||||
// TODO: These are largely compatible, *but* contain function pointer members that need adjustment!
|
||||
template<>
|
||||
struct fex_gen_type<XExtData> : fexgen::assume_compatible_data_layout {};
|
||||
#endif
|
||||
struct fex_gen_type<XVisualInfo> : fexgen::emit_layout_wrappers {};
|
||||
template<>
|
||||
struct fex_gen_type<Visual> : fexgen::opaque_type {}; // Used in XVisualInfo; treat as opaque
|
||||
|
||||
// Symbols queryable through glXGetProcAddr
|
||||
namespace internal {
|
||||
template<auto>
|
||||
struct fex_gen_config : fexgen::generate_guest_symtable, fexgen::indirect_guest_calls {};
|
||||
|
||||
template<auto, int, typename = void>
|
||||
struct fex_gen_param {};
|
||||
|
||||
template<>
|
||||
struct fex_gen_config<glXQueryCurrentRendererStringMESA> {};
|
||||
template<>
|
||||
@ -65,9 +81,11 @@ struct fex_gen_config<glXImportContextEXT> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetCurrentReadDrawableSGI> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXChooseFBConfigSGIX> {};
|
||||
struct fex_gen_config<glXChooseFBConfigSGIX> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetFBConfigFromVisualSGIX> {};
|
||||
struct fex_gen_config<glXGetFBConfigFromVisualSGIX> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_param<glXGetFBConfigFromVisualSGIX, 1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreateGLXPbufferSGIX> {};
|
||||
template<>
|
||||
@ -119,7 +137,9 @@ struct fex_gen_config<glXReleaseTexImageEXT> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXSelectEventSGIX> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetVisualFromFBConfigSGIX> {};
|
||||
struct fex_gen_config<glXGetVisualFromFBConfigSGIX> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_param<glXGetVisualFromFBConfigSGIX, -1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetClientString> {};
|
||||
template<>
|
||||
@ -129,7 +149,9 @@ struct fex_gen_config<glXQueryServerString> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetCurrentDisplay> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreateContext> {};
|
||||
struct fex_gen_config<glXCreateContext> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_param<glXCreateContext, 1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreateNewContext> {};
|
||||
template<>
|
||||
@ -139,19 +161,23 @@ struct fex_gen_config<glXGetCurrentDrawable> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetCurrentReadDrawable> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXChooseFBConfig> {};
|
||||
struct fex_gen_config<glXChooseFBConfig> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetFBConfigs> {};
|
||||
struct fex_gen_config<glXGetFBConfigs> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreatePbuffer> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreateGLXPixmap> {};
|
||||
struct fex_gen_config<glXCreateGLXPixmap> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_param<glXCreateGLXPixmap, 1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreatePixmap> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreateWindow> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetConfig> {};
|
||||
struct fex_gen_config<glXGetConfig> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_param<glXGetConfig, 1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetFBConfigAttrib> {};
|
||||
template<>
|
||||
@ -195,9 +221,13 @@ struct fex_gen_config<glXUseXFont> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXWaitGL> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXChooseVisual> {};
|
||||
struct fex_gen_config<glXChooseVisual> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetVisualFromFBConfig> {};
|
||||
struct fex_gen_param<glXChooseVisual, -1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetVisualFromFBConfig> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_param<glXGetVisualFromFBConfig, -1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
|
||||
// template<> struct fex_gen_config<glXCreateContextAttribs> {};
|
||||
template<>
|
||||
@ -6179,7 +6209,9 @@ struct fex_gen_config<glXGetCurrentDisplayEXT> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXGetAGPOffsetMESA> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXCreateGLXPixmapMESA> {};
|
||||
struct fex_gen_config<glXCreateGLXPixmapMESA> : fexgen::custom_host_impl {};
|
||||
template<>
|
||||
struct fex_gen_param<glXCreateGLXPixmapMESA, 1, XVisualInfo*> : fexgen::ptr_passthrough {};
|
||||
template<>
|
||||
struct fex_gen_config<glXReleaseBuffersMESA> {};
|
||||
template<>
|
||||
@ -6193,7 +6225,7 @@ struct fex_gen_config<glXCopyImageSubDataNV> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXDelayBeforeSwapNV> {};
|
||||
template<>
|
||||
struct fex_gen_config<glXEnumerateVideoDevicesNV> {};
|
||||
struct fex_gen_config<glXEnumerateVideoDevicesNV> {}; // TODO: Custom host impl
|
||||
template<>
|
||||
struct fex_gen_config<glXBindVideoDeviceNV> {};
|
||||
template<>
|
||||
|
Loading…
Reference in New Issue
Block a user