Skip to content

Commit f2ea04e

Browse files
committed
Fix glfw_wgpu backend dpi scaling
Closes #3
1 parent b1c775d commit f2ea04e

File tree

6 files changed

+49
-122
lines changed

6 files changed

+49
-122
lines changed

build.zig

+6-2
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,11 @@ pub fn build(b: *std.Build) void {
241241
"libs/imgui/backends/imgui_impl_glfw.cpp",
242242
"libs/imgui/backends/imgui_impl_wgpu.cpp",
243243
},
244-
.flags = cflags,
244+
.flags = &(cflags.* ++ .{
245+
"-DGLFW_INCLUDE_NONE",
246+
// TODO: This should be IMGUI_IMPL_WEBGPU_BACKEND_DAWN but we're using an old version of Dawn that looks more like wgpu_native
247+
"-DIMGUI_IMPL_WEBGPU_BACKEND_WGPU",
248+
}),
245249
});
246250
},
247251
.glfw_opengl3 => {
@@ -265,7 +269,7 @@ pub fn build(b: *std.Build) void {
265269
"libs/imgui/backends/imgui_impl_glfw.cpp",
266270
"libs/imgui/backends/imgui_impl_dx12.cpp",
267271
},
268-
.flags = cflags,
272+
.flags = &(cflags.* ++ .{"-DGLFW_INCLUDE_NONE"}),
269273
});
270274
imgui.linkSystemLibrary("d3dcompiler_47");
271275
},

libs/imgui/backends/imgui_impl_glfw.cpp

+6-53
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@
9090

9191
#include "imgui.h"
9292
#ifndef IMGUI_DISABLE
93-
// FIX(zig-gamedev):
94-
// #include "imgui_impl_glfw.h"
93+
#include "imgui_impl_glfw.h"
9594

9695
// Clang warnings with -Weverything
9796
#if defined(__clang__)
@@ -101,8 +100,6 @@
101100
#endif
102101

103102
// GLFW
104-
// FIX(zig-gamedev):
105-
#define GLFW_INCLUDE_NONE
106103
#include <GLFW/glfw3.h>
107104

108105
#ifdef _WIN32
@@ -160,41 +157,6 @@
160157
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
161158
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
162159
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
163-
#include <math.h>
164-
165-
// FIX(zig-gamedev):
166-
extern "C" {
167-
168-
bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
169-
bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
170-
bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
171-
void ImGui_ImplGlfw_Shutdown();
172-
void ImGui_ImplGlfw_NewFrame();
173-
174-
// GLFW callbacks install
175-
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
176-
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
177-
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
178-
void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
179-
180-
// GFLW callbacks options:
181-
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
182-
void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);
183-
184-
// GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks)
185-
void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84
186-
void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84
187-
void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87
188-
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
189-
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
190-
void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
191-
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
192-
void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
193-
194-
// GLFW helpers
195-
void ImGui_ImplGlfw_Sleep(int milliseconds);
196-
197-
} // extern "C"
198160

199161
// GLFW data
200162
enum GlfwClientApi
@@ -218,8 +180,6 @@ struct ImGui_ImplGlfw_Data
218180
bool InstalledCallbacks;
219181
bool CallbacksChainForAllWindows;
220182
bool WantUpdateMonitors;
221-
222-
ImVec2 DpiScale; // fix(zig-gamedev)
223183
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
224184
const char* CanvasSelector;
225185
#endif
@@ -510,7 +470,7 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
510470
{
511471
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
512472
if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
513-
bd->PrevUserCallbackCursorPos(window, x * bd->DpiScale.x, y * bd->DpiScale.y); // fix(zig-gamedev)
473+
bd->PrevUserCallbackCursorPos(window, x, y);
514474

515475
ImGuiIO& io = ImGui::GetIO();
516476
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
@@ -520,8 +480,8 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
520480
x += window_x;
521481
y += window_y;
522482
}
523-
io.AddMousePosEvent((float)x * bd->DpiScale.x, (float)y * bd->DpiScale.y); // fix(zig-gamedev)
524-
bd->LastValidMousePos = ImVec2((float)x * bd->DpiScale.x, (float)y * bd->DpiScale.y); // fix(zig-gamedev)
483+
io.AddMousePosEvent((float)x, (float)y);
484+
bd->LastValidMousePos = ImVec2((float)x, (float)y);
525485
}
526486

527487
// Workaround: X11 seems to send spurious Leave/Enter events which would make us lose our position,
@@ -668,8 +628,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
668628
bd->Time = 0.0;
669629
bd->WantUpdateMonitors = true;
670630

671-
bd->DpiScale = ImVec2{ 1.0f, 1.0f }; // fix(zig-gamedev)
672-
673631
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
674632
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(nullptr, text); };
675633
platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(nullptr); };
@@ -837,8 +795,8 @@ static void ImGui_ImplGlfw_UpdateMouseData()
837795
mouse_x += window_x;
838796
mouse_y += window_y;
839797
}
840-
bd->LastValidMousePos = ImVec2((float)mouse_x * bd->DpiScale.x, (float)mouse_y * bd->DpiScale.y); // fix(zig-gamedev)
841-
io.AddMousePosEvent((float)mouse_x * bd->DpiScale.x, (float)mouse_y * bd->DpiScale.y); // fix(zig-gamedev)
798+
bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y);
799+
io.AddMousePosEvent((float)mouse_x, (float)mouse_y);
842800
}
843801
}
844802

@@ -1007,11 +965,6 @@ void ImGui_ImplGlfw_NewFrame()
1007965
io.DisplaySize = ImVec2((float)w, (float)h);
1008966
if (w > 0 && h > 0)
1009967
io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);
1010-
1011-
// fix(zig-gamedev)
1012-
bd->DpiScale.x = ceil(io.DisplayFramebufferScale.x);
1013-
bd->DpiScale.y = ceil(io.DisplayFramebufferScale.y);
1014-
1015968
if (bd->WantUpdateMonitors)
1016969
ImGui_ImplGlfw_UpdateMonitors();
1017970

libs/imgui/backends/imgui_impl_glfw.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
1212
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
1313
// Missing features or Issues:
14-
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
14+
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
15+
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
16+
// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
1517

1618
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
1719
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -29,11 +31,13 @@ struct GLFWwindow;
2931
struct GLFWmonitor;
3032

3133
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
32-
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
33-
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
34-
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
35-
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
36-
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
34+
extern "C" { // fix(zig-gamedev)
35+
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
36+
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
37+
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
38+
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
39+
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
40+
};
3741

3842
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
3943
#ifdef __EMSCRIPTEN__

libs/imgui/backends/imgui_impl_wgpu.cpp

+1-46
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@
4545
// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
4646
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
4747

48-
// FIX(zig-gamedev)
49-
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
50-
5148
#ifndef __EMSCRIPTEN__
5249
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
5350
#error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
@@ -61,8 +58,7 @@
6158
#include "imgui.h"
6259
#ifndef IMGUI_DISABLE
6360

64-
// FIX(zig-gamedev):
65-
// #include "imgui_impl_wgpu.h"
61+
#include "imgui_impl_wgpu.h"
6662

6763
#include <limits.h>
6864
#include <webgpu/webgpu.h>
@@ -71,47 +67,6 @@
7167
extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0);
7268
#define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro).
7369

74-
// FIX(zig-gamedev): We removed header file and declare all our external functions here.
75-
extern "C" {
76-
77-
// Initialization data, for ImGui_ImplWGPU_Init()
78-
struct ImGui_ImplWGPU_InitInfo
79-
{
80-
WGPUDevice Device;
81-
int NumFramesInFlight = 3;
82-
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
83-
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;
84-
WGPUMultisampleState PipelineMultisampleState = {};
85-
86-
ImGui_ImplWGPU_InitInfo()
87-
{
88-
PipelineMultisampleState.count = 1;
89-
PipelineMultisampleState.mask = UINT32_MAX;
90-
PipelineMultisampleState.alphaToCoverageEnabled = false;
91-
}
92-
};
93-
94-
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
95-
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info);
96-
IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown();
97-
IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame();
98-
IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder);
99-
100-
// Use if you want to reset your rendering device without losing Dear ImGui state.
101-
IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
102-
IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
103-
104-
// [BETA] Selected render state data shared with callbacks.
105-
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplWGPU_RenderDrawData() call.
106-
// (Please open an issue if you feel you need access to more data)
107-
struct ImGui_ImplWGPU_RenderState
108-
{
109-
WGPUDevice Device;
110-
WGPURenderPassEncoder RenderPassEncoder;
111-
};
112-
113-
} // extern "C"
114-
11570
// WebGPU data
11671
struct RenderResources
11772
{

libs/imgui/backends/imgui_impl_wgpu.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface.
99
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
1010

11-
// FIX(zig-gamedev)
12-
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
13-
1411
// Implemented features:
1512
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
1613
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
@@ -32,6 +29,9 @@
3229

3330
#include <webgpu/webgpu.h>
3431

32+
// FIX(zig-gamedev)
33+
extern "C" {
34+
3535
// Initialization data, for ImGui_ImplWGPU_Init()
3636
struct ImGui_ImplWGPU_InitInfo
3737
{
@@ -47,7 +47,6 @@ struct ImGui_ImplWGPU_InitInfo
4747
PipelineMultisampleState.mask = UINT32_MAX;
4848
PipelineMultisampleState.alphaToCoverageEnabled = false;
4949
}
50-
};
5150

5251
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
5352
IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info);
@@ -68,4 +67,9 @@ struct ImGui_ImplWGPU_RenderState
6867
WGPURenderPassEncoder RenderPassEncoder;
6968
};
7069

70+
};
71+
72+
// FIX(zig-gamedev)
73+
} // extern "C"
74+
7175
#endif // #ifndef IMGUI_DISABLE

src/backend_glfw_wgpu.zig

+18-11
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ pub fn init(
1010
wgpu_swap_chain_format: u32, // wgpu.TextureFormat
1111
wgpu_depth_format: u32, // wgpu.TextureFormat
1212
) void {
13-
backend_glfw.init(window);
14-
1513
var info = ImGui_ImplWGPU_InitInfo{
1614
.device = wgpu_device,
1715
.num_frames_in_flight = 1,
@@ -23,20 +21,27 @@ pub fn init(
2321
if (!ImGui_ImplWGPU_Init(&info)) {
2422
unreachable;
2523
}
24+
25+
backend_glfw.init(window);
2626
}
2727

2828
pub fn deinit() void {
2929
ImGui_ImplWGPU_Shutdown();
3030
backend_glfw.deinit();
3131
}
3232

33-
pub fn newFrame(fb_width: u32, fb_height: u32) void {
33+
var _width: u32 = 0;
34+
var _height: u32 = 0;
35+
pub fn newFrame(width: u32, height: u32) void {
36+
if (width != _width or height != _height) {
37+
ImGui_ImplWGPU_InvalidateDeviceObjects();
38+
if (ImGui_ImplWGPU_CreateDeviceObjects()) {
39+
_width = width;
40+
_height = height;
41+
}
42+
}
3443
ImGui_ImplWGPU_NewFrame();
3544
backend_glfw.newFrame();
36-
37-
gui.io.setDisplaySize(@floatFromInt(fb_width), @floatFromInt(fb_height));
38-
gui.io.setDisplayFramebufferScale(1.0, 1.0);
39-
4045
gui.newFrame();
4146
}
4247

@@ -61,7 +66,9 @@ pub const ImGui_ImplWGPU_InitInfo = extern struct {
6166

6267
// Those functions are defined in 'imgui_impl_wgpu.cpp`
6368
// (they include few custom changes).
64-
extern fn ImGui_ImplWGPU_Init(init_info: *ImGui_ImplWGPU_InitInfo) bool;
65-
extern fn ImGui_ImplWGPU_NewFrame() void;
66-
extern fn ImGui_ImplWGPU_RenderDrawData(draw_data: *const anyopaque, pass_encoder: *const anyopaque) void;
67-
extern fn ImGui_ImplWGPU_Shutdown() void;
69+
extern fn ImGui_ImplWGPU_Init(init_info: *ImGui_ImplWGPU_InitInfo) callconv(.c) bool;
70+
extern fn ImGui_ImplWGPU_InvalidateDeviceObjects() callconv(.c) void;
71+
extern fn ImGui_ImplWGPU_CreateDeviceObjects() callconv(.c) bool;
72+
extern fn ImGui_ImplWGPU_NewFrame() callconv(.c) void;
73+
extern fn ImGui_ImplWGPU_RenderDrawData(draw_data: *const anyopaque, pass_encoder: *const anyopaque) callconv(.c) void;
74+
extern fn ImGui_ImplWGPU_Shutdown() callconv(.c) void;

0 commit comments

Comments
 (0)