Last active
April 25, 2022 08:01
-
-
Save sulix/fe951daaeb4e51dfb329e5935e705cbf to your computer and use it in GitHub Desktop.
A hacky implementation of just the bits of GLX that Cg requires on top of SDL2, so you can run Cg-using games under Wayland
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A hacky implementation of just the bits of GLX that Cg requires on top of SDL2 | |
// | |
// All blame should go to David Gow <[email protected]> | |
// | |
// Build it with: | |
// cc -g -o libglx_wrapper.so glx_wrapper.c `sdl2-config --cflags --libs` -fpic --shared | |
// cc -g -m32 -o libglx_wrapper32.so glx_wrapper.c `/usr/lib/baselibs-32bit/bin/sdl2-config --cflags --libs` -fpic --shared | |
// | |
// Then run your game with: | |
// SDL_VIDEODRIVER=wayland SDL_DYNAMIC_API=path-to/libSDL2-2.0.so.0 LD_PRELOAD=libglx_wrapper.so | |
// (Or libglx_wrapper32.so for a 32-bit game.) | |
// | |
// Depending on the version of Cg being used, you may not be able to use LD_PRELOAD | |
// to inject this, in which case you'll need to do some hex-editing. | |
// To do this: | |
// - Rename libglx_wrapper[32].so → libCgWL.so, and make sure it's in the library search path | |
// - Hex edit the game's libCgGL.so, replacing "libGL.so.1" with "libCgWL.so" | |
// You can do this with: | |
// perl -pe 's/libGL.so.1/libCgWL.so/' <libCgGL.so.bak >libCgGL.so | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include "SDL.h" | |
#include "SDL_opengl.h" | |
#define XLIB_ILLEGAL_ACCESS | |
#include <X11/X.h> | |
#include <X11/Xlib.h> | |
#include <GL/glx.h> | |
Display fakeDisplay; | |
void debugf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); | |
void debugf(const char *format, ...) | |
{ | |
if (!SDL_getenv("FAKEGLX_DEBUG")) | |
return; | |
va_list args; | |
va_start(args, format); | |
vprintf(format, args); | |
va_end(args); | |
} | |
typedef void (*GLfunction)(); | |
__GLXextFuncPtr glXGetProcAddressARB (const GLubyte *name) | |
{ | |
debugf("glGetProcAddressARB(%s)\n", name); | |
return SDL_GL_GetProcAddress(name); | |
} | |
__GLXextFuncPtr glXGetProcAddress (const GLubyte *name) | |
{ | |
debugf("glGetProcAddress(%s)\n", name); | |
return SDL_GL_GetProcAddress(name); | |
} | |
Bool glXQueryVersion(Display *disp, int *major, int *minor) | |
{ | |
debugf("glXQueryVersion(%p, %p, %p)\n"); | |
return false; | |
} | |
GLXContext glXGetCurrentContext() | |
{ | |
debugf("glXGetCurrentContext()\n"); | |
return (GLXContext)0x1234; | |
} | |
Bool glXMakeCurrent(Display * dpy, GLXDrawable drawable, GLXContext ctx) | |
{ | |
debugf("glXMakeCurrent(%p, %p, %p)\n", dpy, drawable, ctx); | |
return True; | |
} | |
void *glXCreateContextWithConfigSGIX(void *dpy, GLXFBConfigSGIX config, int render_type, void *sharelists, bool direct) | |
{ | |
debugf("glXCreateContextWithConfigSGIX(%p, %p, %d, %p, %d)\n", dpy, config, render_type, sharelists, direct); | |
return (void*)0x1234; | |
} | |
Display *glXGetCurrentDisplay() | |
{ | |
debugf("glXGetCurrentDisplay()\n"); | |
return &fakeDisplay; | |
} | |
const GLubyte *APIENTRY glGetString(GLenum str) | |
{ | |
const GLubyte *(APIENTRY * glGetStringFunc) (GLenum); | |
debugf("glGetString(%x)\n", str); | |
glGetStringFunc = SDL_GL_GetProcAddress("glGetString"); | |
return glGetStringFunc(str); | |
} | |
const char * glXQueryExtensionsString(Display *dpy, int screen) | |
{ | |
const GLubyte *(APIENTRY * glGetStringFunc) (GLenum); | |
debugf("glXQueryExtensionsString(%p, %d)\n", dpy, screen); | |
glGetStringFunc = SDL_GL_GetProcAddress("glGetString"); | |
return glGetStringFunc(GL_EXTENSIONS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment