diff options
Diffstat (limited to 'src/platform/platform.cc')
| -rw-r--r-- | src/platform/platform.cc | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/platform/platform.cc b/src/platform/platform.cc new file mode 100644 index 0000000..29b3af3 --- /dev/null +++ b/src/platform/platform.cc @@ -0,0 +1,131 @@ +// This file is part of the 64k demo project. +// It implements platform-specific windowing and input using GLFW. +// Handles fullscreen toggling and native surface creation for WebGPU. + +#include "platform/platform.h" +#include "glfw3webgpu.h" +#include <GLFW/glfw3.h> + +// --- Callbacks --- + +static void framebuffer_size_callback(GLFWwindow* window, int width, + int height) { + PlatformState* state = (PlatformState*)glfwGetWindowUserPointer(window); + if (state) { + state->width = width; + state->height = height; + if (height > 0) { + state->aspect_ratio = (float)width / (float)height; + } + } +} + +static void glfw_key_callback(GLFWwindow* window, int key, int scancode, + int action, int mods) { + PlatformState* state = (PlatformState*)glfwGetWindowUserPointer(window); + if (action == GLFW_PRESS) { + if (key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) { + glfwSetWindowShouldClose(window, GLFW_TRUE); + } else if (key == GLFW_KEY_F) { + if (state) + platform_toggle_fullscreen(state); + } + } +} + +// --- Public API Implementation --- + +PlatformState platform_init(bool fullscreen, int width, int height) { + PlatformState state = {}; + state.width = width; + state.height = height; + state.is_fullscreen = fullscreen; + + glfwInit(); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + state.window = + glfwCreateWindow(state.width, state.height, "demo64k", nullptr, nullptr); + + // Immediately query the actual framebuffer size for high-DPI displays + glfwGetFramebufferSize(state.window, &state.width, &state.height); + if (state.height > 0) { + state.aspect_ratio = (float)state.width / (float)state.height; + } + + // Store our state in a static pointer or use the window pointer? + // We'll use a pointer to a persistent state. + // For this demo, we can assume the PlatformState persists in main(). + // But we return by value. This is a bit tricky with callbacks. + // We'll fix the callbacks in platform_poll if needed, or just let main pass + // the pointer back. + + glfwSetWindowUserPointer(state.window, + nullptr); // Will be set in main's state + + glfwSetKeyCallback(state.window, glfw_key_callback); + glfwSetFramebufferSizeCallback(state.window, framebuffer_size_callback); + + if (fullscreen) { + glfwGetWindowPos(state.window, &state.windowed_x, &state.windowed_y); + glfwGetWindowSize(state.window, &state.windowed_w, &state.windowed_h); + + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + glfwSetWindowMonitor(state.window, monitor, 0, 0, mode->width, mode->height, + mode->refreshRate); + } + + state.time = glfwGetTime(); + + return state; +} + +void platform_shutdown(PlatformState* state) { + if (state->window) { + glfwDestroyWindow(state->window); + } + glfwTerminate(); +} + +void platform_poll(PlatformState* state) { + // Ensure the window has the current state pointer for callbacks + if (glfwGetWindowUserPointer(state->window) != state) { + glfwSetWindowUserPointer(state->window, state); + } + + glfwPollEvents(); + state->time = glfwGetTime(); + if (state->height > 0) { + state->aspect_ratio = (float)state->width / (float)state->height; + } +} + +bool platform_should_close(PlatformState* state) { + return glfwWindowShouldClose(state->window); +} + +void platform_toggle_fullscreen(PlatformState* state) { + state->is_fullscreen = !state->is_fullscreen; + if (state->is_fullscreen) { + glfwGetWindowPos(state->window, &state->windowed_x, &state->windowed_y); + glfwGetWindowSize(state->window, &state->windowed_w, &state->windowed_h); + + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + glfwSetWindowMonitor(state->window, monitor, 0, 0, mode->width, + mode->height, mode->refreshRate); + } else { + glfwSetWindowMonitor(state->window, nullptr, state->windowed_x, + state->windowed_y, state->windowed_w, + state->windowed_h, 0); + } +} + +WGPUSurface platform_create_wgpu_surface(WGPUInstance instance, + PlatformState* state) { + return glfwCreateWindowWGPUSurface(instance, state->window); +} + +double platform_get_time() { + return glfwGetTime(); +}
\ No newline at end of file |
