Add xlib example

This commit is contained in:
blackle 2019-04-02 01:13:23 -04:00
parent e692a1e447
commit fc598a3404
4 changed files with 176 additions and 6 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.elf
gtk-webkit
gtk-opengl
shader.h
xlib-opengl
shader.h

View File

@ -1,5 +1,5 @@
all : gtk-webkit gtk-opengl
all : gtk-webkit gtk-opengl xlib-opengl
.PHONY: clean
@ -16,12 +16,18 @@ gtk-webkit.elf : gtk-webkit.c Makefile
gtk-opengl.elf : gtk-opengl.c shader.h Makefile
gcc -o $@ $< `pkg-config --cflags gtk+-3.0` -lglib-2.0 -lGL -lgtk-3 -lgdk-3 -lgobject-2.0 -no-pie -fno-plt -Os -std=gnu11 -nostartfiles -nostdlib
xlib-opengl.elf : xlib-opengl.c shader.h Makefile
gcc -o $@ $< -lX11 -lGL -lcairo -lXrandr -no-pie -fno-plt -Os -std=gnu11 -nostartfiles -nostdlib
gtk-webkit : gtk-webkit_opt.elf.packed
mv $< $@
gtk-opengl : gtk-opengl_opt.elf.packed
mv $< $@
xlib-opengl : xlib-opengl_opt.elf.packed
mv $< $@
#all the rest of these rules just takes a compiled elf file and generates a packed version of it with vondehi
%_opt.elf : %.elf Makefile
@ -50,4 +56,4 @@ gtk-opengl : gtk-opengl_opt.elf.packed
wc -c $@
clean :
-rm *.elf shader.h gtk-webkit
-rm *.elf shader.h gtk-webkit gtk-opengl xlib-opengl

View File

@ -1,11 +1,15 @@
# Linux-OpenGL-Examples
Some code examples for opening windows for various purposes in very few bytes.
Some code examples for opening windows for various purposes in very few bytes. Unfortunately each example does its own thing, so comparing the sizes is an apple to oranges thing.
## gtk-opengl - 1585 bytes
Example code for opening a glsl shader fullscreen with gtk. Closes with the standard alt+f4 on Ubuntu. Shaders get passed an iTime uniform in seconds. App closes automatically after 10 seconds.
Example code for opening a glsl shader fullscreen with gtk. Closes with the standard ALT+F4 on Ubuntu. Shaders get passed an iTime uniform in seconds. App closes automatically after 10 seconds.
## gtk-webkit - 1074 bytes
Example code for opening an html page fullscreen with gtk. Closes with the standard alt+f4 on Ubuntu. WebGL is enabled however is not used in the example. Testing with webkit gtk has found that most(?) shadertoy shaders seem to work. It has yet to be seen if initializing a shader in javascript takes fewer bytes than with gtk's opengl code.
Example code for opening an html page fullscreen with gtk. Closes with the standard ALT+F4 on Ubuntu. WebGL is enabled however is not used in the example. Testing with webkit gtk has found that most(?) shadertoy shaders seem to work. It has yet to be seen if initializing a shader in javascript takes fewer bytes than with gtk's opengl code.
## xlib-opengl
Example code for opening a glsl shader fullscreen with vanilla xlib. Unlike gtk-opengl, this does not pass in an iTime or render the shader more than once, and also must be closed with ESC. This code is based on the code for Cenotaph For Soda, a 4k gfx demo for Revision 2018

159
xlib-opengl.c Normal file
View File

@ -0,0 +1,159 @@
#define GL_GLEXT_PROTOTYPES why
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<stdint.h>
#include<X11/X.h>
#include<X11/Xlib.h>
#include<X11/extensions/Xrandr.h>
#include<GL/gl.h>
#include<GL/glx.h>
#include<GL/glu.h>
#include "shader.h"
#define CANVAS_WIDTH 1920
#define CANVAS_HEIGHT 1080
// #define DEBUG true
static unsigned char fbdata[4 * CANVAS_HEIGHT * CANVAS_WIDTH];
void _start() {
asm volatile("sub $8, %rsp\n");
Display* dpy = XOpenDisplay(NULL);
Window root = DefaultRootWindow(dpy);
static GLint att[] = { GLX_RGBA, None };
XVisualInfo* vi = glXChooseVisual(dpy, 0, att);
//I really hate this and I wish this call was unneeded. it feels useless
Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
//hide cursor
XColor xcolor;
Pixmap csr= XCreatePixmap(dpy,root,1,1,1);
Cursor cursor= XCreatePixmapCursor(dpy,csr,csr,&xcolor,&xcolor,1,1);
//this enables things like events, fullscreen, and sets the invisible cursor
static XSetWindowAttributes swa = { .override_redirect = 1, .event_mask = ExposureMask | KeyPressMask };
swa.colormap = cmap;
swa.cursor = cursor;
Window win = XCreateWindow(dpy, root, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask | CWOverrideRedirect | CWCursor, &swa);
//this actually opens the window
XMapWindow(dpy, win);
//now we can do opengl calls!!!!
GLXContext glc = glXCreateContext(dpy, vi, NULL, 1);
#ifdef DEBUG
if (glc == NULL) {
return;
}
#endif
glXMakeCurrent(dpy, win, glc);
glClear(GL_COLOR_BUFFER_BIT);
//oh yeah grab the keyboard
XGrabKeyboard(dpy, win, true, GrabModeAsync, GrabModeAsync, CurrentTime);
//create a floating point backing texture for a framebuffer
GLuint textureA;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &textureA);
glBindTexture(GL_TEXTURE_2D, textureA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, fbdata);
//create a framebuffer we can render everything to
GLuint fboA;
glGenFramebuffers(1, &fboA);
glBindFramebuffer(GL_FRAMEBUFFER, fboA);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, textureA, 0);
// compile shader
GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, &shader_frag, NULL);
glCompileShader(f);
#ifdef DEBUG
GLint isCompiled = 0;
glGetShaderiv(f, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE) {
GLint maxLength = 0;
glGetShaderiv(f, GL_INFO_LOG_LENGTH, &maxLength);
char* error = malloc(maxLength);
glGetShaderInfoLog(f, maxLength, &maxLength, error);
printf("%s\n", error);
exit(-10);
}
#endif
// link shader
GLuint p = glCreateProgram();
glAttachShader(p,f);
glLinkProgram(p);
#ifdef DEBUG
GLint isLinked = 0;
glGetProgramiv(p, GL_LINK_STATUS, (int *)&isLinked);
if (isLinked == GL_FALSE) {
GLint maxLength = 0;
glGetProgramiv(p, GL_INFO_LOG_LENGTH, &maxLength);
char* error = malloc(maxLength);
glGetProgramInfoLog(p, maxLength, &maxLength,error);
printf("%s\n", error);
exit(-10);
}
#endif
glUseProgram(p);
//switch to using our framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, fboA);
//clear it
// glClear(GL_COLOR_BUFFER_BIT);
//enable additive blending so we don't have to do so in the shader
glEnable(GL_BLEND);
// glBlendEquationSeparate( GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFunc( GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
// glFinish();
glRecti(-1,-1,1,1);
//blit our framebuffer to the screen
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboA);
glBlitFramebuffer(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
static XEvent xev;
while(1) {
XNextEvent(dpy, &xev);
//wait for escape key, then exit without glib :3
if(xev.type == KeyPress && xev.xkey.keycode == 0x09) {
//blackle mori no likey AT&T
asm volatile(".intel_syntax noprefix");
asm volatile("push 60");
asm volatile("pop rax");
asm volatile("xor edi, edi");
asm volatile("syscall");
asm volatile(".att_syntax prefix");
__builtin_unreachable();
}
}
}