EchoMap 2026-07-25 6d3977c
An experimental cross-platform digital signal processing application for sound-source localisation.
Loading...
Searching...
No Matches
SurfaceFactory.cpp
Go to the documentation of this file.
1
7
8#include "SurfaceFactory.hpp"
9
10#include <GLFW/glfw3.h>
11
12#if defined(_WIN32)
13#define GLFW_EXPOSE_NATIVE_WIN32 1
14#define GOT_SUPPORTED_PLATFORM
15#endif
16
17#if defined(__APPLE__)
18#define GLFW_EXPOSE_NATIVE_COCOA 1
19#define GOT_SUPPORTED_PLATFORM
20#endif
21
22#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
23#define GLFW_EXPOSE_NATIVE_X11 1
24#define GLFW_EXPOSE_NATIVE_WAYLAND 1
25#define GOT_SUPPORTED_PLATFORM
26#endif
27
28#if defined(__EMSCRIPTEN__)
29#define GOT_SUPPORTED_PLATFORM
30#endif
31
32#if !defined(GOT_SUPPORTED_PLATFORM)
33#error "No supported platforms for the SurfaceFactory."
34#error "Supported platforms are: Emscripten; Wayland; X11; Win32; Cocoa (Apple)."
35#endif
36
37#if !defined(__EMSCRIPTEN__)
38#include <GLFW/glfw3native.h>
39#endif
40
41#if defined(__APPLE__)
42
43// If we're on an Apple platform, define C++ shims to despatch messages through the Objective-C interface.
44
45#include <objc/message.h>
46#include <objc/objc.h>
47#include <objc/runtime.h>
48
49namespace
50{
51
52template <typename T, typename... Args>
53T objc_call(id obj, const char * const sel, Args... args) {
54 using FuncPtr = T (*)(id, SEL, Args...);
55 return reinterpret_cast<FuncPtr>(objc_msgSend)(obj, sel_registerName(sel), args...);
56}
57
58template <typename T, typename... Args>
59T objc_call(const char *clazz, const char * const sel, Args... args) {
60 return objc_call<T>(reinterpret_cast<id>(objc_getClass(clazz)), sel, args...);
61}
62
63}
64
65#endif
66
67namespace echomap
68{
69
71 const wgpu::Instance& instance,
72 GLFWwindow* window
73)
74{
75 const auto chainedDescriptor = get_surface_descriptor(window);
76 if (chainedDescriptor == nullptr)
77 throw std::runtime_error("Could not create and bind a Surface to the given window.");
78
79 wgpu::SurfaceDescriptor descriptor;
80 descriptor.nextInChain = chainedDescriptor.get();
81
82 return instance.CreateSurface(&descriptor);
83}
84
86 GLFWwindow* const window
87)
88{
89 // Verify that the window is valid in the runtime.
90 if (glfwGetWindowAttrib(window, GLFW_CLIENT_API) != GLFW_NO_API)
91 return nullptr;
92
93#if defined(__EMSCRIPTEN__)
95 desc->selector = "#canvas";
96 return desc;
97#else
98 // Use the GLFW_EXPOSE_NATIVE_* flags to determine which GLFW platforms we can handle.
99
100 // ReSharper disable once CppDefaultCaseNotHandledInSwitchStatement
101 switch (glfwGetPlatform()) {
102#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
103 case GLFW_PLATFORM_WAYLAND: {
105 desc->display = glfwGetWaylandDisplay();
106 desc->surface = glfwGetWaylandWindow(window);
107 return desc;
108 }
109#endif
110#if defined(GLFW_EXPOSE_NATIVE_X11)
111 case GLFW_PLATFORM_X11: {
113 desc->display = glfwGetX11Display();
114 desc->window = glfwGetX11Window(window);
115 return desc;
116 }
117#endif
118#if defined(GLFW_EXPOSE_NATIVE_WIN32)
119 case GLFW_PLATFORM_WIN32: {
121 desc->hwnd = glfwGetWin32Window(window);
122 desc->hinstance = GetModuleHandle(nullptr);
123 return desc;
124 }
125#endif
126#if defined(GLFW_EXPOSE_NATIVE_COCOA)
127 case GLFW_PLATFORM_COCOA: {
128 /*
129 * On Apple platforms, more work is required to configure the Metal layer on the Cocoa Surface through the
130 * Objective-C messaging APIs.
131 */
132 auto ns_window = glfwGetCocoaWindow(window);
133 CFRetain(ns_window);
134
135 auto view = objc_call<id>(ns_window, "contentView");
136 CFRetain(view);
137
138 objc_call<void, BOOL>(view, "setWantsLayer:", YES);
139 auto layer = objc_call<id>("CAMetalLayer", "layer");
140 auto scale_factor = objc_call<CGFloat>(ns_window, "backingScaleFactor");
141 objc_call<void, CGFloat>(layer, "setContentsScale:", scale_factor);
142 objc_call<void, id>(view, "setLayer:", layer);
143
145 desc->layer = layer;
146 CFRelease(view);
147 CFRelease(ns_window);
148
149 return desc;
150 }
151#endif
152 }
153#endif
154
155 // No handlers were enabled. This should be caught be a compile-time check.
156 // ReSharper disable once CppDFAUnreachableCode
157 return nullptr;
158}
159
160} // namespace echomap
EchoMap WebGPU-GLFW Surface factory specification.
static wgpu::Surface create_surface(const wgpu::Instance &instance, GLFWwindow *window)
Creates and binds a Surface to the given GLFW window.
static std::unique_ptr< wgpu::ChainedStruct > get_surface_descriptor(GLFWwindow *window)
Produce an owning container of the WebGPU Surface descriptor for the given GLFW window.
T make_unique(T... args)
The main EchoMap outermost namespace for all non-exported symbols.