Instantly share code, notes, and snippets.

@jsimmons /demo.c
Last active Aug 29, 2016

Embed
What would you like to do?
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

This comment has been minimized.

Show comment
Hide comment
@jsimmons

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

Owner

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