summaryrefslogtreecommitdiff
path: root/src/platform.cc
blob: 464003f2e462c014d133f918458d979e4d28c173 (plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// 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>

static GLFWwindow* window = nullptr;
static int windowed_x, windowed_y, windowed_w, windowed_h;
static bool g_is_fullscreen = false;

// --- New state for framebuffer size ---
static int g_width = 1280;
static int g_height = 720;

// Forward declaration for callback
void platform_toggle_fullscreen();

// --- Callbacks ---

static void framebuffer_size_callback(GLFWwindow* cb_window, int width, int height) {
    (void)cb_window; // Unused
    g_width = width;
    g_height = height;
    // Note: We would trigger a swap chain resize here, but our demo handles it implicitly.
}

static void glfw_key_callback(GLFWwindow* cb_window, int key, int scancode,
                              int action, int mods) {
  if (action == GLFW_PRESS) {
    if (key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) {
      glfwSetWindowShouldClose(cb_window, GLFW_TRUE);
    } else if (key == GLFW_KEY_F) {
      platform_toggle_fullscreen();
    }
  }
}

void platform_init_window(bool fullscreen, int* width_ptr, int* height_ptr) {
  if (width_ptr && height_ptr) {
      g_width = *width_ptr;
      g_height = *height_ptr;
  }

  glfwInit();
  glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  window = glfwCreateWindow(g_width, g_height, "demo64k", nullptr, nullptr);
  
  // Immediately query the actual framebuffer size for high-DPI displays
  glfwGetFramebufferSize(window, &g_width, &g_height);

  glfwSetKeyCallback(window, glfw_key_callback);
  glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

  g_is_fullscreen = fullscreen;
  if (fullscreen) {
    // Save current windowed mode dimensions before going fullscreen
    glfwGetWindowPos(window, &windowed_x, &windowed_y);
    glfwGetWindowSize(window, &windowed_w, &windowed_h);

    GLFWmonitor* monitor = glfwGetPrimaryMonitor();
    const GLFWvidmode* mode = glfwGetVideoMode(monitor);
    glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height,
                         mode->refreshRate);
  }
}

void platform_shutdown() {
  glfwDestroyWindow(window);
  glfwTerminate();
}

void platform_poll() {
  glfwPollEvents();
}

bool platform_should_close() {
  return glfwWindowShouldClose(window);
}

void platform_toggle_fullscreen() {
  g_is_fullscreen = !g_is_fullscreen;
  if (g_is_fullscreen) {
    glfwGetWindowPos(window, &windowed_x, &windowed_y);
    glfwGetWindowSize(window, &windowed_w, &windowed_h);

    GLFWmonitor* monitor = glfwGetPrimaryMonitor();
    const GLFWvidmode* mode = glfwGetVideoMode(monitor);
    glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height,
                         mode->refreshRate);
  } else {
    glfwSetWindowMonitor(window, nullptr, windowed_x, windowed_y, windowed_w,
                         windowed_h, 0);
  }
}

GLFWwindow* platform_get_window() {
  return window;
}

double platform_get_time() {
  return glfwGetTime();
}

// --- New dimension getters ---
int platform_get_width() {
    return g_width;
}

int platform_get_height() {
    return g_height;
}

float platform_get_aspect_ratio() {
    if (g_height == 0) return 1.0f;
    return (float)g_width / (float)g_height;
}

WGPUSurface platform_create_wgpu_surface(WGPUInstance instance) {
  return glfwCreateWindowWGPUSurface(instance, window);
}