#include "platform.h" #ifdef _WIN32 #define GLFW_EXPOSE_NATIVE_WIN32 #elif defined(__APPLE__) #define GLFW_EXPOSE_NATIVE_COCOA #else #define GLFW_EXPOSE_NATIVE_X11 #define GLFW_EXPOSE_NATIVE_WAYLAND #endif #include #include #ifdef __APPLE__ #import #import #import #endif static GLFWwindow *window = nullptr; static int windowed_x, windowed_y, windowed_w, windowed_h; static bool g_is_fullscreen = false; 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) { glfwSetWindowShouldClose(cb_window, GLFW_TRUE); } else if (key == GLFW_KEY_F) { platform_toggle_fullscreen(); } } } void platform_init_window(bool fullscreen) { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); window = glfwCreateWindow(1280, 720, "demo64k", nullptr, nullptr); glfwSetKeyCallback(window, glfw_key_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(); } WGPUSurface platform_create_wgpu_surface(WGPUInstance instance) { #if defined(GLFW_EXPOSE_NATIVE_COCOA) id metal_layer = NULL; NSWindow *ns_window = glfwGetCocoaWindow(window); [ns_window.contentView setWantsLayer:YES]; metal_layer = [CAMetalLayer layer]; [ns_window.contentView setLayer:metal_layer]; WGPUSurfaceSourceMetalLayer metal_src = {}; metal_src.chain.sType = WGPUSType_SurfaceSourceMetalLayer; metal_src.layer = metal_layer; WGPUSurfaceDescriptor surface_desc = {}; surface_desc.nextInChain = (const WGPUChainedStruct *)&metal_src; return wgpuInstanceCreateSurface(instance, &surface_desc); #elif defined(GLFW_EXPOSE_NATIVE_WIN32) HWND hwnd = glfwGetWin32Window(window); HINSTANCE hinstance = GetModuleHandle(NULL); WGPUSurfaceSourceWindowsHWND win_src = {}; win_src.chain.sType = WGPUSType_SurfaceSourceWindowsHWND; win_src.hinstance = hinstance; win_src.hwnd = hwnd; WGPUSurfaceDescriptor surface_desc = {}; surface_desc.nextInChain = (const WGPUChainedStruct *)&win_src; return wgpuInstanceCreateSurface(instance, &surface_desc); #elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_WAYLAND) if (glfwGetPlatform() == GLFW_PLATFORM_X11) { Display *x11_display = glfwGetX11Display(); Window x11_window = glfwGetX11Window(window); WGPUSurfaceSourceXlibWindow x11_src = {}; x11_src.chain.sType = WGPUSType_SurfaceSourceXlibWindow; x11_src.display = x11_display; x11_src.window = x11_window; WGPUSurfaceDescriptor surface_desc = {}; surface_desc.nextInChain = (const WGPUChainedStruct *)&x11_src; return wgpuInstanceCreateSurface(instance, &surface_desc); } else if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) { struct wl_display *wayland_display = glfwGetWaylandDisplay(); struct wl_surface *wayland_surface = glfwGetWaylandWindow(window); WGPUSurfaceSourceWaylandSurface wl_src = {}; wl_src.chain.sType = WGPUSType_SurfaceSourceWaylandSurface; wl_src.display = wayland_display; wl_src.surface = wayland_surface; WGPUSurfaceDescriptor surface_desc = {}; surface_desc.nextInChain = (const WGPUChainedStruct *)&wl_src; return wgpuInstanceCreateSurface(instance, &surface_desc); } #endif return nullptr; }