Skip to content

Instantly share code, notes, and snippets.

@sulix
Last active April 25, 2022 08:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sulix/fe951daaeb4e51dfb329e5935e705cbf to your computer and use it in GitHub Desktop.
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
// A hacky implementation of just the bits of GLX that Cg requires on top of SDL2
//
// All blame should go to David Gow <david@davidgow.net>
//
// 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