diff options
author | Lassi Pulkkinen <lassi@pulk.fi> | 2024-10-31 03:11:21 +0200 |
---|---|---|
committer | Lassi Pulkkinen <lassi@pulk.fi> | 2024-10-31 03:51:35 +0200 |
commit | ae44478b30d890fe0fb04022f44d474dcdcc3f9d (patch) | |
tree | 5f462459ae4b47d22114eed717d1382d08cf4dfe /glw |
Diffstat (limited to 'glw')
-rw-r--r-- | glw/debug.ha | 34 | ||||
-rw-r--r-- | glw/glw.ha | 91 |
2 files changed, 125 insertions, 0 deletions
diff --git a/glw/debug.ha b/glw/debug.ha new file mode 100644 index 0000000..2ffe3c4 --- /dev/null +++ b/glw/debug.ha @@ -0,0 +1,34 @@ +use strings; +use types::c; +use trace; + +use gl::*; + +fn debug_callback( + source: gl_enum, + type_: gl_enum, + id: uint, + severity: gl_enum, + length: i32, + message: nullable *const c::char, + user_data: nullable *opaque, +) void = { + // (2024 note): I'm painfully aware of the data race present here: + // The GL driver can call this from another thread, and the stdlib has + // some non-thread-safe stuff in it that we use, in particular strconv. + // I've seen it happen at times, but it's pretty rare. + const message = (message: *const [*]u8)[..length]; + const message = strings::fromutf8(message)!; + const message = strings::trimsuffix(message, "\n"); + trace::debug(&trace::root, "gl: {}", message); +}; + +export fn init_debug_logging() void = { + let ctxflags = 0i32; + glGetIntegerv(GL_CONTEXT_FLAGS, &ctxflags); + + if (ctxflags & GL_CONTEXT_FLAG_DEBUG_BIT: i32 != 0) { + trace::info(&trace::root, "opengl debugging is enabled"); + glDebugMessageCallback(&debug_callback, null); + }; +}; diff --git a/glw/glw.ha b/glw/glw.ha new file mode 100644 index 0000000..a3a2b65 --- /dev/null +++ b/glw/glw.ha @@ -0,0 +1,91 @@ +use strings; +use trace; +use types::c; + +use gl::*; + +export fn get_string(name: gl_enum) str = { + match (glGetString(name)) { + case null => + return ""; + case let s: *const u8 => + return c::tostr(s: *const c::char)!; + }; +}; + +export fn buffer_data( + target: gl_enum, + data: []opaque, + itemsz: size, + usage: gl_enum, +) void = { + glBufferData( + target, + (len(data) * itemsz): uintptr, + data: nullable *[*]u8: nullable *opaque, + usage, + ); +}; + +export fn compile_shader_src(type_: gl_enum, src: str) uint = { + const shader = glCreateShader(type_); + glShaderSource( + shader, 1, + &(strings::toutf8(src): *[*]i8: nullable *const i8), + &(len(src): i32), + ); + glCompileShader(shader); + + let status = 0i32; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + + if (status == 0) { + let log_len = 0i32; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len); + + const log_buf = alloc([0u8...], log_len: size); + glGetShaderInfoLog( + shader, log_len, + null, log_buf: *[*]i8: *i8, + ); + + const log = strings::fromutf8(log_buf)!; + + const type_str = switch (type_) { + case GL_VERTEX_SHADER => yield "vertex"; + case GL_FRAGMENT_SHADER => yield "fragment"; + case GL_GEOMETRY_SHADER => yield "geometry"; + case => yield "(unknown)"; + }; + + trace::error(&trace::root, + "{} shader compilation failed:\n{}", + type_str, log): void; + }; + + return shader; +}; + +export fn link_program(program: uint) void = { + glLinkProgram(program); + + let status = 0i32; + glGetProgramiv(program, GL_LINK_STATUS, &status); + + if (status == 0) { + let log_len = 0i32; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len); + + const log_buf = alloc([0u8...], log_len: size); + glGetProgramInfoLog( + program, log_len, + null, log_buf: *[*]i8: *i8, + ); + + const log = strings::fromutf8(log_buf)!; + + trace::error(&trace::root, + "program linking failed:\n{}", + log): void; + }; +}; |