Aaro Saila 4 ay önce
ebeveyn
işleme
94ea46a320
6 değiştirilmiş dosya ile 325 ekleme ve 67 silme
  1. 2 0
      meson.build
  2. 226 67
      src/main.c
  3. 33 0
      src/pltf/gl_funcs.c
  4. 40 0
      src/pltf/gl_funcs.h
  5. 14 0
      src/pltf/pltf.c
  6. 10 0
      src/pltf/pltf.h

+ 2 - 0
meson.build

@@ -40,6 +40,8 @@ endif
 
 executable(
   'scuffedcraft',
+  'src/pltf/gl_funcs.c',
+  'src/pltf/pltf.c',
   'src/DynArray.c',
   'src/DynString.c',
   'src/log.c',

+ 226 - 67
src/main.c

@@ -13,11 +13,8 @@
 #include "DynArray.h"
 #include "DynString.h"
 #include "log.h"
-
-#include <time.h>
-#include <sys/time.h>
-
-HMODULE opengl_module = NULL;
+#include "pltf/gl_funcs.h"
+#include "pltf/pltf.h"
 
 // int _main() {
 //     return 0;
@@ -32,23 +29,6 @@ typedef struct {
     int num;
 } State;
 
-void* gl_function_load(const char* name) {
-    assert(opengl_module != NULL);
-    void* gl_func = (void*) wglGetProcAddress(name);
-    if (gl_func == NULL || gl_func == (void*) 1 || gl_func == (void*) 2 || gl_func == (void*) 3 || gl_func == (void*) -1) {
-        void* gl32_func = (void*) GetProcAddress(opengl_module, name);
-        if (gl32_func == NULL || gl32_func == (void*) 1 || gl32_func == (void*) 2 || gl32_func == (void*) 3 || gl32_func == (void*) -1) {
-            LOG_ERRORF("wglGetProcAddress failed to load gl function %s. Returned %p\n", name, gl_func);
-            LOG_ERRORF("GetProcAddress    failed to load gl function %s. Returned %p\n", name, gl32_func);
-            return NULL;
-        }
-
-        return gl32_func;
-    }
-
-    return gl_func;
-}
-
 bool has_wgl_extension(const DynString* name) {
     assert(!DynString_is_null(name));
     assert(!DynArray_DynString_is_null(&wgl_extensions));
@@ -69,12 +49,35 @@ bool has_wgl_extension_c_str(const char* name) {
     return res;
 }
 
-struct timespec thread_time_get() {
-    struct timespec t = { 0 };
-    if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t) == -1) {
-        LOG_FATALF("Failed to get thread time. errno: %d", errno);
+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");
+        }
     }
-    return t;
+
+    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) {
@@ -131,7 +134,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             0,
         };
 
-        HDC hdc = GetWindowDC(hwnd);
+        HDC hdc = GetDC(hwnd);
         if (hdc == NULL) {
             LOG_ERROR("Failed to get window DC");
             return 1;
@@ -153,37 +156,12 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             return 1;
         }
 
-        PFNGLGETINTEGERVPROC glGetIntegerv = (PFNGLGETINTEGERVPROC) gl_function_load("glGetIntegerv");
-        if (glGetIntegerv == NULL) {
-            return 1;
-        }
-        int major = 0;
-        int minor = 0;
-        glGetIntegerv(GL_MAJOR_VERSION, &major);
-        glGetIntegerv(GL_MINOR_VERSION, &minor);
-        printf("OpenGL version %d.%d\n", major, minor);
-
-        int profile_mask = 0;
-        glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile_mask);
-        if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT) {
-            printf("OpenGL profile: core\n");
-        } else if (profile_mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) {
-            printf("OpenGL profile: compatibility\n");
-        } else {
-            LOG_ERRORF(
-                "GL_CONTEXT_PROFILE_MASK did not contain either bit. profile_mask: %d",
-                profile_mask
-            );
-        }
+        printf("Dummy context info: ");
+        print_opengl_info();
 
-        PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) gl_function_load("wglGetExtensionsStringARB");
-        if (wglGetExtensionsStringARB == NULL) {
-            LOG_ERROR("Could not load wgl extensions string.");
-            return 1;
-        }
+        PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) pltf_gl_function_load("wglGetExtensionsStringARB");
 
         char* wgl_extensions_str = (char*) wglGetExtensionsStringARB(hdc);
-        printf("wgl extensions: %s\n", wgl_extensions_str);
 
         char* wgl_extensions_str_copy = strdup(wgl_extensions_str);
 
@@ -209,20 +187,73 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             if (ext == NULL) {
                 break;
             }
-
         }
 
         free(wgl_extensions_str_copy);
 
-        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));
+        // 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(gl_ctx) == FALSE) {
+            LOG_FATAL("Failed to delete dummy context");
         }
 
-        const struct timespec b = thread_time_get();
-        has_wgl_extension_c_str("WGL_ARB_create_context");
-        const struct timespec a = thread_time_get();
-        printf("time: %ld\n", a.tv_nsec - b.tv_nsec);
+        {
+            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
+            };
+            gl_ctx = wglCreateContextAttribsARB(hdc, NULL, attribIList);
+            if (gl_ctx == NULL) {
+                LOG_FATAL("wglCreateContextAttribsARB did not create a context");
+            }
+        }
+
+        if (wglMakeCurrent(hdc, 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;
     }
@@ -271,7 +302,9 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 }
 
 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow) {
-    opengl_module = LoadLibraryA("opengl32.dll");
+    // opengl_module = LoadLibraryA("opengl32.dll");
+
+    pltf_init();
 
     // Register the window class
     const wchar_t* CLASS_NAME = L"Sample Window Class";
@@ -314,10 +347,136 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine,
 
     // Message loop
 
-    MSG msg = { };
-    while (GetMessage(&msg, NULL, 0, 0) > 0) {
+    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
+    const float triangle_verts[] = {
+        // pos
+        0.0f, 0.5f, 0.0f, // top
+        -0.5f, -0.5f, 0.0f, // bottom-left
+        0.5f, -0.5f, 0.0f // bottom-right
+
+    };
+    // clang-format on
+
+    const size_t triangle_vert_count = sizeof(triangle_verts) / sizeof(triangle_verts[0]) / 3;
+
+    unsigned int triangle_vao = 0;
+    glGenVertexArrays(1, &triangle_vao);
+    glBindVertexArray(triangle_vao);
+
+    unsigned int triangle_vbo = 0;
+    glGenBuffers(1, &triangle_vbo);
+    glBindBuffer(GL_ARRAY_BUFFER, triangle_vbo);
+    glBufferData(
+        GL_ARRAY_BUFFER,
+        sizeof(triangle_verts),
+        triangle_verts,
+        GL_STATIC_DRAW
+    );
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(
+        0,
+        3,
+        GL_FLOAT,
+        GL_FALSE,
+        sizeof(float) * 3,
+        (void*) 0
+    );
+
+    glBindVertexArray(0);
+
+    // clang-format off
+    const char* vertex_shader_src =
+    "#version 460 core\n"
+    "layout (location = 0) in vec3 a_pos;\n"
+    "void main() {\n"
+    "   gl_Position = vec4(a_pos, 1.0);\n"
+    "}\n"
+    ;
+
+    const char* fragment_shader_src =
+    "#version 460 core\n"
+    "out vec4 frag_color;\n"
+    "void main() {\n"
+    "   frag_color = vec4(0.0, 0.0, 0.0, 1.0);\n"
+    "}\n"
+    ;
+    // clang-format on
+
+    const unsigned int vert_shader = glCreateShader(GL_VERTEX_SHADER);
+    {
+        const int len = strlen(vertex_shader_src);
+        glShaderSource(vert_shader, 1, &vertex_shader_src, &len);
+        glCompileShader(vert_shader);
+        int compile_status = 0;
+        glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &compile_status);
+        if (compile_status != GL_TRUE) {
+            int info_log_len = 0;
+            glGetShaderiv(vert_shader, GL_INFO_LOG_LENGTH, &info_log_len);
+            char* err_str = (char*) malloc(sizeof(char) * info_log_len);
+            glGetShaderInfoLog(vert_shader, info_log_len - 1, NULL, err_str);
+            LOG_FATALF("Failed to compile vertex shader: %s", err_str);
+        }
+    }
+    const unsigned int frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
+    {
+        const int len = strlen(fragment_shader_src);
+        glShaderSource(frag_shader, 1, &fragment_shader_src, &len);
+        glCompileShader(frag_shader);
+        int compile_status = 0;
+        glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &compile_status);
+        if (compile_status != GL_TRUE) {
+            int info_log_len = 0;
+            glGetShaderiv(frag_shader, GL_INFO_LOG_LENGTH, &info_log_len);
+            char* err_str = (char*) malloc(sizeof(char) * info_log_len);
+            glGetShaderInfoLog(frag_shader, info_log_len - 1, NULL, err_str);
+            LOG_FATALF("Failed to compile fragment shader: %s", err_str);
+        }
+    }
+
+    const unsigned int shader_program = glCreateProgram();
+    {
+
+        glAttachShader(shader_program, vert_shader);
+        glAttachShader(shader_program, frag_shader);
+        glLinkProgram(shader_program);
+        int compile_status = 0;
+        glGetProgramiv(shader_program, GL_LINK_STATUS, &compile_status);
+        if (compile_status != GL_TRUE) {
+            LOG_FATAL("Failed to link shader program.");
+        }
+        glDeleteShader(vert_shader);
+        glDeleteShader(frag_shader);
+    }
+
+    MSG msg = { 0 };
+    while (true) {
+        if (GetMessage(&msg, NULL, 0, 0) <= 0) {
+            break;
+        }
         TranslateMessage(&msg);
         DispatchMessage(&msg);
+
+        printf("MSG LOOP\n");
+
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        glUseProgram(shader_program);
+        glBindVertexArray(triangle_vao);
+        glDrawArrays(GL_TRIANGLE_STRIP, 0, triangle_vert_count);
+
+        wglSwapLayerBuffers(hdc, WGL_SWAP_MAIN_PLANE);
     }
 
     return 0;

+ 33 - 0
src/pltf/gl_funcs.c

@@ -0,0 +1,33 @@
+#include "gl_funcs.h"
+#include "log.h"
+#include "pltf.h"
+
+#define X(type, name) \
+type name = NULL
+
+PLTF_GL_FUNCS(X)
+#undef X
+
+#define X(type, name) \
+name = (type) pltf_gl_function_load(#name)
+
+void* pltf_gl_function_load(const char* name) {
+    void* gl_func = (void*) wglGetProcAddress(name);
+    if (gl_func == NULL || gl_func == (void*) 1 || gl_func == (void*) 2 || gl_func == (void*) 3 || gl_func == (void*) -1) {
+        void* gl32_func = (void*) GetProcAddress(opengl_module, name);
+        if (gl32_func == NULL || gl32_func == (void*) 1 || gl32_func == (void*) 2 || gl32_func == (void*) 3 || gl32_func == (void*) -1) {
+            LOG_ERRORF("wglGetProcAddress failed to load gl function %s. Returned %p\n", name, gl_func);
+            LOG_ERRORF("GetProcAddress    failed to load gl function %s. Returned %p\n", name, gl32_func);
+            return NULL;
+        }
+
+        return gl32_func;
+    }
+
+    return gl_func;
+}
+
+void pltf_load_gl_funcs() {
+    PLTF_GL_FUNCS(X)
+}
+

+ 40 - 0
src/pltf/gl_funcs.h

@@ -0,0 +1,40 @@
+#ifndef GL_FUNCS_H_
+#define GL_FUNCS_H_
+
+#include <GL/glcorearb.h>
+
+#define PLTF_GL_FUNCS(X) \
+X(PFNGLGETINTEGERVPROC, glGetIntegerv); \
+X(PFNGLGETFLOATVPROC, glGetFloatv); \
+X(PFNGLCLEARCOLORPROC, glClearColor); \
+X(PFNGLCLEARPROC, glClear); \
+X(PFNGLGETERRORPROC, glGetError); \
+X(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); \
+X(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); \
+X(PFNGLGENBUFFERSPROC, glGenBuffers); \
+X(PFNGLBINDBUFFERPROC, glBindBuffer); \
+X(PFNGLBUFFERDATAPROC, glBufferData); \
+X(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); \
+X(PFNGLCREATESHADERPROC, glCreateShader); \
+X(PFNGLSHADERSOURCEPROC, glShaderSource); \
+X(PFNGLCOMPILESHADERPROC, glCompileShader); \
+X(PFNGLGETSHADERIVPROC, glGetShaderiv); \
+X(PFNGLCREATEPROGRAMPROC, glCreateProgram); \
+X(PFNGLATTACHSHADERPROC, glAttachShader); \
+X(PFNGLLINKPROGRAMPROC, glLinkProgram); \
+X(PFNGLGETPROGRAMIVPROC, glGetProgramiv); \
+X(PFNGLUSEPROGRAMPROC, glUseProgram); \
+X(PFNGLDRAWARRAYSPROC, glDrawArrays); \
+X(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); \
+X(PFNGLDELETESHADERPROC, glDeleteShader); \
+X(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); \
+
+#define X(type, name) extern type name
+
+PLTF_GL_FUNCS(X)
+#undef X
+
+void* pltf_gl_function_load(const char* name);
+void pltf_load_gl_funcs();
+
+#endif // GL_FUNCS_H_

+ 14 - 0
src/pltf/pltf.c

@@ -0,0 +1,14 @@
+#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");
+    }
+}

+ 10 - 0
src/pltf/pltf.h

@@ -0,0 +1,10 @@
+#ifndef PLTF_H_
+#define PLTF_H_
+
+#include <minwindef.h>
+
+extern HMODULE opengl_module;
+
+void pltf_init();
+
+#endif // PLTF_H_