This commit is contained in:
2026-06-30 00:27:38 +03:00
parent 0b9cfab8ff
commit 94ea46a320
6 changed files with 325 additions and 67 deletions

View File

@@ -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',

View File

@@ -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);
printf("Dummy context info: ");
print_opengl_info();
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
);
}
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");
}
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);
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 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
src/pltf/gl_funcs.c Normal file
View File

@@ -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
src/pltf/gl_funcs.h Normal file
View File

@@ -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
src/pltf/pltf.c Normal file
View File

@@ -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
src/pltf/pltf.h Normal file
View File

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