Skip to content

Instantly share code, notes, and snippets.

@skeeto
Last active June 6, 2022 17:30
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 skeeto/8c3502ff22693a9a4f0f7b1efe9c4e0c to your computer and use it in GitHub Desktop.
Save skeeto/8c3502ff22693a9a4f0f7b1efe9c4e0c to your computer and use it in GitHub Desktop.
OpenGL mini framebuffer display example
// cc example.c -lX11 -lGL
// This is free and unencumbered software released into the public domain.
#define GLX_GLXEXT_PROTOTYPES
#include <stdio.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#define WIDTH 256
#define HEIGHT 128
#define SCALE 4
int main(void)
{
Display *d = XOpenDisplay(0);
if (!d) {
fputs("XOpenDisplay\n", stderr);
return 1;
}
static const int attribs[] = {
GLX_X_RENDERABLE, True,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_DOUBLEBUFFER, True,
GLX_SAMPLE_BUFFERS, 1,
GLX_SAMPLES, 4,
None
};
int fbcount;
int screen = DefaultScreen(d);
GLXFBConfig *fbcs = glXChooseFBConfig(d, screen, attribs, &fbcount);
if (!fbcs || !fbcount) {
fputs("glXChooseFBConfig\n", stderr);
return 1;
}
GLXFBConfig fbc = fbcs[0];
XFree(fbcs);
XVisualInfo *vi = glXGetVisualFromFBConfig(d, fbc);
XSetWindowAttributes swa;
swa.colormap = XCreateColormap(d, RootWindow(d, vi->screen), vi->visual, AllocNone);
swa.background_pixmap = None;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
Window win = XCreateWindow(d, RootWindow(d, vi->screen),
0, 0, WIDTH*SCALE, HEIGHT*SCALE,
0, vi->depth, InputOutput, vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa);
if (!win) {
fputs("XCreateWindow\n", stderr);
return 1;
}
XStoreName(d, win, "MCU");
XMapWindow(d, win);
GLXContext ctx = glXCreateContext(d, vi, 0, True);
XFree(vi);
XSync(d, False);
if (!ctx) {
fputs("glXCreateContext\n", stderr);
return 1;
}
glXMakeCurrent(d, win, ctx);
glXSwapIntervalEXT(d, glXGetCurrentDrawable(), 1);
GLuint tex;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
unsigned long long rng = 1;
unsigned char framebuffer[HEIGHT][WIDTH][3];
for (;;) {
// Fill framebuffer with random data for demonstration
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
rng = rng*0x3243f6a8885a308d + 1;
framebuffer[y][x][0] = rng >> 40;
framebuffer[y][x][1] = rng >> 48;
framebuffer[y][x][2] = rng >> 56;
}
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT,
GL_RGB, GL_UNSIGNED_BYTE, framebuffer);
glBegin(GL_QUADS);
glVertex2f(-1, -1); glTexCoord2f(0, 0);
glVertex2f(-1, +1); glTexCoord2f(1, 0);
glVertex2f(+1, +1); glTexCoord2f(1, 1);
glVertex2f(+1, -1); glTexCoord2f(0, 1);
glEnd();
glXSwapBuffers(d, win);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment