win32 stuff moved under pltf

This commit is contained in:
2026-07-03 17:32:50 +03:00
parent ea8c4bba36
commit 10a96ec02b
8 changed files with 385 additions and 391 deletions

View File

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

View File

@@ -1,366 +1,19 @@
#include <GL/glcorearb.h>
#include <GL/wglext.h>
#include <assert.h> #include <assert.h>
#include <shobjidl.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <string.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/pltf.h"
#include "pltf/gl_funcs.h"
#include "shader.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() { int main() {
pltf_init(); pltf_init();
pltf_window_create();
pltf_gl_ctx_create();
pltf_gl_funcs_load();
HMODULE module = GetModuleHandle(NULL); pltf_gl_ctx_info_print();
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);
// clang-format off // clang-format off
const float triangle_verts[] = { const float triangle_verts[] = {
@@ -404,33 +57,26 @@ int main() {
"shader.frag" "shader.frag"
); );
MSG msg = { 0 }; glClearColor(0.0f, 0.0f, 0.8f, 1.0f);
int exit_code = 0;
while (true) { while (true) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (pltf_window_event_handle() == PLTF_WE_QUIT) {
TranslateMessage(&msg); goto cleanup;
DispatchMessage(&msg);
if (msg.message == WM_QUIT) {
exit_code = msg.wParam;
goto cleanup;
}
} }
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader); glUseProgram(shader);
glBindVertexArray(triangle_vao); 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: cleanup:
UnregisterClass(CLASS_NAME, module); pltf_gl_ctx_destroy();
return exit_code; pltf_window_destroy();
pltf_deinit();
return 0; return 0;
} }

View File

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

View File

@@ -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");
}
}

View File

@@ -1,10 +1,21 @@
#ifndef PLTF_H_ #ifndef PLTF_H_
#define 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_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_ #endif // PLTF_H_

View File

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

343
src/pltf/win32/pltf.c Normal file
View File

@@ -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);
}

View File

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