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