Skip to content

Instantly share code, notes, and snippets.

@jsimmons
Last active August 7, 2023 03:49
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jsimmons/0740ab730fb375f928e7 to your computer and use it in GitHub Desktop.
Save jsimmons/0740ab730fb375f928e7 to your computer and use it in GitHub Desktop.
Minimal OpenGL X11 Demo Linux
#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"
);
#!/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
@jsimmons
Copy link
Author

jsimmons commented Apr 8, 2016

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. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment