bundled global pltf variables into a struct

This commit is contained in:
2026-07-03 19:04:49 +03:00
parent 10a96ec02b
commit c809aa98f5
2 changed files with 56 additions and 49 deletions

View File

@@ -88,7 +88,7 @@
#define DYN_ARRAY_AT(type, type_name, func_name) \ #define DYN_ARRAY_AT(type, type_name, func_name) \
DYN_ARRAY_AT_SIG(type, type_name, func_name) { \ DYN_ARRAY_AT_SIG(type, type_name, func_name) { \
if (i < 0 || i > darr->len) { \ if (i < 0 || i > darr->len) { \
LOG_FATALF(#func_name " exceeded bounds! i: %zu, len: %zu", i, darr->len); \ LOG_FATALF(#func_name " out-of-bounds. i: %zu, len: %zu", i, darr->len); \
} \ } \
\ \
return &darr->data[i]; \ return &darr->data[i]; \

View File

@@ -13,24 +13,33 @@
typedef struct { typedef struct {
HGLRC gl_ctx; HGLRC gl_ctx;
} State; } WinState;
HMODULE opengl_module = NULL; HMODULE opengl_module = NULL;
static const wchar_t* wc_name = L"Sample Window Class"; static struct {
static HMODULE exe_module = NULL; const wchar_t* wc_name;
static HWND hwnd = NULL; HMODULE exe_module;
static HDC hdc = NULL; HWND hwnd;
static DynArray_DynString wgl_extensions = { 0 }; HDC hdc;
static State window_state = { DynArray_DynString wgl_extensions;
WinState window_state;
} pltf_state = {
.wc_name = L"Sample Window Class",
.exe_module = NULL,
.hwnd = NULL,
.hdc = NULL,
.wgl_extensions = { 0 },
.window_state = (WinState) {
.gl_ctx = NULL .gl_ctx = NULL
}
}; };
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void pltf_init() { void pltf_init() {
exe_module = GetModuleHandle(NULL); pltf_state.exe_module = GetModuleHandle(NULL);
if (exe_module == NULL) { if (pltf_state.exe_module == NULL) {
LOG_FATAL("Failed to get module"); LOG_FATAL("Failed to get module");
} }
@@ -42,20 +51,20 @@ void pltf_init() {
// Register the window class // Register the window class
WNDCLASS wc = { }; WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc; wc.lpfnWndProc = WindowProc;
wc.hInstance = exe_module; wc.hInstance = pltf_state.exe_module;
wc.lpszClassName = wc_name; wc.lpszClassName = pltf_state.wc_name;
wc.style = CS_OWNDC; wc.style = CS_OWNDC;
RegisterClass(&wc); RegisterClass(&wc);
} }
void pltf_deinit() { void pltf_deinit() {
UnregisterClass(wc_name, exe_module); UnregisterClass(pltf_state.wc_name, pltf_state.exe_module);
} }
static bool pltf_has_wgl_extension(const DynString* name) { static bool pltf_has_wgl_extension(const DynString* name) {
for (size_t i = 0; i < wgl_extensions.len; i++) { for (size_t i = 0; i < pltf_state.wgl_extensions.len; i++) {
if (DynString_equal(name, DynArray_DynString_at(&wgl_extensions, i))) { if (DynString_equal(name, DynArray_DynString_at(&pltf_state.wgl_extensions, i))) {
return true; return true;
} }
} }
@@ -72,9 +81,9 @@ static bool pltf_has_wgl_extension_c_str(const char* name) {
void pltf_window_create() { void pltf_window_create() {
// Create the window // Create the window
hwnd = CreateWindowEx( pltf_state.hwnd = CreateWindowEx(
0, // Optional window styles 0, // Optional window styles
wc_name, // Window class pltf_state.wc_name, // Window class
L"Learn to Program Windows", // Window text L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style WS_OVERLAPPEDWINDOW, // Window style
@@ -83,26 +92,26 @@ void pltf_window_create() {
NULL, // Parent window NULL, // Parent window
NULL, // Menu NULL, // Menu
exe_module, // Instance handle pltf_state.exe_module, // Instance handle
&window_state // Additional application data &pltf_state.window_state // Additional application data
); );
if (hwnd == NULL) { if (pltf_state.hwnd == NULL) {
LOG_FATAL("ERROR: hwnd was NULL"); LOG_FATAL("ERROR: hwnd was NULL");
} }
hdc = GetDC(hwnd); pltf_state.hdc = GetDC(pltf_state.hwnd);
if (hdc == NULL) { if (pltf_state.hdc == NULL) {
LOG_FATAL("Failed to get HDC"); LOG_FATAL("Failed to get HDC");
} }
ShowWindow(hwnd, SW_SHOWDEFAULT); ShowWindow(pltf_state.hwnd, SW_SHOWDEFAULT);
} }
void pltf_window_destroy() { void pltf_window_destroy() {
if (hwnd != NULL) { if (pltf_state.hwnd != NULL) {
DestroyWindow(hwnd); DestroyWindow(pltf_state.hwnd);
hwnd = NULL; pltf_state.hwnd = NULL;
} }
} }
@@ -131,7 +140,7 @@ void pltf_gl_ctx_create() {
0, 0,
}; };
HDC hdc = GetDC(hwnd); HDC hdc = GetDC(pltf_state.hwnd);
if (hdc == NULL) { if (hdc == NULL) {
LOG_ERROR("Failed to get window DC"); LOG_ERROR("Failed to get window DC");
return; return;
@@ -142,29 +151,28 @@ void pltf_gl_ctx_create() {
return; return;
} }
window_state.gl_ctx = wglCreateContext(hdc); pltf_state.window_state.gl_ctx = wglCreateContext(hdc);
if (window_state.gl_ctx == NULL) { if (pltf_state.window_state.gl_ctx == NULL) {
LOG_ERRORF("Failed to create OpenGL context. Error: %d", GetLastError()); LOG_ERRORF("Failed to create OpenGL context. Error: %d", GetLastError());
return; return;
} }
if (wglMakeCurrent(hdc, window_state.gl_ctx) == FALSE) { if (wglMakeCurrent(hdc, pltf_state.window_state.gl_ctx) == FALSE) {
LOG_ERRORF("Failed to make OpenGL context current. Error: %d", GetLastError()); LOG_ERRORF("Failed to make OpenGL context current. Error: %d", GetLastError());
return; return;
} }
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) pltf_gl_function_load("wglGetExtensionsStringARB"); PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) pltf_gl_function_load("wglGetExtensionsStringARB");
char* wgl_extensions_str = (char*) wglGetExtensionsStringARB(hdc); // Copy to prevent modifying the original string. Might be useless but doing it just in case.
char* wgl_extensions_str = strdup(wglGetExtensionsStringARB(hdc));
char* wgl_extensions_str_copy = strdup(wgl_extensions_str); if (!DynArray_DynString_alloc(&pltf_state.wgl_extensions)) {
if (!DynArray_DynString_alloc(&wgl_extensions)) {
LOG_ERROR("Failed to allocate wgl_extensions"); LOG_ERROR("Failed to allocate wgl_extensions");
return; return;
} }
char* ext = strtok(wgl_extensions_str_copy, " "); char* ext = strtok(wgl_extensions_str, " ");
if (ext == NULL) { if (ext == NULL) {
LOG_ERROR("wgl_extensions_str was empty"); LOG_ERROR("wgl_extensions_str was empty");
return; return;
@@ -172,7 +180,7 @@ void pltf_gl_ctx_create() {
while (ext != NULL) { while (ext != NULL) {
DynString ext_dstr = DynString_alloc(ext, strlen(ext)); DynString ext_dstr = DynString_alloc(ext, strlen(ext));
if (!DynArray_DynString_push_back(&wgl_extensions, &ext_dstr)) { if (!DynArray_DynString_push_back(&pltf_state.wgl_extensions, &ext_dstr)) {
LOG_ERROR("Failed to push back extension string"); LOG_ERROR("Failed to push back extension string");
return; return;
} }
@@ -183,7 +191,7 @@ void pltf_gl_ctx_create() {
} }
} }
free(wgl_extensions_str_copy); free(wgl_extensions_str);
if (!pltf_has_wgl_extension_c_str("WGL_ARB_pixel_format")) { if (!pltf_has_wgl_extension_c_str("WGL_ARB_pixel_format")) {
LOG_FATAL("WGL_ARB_create_context extension required."); LOG_FATAL("WGL_ARB_create_context extension required.");
@@ -217,7 +225,7 @@ void pltf_gl_ctx_create() {
LOG_FATAL("Failed to set wgl_pixel_format"); LOG_FATAL("Failed to set wgl_pixel_format");
} }
if (wglDeleteContext(window_state.gl_ctx) == FALSE) { if (wglDeleteContext(pltf_state.window_state.gl_ctx) == FALSE) {
LOG_FATAL("Failed to delete dummy context"); LOG_FATAL("Failed to delete dummy context");
} }
@@ -228,20 +236,20 @@ void pltf_gl_ctx_create() {
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
}; };
window_state.gl_ctx = wglCreateContextAttribsARB(hdc, NULL, attribIList); pltf_state.window_state.gl_ctx = wglCreateContextAttribsARB(hdc, NULL, attribIList);
if (window_state.gl_ctx == NULL) { if (pltf_state.window_state.gl_ctx == NULL) {
LOG_FATAL("wglCreateContextAttribsARB did not create a context"); LOG_FATAL("wglCreateContextAttribsARB did not create a context");
} }
} }
if (wglMakeCurrent(hdc, window_state.gl_ctx) == FALSE) { if (wglMakeCurrent(hdc, pltf_state.window_state.gl_ctx) == FALSE) {
LOG_FATAL("Failed to set proper context as current"); LOG_FATAL("Failed to set proper context as current");
} }
} }
void pltf_gl_ctx_destroy() { void pltf_gl_ctx_destroy() {
wglDeleteContext(window_state.gl_ctx); wglDeleteContext(pltf_state.window_state.gl_ctx);
window_state.gl_ctx = NULL; pltf_state.window_state.gl_ctx = NULL;
} }
void pltf_gl_ctx_info_print() { void pltf_gl_ctx_info_print() {
@@ -275,7 +283,7 @@ void pltf_gl_ctx_info_print() {
} }
void pltf_swap_buffers() { void pltf_swap_buffers() {
wglSwapLayerBuffers(hdc, WGL_SWAP_MAIN_PLANE); wglSwapLayerBuffers(pltf_state.hdc, WGL_SWAP_MAIN_PLANE);
} }
PltfWindowEvent pltf_window_event_handle() { PltfWindowEvent pltf_window_event_handle() {
@@ -292,14 +300,14 @@ PltfWindowEvent pltf_window_event_handle() {
} }
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
State* pState = NULL; WinState* pState = NULL;
if (uMsg == WM_CREATE) { if (uMsg == WM_CREATE) {
CREATESTRUCT* pCreate = (CREATESTRUCT*) lParam; CREATESTRUCT* pCreate = (CREATESTRUCT*) lParam;
pState = (State*) pCreate->lpCreateParams; pState = (WinState*) pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pState); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pState);
} else { } else {
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA); LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
pState = (State*) ptr; pState = (WinState*) ptr;
} }
switch (uMsg) { switch (uMsg) {
@@ -317,7 +325,6 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
// } // }
case WM_CREATE: { case WM_CREATE: {
return 0; return 0;
} }