summaryrefslogtreecommitdiffstats
path: root/src/detection/opengl/opengl_linux.c
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/opengl/opengl_linux.c
Add the files
Diffstat (limited to 'src/detection/opengl/opengl_linux.c')
-rw-r--r--src/detection/opengl/opengl_linux.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/detection/opengl/opengl_linux.c b/src/detection/opengl/opengl_linux.c
new file mode 100644
index 0000000..5f88b7e
--- /dev/null
+++ b/src/detection/opengl/opengl_linux.c
@@ -0,0 +1,200 @@
+#include "fastfetch.h"
+#include "opengl.h"
+#include "common/io.h"
+
+#include <string.h>
+
+#if __ANDROID__ && !defined(FF_HAVE_EGL)
+ // On Android, installing OpenGL headers is enough (mesa-dev)
+ #if __has_include(<EGL/egl.h>)
+ #define FF_HAVE_EGL 1
+ #endif
+#endif
+
+#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX)
+ #define FF_HAVE_GL 1
+
+ #include "common/library.h"
+
+ #include <GL/gl.h>
+
+void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglGetString);
+
+#endif // FF_HAVE_GL
+
+#ifdef FF_HAVE_GLX
+ #include <GL/glx.h>
+
+typedef struct GLXData {
+ FF_LIBRARY_SYMBOL(glGetString)
+ FF_LIBRARY_SYMBOL(glXGetProcAddress)
+ FF_LIBRARY_SYMBOL(glXQueryVersion)
+ FF_LIBRARY_SYMBOL(XOpenDisplay)
+ FF_LIBRARY_SYMBOL(glXChooseVisual)
+ FF_LIBRARY_SYMBOL(XCreatePixmap)
+ FF_LIBRARY_SYMBOL(glXCreateGLXPixmap)
+ FF_LIBRARY_SYMBOL(glXCreateContext)
+ FF_LIBRARY_SYMBOL(glXMakeCurrent)
+ FF_LIBRARY_SYMBOL(glXDestroyContext)
+ FF_LIBRARY_SYMBOL(glXDestroyGLXPixmap)
+ FF_LIBRARY_SYMBOL(XFreePixmap)
+ FF_LIBRARY_SYMBOL(XCloseDisplay)
+ FF_LIBRARY_SYMBOL(XFree)
+
+ Display* display;
+ XVisualInfo* visualInfo;
+ Pixmap pixmap;
+ GLXPixmap glxPixmap;
+ GLXContext context;
+} GLXData;
+
+static const char* glxHandleContext(FFOpenGLResult* result, GLXData* data) {
+ if (data->ffglXMakeCurrent(data->display, data->glxPixmap, data->context) != True) {
+ return "glXMakeCurrent returned False";
+ }
+ ffOpenGLHandleResult(result, data->ffglGetString);
+
+ int major, minor;
+ if (data->ffglXQueryVersion(data->display, &major, &minor)) {
+ ffStrbufSetF(&result->library, "GLX %d.%d", major, minor);
+ } else {
+ ffStrbufSetStatic(&result->library, "GLX");
+ }
+
+ return NULL;
+}
+
+static const char* glxHandleGLXPixmap(FFOpenGLResult* result, GLXData* data) {
+ data->context = data->ffglXCreateContext(data->display, data->visualInfo, NULL, True);
+ if (data->context == NULL) {
+ return "glXCreateContext returned NULL";
+ }
+
+ const char* error = glxHandleContext(result, data);
+ data->ffglXDestroyContext(data->display, data->context);
+ return error;
+}
+
+static const char* glxHandlePixmap(FFOpenGLResult* result, GLXData* data) {
+ data->glxPixmap = data->ffglXCreateGLXPixmap(data->display, data->visualInfo, data->pixmap);
+ if (data->glxPixmap == None) {
+ return "glXCreateGLXPixmap returned None";
+ }
+
+ const char* error = glxHandleGLXPixmap(result, data);
+ data->ffglXDestroyGLXPixmap(data->display, data->glxPixmap);
+ return error;
+}
+
+static const char* glxHandleVisualInfo(FFOpenGLResult* result, GLXData* data) {
+ data->pixmap = data->ffXCreatePixmap(data->display, DefaultRootWindow(data->display), FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, (unsigned int) data->visualInfo->depth);
+ if (data->pixmap == None) {
+ return "XCreatePixmap returned None";
+ }
+
+ const char* error = glxHandlePixmap(result, data);
+ data->ffXFreePixmap(data->display, data->pixmap);
+ return error;
+}
+
+static const char* glxHandleDisplay(FFOpenGLResult* result, GLXData* data) {
+ data->visualInfo = data->ffglXChooseVisual(data->display, DefaultScreen(data->display), (int[]) { None });
+ if (data->visualInfo == NULL) {
+ return "glXChooseVisual returned NULL";
+ }
+
+ const char* error = glxHandleVisualInfo(result, data);
+ data->ffXFree(data->visualInfo);
+ return error;
+}
+
+static const char* glxHandleData(FFOpenGLResult* result, GLXData* data) {
+ data->ffglGetString = (__typeof__(data->ffglGetString)) data->ffglXGetProcAddress((const GLubyte*) "glGetString");
+ if (data->ffglGetString == NULL) {
+ return "glXGetProcAddress(glGetString) returned NULL";
+ }
+
+ data->display = data->ffXOpenDisplay(NULL);
+ if (data->display == NULL) {
+ return "XOpenDisplay returned NULL";
+ }
+
+ const char* error = glxHandleDisplay(result, data);
+ data->ffXCloseDisplay(data->display);
+ return error;
+}
+
+static const char* detectByGlx(FFOpenGLResult* result) {
+ GLXData data;
+
+ FF_LIBRARY_LOAD_MESSAGE(glx,
+ #if !__OpenBSD__ && !__NetBSD__
+ "libGLX"
+ #else
+ "libGL"
+ #endif
+ FF_LIBRARY_EXTENSION,
+ 1);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXQueryVersion);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXChooseVisual);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCreatePixmap);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXCreateGLXPixmap);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXCreateContext);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXMakeCurrent);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXDestroyContext);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXDestroyGLXPixmap);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XFreePixmap);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCloseDisplay);
+ FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XFree);
+
+ FF_SUPPRESS_IO();
+
+ return glxHandleData(result, &data);
+}
+
+#endif // FF_HAVE_GLX
+
+const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result) {
+#if FF_HAVE_GL
+
+ if (options->library == FF_OPENGL_LIBRARY_GLX) {
+ #ifdef FF_HAVE_GLX
+ return detectByGlx(result);
+ #else
+ return "fastfetch was compiled without glx support";
+ #endif
+ }
+
+ if (options->library == FF_OPENGL_LIBRARY_EGL) {
+ #ifdef FF_HAVE_EGL
+ const char* ffOpenGLDetectByEGL(FFOpenGLResult * result);
+ return ffOpenGLDetectByEGL(result);
+ #else
+ return "fastfetch was compiled without egl support";
+ #endif
+ }
+
+ const char* error = ""; // not NULL dummy value
+
+ #ifdef FF_HAVE_EGL
+ const char* ffOpenGLDetectByEGL(FFOpenGLResult * result);
+ error = ffOpenGLDetectByEGL(result);
+ #endif
+
+ #ifdef FF_HAVE_GLX
+ if (error != NULL) {
+ error = detectByGlx(result);
+ }
+ #endif
+
+ return error;
+
+#else
+
+ FF_UNUSED(options, result);
+ return "Fastfetch was built without gl support.";
+
+#endif // FF_HAVE_GL
+}