1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// 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.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;
}
}
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 ---
void platform_init(PlatformState* state, bool fullscreen, int* width_ptr,
int* height_ptr) {
if (width_ptr && height_ptr) {
state->width = *width_ptr;
state->height = *height_ptr;
}
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
state->window = glfwCreateWindow(state->width, state->height, "demo64k",
nullptr, nullptr);
// Store our state pointer in the window for callbacks
glfwSetWindowUserPointer(state->window, state);
// Immediately query the actual framebuffer size for high-DPI displays
glfwGetFramebufferSize(state->window, &state->width, &state->height);
glfwSetKeyCallback(state->window, glfw_key_callback);
glfwSetFramebufferSizeCallback(state->window, framebuffer_size_callback);
state->is_fullscreen = fullscreen;
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);
}
}
void platform_shutdown(PlatformState* state) {
if (state->window) {
glfwDestroyWindow(state->window);
}
glfwTerminate();
}
void platform_poll(PlatformState* state) {
glfwPollEvents();
}
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);
}
// Note: platform_get_* functions are now inline in the header.
// platform_get_time() remains global.
|