소스 검색

Working glx pltf implementation

Aaro Saila 3 달 전
부모
커밋
dc65a5c07e

+ 29 - 0
generate_gl_func_alias.py

@@ -0,0 +1,29 @@
+import os
+from sys import argv
+
+sc_dir = os.path.dirname(os.path.realpath(argv[0]))
+os.chdir(sc_dir)
+
+hg_tag = "PLTF_GL_FUNC_ALIAS_H_"
+
+lines: list[str] = [
+    f"#ifndef {hg_tag}\n",
+    f"#define {hg_tag}\n"
+]
+
+with open("./src/pltf/internal/gl_func_decl.h", "r") as f:
+    header = f.readlines()
+    for h_line in header:
+        h_split = h_line.split(" ")
+        for token in h_split:
+            if token[0] == "g" and token[1] == "l":
+                token = token.removesuffix(");")
+                line = f"#define {token} pltf_{token}\n"
+                lines.append(line)
+
+lines.append(f"#endif // {hg_tag}\n")
+# for line in lines:
+#     print(line)
+
+with open("./src/pltf/internal/gl_func_alias.h", "w") as f:
+    f.writelines(lines)

+ 4 - 2
meson.build

@@ -28,14 +28,16 @@ test_include_dirs = [
 
 if host_machine.system() == 'linux'
   pltf_src = [
-    'src/pltf/glx/gl_funcs.c'
+    'src/pltf/glx/gl_funcs.c',
+    'src/pltf/glx/internal.c',
+    'src/pltf/glx/pltf.c',
+    'src/pltf/glx/util.c',
   ]
 
   dependencies += [
     dependency('x11'),
     dependency('glx'),
     dependency('libglvnd'),
-    dependency('opengl'),
   ]
 
   libcmocka = cc.find_library(

+ 18 - 382
src/main.c

@@ -1,5 +1,3 @@
-#ifdef _WIN32
-
 #include <assert.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -9,26 +7,25 @@
 #include "pltf/pltf.h"
 #include "shader.h"
 
-typedef struct {
-    const char* up_msg;
-    const char* down_msg;
-    int up_count;
-    int down_count;
-} MsgState;
-
-void msg_cb(const PltfKeyAction action, void* user_data) {
-    MsgState* state = (MsgState*) user_data;
-    switch (action) {
-    case PLTF_KEY_DOWN:
-        printf("Key: %s Count: %d\n", state->down_msg, state->down_count);
-        state->down_count++;
+void key_cb(const PltfKey key, const PltfKeyAction action) {
+    switch (key) {
+    case PLTF_KEY_ESC:
+        pltf_window_destroy();
         break;
-    case PLTF_KEY_UP:
-        printf("Key: %s Count: %d\n", state->up_msg, state->up_count);
-        state->up_count++;
+    case PLTF_KEY_Q:
+    {
+        switch (action) {
+        case PLTF_KEY_UP:
+            printf("Q up\n");
+            break;
+        case PLTF_KEY_DOWN:
+            printf("Q down\n");
+            break;
+        }
         break;
+    }
     default:
-        printf("INVALID PltfKeyAction. Was %d\n", action);
+        break;
     }
 }
 
@@ -38,13 +35,9 @@ int main() {
     pltf_gl_ctx_create();
     pltf_gl_funcs_load();
 
-    pltf_gl_ctx_info_print();
-
-    pltf_key_callback_set(PLTF_KEY_ESC, pltf_window_close, NULL);
-    MsgState msg_state = { .up_msg = "UP", .down_msg = "DOWN", .up_count = 0, .down_count = 0 };
-    pltf_key_callback_set(PLTF_KEY_Q, msg_cb, &msg_state);
+    pltf_key_callback_set(key_cb);
 
-    // clang-format off
+        // clang-format off
     const float triangle_verts[] = {
         // pos
         0.0f, 0.5f, 0.0f, // top
@@ -110,360 +103,3 @@ int main() {
     return 0;
 }
 
-#endif // _WIN32
-
-#ifdef __linux__
-
-#include <GL/glcorearb.h>
-#include <GL/glx.h>
-#include <GL/glxext.h>
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/cursorfont.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "DynString.h"
-#include "log.h"
-
-void print_pixmap_format_values(const XPixmapFormatValues* px) {
-    puts("{");
-    printf("  depth         : %d\n", px->depth);
-    printf("  bits_per_pixel: %d\n", px->bits_per_pixel);
-    printf("  scanline_pad  : %d\n", px->scanline_pad);
-    puts("}");
-}
-
-void print_visual_info(const XVisualInfo* vi) {
-    puts("{");
-    printf("  visual       : %p\n", vi->visual);
-    printf("  visualid     : %lu\n", vi->visualid);
-    printf("  screen       : %d\n", vi->screen);
-    printf("  depth        : %u\n", vi->depth);
-    printf("  class        : %d\n", vi->class);
-    printf("  red_mask     : %lu\n", vi->red_mask);
-    printf("  green_mask   : %lu\n", vi->green_mask);
-    printf("  blue_mask    : %lu\n", vi->blue_mask);
-    printf("  colormap_size: %d\n", vi->colormap_size);
-    printf("  bits_per_rgb : %d\n", vi->bits_per_rgb);
-    puts("}");
-}
-
-void print_info(Display* display) {
-    const int screen_num = DefaultScreen(display);
-    Colormap color_map = DefaultColormap(display, screen_num);
-    int default_depth = DefaultDepth(display, screen_num);
-    int depths_count = 0;
-    int* depths = XListDepths(display, screen_num, &depths_count);
-    if (depths == NULL) {
-        LOG_FATAL("XListDepths failed");
-    }
-    int cells = DisplayCells(display, screen_num);
-    int color_depth = DisplayPlanes(display, screen_num);
-    char* display_string = DisplayString(display);
-    int queue_length = QLength(display);
-    int screen_count = ScreenCount(display);
-    char* server_vendor = ServerVendor(display);
-    int vendor_release = VendorRelease(display);
-
-    printf("DefaultScreen  : %d\n", screen_num);
-    printf("DefaultColormap: %lu\n", color_map);
-    printf("DefaultDepth   : %d\n", default_depth);
-    printf("XListDepths    : ");
-    for (int i = 0; i < depths_count; i++) {
-        printf("%d ", depths[i]);
-    }
-    puts("");
-    printf("DisplayCells   : %d\n", cells);
-    printf("DisplayPlanes  : %d\n", color_depth);
-    printf("DisplayString  : %s\n", display_string);
-    printf("QLength        : %d\n", queue_length);
-    printf("ScreenCount    : %d\n", screen_count);
-    printf("ServerVendor   : %s\n", server_vendor);
-    printf("VendorRelease  : %d\n", vendor_release);
-
-    XFree(depths);
-
-    int d_supported_pixmap_formats_n = 0;
-    XPixmapFormatValues* d_supported_pixmap_formats = XListPixmapFormats(display, &d_supported_pixmap_formats_n);
-    if (d_supported_pixmap_formats == NULL) {
-        LOG_FATAL("XListPixmapFormats failed");
-    }
-    int img_byte_order = ImageByteOrder(display);
-    int bitmap_unit = XBitmapUnit(display);
-    int bitmap_bit_order = BitmapBitOrder(display);
-    int bitmap_pad = BitmapPad(display);
-    int s_height_px = DisplayHeight(display, screen_num);
-    int s_height_mm = DisplayHeightMM(display, screen_num);
-    int s_width_px = DisplayWidth(display, screen_num);
-    int s_width_mm = DisplayWidthMM(display, screen_num);
-
-    puts("");
-    printf("XListPixmapFormats (%d):\n", d_supported_pixmap_formats_n);
-    for (int i = 0; i < d_supported_pixmap_formats_n; i++) {
-        print_pixmap_format_values(d_supported_pixmap_formats + i);
-    }
-    printf("ImageByteOrder                 : %s\n", img_byte_order == LSBFirst ? "LSBFirst" : "MSBFirst");
-    printf("XBitmapUnit                    : %d\n", bitmap_unit);
-    printf("BitmapBitOrder                 : %s\n", bitmap_bit_order == LSBFirst ? "LSBFirst" : "MSBFirst");
-    printf("BitmapPad                      : %d\n", bitmap_pad);
-    printf("DisplayHeight   (DefaultScreen): %d\n", s_height_px);
-    printf("DisplayHeightMM (DefaultScreen): %d\n", s_height_mm);
-    printf("DisplayWidth    (DefaultScreen): %d\n", s_width_px);
-    printf("DisplayWidthMM  (DefaultScreen): %d\n", s_width_mm);
-
-    XFree(d_supported_pixmap_formats);
-
-    Screen* screen = ScreenOfDisplay(display, screen_num);
-    unsigned long s_black_pixel = BlackPixelOfScreen(screen);
-    unsigned long s_white_pixel = WhitePixelOfScreen(screen);
-    int s_cells = CellsOfScreen(screen);
-    int s_default_depth = DefaultDepthOfScreen(screen);
-    int does_backing_store = DoesBackingStore(screen);
-    bool does_save_unders = DoesSaveUnders(screen);
-    int s_max_colormaps = MaxCmapsOfScreen(screen);
-    int s_min_colormaps = MinCmapsOfScreen(screen);
-    int s_planes_n = PlanesOfScreen(screen);
-
-    puts("\n(Default Screen)");
-    printf("BlackPixelOfScreen  : %lu\n", s_black_pixel);
-    printf("WhitePixelOfScreen  : %lu\n", s_white_pixel);
-    printf("CellsOfScreen       : %d\n", s_cells);
-    printf("DefaultDepthOfScreen: %d\n", s_default_depth);
-    printf("DoesBackingStore    : %s\n", does_backing_store == WhenMapped ? "WhenMapped" : (does_backing_store == NotUseful ? "NotUseful" : "Always"));
-    printf("DoesSaveUnders      : %s\n", does_save_unders ? "true" : "false");
-    printf("MaxCmapsOfScreen    : %d\n", s_max_colormaps);
-    printf("MinCmapsOfScreen    : %d\n", s_min_colormaps);
-    printf("PlanesOfScreen      : %d\n", s_planes_n);
-    puts("");
-}
-
-void glx_print_client_info(Display* display) {
-    const char* glx_client_vendor_str = glXGetClientString(display, GLX_VENDOR);
-    printf("Client GLX_VENDOR: %s\n", glx_client_vendor_str);
-    const char* glx_client_version_str = glXGetClientString(display, GLX_VERSION);
-    printf("Client GLX_VERSION: %s\n", glx_client_version_str);
-    const char* glx_client_extensions_str = glXGetClientString(display, GLX_EXTENSIONS);
-    printf("Client GLX_EXTENSIONS: %s\n", glx_client_extensions_str);
-}
-
-void glx_print_server_info(Display* display) {
-    const char* glx_server_vendor_str = glXQueryServerString(display, DefaultScreen(display), GLX_VENDOR);
-    printf("Server GLX_VENDOR: %s\n", glx_server_vendor_str);
-    const char* glx_server_version_str = glXQueryServerString(display, DefaultScreen(display), GLX_VERSION);
-    printf("Server GLX_VERSION: %s\n", glx_server_version_str);
-    const char* glx_server_extensions_str = glXQueryServerString(display, DefaultScreen(display), GLX_EXTENSIONS);
-    printf("Server GLX_EXTENSIONS: %s\n", glx_server_extensions_str);
-}
-
-void print_glxfbconfig(Display* display, const GLXFBConfig* cfg) {
-    int value = 0;
-
-#define PRINT_GLXFBCONFIG_VALUE(attrib)                                   \
-    value = 0;                                                            \
-    if (glXGetFBConfigAttrib(display, *cfg, attrib, &value) != Success) { \
-        LOG_FATALF("Invalid attrib %s", #attrib);                         \
-    }                                                                     \
-    printf("  %s: %d\n", #attrib, value)
-
-    puts("{");
-    PRINT_GLXFBCONFIG_VALUE(GLX_FBCONFIG_ID);
-    PRINT_GLXFBCONFIG_VALUE(GLX_BUFFER_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_LEVEL);
-    PRINT_GLXFBCONFIG_VALUE(GLX_DOUBLEBUFFER);
-    PRINT_GLXFBCONFIG_VALUE(GLX_STEREO);
-    PRINT_GLXFBCONFIG_VALUE(GLX_AUX_BUFFERS);
-    PRINT_GLXFBCONFIG_VALUE(GLX_RED_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_GREEN_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_BLUE_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_ALPHA_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_DEPTH_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_STENCIL_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_RED_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_GREEN_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_BLUE_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_ALPHA_SIZE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_SAMPLE_BUFFERS);
-    PRINT_GLXFBCONFIG_VALUE(GLX_SAMPLES);
-    PRINT_GLXFBCONFIG_VALUE(GLX_RENDER_TYPE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_DRAWABLE_TYPE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_X_RENDERABLE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_X_VISUAL_TYPE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_CONFIG_CAVEAT);
-    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_TYPE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_INDEX_VALUE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_RED_VALUE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_GREEN_VALUE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_BLUE_VALUE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_ALPHA_VALUE);
-    PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_WIDTH);
-    PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_HEIGHT);
-    PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_PIXELS);
-    PRINT_GLXFBCONFIG_VALUE(GLX_VISUAL_ID);
-    puts("}");
-
-#undef PRINT_GLXFBCONFIG_VALUE
-}
-
-int main() {
-    Display* display = XOpenDisplay(NULL);
-    if (display == NULL) {
-        LOG_FATAL("XOpenDisplay failed.");
-    }
-
-    int err_base = 0;
-    int event_base = 0;
-    if (!glXQueryExtension(display, &err_base, &event_base)) {
-        LOG_FATALF(
-            "GLX extension not supported. err_base: %d, event_base: %d",
-            err_base,
-            event_base
-        );
-    }
-
-    int glx_major = 0;
-    int glx_minor = 0;
-    if (glXQueryVersion(display, &glx_major, &glx_minor)) {
-        printf("GLX Version %d.%d\n", glx_major, glx_minor);
-        if (glx_minor < 1) {
-            LOG_FATAL("GLX Version must be at least 1.1");
-        }
-    } else {
-        LOG_ERROR("glXQueryVersion failed");
-    }
-
-    const char* glx_extensions_c_str = glXQueryExtensionsString(display, DefaultScreen(display));
-    printf("glx_extensions_c_str: %s\n", glx_extensions_c_str);
-    DynString glx_extensions_str = DynString_alloc(glx_extensions_c_str, strlen(glx_extensions_c_str));
-    size_t glx_ext_n = 0;
-    DynString* glx_extensions = DynString_split(&glx_extensions_str, " ", &glx_ext_n);
-
-    printf("GLX extensions:\n");
-    for (size_t i = 0; i < glx_ext_n; i++) {
-        printf("  %s\n", DynString_c_str(glx_extensions + i));
-    }
-
-    // clang-format off
-    int fb_cfg_attrib_list[] = {
-        GLX_BUFFER_SIZE, 32,
-        GLX_DOUBLEBUFFER, true,
-        GLX_DEPTH_SIZE, 24,
-        GLX_STENCIL_SIZE, 8,
-        GLX_RENDER_TYPE, GLX_RGBA_BIT,
-        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
-        None
-    };
-    // clang-format on
-    int fb_cfg_n = 0;
-    GLXFBConfig* fb_cfg = glXChooseFBConfig(display, DefaultScreen(display), fb_cfg_attrib_list, &fb_cfg_n);
-    if (fb_cfg == NULL) {
-        LOG_FATAL("Invalid input to glXChooseFBConfig");
-    }
-    if (fb_cfg_n == 0) {
-        LOG_FATAL("Could not get a fitting GLXFBConfig");
-    }
-    printf("GLXFBConfig: ");
-    print_glxfbconfig(display, fb_cfg);
-
-    XVisualInfo* visual_info = glXGetVisualFromFBConfig(display, *fb_cfg);
-
-    XSetWindowAttributes win_attr = {
-        .colormap = XCreateColormap(
-            display,
-            RootWindowOfScreen(DefaultScreenOfDisplay(display)),
-            visual_info->visual,
-            AllocNone
-        )
-    };
-
-    // clang-format off
-    Window window = XCreateWindow(
-        display,
-        RootWindowOfScreen(DefaultScreenOfDisplay(display)), 
-        0, 0,
-        800, 600,
-        0,
-        visual_info->depth,
-        InputOutput,
-        visual_info->visual,
-        CWColormap,
-        &win_attr
-    );
-    // clang-format on
-
-    GLXWindow glx_window = glXCreateWindow(
-        display,
-        *fb_cfg,
-        window,
-        NULL
-    );
-
-    XStoreName(display, window, "GLX");
-
-    PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB");
-
-    // clang-format off
-    GLXContext gl_ctx = glXCreateContextAttribsARB(
-        display,
-        *fb_cfg,
-        NULL,
-        true,
-        (int[]) {
-            GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
-            GLX_CONTEXT_MINOR_VERSION_ARB, 6,
-            GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
-            None   
-        }
-    );
-    // clang-format on
-
-    glXMakeCurrent(
-        display,
-        window,
-        gl_ctx
-    );
-
-    glXWaitX();
-    XSync(display, false);
-
-    XMapWindow(display, window);
-
-    printf("OpenGL %s\n", glGetString(GL_VERSION));
-
-    PFNGLGETINTEGERVPROC glGetIntegerv = (PFNGLGETINTEGERVPROC) glXGetProcAddress((const GLubyte*) "glGetIntegerv");
-    PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glXGetProcAddress((const GLubyte*) "glClear");
-    PFNGLCLEARCOLORPROC glClearColor = (PFNGLCLEARCOLORPROC) glXGetProcAddress((const GLubyte*) "glClearColor");
-
-    int gl_major = 0;
-    int gl_minor = 0;
-    int gl_ctx_profile_mask = 0;
-    glGetIntegerv(GL_MAJOR_VERSION, &gl_major);
-    glGetIntegerv(GL_MINOR_VERSION, &gl_minor);
-    glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &gl_ctx_profile_mask);
-    printf(
-        "OpenGL %d.%d %s\n",
-        gl_major,
-        gl_minor,
-        gl_ctx_profile_mask == GL_CONTEXT_CORE_PROFILE_BIT
-            ? "Core"
-            : "Compatibility"
-    );
-
-    glClearColor(0.0, 0.0, 0.8, 1.0);
-
-    while (1) {
-        glClear(GL_COLOR_BUFFER_BIT);
-        glXSwapBuffers(display, window);
-    }
-
-    XFree(visual_info);
-
-    XCloseDisplay(display);
-
-    return 0;
-}
-
-#endif // __linux__

+ 5 - 44
src/pltf/gl_funcs.h

@@ -1,46 +1,7 @@
-#ifndef GL_FUNCS_H_
-#define GL_FUNCS_H_
+#ifndef PLTF_GL_FUNCS_H_
+#define PLTF_GL_FUNCS_H_
 
-#include <GL/glcorearb.h>
+#include "internal/gl_func_decl.h" // IWYU pragma: export
+#include "internal/gl_func_alias.h" // IWYU pragma: export
 
-#define PLTF_GL_FUNCS(X) \
-X(PFNGLSHADERSOURCEPROC, glShaderSource); \
-X(PFNGLCREATESHADERPROC, glCreateShader); \
-X(PFNGLCOMPILESHADERPROC, glCompileShader); \
-X(PFNGLGETSHADERIVPROC, glGetShaderiv); \
-X(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); \
-X(PFNGLCREATEPROGRAMPROC, glCreateProgram); \
-X(PFNGLATTACHSHADERPROC, glAttachShader); \
-X(PFNGLLINKPROGRAMPROC, glLinkProgram); \
-X(PFNGLGETPROGRAMIVPROC, glGetProgramiv); \
-X(PFNGLDELETESHADERPROC, glDeleteShader); \
-X(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); \
-X(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); \
-X(PFNGLGENBUFFERSPROC, glGenBuffers); \
-X(PFNGLBINDBUFFERPROC, glBindBuffer); \
-X(PFNGLBUFFERDATAPROC, glBufferData); \
-X(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); \
-X(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); \
-X(PFNGLCLEARCOLORPROC, glClearColor); \
-X(PFNGLCLEARPROC, glClear); \
-X(PFNGLUSEPROGRAMPROC, glUseProgram); \
-X(PFNGLDRAWARRAYSPROC, glDrawArrays); \
-X(PFNGLGETINTEGERVPROC, glGetIntegerv); \
-X(PFNGLGETFLOATVPROC, glGetFloatv); \
-X(PFNGLGETERRORPROC, glGetError); \
-
-#define X(type, name) \
-extern type name;
-
-PLTF_GL_FUNCS(X)
-#undef X
-
-#ifdef __linux__
-    void* pltf_gl_function_load(const unsigned char* name);
-#else
-    void* pltf_gl_function_load(const char* name);
-#endif // __linux__
-
-void pltf_gl_funcs_load();
-
-#endif // GL_FUNCS_H_
+#endif // PLTF_GL_FUNCS_H_

+ 12 - 7
src/pltf/glx/gl_funcs.c

@@ -2,22 +2,27 @@
 
 #include <stddef.h>
 #include <GL/glcorearb.h>
+#include <GL/glx.h>
 
 #include "../gl_funcs.h"
 
 #define X(type, name) \
-type name = NULL
+type pltf_##name = NULL
 
 PLTF_GL_FUNCS(X)
 #undef X
 
-// #define X(type, name) \
-// name = (type) pltf_gl_function_load((const GLubyte*) #name);
+#define X(type, name) \
+pltf_##name = (type) pltf_gl_function_load(#name);
+
+void* pltf_gl_function_load(const char* name) {
+    return glXGetProcAddress((const GLubyte*) name);
+}
 
-// void pltf_gl_funcs_load() {
-    // PLTF_GL_FUNCS(X)
-// }
+void pltf_gl_funcs_load() {
+    PLTF_GL_FUNCS(X)
+}
 
-// #undef X
+#undef X
 
 #endif // __linux__

+ 16 - 0
src/pltf/glx/internal.c

@@ -0,0 +1,16 @@
+#ifdef __linux__
+
+#include "./internal.h"
+
+PltfStateGlx pltf_state = {};
+
+bool has_glx_extension(const char *name) {
+    for (size_t i = 0; i < pltf_state.glx_extensions.len; i++) {
+        if (DynString_equal_c_str(DynArray_DynString_at(&pltf_state.glx_extensions, i), name)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+#endif // __linux__

+ 28 - 0
src/pltf/glx/internal.h

@@ -0,0 +1,28 @@
+#ifdef __linux__
+
+#ifndef PLTF_GLX_INTERNAL_H_
+#define PLTF_GLX_INTERNAL_H_
+
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+#include "../pltf.h"
+#include "DynArray.h"
+
+typedef struct {
+    Display* display;
+    Window window;
+    GLXWindow glx_window;
+    GLXFBConfig* fb_cfg;
+    GLXContext gl_ctx;
+    DynArray_DynString glx_extensions;
+    PltfKeyCallback key_cb;
+} PltfStateGlx;
+
+extern PltfStateGlx pltf_state;
+
+bool has_glx_extension(const char* name);
+
+#endif // PLTF_GLX_INTERNAL_H_
+
+#endif // __linux__

+ 204 - 0
src/pltf/glx/pltf.c

@@ -0,0 +1,204 @@
+#include <X11/Xlib.h>
+#ifdef __linux__
+
+#include <string.h>
+
+#include <GL/glx.h>
+#include <X11/X.h>
+#include <X11/keysymdef.h>
+
+#include "../pltf.h"
+#include "./internal.h"
+#include "DynArray.h"
+#include "DynString.h"
+#include "log.h"
+
+static PltfKey keysym_to_pltf_key(const KeySym sym) {
+    switch (sym) {
+    case XK_Escape:
+        return PLTF_KEY_ESC;
+    case XK_Q:
+    case XK_q:
+        return PLTF_KEY_Q;
+    }
+
+    return PLTF_KEY_NONE;
+}
+
+void pltf_init() {
+    pltf_state.display = XOpenDisplay(NULL);
+    if (pltf_state.display == NULL) {
+        LOG_FATAL("XOpenDisplay failed.");
+    }
+
+    if (!DynArray_DynString_alloc(&pltf_state.glx_extensions)) {
+        LOG_FATAL("Failed to allocate pltf_state.glx_extensions");
+    }
+    const char* glx_extensions_c_str = glXQueryExtensionsString(pltf_state.display, DefaultScreen(pltf_state.display));
+    // Copying the extension string to prevent modifying the original. Might be pointless, doing this just in case.
+    DynString glx_extensions_str = DynString_alloc(glx_extensions_c_str, strlen(glx_extensions_c_str));
+    size_t glx_ext_n = 0;
+    DynString* glx_extensions = DynString_split(&glx_extensions_str, " ", &glx_ext_n);
+    for (size_t i = 0; i < glx_ext_n; i++) {
+        DynArray_DynString_push_back(&pltf_state.glx_extensions, glx_extensions + i);
+    }
+    DynString_free(&glx_extensions_str);
+}
+
+void pltf_deinit() {
+    XCloseDisplay(pltf_state.display);
+}
+
+void pltf_window_create() {
+    // clang-format off
+    int fb_cfg_attrib_list[] = {
+        GLX_BUFFER_SIZE, 32,
+        GLX_DOUBLEBUFFER, true,
+        GLX_DEPTH_SIZE, 24,
+        GLX_STENCIL_SIZE, 8,
+        GLX_RENDER_TYPE, GLX_RGBA_BIT,
+        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+        None
+    };
+    // clang-format on
+    int fb_cfg_n = 0;
+    pltf_state.fb_cfg = glXChooseFBConfig(pltf_state.display, DefaultScreen(pltf_state.display), fb_cfg_attrib_list, &fb_cfg_n);
+    if (pltf_state.fb_cfg == NULL) {
+        LOG_FATAL("Invalid input to glXChooseFBConfig");
+    }
+    if (fb_cfg_n == 0) {
+        LOG_FATAL("Could not get a fitting GLXFBConfig");
+    }
+
+    XVisualInfo* visual_info = glXGetVisualFromFBConfig(pltf_state.display, *pltf_state.fb_cfg);
+
+    XSetWindowAttributes win_attr = {
+        .colormap = XCreateColormap(
+            pltf_state.display,
+            RootWindowOfScreen(DefaultScreenOfDisplay(pltf_state.display)),
+            visual_info->visual,
+            AllocNone
+        ),
+        .event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask
+    };
+
+    // clang-format off
+    pltf_state.window = XCreateWindow(
+        pltf_state.display,
+        RootWindowOfScreen(DefaultScreenOfDisplay(pltf_state.display)), 
+        0, 0,
+        PLTF_DEFAULT_WINDOW_WIDTH, PLTF_DEFAULT_WINDOW_HEIGHT,
+        0,
+        visual_info->depth,
+        InputOutput,
+        visual_info->visual,
+        CWColormap |
+        CWEventMask,
+        &win_attr
+    );
+    // clang-format on
+
+    XFree(visual_info);
+    visual_info = NULL;
+
+    pltf_state.glx_window = glXCreateWindow(
+        pltf_state.display,
+        *pltf_state.fb_cfg,
+        pltf_state.window,
+        NULL
+    );
+
+    XStoreName(pltf_state.display, pltf_state.window, "GLX");
+
+    XMapWindow(pltf_state.display, pltf_state.window);
+
+    XFlush(pltf_state.display);
+}
+
+void pltf_window_destroy() {
+    XEvent ev = {
+        .type = DestroyNotify
+    };
+    XSendEvent(
+        pltf_state.display,
+        pltf_state.window,
+        false,
+        StructureNotifyMask,
+        &ev
+    );
+}
+
+void pltf_gl_ctx_create() {
+    if (!has_glx_extension("GLX_ARB_create_context")) {
+        LOG_FATAL("GLX extension GLX_ARB_create_context is required");
+    }
+    PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB");
+
+    // clang-format off
+    pltf_state.gl_ctx = glXCreateContextAttribsARB(
+        pltf_state.display,
+        *pltf_state.fb_cfg,
+        NULL,
+        true,
+        (int[]) {
+            GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
+            GLX_CONTEXT_MINOR_VERSION_ARB, 6,
+            GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+            None   
+        }
+    );
+    // clang-format on
+
+    glXMakeCurrent(
+        pltf_state.display,
+        pltf_state.window,
+        pltf_state.gl_ctx
+    );
+}
+
+void pltf_gl_ctx_destroy() {
+    glXDestroyContext(pltf_state.display, pltf_state.gl_ctx);
+    XFlush(pltf_state.display);
+}
+
+void pltf_swap_buffers() {
+    glXSwapBuffers(pltf_state.display, pltf_state.window);
+}
+
+static int x_check_if_event_predicate(Display* d, XEvent* e, XPointer p) {
+    return true;
+}
+
+PltfWindowEvent pltf_window_event_handle() {
+    PltfWindowEvent ret_ev = PLTF_WE_NONE;
+    XEvent ev = { };
+    if (XCheckIfEvent(pltf_state.display, &ev, x_check_if_event_predicate, NULL)) {
+        switch (ev.type) {
+        case DestroyNotify:
+            ret_ev = PLTF_WE_DESTROY;
+            break;
+
+        case KeyRelease:
+        {
+            KeySym sym = XLookupKeysym(&ev.xkey, 0);
+            pltf_state.key_cb(keysym_to_pltf_key(sym), PLTF_KEY_UP);
+            break;
+        }
+
+        case KeyPress:
+        {
+            KeySym sym = XLookupKeysym(&ev.xkey, 0);
+            pltf_state.key_cb(keysym_to_pltf_key(sym), PLTF_KEY_DOWN);
+            break;
+        }
+        }
+    }
+
+    return ret_ev;
+}
+
+void pltf_key_callback_set(const PltfKeyCallback cb) {
+    pltf_state.key_cb = cb;
+}
+
+#endif // __linux__

+ 190 - 0
src/pltf/glx/util.c

@@ -0,0 +1,190 @@
+#ifdef __linux__
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+
+#include "log.h"
+
+void pltf_glx_print_pixmap_format_values(const XPixmapFormatValues* px) {
+    puts("{");
+    printf("  depth         : %d\n", px->depth);
+    printf("  bits_per_pixel: %d\n", px->bits_per_pixel);
+    printf("  scanline_pad  : %d\n", px->scanline_pad);
+    puts("}");
+}
+
+void pltf_glx_print_visual_info(const XVisualInfo* vi) {
+    puts("{");
+    printf("  visual       : %p\n", vi->visual);
+    printf("  visualid     : %lu\n", vi->visualid);
+    printf("  screen       : %d\n", vi->screen);
+    printf("  depth        : %u\n", vi->depth);
+    printf("  class        : %d\n", vi->class);
+    printf("  red_mask     : %lu\n", vi->red_mask);
+    printf("  green_mask   : %lu\n", vi->green_mask);
+    printf("  blue_mask    : %lu\n", vi->blue_mask);
+    printf("  colormap_size: %d\n", vi->colormap_size);
+    printf("  bits_per_rgb : %d\n", vi->bits_per_rgb);
+    puts("}");
+}
+
+void pltf_glx_print_info(Display* display) {
+    const int screen_num = DefaultScreen(display);
+    Colormap color_map = DefaultColormap(display, screen_num);
+    int default_depth = DefaultDepth(display, screen_num);
+    int depths_count = 0;
+    int* depths = XListDepths(display, screen_num, &depths_count);
+    if (depths == NULL) {
+        LOG_FATAL("XListDepths failed");
+    }
+    int cells = DisplayCells(display, screen_num);
+    int color_depth = DisplayPlanes(display, screen_num);
+    char* display_string = DisplayString(display);
+    int queue_length = QLength(display);
+    int screen_count = ScreenCount(display);
+    char* server_vendor = ServerVendor(display);
+    int vendor_release = VendorRelease(display);
+
+    printf("DefaultScreen  : %d\n", screen_num);
+    printf("DefaultColormap: %lu\n", color_map);
+    printf("DefaultDepth   : %d\n", default_depth);
+    printf("XListDepths    : ");
+    for (int i = 0; i < depths_count; i++) {
+        printf("%d ", depths[i]);
+    }
+    puts("");
+    printf("DisplayCells   : %d\n", cells);
+    printf("DisplayPlanes  : %d\n", color_depth);
+    printf("DisplayString  : %s\n", display_string);
+    printf("QLength        : %d\n", queue_length);
+    printf("ScreenCount    : %d\n", screen_count);
+    printf("ServerVendor   : %s\n", server_vendor);
+    printf("VendorRelease  : %d\n", vendor_release);
+
+    XFree(depths);
+
+    int d_supported_pixmap_formats_n = 0;
+    XPixmapFormatValues* d_supported_pixmap_formats = XListPixmapFormats(display, &d_supported_pixmap_formats_n);
+    if (d_supported_pixmap_formats == NULL) {
+        LOG_FATAL("XListPixmapFormats failed");
+    }
+    int img_byte_order = ImageByteOrder(display);
+    int bitmap_unit = XBitmapUnit(display);
+    int bitmap_bit_order = BitmapBitOrder(display);
+    int bitmap_pad = BitmapPad(display);
+    int s_height_px = DisplayHeight(display, screen_num);
+    int s_height_mm = DisplayHeightMM(display, screen_num);
+    int s_width_px = DisplayWidth(display, screen_num);
+    int s_width_mm = DisplayWidthMM(display, screen_num);
+
+    puts("");
+    printf("XListPixmapFormats (%d):\n", d_supported_pixmap_formats_n);
+    for (int i = 0; i < d_supported_pixmap_formats_n; i++) {
+        pltf_glx_print_pixmap_format_values(d_supported_pixmap_formats + i);
+    }
+    printf("ImageByteOrder                 : %s\n", img_byte_order == LSBFirst ? "LSBFirst" : "MSBFirst");
+    printf("XBitmapUnit                    : %d\n", bitmap_unit);
+    printf("BitmapBitOrder                 : %s\n", bitmap_bit_order == LSBFirst ? "LSBFirst" : "MSBFirst");
+    printf("BitmapPad                      : %d\n", bitmap_pad);
+    printf("DisplayHeight   (DefaultScreen): %d\n", s_height_px);
+    printf("DisplayHeightMM (DefaultScreen): %d\n", s_height_mm);
+    printf("DisplayWidth    (DefaultScreen): %d\n", s_width_px);
+    printf("DisplayWidthMM  (DefaultScreen): %d\n", s_width_mm);
+
+    XFree(d_supported_pixmap_formats);
+
+    Screen* screen = ScreenOfDisplay(display, screen_num);
+    unsigned long s_black_pixel = BlackPixelOfScreen(screen);
+    unsigned long s_white_pixel = WhitePixelOfScreen(screen);
+    int s_cells = CellsOfScreen(screen);
+    int s_default_depth = DefaultDepthOfScreen(screen);
+    int does_backing_store = DoesBackingStore(screen);
+    bool does_save_unders = DoesSaveUnders(screen);
+    int s_max_colormaps = MaxCmapsOfScreen(screen);
+    int s_min_colormaps = MinCmapsOfScreen(screen);
+    int s_planes_n = PlanesOfScreen(screen);
+
+    puts("\n(Default Screen)");
+    printf("BlackPixelOfScreen  : %lu\n", s_black_pixel);
+    printf("WhitePixelOfScreen  : %lu\n", s_white_pixel);
+    printf("CellsOfScreen       : %d\n", s_cells);
+    printf("DefaultDepthOfScreen: %d\n", s_default_depth);
+    printf("DoesBackingStore    : %s\n", does_backing_store == WhenMapped ? "WhenMapped" : (does_backing_store == NotUseful ? "NotUseful" : "Always"));
+    printf("DoesSaveUnders      : %s\n", does_save_unders ? "true" : "false");
+    printf("MaxCmapsOfScreen    : %d\n", s_max_colormaps);
+    printf("MinCmapsOfScreen    : %d\n", s_min_colormaps);
+    printf("PlanesOfScreen      : %d\n", s_planes_n);
+    puts("");
+}
+
+void pltf_glx_print_client_info(Display* display) {
+    const char* glx_client_vendor_str = glXGetClientString(display, GLX_VENDOR);
+    printf("Client GLX_VENDOR: %s\n", glx_client_vendor_str);
+    const char* glx_client_version_str = glXGetClientString(display, GLX_VERSION);
+    printf("Client GLX_VERSION: %s\n", glx_client_version_str);
+    const char* glx_client_extensions_str = glXGetClientString(display, GLX_EXTENSIONS);
+    printf("Client GLX_EXTENSIONS: %s\n", glx_client_extensions_str);
+}
+
+void pltf_glx_print_server_info(Display* display) {
+    const char* glx_server_vendor_str = glXQueryServerString(display, DefaultScreen(display), GLX_VENDOR);
+    printf("Server GLX_VENDOR: %s\n", glx_server_vendor_str);
+    const char* glx_server_version_str = glXQueryServerString(display, DefaultScreen(display), GLX_VERSION);
+    printf("Server GLX_VERSION: %s\n", glx_server_version_str);
+    const char* glx_server_extensions_str = glXQueryServerString(display, DefaultScreen(display), GLX_EXTENSIONS);
+    printf("Server GLX_EXTENSIONS: %s\n", glx_server_extensions_str);
+}
+
+void pltf_glx_print_fbconfig(Display* display, const GLXFBConfig* cfg) {
+    int value = 0;
+
+#define PRINT_GLXFBCONFIG_VALUE(attrib)                                   \
+    value = 0;                                                            \
+    if (glXGetFBConfigAttrib(display, *cfg, attrib, &value) != Success) { \
+        LOG_FATALF("Invalid attrib %s", #attrib);                         \
+    }                                                                     \
+    printf("  %s: %d\n", #attrib, value)
+
+    puts("{");
+    PRINT_GLXFBCONFIG_VALUE(GLX_FBCONFIG_ID);
+    PRINT_GLXFBCONFIG_VALUE(GLX_BUFFER_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_LEVEL);
+    PRINT_GLXFBCONFIG_VALUE(GLX_DOUBLEBUFFER);
+    PRINT_GLXFBCONFIG_VALUE(GLX_STEREO);
+    PRINT_GLXFBCONFIG_VALUE(GLX_AUX_BUFFERS);
+    PRINT_GLXFBCONFIG_VALUE(GLX_RED_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_GREEN_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_BLUE_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_ALPHA_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_DEPTH_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_STENCIL_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_RED_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_GREEN_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_BLUE_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_ALPHA_SIZE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_SAMPLE_BUFFERS);
+    PRINT_GLXFBCONFIG_VALUE(GLX_SAMPLES);
+    PRINT_GLXFBCONFIG_VALUE(GLX_RENDER_TYPE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_DRAWABLE_TYPE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_X_RENDERABLE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_X_VISUAL_TYPE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_CONFIG_CAVEAT);
+    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_TYPE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_INDEX_VALUE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_RED_VALUE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_GREEN_VALUE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_BLUE_VALUE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_ALPHA_VALUE);
+    PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_WIDTH);
+    PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_HEIGHT);
+    PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_PIXELS);
+    PRINT_GLXFBCONFIG_VALUE(GLX_VISUAL_ID);
+    puts("}");
+
+#undef PRINT_GLXFBCONFIG_VALUE
+}
+
+#endif // __linux__

+ 27 - 0
src/pltf/internal/gl_func_alias.h

@@ -0,0 +1,27 @@
+#ifndef PLTF_GL_FUNC_ALIAS_H_
+#define PLTF_GL_FUNC_ALIAS_H_
+#define glShaderSource pltf_glShaderSource
+#define glCreateShader pltf_glCreateShader
+#define glCompileShader pltf_glCompileShader
+#define glGetShaderiv pltf_glGetShaderiv
+#define glGetShaderInfoLog pltf_glGetShaderInfoLog
+#define glCreateProgram pltf_glCreateProgram
+#define glAttachShader pltf_glAttachShader
+#define glLinkProgram pltf_glLinkProgram
+#define glGetProgramiv pltf_glGetProgramiv
+#define glDeleteShader pltf_glDeleteShader
+#define glGenVertexArrays pltf_glGenVertexArrays
+#define glBindVertexArray pltf_glBindVertexArray
+#define glGenBuffers pltf_glGenBuffers
+#define glBindBuffer pltf_glBindBuffer
+#define glBufferData pltf_glBufferData
+#define glEnableVertexAttribArray pltf_glEnableVertexAttribArray
+#define glVertexAttribPointer pltf_glVertexAttribPointer
+#define glClearColor pltf_glClearColor
+#define glClear pltf_glClear
+#define glUseProgram pltf_glUseProgram
+#define glDrawArrays pltf_glDrawArrays
+#define glGetIntegerv pltf_glGetIntegerv
+#define glGetFloatv pltf_glGetFloatv
+#define glGetError pltf_glGetError
+#endif // PLTF_GL_FUNC_ALIAS_H_

+ 38 - 0
src/pltf/internal/gl_func_decl.h

@@ -0,0 +1,38 @@
+#ifndef PLTF_GL_FUNC_DECL_H_
+#define PLTF_GL_FUNC_DECL_H_
+
+#include <GL/glcorearb.h>
+
+#define PLTF_GL_FUNCS(X) \
+X(PFNGLSHADERSOURCEPROC, glShaderSource); \
+X(PFNGLCREATESHADERPROC, glCreateShader); \
+X(PFNGLCOMPILESHADERPROC, glCompileShader); \
+X(PFNGLGETSHADERIVPROC, glGetShaderiv); \
+X(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); \
+X(PFNGLCREATEPROGRAMPROC, glCreateProgram); \
+X(PFNGLATTACHSHADERPROC, glAttachShader); \
+X(PFNGLLINKPROGRAMPROC, glLinkProgram); \
+X(PFNGLGETPROGRAMIVPROC, glGetProgramiv); \
+X(PFNGLDELETESHADERPROC, glDeleteShader); \
+X(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); \
+X(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); \
+X(PFNGLGENBUFFERSPROC, glGenBuffers); \
+X(PFNGLBINDBUFFERPROC, glBindBuffer); \
+X(PFNGLBUFFERDATAPROC, glBufferData); \
+X(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); \
+X(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); \
+X(PFNGLCLEARCOLORPROC, glClearColor); \
+X(PFNGLCLEARPROC, glClear); \
+X(PFNGLUSEPROGRAMPROC, glUseProgram); \
+X(PFNGLDRAWARRAYSPROC, glDrawArrays); \
+X(PFNGLGETINTEGERVPROC, glGetIntegerv); \
+X(PFNGLGETFLOATVPROC, glGetFloatv); \
+X(PFNGLGETERRORPROC, glGetError); \
+
+#define X(type, name) \
+extern type pltf_##name;
+
+PLTF_GL_FUNCS(X)
+#undef X
+
+#endif // PLTF_GL_FUNC_DECL_H_

+ 5 - 6
src/pltf/pltf.h

@@ -31,22 +31,21 @@ typedef enum {
     PLTF_KEY_DOWN
 } PltfKeyAction;
 
-typedef void (*PltfKeyCallback)(const PltfKeyAction action, void* user_data);
+typedef void (*PltfKeyCallback)(const PltfKey key, const PltfKeyAction action);
 
 void pltf_init();
 void pltf_deinit();
 void pltf_window_create();
-void pltf_window_close();
 void pltf_window_destroy();
 void pltf_gl_ctx_create();
 void pltf_gl_ctx_destroy();
-void pltf_gl_ctx_info_print();
 void pltf_swap_buffers();
 PltfWindowEvent pltf_window_event_handle();
 void pltf_key_callback_set(
-    const PltfKey key,
-    const PltfKeyCallback cb,
-    void* user_data
+    const PltfKeyCallback cb
 );
 
+void* pltf_gl_function_load(const char* name);
+void pltf_gl_funcs_load();
+
 #endif // PLTF_H_

+ 2 - 2
src/pltf/win32/gl_funcs.c

@@ -5,13 +5,13 @@
 #include "internal.h"
 
 #define X(type, name) \
-type name = NULL
+type pltf_##name = NULL
 
 PLTF_GL_FUNCS(X)
 #undef X
 
 #define X(type, name) \
-name = (type) pltf_gl_function_load(#name)
+pltf_##name = (type) pltf_gl_function_load(#name)
 
 void* pltf_gl_function_load(const char* name) {
     void* gl_func = (void*) wglGetProcAddress(name);

+ 2 - 9
src/pltf/win32/internal.c

@@ -7,11 +7,7 @@
 
 HMODULE opengl_module = NULL;
 
-#define PLTF_KEYS_X(lower, upper) \
-    .key_##lower##_cb = NULL,     \
-    .key_##lower##_cb_user_data = NULL,
-
-PltfWin32State pltf_state = {
+PltfStateWin32 pltf_state = {
     .wc_name = L"Scuffedcraft Window Class",
     .exe_module = NULL,
     .hwnd = NULL,
@@ -19,12 +15,9 @@ PltfWin32State pltf_state = {
     .wgl_extensions = { 0 },
     .window_state = (WinState) {
         .gl_ctx = NULL },
-
-    PLTF_KEYS(PLTF_KEYS_X)
+    .key_cb = NULL
 };
 
-#undef PLTF_KEYS_X
-
 bool pltf_has_wgl_extension(const char* name) {
     for (size_t i = 0; i < pltf_state.wgl_extensions.len; i++) {
         if (DynString_equal_c_str(DynArray_DynString_at(&pltf_state.wgl_extensions, i), name)) {

+ 3 - 10
src/pltf/win32/internal.h

@@ -12,10 +12,6 @@ typedef struct {
     HGLRC gl_ctx;
 } WinState;
 
-#define PLTF_KEYS_X(lower, upper)     \
-    PltfKeyCallback key_##lower##_cb; \
-    void* key_##lower##_cb_user_data;
-
 typedef struct {
     const wchar_t* wc_name;
     HMODULE exe_module;
@@ -23,13 +19,10 @@ typedef struct {
     HDC hdc;
     DynArray_DynString wgl_extensions;
     WinState window_state;
+    PltfKeyCallback key_cb;
+} PltfStateWin32;
 
-    PLTF_KEYS(PLTF_KEYS_X);
-} PltfWin32State;
-
-#undef PLTF_KEYS_X
-
-extern PltfWin32State pltf_state;
+extern PltfStateWin32 pltf_state;
 extern HMODULE opengl_module;
 
 bool pltf_has_wgl_extension(const char* name);

+ 3 - 56
src/pltf/win32/pltf.c

@@ -9,7 +9,6 @@
 #include <windows.h>
 #include <windowsx.h>
 
-#include "../gl_funcs.h"
 #include "../pltf.h"
 #include "DynArray.h"
 #include "DynString.h"
@@ -85,14 +84,9 @@ void pltf_window_create() {
     ShowWindow(pltf_state.hwnd, SW_SHOWDEFAULT);
 }
 
-void pltf_window_close() {
-    PostMessage(pltf_state.hwnd, WM_CLOSE, 0, 0);
-}
-
 void pltf_window_destroy() {
     if (pltf_state.hwnd != NULL) {
-        DestroyWindow(pltf_state.hwnd);
-        pltf_state.hwnd = NULL;
+        PostMessage(pltf_state.hwnd, WM_DESTROY, 0, 0);
     }
 }
 
@@ -233,36 +227,6 @@ void pltf_gl_ctx_destroy() {
     pltf_state.window_state.gl_ctx = NULL;
 }
 
-void pltf_gl_ctx_info_print() {
-    if (glGetIntegerv == NULL) {
-        glGetIntegerv = (PFNGLGETINTEGERVPROC) pltf_gl_function_load("glGetIntegerv");
-        if (glGetIntegerv == NULL) {
-            LOG_FATAL("Could not load glGetIntegerv");
-        }
-    }
-
-    int major = 0;
-    int minor = 0;
-    glGetIntegerv(GL_MAJOR_VERSION, &major);
-    glGetIntegerv(GL_MINOR_VERSION, &minor);
-
-    int profile_mask = 0;
-    char* profile;
-    glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile_mask);
-    if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT) {
-        profile = "core";
-    } else if (profile_mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) {
-        profile = "compatibility";
-    } else {
-        LOG_ERRORF(
-            "GL_CONTEXT_PROFILE_MASK did not contain either bit. profile_mask: %d",
-            profile_mask
-        );
-        return;
-    }
-    printf("OpenGL version %d.%d %s\n", major, minor, profile);
-}
-
 void pltf_swap_buffers() {
     wglSwapLayerBuffers(pltf_state.hdc, WGL_SWAP_MAIN_PLANE);
 }
@@ -281,27 +245,10 @@ PltfWindowEvent pltf_window_event_handle() {
     return PLTF_WE_NONE;
 }
 
-#define PLTF_KEYS_X(lower, upper)                          \
-    case PLTF_KEY_##upper: {                               \
-        pltf_state.key_##lower##_cb = cb;                  \
-        pltf_state.key_##lower##_cb_user_data = (void*) user_data; \
-        break;                                             \
-    }
-
 void pltf_key_callback_set(
-    const PltfKey key,
-    const PltfKeyCallback cb,
-    void* user_data
+    const PltfKeyCallback cb
 ) {
-
-    switch (key) {
-    case PLTF_KEY_NONE:
-        break;
-
-        PLTF_KEYS(PLTF_KEYS_X);
-    }
+    pltf_state.key_cb = cb;
 }
 
-#undef PLTF_KEYS_X
-
 #endif // _WIN32

+ 6 - 9
src/pltf/win32/win_proc.c

@@ -8,18 +8,15 @@
 #define PLTF_KEYS_X(lower, upper)                  \
     case PLTF_KEY_##upper:                         \
         if (pltf_state.key_##lower##_cb != NULL) { \
-           pltf_state.key_##lower##_cb(action, pltf_state.key_##lower##_cb_user_data);         \
+           pltf_state.key_##lower##_cb(action);         \
         }                                          \
         break;
 
 static void handle_key(const WPARAM key, const PltfKeyAction action) {
     const PltfKey pltf_key = vk_to_pltf_key(key);
 
-    switch (pltf_key) {
-        case PLTF_KEY_NONE:
-            break;
-
-        PLTF_KEYS(PLTF_KEYS_X);
+    if (pltf_state.key_cb != NULL) {
+        pltf_state.key_cb(pltf_key, action);
     }
 }
 
@@ -63,9 +60,9 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         return 0;
 
     case WM_CLOSE:
-        if (MessageBox(hwnd, L"Really quit?", L"My Application", MB_OKCANCEL) == IDOK) {
-            PostMessage(hwnd, WM_DESTROY, 0, 0);
-        }
+        // if (MessageBox(hwnd, L"Really quit?", L"My Application", MB_OKCANCEL) == IDOK) {
+        // }
+        PostMessage(hwnd, WM_DESTROY, 0, 0);
         return 0;
     }
     return DefWindowProc(hwnd, uMsg, wParam, lParam);