David Gonzalez Martin b6220d182c Actually fix RenderDoc issue
Factor out shader compilation stage GLSL -> SPIRV
2024-12-27 19:26:55 -06:00

435 lines
13 KiB
C

#include <std/window.h>
#ifndef __APPLE__
#include <volk.h>
#endif
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
global_variable OSWindowingCallbacks callbacks;
// TODO: thread local
global_variable OSEventQueue* event_queue = 0;
fn void monitor_callback(GLFWmonitor* monitor, int event)
{
unused(monitor);
unused(event);
todo();
}
fn void joystick_callback(int joystick_id, int event)
{
unused(joystick_id);
unused(event);
todo();
}
fn void bitset_list_add(VirtualBuffer(OSEventBitset)* list, u32* counter, u64 value)
{
auto event_index = *counter;
if (unlikely(event_index % OS_EVENT_BITSET_SIZE == 0))
{
*vb_add(list, 1) = (OSEventBitset) {
.value = 0,
};
}
auto bitset_index = event_index / OS_EVENT_BITSET_SIZE;
u64 bit_index = event_index % OS_EVENT_BITSET_SIZE;
list->pointer[bitset_index].value |= (value << bit_index);
}
void os_windowing_init(OSWindowingInitializationOptions options)
{
#ifdef __linux__
int platform_hint = options.should_use_x11 ? GLFW_PLATFORM_X11 : GLFW_PLATFORM_WAYLAND;
glfwInitHint(GLFW_PLATFORM, platform_hint);
#endif
if (glfwInit() != GLFW_TRUE)
{
failed_execution();
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
// From GLFW documentation:
// This is called when a monitor is connected to or disconnected from the system.
glfwSetMonitorCallback(&monitor_callback);
glfwSetJoystickCallback(&joystick_callback);
callbacks = options.callback;
}
fn void glfw_window_drop_callback(GLFWwindow* window, int path_count, const char* paths[])
{
void* context = glfwGetWindowUserPointer(window);
auto* drop_callback = callbacks.window_drop;
print("DROP\n");
if (drop_callback)
{
drop_callback(window, context, (CStringSlice) { .pointer = (char**)paths, .length = path_count });
}
}
fn void glfw_window_scroll_callback(GLFWwindow* window, double x, double y)
{
void* context = glfwGetWindowUserPointer(window);
auto* scroll_callback = callbacks.window_scroll;
print("SCROLL\n");
if (scroll_callback)
{
scroll_callback(window, context, x, y);
}
}
fn void glfw_window_cursor_enter_callback(GLFWwindow* window, int entered)
{
void* context = glfwGetWindowUserPointer(window);
auto* cursor_enter_callback = callbacks.window_cursor_enter;
print("CURSOR_ENTER: {u32}\n", entered);
auto event_index = event_queue->cursor_enter_count;
*vb_add(&event_queue->descriptors, 1) = (OSEventDescriptor) {
.type = OS_EVENT_TYPE_WINDOW_FOCUS,
.index = event_index,
};
bitset_list_add(&event_queue->cursor_enters, &event_queue->cursor_enter_count, entered);
if (cursor_enter_callback)
{
cursor_enter_callback(window, context, entered);
}
}
fn void glfw_window_cursor_position_callback(GLFWwindow* window, double x, double y)
{
void* context = glfwGetWindowUserPointer(window);
auto* cursor_position_callback = callbacks.window_cursor_position;
*vb_add(&event_queue->descriptors, 1) = (OSEventDescriptor) {
.index = event_queue->cursor_positions.length,
.type = OS_EVENT_TYPE_CURSOR_POSITION,
};
*vb_add(&event_queue->cursor_positions, 1) = (OSEventCursorPosition) {
.x = x,
.y = y,
};
if (cursor_position_callback)
{
cursor_position_callback(window, context, x, y);
}
}
fn void glfw_window_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
void* context = glfwGetWindowUserPointer(window);
auto* mouse_button_callback = callbacks.window_mouse_button;
*vb_add(&event_queue->descriptors, 1) = (OSEventDescriptor) {
.index = event_queue->mouse_buttons.length,
.type = OS_EVENT_TYPE_MOUSE_BUTTON,
};
print("Button: {u32:x}. Action: {u32:x}. Mods: {u32:x}\n", button, action, mods);
OSEventMouseButtonAction os_action;
switch (action)
{
case GLFW_RELEASE: os_action = OS_EVENT_MOUSE_RELEASE; break;
case GLFW_PRESS: os_action = OS_EVENT_MOUSE_PRESS; break;
case GLFW_REPEAT: os_action = OS_EVENT_MOUSE_REPEAT; break;
default: unreachable();
}
OSEventMouseButtonKind mouse_button = 0;
switch (button)
{
case GLFW_MOUSE_BUTTON_1:
mouse_button = OS_EVENT_MOUSE_BUTTON_1;
break;
case GLFW_MOUSE_BUTTON_2:
mouse_button = OS_EVENT_MOUSE_BUTTON_2;
break;
case GLFW_MOUSE_BUTTON_3:
mouse_button = OS_EVENT_MOUSE_BUTTON_3;
break;
case GLFW_MOUSE_BUTTON_4:
mouse_button = OS_EVENT_MOUSE_BUTTON_4;
break;
case GLFW_MOUSE_BUTTON_5:
mouse_button = OS_EVENT_MOUSE_BUTTON_5;
break;
case GLFW_MOUSE_BUTTON_6:
mouse_button = OS_EVENT_MOUSE_BUTTON_6;
break;
case GLFW_MOUSE_BUTTON_7:
mouse_button = OS_EVENT_MOUSE_BUTTON_7;
break;
case GLFW_MOUSE_BUTTON_8:
mouse_button = OS_EVENT_MOUSE_BUTTON_8;
break;
}
*vb_add(&event_queue->mouse_buttons, 1) = (OSEventMouseButton) {
.button = mouse_button,
.event = (OSEventMouseButtonEvent){
.action = os_action,
.mod_shift = !!(mods & GLFW_MOD_SHIFT),
.mod_control = !!(mods & GLFW_MOD_CONTROL),
.mod_alt = !!(mods & GLFW_MOD_ALT),
.mod_super = !!(mods & GLFW_MOD_SUPER),
.mod_caps_lock = !!(mods & GLFW_MOD_CAPS_LOCK),
.mod_num_lock = !!(mods & GLFW_MOD_NUM_LOCK),
},
};
if (mouse_button_callback)
{
mouse_button_callback(window, context, button, action, mods);
}
}
fn void glfw_window_character_modifier_callback(GLFWwindow* window, unsigned int codepoint, int mods)
{
void* context = glfwGetWindowUserPointer(window);
auto* character_modifier_callback = callbacks.window_character_modifier;
// print("CHAR_MODIFIER. Codepoint: {u32}. Mods: {u32}\n", codepoint, mods);
if (character_modifier_callback)
{
character_modifier_callback(window, context, codepoint, mods);
}
}
fn void glfw_window_character_callback(GLFWwindow* window, unsigned int codepoint)
{
void* context = glfwGetWindowUserPointer(window);
auto* character_callback = callbacks.window_character;
// print("CHAR. Codepoint: {u32}\n", codepoint);
if (character_callback)
{
character_callback(window, context, codepoint);
}
}
fn void glfw_window_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
void* context = glfwGetWindowUserPointer(window);
auto* key_callback = callbacks.window_key;
print("Key: {u32}. Scancode: {u32}. Action: {u32}. Mods: {u32}\n", key, scancode, action, mods);
if (key_callback)
{
key_callback(window, context, key, scancode, action, mods);
}
}
fn void glfw_window_content_scale_callback(GLFWwindow* window, float x, float y)
{
void* context = glfwGetWindowUserPointer(window);
print("CONTENT_SCALE\n");
auto* content_scale_callback = callbacks.window_content_scale;
if (content_scale_callback)
{
content_scale_callback(window, context, x, y);
}
}
fn void glfw_window_maximize_callback(GLFWwindow* window, int maximized)
{
void* context = glfwGetWindowUserPointer(window);
print("MAXIMIZE\n");
auto* maximize_callback = callbacks.window_maximize;
if (maximize_callback)
{
maximize_callback(window, context, maximized);
}
}
fn void glfw_window_iconify_callback(GLFWwindow* window, int iconified)
{
void* context = glfwGetWindowUserPointer(window);
print("ICONIFY\n");
auto* iconify_callback = callbacks.window_iconify;
if (iconify_callback)
{
iconify_callback(window, context, iconified);
}
}
fn void glfw_window_focus_callback(GLFWwindow* window, int focused)
{
void* context = glfwGetWindowUserPointer(window);
print("FOCUS\n");
auto* focus_callback = callbacks.window_focus;
auto event_index = event_queue->window_focuses_count;
*vb_add(&event_queue->descriptors, 1) = (OSEventDescriptor) {
.type = OS_EVENT_TYPE_WINDOW_FOCUS,
.index = event_index,
};
bitset_list_add(&event_queue->window_focuses, &event_queue->window_focuses_count, focused);
if (focus_callback)
{
focus_callback(window, context, focused);
}
}
fn void glfw_window_close_callback(GLFWwindow* window)
{
void* context = glfwGetWindowUserPointer(window);
*vb_add(&event_queue->descriptors, 1) = (OSEventDescriptor) {
.type = OS_EVENT_TYPE_WINDOW_CLOSE,
};
auto* close_callback = callbacks.window_close;
if (close_callback)
{
close_callback(window, context);
}
}
fn void glfw_window_position_callback(GLFWwindow* window, int x, int y)
{
void* context = glfwGetWindowUserPointer(window);
print("WINDOW_POSITION: {u32}x{u32}\n", x, y);
auto* position_callback = callbacks.window_position;
*vb_add(&event_queue->descriptors, 1) = (OSEventDescriptor) {
.index = event_queue->window_positions.length,
.type = OS_EVENT_TYPE_WINDOW_POSITION,
};
*vb_add(&event_queue->window_positions, 1) = (OSEventWindowPosition) {
.x = x,
.y = y,
};
if (position_callback)
{
position_callback(window, context, x, y);
}
}
fn void glfw_window_size_callback(GLFWwindow* window, int width, int height)
{
void* context = glfwGetWindowUserPointer(window);
print("WINDOW_SIZE\n");
auto* window_resize_callback = callbacks.window_resize;
if (window_resize_callback)
{
window_resize_callback(window, context, width, height);
}
}
fn void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
void* context = glfwGetWindowUserPointer(window);
print("FRAMEBUFFER_SIZE\n");
auto* framebuffer_resize_callback = callbacks.framebuffer_resize;
if (framebuffer_resize_callback)
{
framebuffer_resize_callback(window, context, width, height);
}
}
fn void glfw_window_refresh_callback(GLFWwindow* w)
{
void* context = glfwGetWindowUserPointer(w);
print("REFRESH\n");
auto refresh_callback = callbacks.window_refresh;
if (refresh_callback)
{
refresh_callback(w, context);
}
}
OSWindow os_window_create(OSWindowCreate create)
{
// glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
GLFWmonitor* monitor = 0;
GLFWwindow* share = 0;
GLFWwindow* window = glfwCreateWindow(create.size.width, create.size.height, string_to_c(create.name), monitor, share);
glfwSetWindowUserPointer(window, create.context);
glfwSetWindowPosCallback(window, &glfw_window_position_callback);
glfwSetWindowSizeCallback(window, &glfw_window_size_callback);
glfwSetWindowCloseCallback(window, &glfw_window_close_callback);
glfwSetWindowFocusCallback(window, &glfw_window_focus_callback);
glfwSetWindowIconifyCallback(window, &glfw_window_iconify_callback); // Minimize callback
glfwSetWindowMaximizeCallback(window, &glfw_window_maximize_callback);
glfwSetFramebufferSizeCallback(window, &glfw_framebuffer_size_callback);
glfwSetWindowRefreshCallback(window, &glfw_window_refresh_callback);
glfwSetWindowContentScaleCallback(window, &glfw_window_content_scale_callback);
glfwSetKeyCallback(window, &glfw_window_key_callback);
glfwSetCharCallback(window, &glfw_window_character_callback);
glfwSetCharModsCallback(window, &glfw_window_character_modifier_callback);
glfwSetMouseButtonCallback(window, &glfw_window_mouse_button_callback);
glfwSetCursorPosCallback(window, &glfw_window_cursor_position_callback);
glfwSetCursorEnterCallback(window, &glfw_window_cursor_enter_callback);
glfwSetScrollCallback(window, &glfw_window_scroll_callback);
glfwSetDropCallback(window, &glfw_window_drop_callback);
return window;
}
u8 os_window_should_close(OSWindow window)
{
return glfwWindowShouldClose(window);
}
fn void os_event_queue_reset(OSEventQueue* queue)
{
queue->descriptors.length = 0;
queue->mouse_buttons.length = 0;
queue->cursor_positions.length = 0;
}
fn u8 os_event_bitset_list(VirtualBuffer(OSEventBitset) bitset, u32 index)
{
auto bitset_index = index / bitset.length;
auto bit_index = index % bitset.length;
return !!(bitset.pointer[bitset_index].value & bit_index);
}
u8 os_event_queue_get_window_focus(OSEventQueue* queue, u32 index)
{
assert(index < queue->window_focuses.length);
auto result = os_event_bitset_list(queue->window_focuses, index);
return result;
}
void os_poll_events(OSEventQueue* queue)
{
os_event_queue_reset(queue);
event_queue = queue;
assert(queue->descriptors.length == 0);
glfwPollEvents();
}
OSWindowSize os_window_framebuffer_size_get(OSWindow window)
{
int width;
int height;
glfwGetFramebufferSize(window, &width, &height);
return (OSWindowSize)
{
.width = width,
.height = height,
};
}
OSCursorPosition os_window_cursor_position_get(OSWindow window)
{
OSCursorPosition result;
glfwGetCursorPos(window, &result.x, &result.y);
return result;
}
int window_create_surface(void* instance, OSWindow window, const void* allocator, void** surface)
{
return glfwCreateWindowSurface(instance, window, allocator, (VkSurfaceKHR*)surface);
}