diff options
author | dec05eba <dec05eba@protonmail.com> | 2022-10-16 02:08:40 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2022-10-16 04:15:09 +0200 |
commit | a7e0dbd83381377bd05a3fa988511d3713996370 (patch) | |
tree | 0e18f4c7b95aa4cf79d6646bca77ed5f03c65fb3 /src/gl.c | |
parent | 93d46b976730bced7a70be1617a0171600167314 (diff) |
Refactor xcomposite into abstract capture api
Refactor c++ files into c files, more usable
Diffstat (limited to 'src/gl.c')
-rw-r--r-- | src/gl.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/gl.c b/src/gl.c new file mode 100644 index 0000000..2f471aa --- /dev/null +++ b/src/gl.c @@ -0,0 +1,198 @@ +#include "../include/gl.h" +#include "../include/library_loader.h" +#include <string.h> + +static bool gsr_gl_create_window(gsr_gl *self) { + const int attr[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 0, + None + }; + + GLXFBConfig *fbconfigs = NULL; + XVisualInfo *visual_info = NULL; + GLXFBConfig fbconfig = NULL; + Colormap colormap = None; + GLXContext gl_context = NULL; + Window window = None; + + int numfbconfigs = 0; + fbconfigs = self->glXChooseFBConfig(self->dpy, DefaultScreen(self->dpy), attr, &numfbconfigs); + for(int i = 0; i < numfbconfigs; i++) { + visual_info = self->glXGetVisualFromFBConfig(self->dpy, fbconfigs[i]); + if(!visual_info) + continue; + + fbconfig = fbconfigs[i]; + break; + } + + if(!visual_info) { + fprintf(stderr, "gsr error: gsr_gl_create_window failed: no appropriate visual found\n"); + XFree(fbconfigs); + return false; + } + + /* TODO: Core profile? GLX_CONTEXT_CORE_PROFILE_BIT_ARB. */ + /* TODO: Remove need for 4.2 when copy texture function has been removed. */ + int context_attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + None + }; + + gl_context = self->glXCreateContextAttribsARB(self->dpy, fbconfig, NULL, True, context_attribs); + if(!gl_context) { + fprintf(stderr, "gsr error: gsr_gl_create_window failed: failed to create gl context\n"); + goto fail; + } + + colormap = XCreateColormap(self->dpy, DefaultRootWindow(self->dpy), visual_info->visual, AllocNone); + if(!colormap) { + fprintf(stderr, "gsr error: gsr_gl_create_window failed: failed to create x11 colormap\n"); + goto fail; + } + + XSetWindowAttributes window_attr; + window_attr.colormap = colormap; + + // TODO: Is there a way to remove the need to create a window? + window = XCreateWindow(self->dpy, DefaultRootWindow(self->dpy), 0, 0, 1, 1, 0, visual_info->depth, InputOutput, visual_info->visual, CWColormap, &window_attr); + + if(!window) { + fprintf(stderr, "gsr error: gsr_gl_create_window failed: failed to create gl window\n"); + goto fail; + } + + if(!self->glXMakeContextCurrent(self->dpy, window, window, gl_context)) { + fprintf(stderr, "gsr error: gsr_gl_create_window failed: failed to make gl context current\n"); + goto fail; + } + + self->fbconfigs = fbconfigs; + self->visual_info = visual_info; + self->colormap = colormap; + self->gl_context = gl_context; + self->window = window; + return true; + + fail: + if(window) + XDestroyWindow(self->dpy, window); + if(colormap) + XFreeColormap(self->dpy, colormap); + if(gl_context) + self->glXDestroyContext(self->dpy, gl_context); + if(visual_info) + XFree(visual_info); + XFree(fbconfigs); + return False; +} + +bool gsr_gl_load(gsr_gl *self, Display *dpy) { + memset(self, 0, sizeof(gsr_gl)); + self->dpy = dpy; + + dlerror(); /* clear */ + void *lib = dlopen("libGL.so.1", RTLD_LAZY); + if(!lib) { + fprintf(stderr, "gsr error: gsr_gl_load: failed to load libGL.so.1, error: %s\n", dlerror()); + return false; + } + + dlsym_assign optional_dlsym[] = { + { (void**)&self->glClearTexImage, "glClearTexImage" }, + { (void**)&self->glXSwapIntervalEXT, "glXSwapIntervalEXT" }, + { (void**)&self->glXSwapIntervalMESA, "glXSwapIntervalMESA" }, + { (void**)&self->glXSwapIntervalSGI, "glXSwapIntervalSGI" }, + + { NULL, NULL } + }; + + dlsym_load_list_optional(lib, optional_dlsym); + + dlsym_assign required_dlsym[] = { + { (void**)&self->glXCreatePixmap, "glXCreatePixmap" }, + { (void**)&self->glXDestroyPixmap, "glXDestroyPixmap" }, + { (void**)&self->glXBindTexImageEXT, "glXBindTexImageEXT" }, + { (void**)&self->glXReleaseTexImageEXT, "glXReleaseTexImageEXT" }, + { (void**)&self->glXChooseFBConfig, "glXChooseFBConfig" }, + { (void**)&self->glXGetVisualFromFBConfig, "glXGetVisualFromFBConfig" }, + { (void**)&self->glXCreateContextAttribsARB, "glXCreateContextAttribsARB" }, + { (void**)&self->glXMakeContextCurrent, "glXMakeContextCurrent" }, + { (void**)&self->glXDestroyContext, "glXDestroyContext" }, + { (void**)&self->glXSwapBuffers, "glXSwapBuffers" }, + + { (void**)&self->glGetError, "glGetError" }, + { (void**)&self->glGetString, "glGetString" }, + { (void**)&self->glClear, "glClear" }, + { (void**)&self->glGenTextures, "glGenTextures" }, + { (void**)&self->glDeleteTextures, "glDeleteTextures" }, + { (void**)&self->glBindTexture, "glBindTexture" }, + { (void**)&self->glTexParameteri, "glTexParameteri" }, + { (void**)&self->glGetTexLevelParameteriv, "glGetTexLevelParameteriv" }, + { (void**)&self->glTexImage2D, "glTexImage2D" }, + { (void**)&self->glCopyImageSubData, "glCopyImageSubData" }, + + { NULL, NULL } + }; + + if(!dlsym_load_list(lib, required_dlsym)) { + fprintf(stderr, "gsr error: gsr_gl_load failed: missing required symbols in libGL.so.1\n"); + dlclose(lib); + memset(self, 0, sizeof(gsr_gl)); + return false; + } + + if(!gsr_gl_create_window(self)) { + dlclose(lib); + memset(self, 0, sizeof(gsr_gl)); + return false; + } + + self->library = lib; + return true; +} + +bool gsr_gl_make_context_current(gsr_gl *self) { + return self->glXMakeContextCurrent(self->dpy, self->window, self->window, self->gl_context); +} + +void gsr_gl_unload(gsr_gl *self) { + if(self->window) { + XDestroyWindow(self->dpy, self->window); + self->window = None; + } + + if(self->colormap) { + XFreeColormap(self->dpy, self->colormap); + self->colormap = None; + } + + if(self->gl_context) { + self->glXDestroyContext(self->dpy, self->gl_context); + self->gl_context = NULL; + } + + if(self->visual_info) { + XFree(self->visual_info); + self->visual_info = NULL; + } + + if(self->fbconfigs) { + XFree(self->fbconfigs); + self->fbconfigs = NULL; + } + + if(self->library) { + dlclose(self->library); + memset(self, 0, sizeof(gsr_gl)); + } +} |