win32 stuff moved under pltf
This commit is contained in:
382
src/main.c
382
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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
|
||||
@@ -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
src/pltf/win32/pltf.c
Normal file
343
src/pltf/win32/pltf.c
Normal 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);
|
||||
}
|
||||
|
||||
8
src/pltf/win32/pltf_win32.h
Normal file
8
src/pltf/win32/pltf_win32.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef PLTF_WIN32_H_
|
||||
#define PLTF_WIN32_H_
|
||||
|
||||
#include <windef.h>
|
||||
|
||||
extern HMODULE opengl_module;
|
||||
|
||||
#endif // PLTF_WIN32_H_
|
||||
Reference in New Issue
Block a user