Sfoglia il codice sorgente

win32 stuff moved under pltf

Aaro Saila 4 mesi fa
parent
commit
10a96ec02b
8 ha cambiato i file con 385 aggiunte e 391 eliminazioni
  1. 3 3
      meson.build
  2. 14 368
      src/main.c
  3. 1 1
      src/pltf/gl_funcs.h
  4. 0 14
      src/pltf/pltf.c
  5. 13 2
      src/pltf/pltf.h
  6. 3 3
      src/pltf/win32/gl_funcs.c
  7. 343 0
      src/pltf/win32/pltf.c
  8. 8 0
      src/pltf/win32/pltf_win32.h

+ 3 - 3
meson.build

@@ -8,7 +8,7 @@ cargs = [
   '-Og',
   '-g',
   '-DBOUNDS_CHECK',
-  '-DSHADERS_PATH="../src/shaders/"'
+  '-DSHADERS_PATH="../src/shaders/"',
   ]
 
 dependencies = [
@@ -53,8 +53,8 @@ endif
 
 executable(
   'scuffedcraft',
-  'src/pltf/gl_funcs.c',
-  'src/pltf/pltf.c',
+  'src/pltf/win32/gl_funcs.c',
+  'src/pltf/win32/pltf.c',
   'src/DynArray.c',
   'src/DynString.c',
   'src/log.c',

+ 14 - 368
src/main.c

@@ -1,366 +1,19 @@
-#include <GL/glcorearb.h>
-#include <GL/wglext.h>
 #include <assert.h>
-#include <shobjidl.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
-#include <wchar.h>
-#include <windows.h>
-#include <windowsx.h>
-#include <winuser.h>
 
-#include "DynArray.h"
-#include "DynString.h"
-#include "log.h"
-#include "pltf/gl_funcs.h"
 #include "pltf/pltf.h"
+#include "pltf/gl_funcs.h"
 #include "shader.h"
 
-// int _main() {
-//     return 0;
-// }
-
-// #ifdef __MINGW32__
-
-DynArray_DynString wgl_extensions = { 0 };
-
-typedef struct {
-    HGLRC gl_ctx;
-} State;
-
-bool has_wgl_extension(const DynString* name) {
-    assert(!DynString_is_null(name));
-    assert(!DynArray_DynString_is_null(&wgl_extensions));
-
-    for (size_t i = 0; i < wgl_extensions.len; i++) {
-        if (DynString_equal(name, DynArray_DynString_at(&wgl_extensions, i))) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-bool has_wgl_extension_c_str(const char* name) {
-    DynString name_dstr = DynString_alloc(name, strlen(name));
-    const bool res = has_wgl_extension(&name_dstr);
-    DynString_free(&name_dstr);
-    return res;
-}
-
-void print_opengl_info() {
-    // assert(glGetIntegerv != NULL);
-
-    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[sizeof("compatibility")] = { 0 };
-    glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile_mask);
-    if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT) {
-        strncpy(profile, "core", strlen("core"));
-    } else if (profile_mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) {
-        strncpy(profile, "compatibility", strlen("compatibility"));
-    } else {
-        LOG_ERRORF(
-            "GL_CONTEXT_PROFILE_MASK did not contain either bit. profile_mask: %d",
-            profile_mask
-        );
-    }
-    printf("OpenGL version %d.%d %s\n", major, minor, profile);
-}
-
-void OnSize(HWND hwnd, UINT flag, int width, int height) {
-    printf("Window resize: flag: %d, width: %d, height: %d\n", flag, width, height);
-}
-
-LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
-    State* pState = NULL;
-    if (uMsg == WM_CREATE) {
-        CREATESTRUCT* pCreate = (CREATESTRUCT*) lParam;
-        pState = (State*) pCreate->lpCreateParams;
-        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pState);
-    } else {
-        LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
-        pState = (State*) ptr;
-    }
-
-    switch (uMsg) {
-        // case WM_LBUTTONDOWN: {
-        //     printf("State: msg: %s, num: %d\n", pState->msg, pState->num);
-        //
-        //     printf("lParam: %llx\n", lParam);
-        //     int mouse_x = GET_X_LPARAM(lParam);
-        //     printf("mouse_x: %x\n", mouse_x);
-        //     int mouse_y = GET_Y_LPARAM(lParam);
-        //     printf("mouse_y: %x\n", mouse_y);
-        //     printf("x: %d y: %d\n", mouse_x, mouse_y);
-        //
-        //     return 0;
-        // }
-
-    case WM_CREATE: {
-        const PIXELFORMATDESCRIPTOR pfd = {
-            sizeof(PIXELFORMATDESCRIPTOR),
-            1,
-            PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
-            PFD_TYPE_RGBA,
-            32, // Color depth
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            24, // Depth buffer bits
-            8,  // Stencil buffer bits
-            0,
-        };
-
-        HDC hdc = GetDC(hwnd);
-        if (hdc == NULL) {
-            LOG_ERROR("Failed to get window DC");
-            return 1;
-        }
-        const int pixel_format = ChoosePixelFormat(hdc, &pfd);
-        if (SetPixelFormat(hdc, pixel_format, &pfd) == FALSE) {
-            LOG_ERRORF("Failed to set pixel format. Error: %d", GetLastError());
-            return 1;
-        }
-
-        pState->gl_ctx = wglCreateContext(hdc);
-        if (pState->gl_ctx == NULL) {
-            LOG_ERRORF("Failed to create OpenGL context. Error: %d", GetLastError());
-            return 1;
-        }
-
-        if (wglMakeCurrent(hdc, pState->gl_ctx) == FALSE) {
-            LOG_ERRORF("Failed to make OpenGL context current. Error: %d", GetLastError());
-            return 1;
-        }
-
-        printf("Dummy context info: ");
-        print_opengl_info();
-
-        PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) pltf_gl_function_load("wglGetExtensionsStringARB");
-
-        char* wgl_extensions_str = (char*) wglGetExtensionsStringARB(hdc);
-
-        char* wgl_extensions_str_copy = strdup(wgl_extensions_str);
-
-        if (!DynArray_DynString_alloc(&wgl_extensions)) {
-            LOG_ERROR("Failed to allocate wgl_extensions");
-            return 1;
-        }
-
-        char* ext = strtok(wgl_extensions_str_copy, " ");
-        if (ext == NULL) {
-            LOG_ERROR("wgl_extensions_str was empty");
-            return 1;
-        }
-        while (ext != NULL) {
-            DynString ext_dstr = DynString_alloc(ext, strlen(ext));
-
-            if (!DynArray_DynString_push_back(&wgl_extensions, &ext_dstr)) {
-                LOG_ERROR("Failed to push back extension string");
-                return 1;
-            }
-
-            ext = strtok(NULL, " ");
-            if (ext == NULL) {
-                break;
-            }
-        }
-
-        free(wgl_extensions_str_copy);
-
-        // printf("Available WGL extensions:\n");
-        // for (size_t i = 0; i < wgl_extensions.len; i++) {
-        //     const DynString* ext = DynArray_DynString_at(&wgl_extensions, i);
-        //     printf("%.*s\n", DYN_STRING_FMT(*ext));
-        // }
-
-        if (!has_wgl_extension_c_str("WGL_ARB_pixel_format")) {
-            LOG_FATAL("WGL_ARB_create_context extension required.");
-        }
-        if (!has_wgl_extension_c_str("WGL_ARB_create_context")) {
-            LOG_FATAL("WGL_ARB_create_context extension is required");
-        }
-
-        PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) pltf_gl_function_load("wglChoosePixelFormatARB");
-        PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) pltf_gl_function_load("wglCreateContextAttribsARB");
-
-        int wgl_pixel_format = 0;
-        {
-            UINT num_formats = 0;
-            const int attribIList[] = {
-                WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
-                WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
-                WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
-                WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
-                WGL_COLOR_BITS_ARB, 32,
-                WGL_DEPTH_BITS_ARB, 24,
-                WGL_STENCIL_BITS_ARB, 8,
-                0
-            };
-            if (wglChoosePixelFormatARB(hdc, attribIList, NULL, 1, &wgl_pixel_format, &num_formats) == FALSE) {
-                LOG_FATAL("Failed to get pixel format with wglChoosePixelFormatARB");
-            }
-        }
-
-        if (SetPixelFormat(hdc, wgl_pixel_format, &pfd) == FALSE) {
-            LOG_FATAL("Failed to set wgl_pixel_format");
-        }
-
-        if (wglDeleteContext(pState->gl_ctx) == FALSE) {
-            LOG_FATAL("Failed to delete dummy context");
-        }
-
-        {
-            const int attribIList[] = {
-                WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
-                WGL_CONTEXT_MINOR_VERSION_ARB, 6,
-                WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
-                WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
-            };
-            pState->gl_ctx = wglCreateContextAttribsARB(hdc, NULL, attribIList);
-            if (pState->gl_ctx == NULL) {
-                LOG_FATAL("wglCreateContextAttribsARB did not create a context");
-            }
-        }
-
-        if (wglMakeCurrent(hdc, pState->gl_ctx) == FALSE) {
-            LOG_FATAL("Failed to set proper context as current");
-        }
-
-        printf("Proper context info: ");
-        print_opengl_info();
-
-        pltf_load_gl_funcs();
-
-        return 0;
-    }
-
-    case WM_KEYDOWN:
-        if (wParam == VK_ESCAPE) {
-            PostMessage(hwnd, WM_DESTROY, 0, 0);
-        }
-        return 0;
-
-    case WM_DESTROY:
-        wglDeleteContext(pState->gl_ctx);
-        PostQuitMessage(0);
-        return 0;
-
-    case WM_CLOSE:
-        if (MessageBox(hwnd, L"Really quit?", L"My Application", MB_OKCANCEL) == IDOK) {
-            DestroyWindow(hwnd);
-        }
-        return 0;
-
-    case WM_SIZE: {
-        int width = LOWORD(lParam);
-        int height = HIWORD(lParam);
-        OnSize(hwnd, (UINT) wParam, width, height);
-        return 0;
-    }
-
-        // case WM_PAINT: {
-        //     PAINTSTRUCT ps;
-        //     HDC hdc = BeginPaint(hwnd, &ps);
-        //
-        //     FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW + 1));
-        //     RECT blue = {
-        //         .bottom = 100,
-        //         .left = 0,
-        //         .right = 100,
-        //         .top = 0
-        //     };
-        //     FillRect(hdc, &blue, (HBRUSH) (COLOR_BACKGROUND + 1));
-        //
-        //     EndPaint(hwnd, &ps);
-        //     return 0;
-        // }
-    }
-    return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
 int main() {
     pltf_init();
+    pltf_window_create();
+    pltf_gl_ctx_create();
+    pltf_gl_funcs_load();
 
-    HMODULE module = GetModuleHandle(NULL);
-    if (module == NULL) {
-        LOG_FATAL("Failed to get module");
-    }
-
-    // Register the window class
-    const wchar_t* CLASS_NAME = L"Sample Window Class";
-
-    WNDCLASS wc = { };
-    wc.lpfnWndProc = WindowProc;
-    wc.hInstance = module;
-    wc.lpszClassName = CLASS_NAME;
-    wc.style = CS_OWNDC;
-
-    RegisterClass(&wc);
-
-    State s = {
-        .gl_ctx = NULL
-    };
-
-    // Create the window
-    HWND hwnd = CreateWindowEx(
-        0,                           // Optional window styles
-        CLASS_NAME,                  // Window class
-        L"Learn to Program Windows", // Window text
-        WS_OVERLAPPEDWINDOW,         // Window style
-
-        // Size and position
-        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
-
-        NULL,      // Parent window
-        NULL,      // Menu
-        module, // Instance handle
-        &s         // Additional application data
-    );
-
-    if (hwnd == NULL) {
-        LOG_ERROR("ERROR: hwnd was NULL\n");
-        return 1;
-    }
-
-    ShowWindow(hwnd, SW_SHOWDEFAULT);
-
-    // Message loop
-
-    GLenum gl_err = 0;
-    glClearColor(0.0f, 0.0f, 0.8f, 1.0f);
-    float colors[4] = { 0 };
-    glGetFloatv(GL_COLOR_CLEAR_VALUE, colors);
-    printf("Clear color: %f, %f, %f, %f\n", colors[0], colors[1], colors[2], colors[3]);
-    gl_err = glGetError();
-    if (gl_err != GL_NO_ERROR) {
-        LOG_FATALF("gl error: %d", gl_err);
-    }
-
-    HDC hdc = GetDC(hwnd);
+    pltf_gl_ctx_info_print();
 
     // clang-format off
     const float triangle_verts[] = {
@@ -404,33 +57,26 @@ int main() {
         "shader.frag"
     );
 
-    MSG msg = { 0 };
-    int exit_code = 0;
+    glClearColor(0.0f, 0.0f, 0.8f, 1.0f);
+
     while (true) {
-        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
-            TranslateMessage(&msg);
-            DispatchMessage(&msg);
-            if (msg.message == WM_QUIT) {
-                exit_code = msg.wParam;
-                goto cleanup;
-            }
+        if (pltf_window_event_handle() == PLTF_WE_QUIT) {
+            goto cleanup;
         }
 
         glClear(GL_COLOR_BUFFER_BIT);
 
         glUseProgram(shader);
         glBindVertexArray(triangle_vao);
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, triangle_vert_count);
+        glDrawArrays(GL_TRIANGLES, 0, triangle_vert_count);
 
-        wglSwapLayerBuffers(hdc, WGL_SWAP_MAIN_PLANE);
+        pltf_swap_buffers();
     }
 
-    return 0;
-
 cleanup:
-    UnregisterClass(CLASS_NAME, module);
-    return exit_code;
-
+    pltf_gl_ctx_destroy();
+    pltf_window_destroy();
+    pltf_deinit();
 
     return 0;
 }

+ 1 - 1
src/pltf/gl_funcs.h

@@ -35,6 +35,6 @@ PLTF_GL_FUNCS(X)
 #undef X
 
 void* pltf_gl_function_load(const char* name);
-void pltf_load_gl_funcs();
+void pltf_gl_funcs_load();
 
 #endif // GL_FUNCS_H_

+ 0 - 14
src/pltf/pltf.c

@@ -1,14 +0,0 @@
-#include <windows.h>
-#include <minwindef.h>
-
-#include "pltf.h"
-#include "log.h"
-
-HMODULE opengl_module = NULL;
-
-void pltf_init() {
-    opengl_module = LoadLibraryA("opengl32.dll");
-    if (opengl_module == NULL) {
-        LOG_FATAL("Failed to load opengl32.dll");
-    }
-}

+ 13 - 2
src/pltf/pltf.h

@@ -1,10 +1,21 @@
 #ifndef PLTF_H_
 #define PLTF_H_
 
-#include <minwindef.h>
+#include <stdbool.h>
 
-extern HMODULE opengl_module;
+typedef enum {
+    PLTF_WE_NULL,
+    PLTF_WE_QUIT
+} PltfWindowEvent;
 
 void pltf_init();
+void pltf_deinit();
+void pltf_window_create();
+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();
 
 #endif // PLTF_H_

+ 3 - 3
src/pltf/gl_funcs.c → src/pltf/win32/gl_funcs.c

@@ -1,6 +1,6 @@
-#include "gl_funcs.h"
+#include "../gl_funcs.h"
 #include "log.h"
-#include "pltf.h"
+#include "pltf_win32.h"
 
 #define X(type, name) \
 type name = NULL
@@ -27,7 +27,7 @@ void* pltf_gl_function_load(const char* name) {
     return gl_func;
 }
 
-void pltf_load_gl_funcs() {
+void pltf_gl_funcs_load() {
     PLTF_GL_FUNCS(X)
 }
 

+ 343 - 0
src/pltf/win32/pltf.c

@@ -0,0 +1,343 @@
+#include <GL/glcorearb.h>
+#include <GL/wglext.h>
+#include <assert.h>
+#include <stdio.h>
+#include <windows.h>
+#include <windowsx.h>
+
+#include "../gl_funcs.h"
+#include "../pltf.h"
+#include "DynArray.h"
+#include "DynString.h"
+#include "log.h"
+
+typedef struct {
+    HGLRC gl_ctx;
+} State;
+
+HMODULE opengl_module = NULL;
+
+static const wchar_t* wc_name = L"Sample Window Class";
+static HMODULE exe_module = NULL;
+static HWND hwnd = NULL;
+static HDC hdc = NULL;
+static DynArray_DynString wgl_extensions = { 0 };
+static State window_state = {
+    .gl_ctx = NULL
+};
+
+static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+void pltf_init() {
+    exe_module = GetModuleHandle(NULL);
+    if (exe_module == NULL) {
+        LOG_FATAL("Failed to get module");
+    }
+
+    opengl_module = LoadLibraryA("opengl32.dll");
+    if (opengl_module == NULL) {
+        LOG_FATAL("Failed to load opengl32.dll");
+    }
+
+    // Register the window class
+    WNDCLASS wc = { };
+    wc.lpfnWndProc = WindowProc;
+    wc.hInstance = exe_module;
+    wc.lpszClassName = wc_name;
+    wc.style = CS_OWNDC;
+
+    RegisterClass(&wc);
+}
+
+void pltf_deinit() {
+    UnregisterClass(wc_name, exe_module);
+}
+
+static bool pltf_has_wgl_extension(const DynString* name) {
+    for (size_t i = 0; i < wgl_extensions.len; i++) {
+        if (DynString_equal(name, DynArray_DynString_at(&wgl_extensions, i))) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static bool pltf_has_wgl_extension_c_str(const char* name) {
+    DynString name_dstr = DynString_alloc(name, strlen(name));
+    const bool res = pltf_has_wgl_extension(&name_dstr);
+    DynString_free(&name_dstr);
+    return res;
+}
+
+void pltf_window_create() {
+    // Create the window
+    hwnd = CreateWindowEx(
+        0,                           // Optional window styles
+        wc_name,                     // Window class
+        L"Learn to Program Windows", // Window text
+        WS_OVERLAPPEDWINDOW,         // Window style
+
+        // Size and position
+        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+
+        NULL,         // Parent window
+        NULL,         // Menu
+        exe_module,   // Instance handle
+        &window_state // Additional application data
+    );
+
+    if (hwnd == NULL) {
+        LOG_FATAL("ERROR: hwnd was NULL");
+    }
+
+    hdc = GetDC(hwnd);
+    if (hdc == NULL) {
+        LOG_FATAL("Failed to get HDC");
+    }
+
+    ShowWindow(hwnd, SW_SHOWDEFAULT);
+}
+
+void pltf_window_destroy() {
+    if (hwnd != NULL) {
+        DestroyWindow(hwnd);
+        hwnd = NULL;
+    }
+}
+
+void pltf_gl_ctx_create() {
+    const PIXELFORMATDESCRIPTOR pfd = {
+        sizeof(PIXELFORMATDESCRIPTOR),
+        1,
+        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
+        PFD_TYPE_RGBA,
+        32, // Color depth
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        24, // Depth buffer bits
+        8,  // Stencil buffer bits
+        0,
+    };
+
+    HDC hdc = GetDC(hwnd);
+    if (hdc == NULL) {
+        LOG_ERROR("Failed to get window DC");
+        return;
+    }
+    const int pixel_format = ChoosePixelFormat(hdc, &pfd);
+    if (SetPixelFormat(hdc, pixel_format, &pfd) == FALSE) {
+        LOG_ERRORF("Failed to set pixel format. Error: %d", GetLastError());
+        return;
+    }
+
+    window_state.gl_ctx = wglCreateContext(hdc);
+    if (window_state.gl_ctx == NULL) {
+        LOG_ERRORF("Failed to create OpenGL context. Error: %d", GetLastError());
+        return;
+    }
+
+    if (wglMakeCurrent(hdc, window_state.gl_ctx) == FALSE) {
+        LOG_ERRORF("Failed to make OpenGL context current. Error: %d", GetLastError());
+        return;
+    }
+
+    PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) pltf_gl_function_load("wglGetExtensionsStringARB");
+
+    char* wgl_extensions_str = (char*) wglGetExtensionsStringARB(hdc);
+
+    char* wgl_extensions_str_copy = strdup(wgl_extensions_str);
+
+    if (!DynArray_DynString_alloc(&wgl_extensions)) {
+        LOG_ERROR("Failed to allocate wgl_extensions");
+        return;
+    }
+
+    char* ext = strtok(wgl_extensions_str_copy, " ");
+    if (ext == NULL) {
+        LOG_ERROR("wgl_extensions_str was empty");
+        return;
+    }
+    while (ext != NULL) {
+        DynString ext_dstr = DynString_alloc(ext, strlen(ext));
+
+        if (!DynArray_DynString_push_back(&wgl_extensions, &ext_dstr)) {
+            LOG_ERROR("Failed to push back extension string");
+            return;
+        }
+
+        ext = strtok(NULL, " ");
+        if (ext == NULL) {
+            break;
+        }
+    }
+
+    free(wgl_extensions_str_copy);
+
+    if (!pltf_has_wgl_extension_c_str("WGL_ARB_pixel_format")) {
+        LOG_FATAL("WGL_ARB_create_context extension required.");
+    }
+    if (!pltf_has_wgl_extension_c_str("WGL_ARB_create_context")) {
+        LOG_FATAL("WGL_ARB_create_context extension is required");
+    }
+
+    PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) pltf_gl_function_load("wglChoosePixelFormatARB");
+    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) pltf_gl_function_load("wglCreateContextAttribsARB");
+
+    int wgl_pixel_format = 0;
+    {
+        UINT num_formats = 0;
+        const int attribIList[] = {
+            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
+            WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
+            WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
+            WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
+            WGL_COLOR_BITS_ARB, 32,
+            WGL_DEPTH_BITS_ARB, 24,
+            WGL_STENCIL_BITS_ARB, 8,
+            0
+        };
+        if (wglChoosePixelFormatARB(hdc, attribIList, NULL, 1, &wgl_pixel_format, &num_formats) == FALSE) {
+            LOG_FATAL("Failed to get pixel format with wglChoosePixelFormatARB");
+        }
+    }
+
+    if (SetPixelFormat(hdc, wgl_pixel_format, &pfd) == FALSE) {
+        LOG_FATAL("Failed to set wgl_pixel_format");
+    }
+
+    if (wglDeleteContext(window_state.gl_ctx) == FALSE) {
+        LOG_FATAL("Failed to delete dummy context");
+    }
+
+    {
+        const int attribIList[] = {
+            WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
+            WGL_CONTEXT_MINOR_VERSION_ARB, 6,
+            WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
+            WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
+        };
+        window_state.gl_ctx = wglCreateContextAttribsARB(hdc, NULL, attribIList);
+        if (window_state.gl_ctx == NULL) {
+            LOG_FATAL("wglCreateContextAttribsARB did not create a context");
+        }
+    }
+
+    if (wglMakeCurrent(hdc, window_state.gl_ctx) == FALSE) {
+        LOG_FATAL("Failed to set proper context as current");
+    }
+}
+
+void pltf_gl_ctx_destroy() {
+    wglDeleteContext(window_state.gl_ctx);
+    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(hdc, WGL_SWAP_MAIN_PLANE);
+}
+
+PltfWindowEvent pltf_window_event_handle() {
+    MSG msg = { 0 };
+    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+        if (msg.message == WM_QUIT) {
+            return PLTF_WE_QUIT;
+        }
+    }
+
+    return PLTF_WE_NULL;
+}
+
+static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+    State* pState = NULL;
+    if (uMsg == WM_CREATE) {
+        CREATESTRUCT* pCreate = (CREATESTRUCT*) lParam;
+        pState = (State*) pCreate->lpCreateParams;
+        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pState);
+    } else {
+        LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
+        pState = (State*) ptr;
+    }
+
+    switch (uMsg) {
+        // case WM_LBUTTONDOWN: {
+        //     printf("State: msg: %s, num: %d\n", pState->msg, pState->num);
+        //
+        //     printf("lParam: %llx\n", lParam);
+        //     int mouse_x = GET_X_LPARAM(lParam);
+        //     printf("mouse_x: %x\n", mouse_x);
+        //     int mouse_y = GET_Y_LPARAM(lParam);
+        //     printf("mouse_y: %x\n", mouse_y);
+        //     printf("x: %d y: %d\n", mouse_x, mouse_y);
+        //
+        //     return 0;
+        // }
+
+    case WM_CREATE: {
+
+        return 0;
+    }
+
+    case WM_KEYDOWN:
+        if (wParam == VK_ESCAPE) {
+            PostMessage(hwnd, WM_DESTROY, 0, 0);
+        }
+        return 0;
+
+    case WM_DESTROY:
+        wglDeleteContext(pState->gl_ctx);
+        PostQuitMessage(0);
+        return 0;
+
+    case WM_CLOSE:
+        if (MessageBox(hwnd, L"Really quit?", L"My Application", MB_OKCANCEL) == IDOK) {
+            DestroyWindow(hwnd);
+        }
+        return 0;
+    }
+    return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+

+ 8 - 0
src/pltf/win32/pltf_win32.h

@@ -0,0 +1,8 @@
+#ifndef PLTF_WIN32_H_
+#define PLTF_WIN32_H_
+
+#include <windef.h>
+
+extern HMODULE opengl_module;
+
+#endif // PLTF_WIN32_H_