Last active
August 7, 2023 03:49
-
-
Save jsimmons/0740ab730fb375f928e7 to your computer and use it in GitHub Desktop.
Minimal OpenGL X11 Demo Linux
This file contains 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
#include <stdint.h> | |
#include <X11/Xlib.h> | |
#include <X11/XKBlib.h> | |
#include <GL/glx.h> | |
#include <GL/gl.h> | |
#include <dlfcn.h> | |
#include <stdio.h> | |
#include <sys/syscall.h> | |
#include <time.h> | |
#define SCRW 800 | |
#define SCRH 600 | |
static __inline long __syscall2(long n, long a1, long a2) | |
{ | |
unsigned long ret; | |
__asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) | |
: "rcx", "r11", "memory"); | |
return ret; | |
} | |
static __inline uint64_t time_monotonic(void) | |
{ | |
struct timespec now; | |
__syscall2(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, (long)&now); | |
return now.tv_sec * 1000000 + now.tv_nsec / 1000; | |
} | |
static int visual_hints[] = { | |
GLX_RGBA, | |
GLX_DEPTH_SIZE, 24, | |
GLX_DOUBLEBUFFER, | |
None | |
}; | |
static const char *sym_names = | |
"libX11.so\0" | |
"XOpenDisplay\0" | |
"XCreateSimpleWindow\0" | |
"XSelectInput\0" | |
"XMapWindow\0" | |
"XPending\0" | |
"XNextEvent\0" | |
"XkbKeycodeToKeysym\0" | |
"\0" | |
"libGL.so\0" | |
"glXChooseVisual\0" | |
"glXCreateContext\0" | |
"glXMakeCurrent\0" | |
"glXSwapBuffers\0" | |
"glClear\0\0\0"; | |
static void *syms[12]; | |
#define _XOpenDisplay ((Display *(*)(const char *))syms[0]) | |
#define _XCreateSimpleWindow ((Window (*)(Display *, Window, int, int, unsigned, unsigned, unsigned, unsigned long, unsigned long))syms[1]) | |
#define _XSelectInput ((int (*)(Display *, Window, long))syms[2]) | |
#define _XMapWindow ((int (*)(Display *, Window))syms[3]) | |
#define _XPending ((int (*)(Display *))syms[4]) | |
#define _XNextEvent ((int (*)(Display *, XEvent *))syms[5]) | |
#define _XkbKeycodeToKeysym ((KeySym (*)(Display *, KeyCode, int, int))syms[6]) | |
#define _glXChooseVisual ((XVisualInfo *(*)(Display *, int, int *))syms[7]) | |
#define _glXCreateContext ((GLXContext (*)(Display *, XVisualInfo *, GLXContext, Bool))syms[8]) | |
#define _glXMakeCurrent ((Bool (*)(Display *, GLXDrawable, GLXContext))syms[9]) | |
#define _glXSwapBuffers ((void (*)(Display *, GLXDrawable))syms[10]) | |
#define _glClear ((void (*)(GLbitfield))syms[11]) | |
static void dl_load(void) | |
{ | |
const char *name = sym_names; | |
void **sym = syms; | |
do | |
{ | |
void *dl = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); | |
for(;;) | |
{ | |
while(*name++); | |
if(*name == 0) break; | |
*sym++ = dlsym(dl, name); | |
} | |
} while(*++name); | |
} | |
void my_main(int argc, const char **argv) | |
{ | |
dl_load(); | |
Display *display = _XOpenDisplay(NULL); | |
int screen = DefaultScreen(display); | |
Window window = _XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, SCRW, SCRH, 0, 0, 0); | |
_XSelectInput(display, window, KeyPressMask | KeyReleaseMask); | |
XVisualInfo *visual_info = _glXChooseVisual(display, screen, visual_hints); | |
GLXContext context = _glXCreateContext(display, visual_info, NULL, True); | |
_glXMakeCurrent(display, window, context); | |
_XMapWindow(display, window); | |
uint64_t prev = time_monotonic(); | |
uint64_t t = 0; | |
for(;;) | |
{ | |
XEvent event; | |
while(_XPending(display)) | |
{ | |
_XNextEvent(display, &event); | |
if(event.type == KeyPress) | |
{ | |
switch(_XkbKeycodeToKeysym(display, event.xkey.keycode, 0, 0)) | |
{ | |
case XK_Escape: goto shutdown; | |
} | |
} | |
} | |
// draw demo | |
_glClear(GL_COLOR_BUFFER_BIT); | |
_glXSwapBuffers(display, window); | |
t += time_monotonic() - prev; | |
} | |
shutdown: | |
return; | |
} | |
asm ( | |
".text\n" | |
".global _start\n" | |
"_start:\n" | |
"xor %rbp,%rbp\n" | |
"pop %rdi\n" | |
"mov %rsp,%rsi\n" | |
"andq $-16,%rsp\n" | |
"call my_main\n" | |
"movq $60,%rax\n" | |
"xor %rdi,%rdi\n" | |
"syscall\n" | |
); |
This file contains 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
#!/bin/bash | |
clang -Os -fomit-frame-pointer -nostdlib -ldl demo.c -o demo.o -Wl, -s | |
echo "a=/tmp/I;tail -n+2 \$0|unxz>\$a;chmod +x \$a;\$a;exit" > 4k | |
xz -zce -9 demo.o >> 4k | |
chmod +x 4k |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also I should probably note here that you can't just go grabbing all the GL symbols from libGL.so, at least not everywhere.
But to fix that I'd have to mess with the beautiful symbol loader so for now it's just broken on mesa drivers. :)