ohmu
·
2026-10-15
1#include "opengl.h"
2#include "common/debug.h"
3#include "common/library.h"
4#include "common/printing.h"
5#include "common/windows/nt.h"
6
7#include <windows.h>
8#include <GL/gl.h>
9
10typedef struct WGLData {
11 FF_LIBRARY_SYMBOL(glGetString)
12 FF_LIBRARY_SYMBOL(wglMakeCurrent)
13 FF_LIBRARY_SYMBOL(wglCreateContext)
14 FF_LIBRARY_SYMBOL(wglDeleteContext)
15} WGLData;
16
17void ffOpenGLHandleResult(FFOpenGLResult* result, typeof(&glGetString) ffglGetString);
18
19static const char* wglHandleContext(WGLData* wglData, FFOpenGLResult* result, HDC hdc, HGLRC context) {
20 if (wglData->ffwglMakeCurrent(hdc, context) == FALSE) {
21 FF_DEBUG("wglMakeCurrent() failed: %s", ffDebugWin32Error(GetLastError()));
22 return "wglMakeCurrent() failed";
23 }
24 ffOpenGLHandleResult(result, wglData->ffglGetString);
25 ffStrbufSetStatic(&result->library, "WGL 1.0");
26 if (wglData->ffwglMakeCurrent(nullptr, nullptr) == FALSE) {
27 FF_DEBUG("wglMakeCurrent(nullptr, nullptr) failed: %s", ffDebugWin32Error(GetLastError()));
28 return "wglMakeCurrent(nullptr, nullptr) failed";
29 }
30 return nullptr;
31}
32
33static const char* wglHandlePixelFormat(WGLData* wglData, FFOpenGLResult* result, HWND hWnd) {
34 HDC hdc = GetDC(hWnd);
35
36 if (hdc == nullptr) {
37 FF_DEBUG("GetDC() failed: %s", ffDebugWin32Error(GetLastError()));
38 return "GetDC() failed";
39 }
40
41 PIXELFORMATDESCRIPTOR pfd = {
42 .nSize = sizeof(PIXELFORMATDESCRIPTOR),
43 .nVersion = 1,
44 .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
45 .iPixelType = PFD_TYPE_RGBA,
46 .cColorBits = 32,
47 .cDepthBits = 24,
48 .iLayerType = PFD_MAIN_PLANE
49 };
50 int pixelFormat = ChoosePixelFormat(hdc, &pfd);
51 if (pixelFormat == 0) {
52 FF_DEBUG("ChoosePixelFormat() failed: %s", ffDebugWin32Error(GetLastError()));
53 ReleaseDC(hWnd, hdc);
54 return "ChoosePixelFormat() failed";
55 }
56
57 if (SetPixelFormat(hdc, pixelFormat, &pfd) == FALSE) {
58 FF_DEBUG("SetPixelFormat() failed: %s", ffDebugWin32Error(GetLastError()));
59 ReleaseDC(hWnd, hdc);
60 return "SetPixelFormat() failed";
61 }
62
63 HGLRC context = wglData->ffwglCreateContext(hdc);
64 if (context == nullptr) {
65 FF_DEBUG("wglCreateContext() failed: %s", ffDebugWin32Error(GetLastError()));
66 ReleaseDC(hWnd, hdc);
67 return "wglCreateContext() failed";
68 }
69
70 const char* error = wglHandleContext(wglData, result, hdc, context);
71 wglData->ffwglDeleteContext(context);
72
73 ReleaseDC(hWnd, hdc);
74
75 return error;
76}
77
78static const char* wglDetectOpenGL(FFOpenGLResult* result) {
79 FF_LIBRARY_LOAD_MESSAGE(opengl32, "opengl32" FF_LIBRARY_EXTENSION, 1);
80
81 WGLData data = {};
82
83 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglMakeCurrent);
84 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglCreateContext);
85 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglDeleteContext);
86 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, glGetString);
87
88 HINSTANCE hInstance = ffGetPeb()->ImageBaseAddress;
89
90 WNDCLASSW wc = {
91 .lpfnWndProc = DefWindowProcW,
92 .hInstance = hInstance,
93 .hbrBackground = (HBRUSH) COLOR_BACKGROUND,
94 .lpszClassName = L"ogl_version_check",
95 .style = CS_OWNDC,
96 };
97 if (!RegisterClassW(&wc)) {
98 FF_DEBUG("RegisterClassW() failed: %s", ffDebugWin32Error(GetLastError()));
99 return "RegisterClassW() failed";
100 }
101
102 HWND hWnd = CreateWindowW(wc.lpszClassName, L"ogl_version_check", 0, 0, 0, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, nullptr, nullptr, hInstance, nullptr);
103 if (!hWnd) {
104 FF_DEBUG("CreateWindowW() failed: %s", ffDebugWin32Error(GetLastError()));
105 return "CreateWindowW() failed";
106 }
107
108 const char* error = wglHandlePixelFormat(&data, result, hWnd);
109
110 DestroyWindow(hWnd);
111 UnregisterClassW(wc.lpszClassName, hInstance);
112
113 return error;
114}
115
116const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result) {
117 if (options->library == FF_OPENGL_LIBRARY_AUTO) {
118 return wglDetectOpenGL(result);
119 } else if (options->library == FF_OPENGL_LIBRARY_EGL) {
120#if __has_include(<EGL/egl.h>)
121 const char* ffOpenGLDetectByEGL(FFOpenGLResult * result);
122 return ffOpenGLDetectByEGL(result);
123#else
124 FF_DEBUG("fastfetch was compiled without egl support");
125 return "fastfetch was compiled without egl support";
126#endif
127 } else {
128 FF_DEBUG("Unsupported OpenGL library");
129 return "Unsupported OpenGL library";
130 }
131}