summaryrefslogtreecommitdiff
path: root/src/platform/platform.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/platform.cc')
-rw-r--r--src/platform/platform.cc131
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