Skip to content

Commit 1a68922

Browse files
committed
use custom GLFW and libuv allocators
1 parent aa1ac27 commit 1a68922

6 files changed

Lines changed: 255 additions & 151 deletions

File tree

build.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ const std = @import("std");
22

33
pub fn build(b: *std.Build) !void {
44
const check_step = b.step("check", "Check if app compiles");
5-
const enable_tracy = b.option(bool, "enable_tracy", "Enable Tracy") orelse false;
65
const target = b.standardTargetOptions(.{});
76
const optimize = b.standardOptimizeOption(.{});
8-
try @import("client/build.zig").buildWithoutDupes(b, "client/", true, check_step, target, optimize, enable_tracy);
9-
try @import("server/build.zig").buildWithoutDupes(b, "server/", true, check_step, target, optimize, enable_tracy);
7+
try @import("client/build.zig").buildWithoutDupes(b, "client/", true, check_step, target, optimize, true);
8+
try @import("server/build.zig").buildWithoutDupes(b, "server/", true, check_step, target, optimize, true);
109
}

client/libs/glfw/glfw.zig

Lines changed: 156 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,85 @@ const builtin = @import("builtin");
33

44
const options = @import("options");
55

6-
pub const Hint = enum(i32) {
7-
joystick_hat_buttons = 0x00050001,
8-
angle_platform_type = 0x00050002,
9-
platform = 0x00050003,
10-
cocoa_chdir_resources = 0x00051001,
11-
cocoa_menubar = 0x00051002,
12-
x11_xcb_vulkan_surface = 0x00052001,
13-
wayland_libdecor = 0x00053001,
6+
var glfw_allocator: ?std.mem.Allocator = null;
7+
var pointer_size_map: std.AutoHashMapUnmanaged(usize, usize) = .empty;
8+
var alloc_mutex: std.Thread.Mutex = .{};
9+
const alignment: std.mem.Alignment = .of(std.c.max_align_t);
1410

15-
pub fn set(hint: Hint, value: i32) void {
16-
glfwInitHint(hint, value);
17-
}
18-
extern fn glfwInitHint(hint: Hint, value: i32) void;
11+
fn allocatorMissing() noreturn {
12+
@panic("glfw: Allocator is missing, set it through `stbi.init()`");
13+
}
14+
15+
fn outOfMemory() noreturn {
16+
@panic("glfw: Out of memory");
17+
}
18+
19+
pub const GlfwAllocatorVtable = extern struct {
20+
alloc: *const fn (size: usize, userdata: ?*anyopaque) callconv(.c) ?[*]u8,
21+
realloc: *const fn (maybe_ptr: ?*anyopaque, new_size: usize, userdata: ?*anyopaque) callconv(.c) ?[*]u8,
22+
free: *const fn (maybe_ptr: ?*anyopaque, userdata: ?*anyopaque) callconv(.c) void,
23+
userdata: ?*anyopaque,
1924
};
2025

21-
pub fn init() Error!void {
22-
if (glfwInit() != 0) return;
26+
fn alloc(size: usize, _: ?*anyopaque) callconv(.c) ?[*]u8 {
27+
const allocator = glfw_allocator orelse allocatorMissing();
28+
29+
alloc_mutex.lock();
30+
defer alloc_mutex.unlock();
31+
32+
const mem = allocator.alignedAlloc(u8, alignment, size) catch outOfMemory();
33+
pointer_size_map.put(allocator, @intFromPtr(mem.ptr), size) catch outOfMemory();
34+
return mem.ptr;
35+
}
36+
37+
fn realloc(maybe_ptr: ?*anyopaque, new_size: usize, _: ?*anyopaque) callconv(.c) ?[*]u8 {
38+
const allocator = glfw_allocator orelse allocatorMissing();
39+
40+
alloc_mutex.lock();
41+
defer alloc_mutex.unlock();
42+
43+
const old_size = if (maybe_ptr) |p| pointer_size_map.fetchRemove(@intFromPtr(p)).?.value else 0;
44+
const old_mem: [*]align(alignment.toByteUnits()) u8 = if (maybe_ptr) |p| @ptrCast(@alignCast(p)) else &.{};
45+
const new_mem = allocator.realloc(old_mem[0..old_size], new_size) catch outOfMemory();
46+
pointer_size_map.put(allocator, @intFromPtr(new_mem.ptr), new_size) catch outOfMemory();
47+
return new_mem.ptr;
48+
}
49+
50+
fn free(maybe_ptr: ?*anyopaque, _: ?*anyopaque) callconv(.c) void {
51+
const allocator = glfw_allocator orelse allocatorMissing();
52+
const ptr = maybe_ptr orelse return;
53+
54+
alloc_mutex.lock();
55+
defer alloc_mutex.unlock();
56+
57+
const kv = pointer_size_map.fetchRemove(@intFromPtr(ptr)) orelse {
58+
std.log.err("glfw: Invalid free attempted on {*}", .{ptr});
59+
return;
60+
};
61+
const mem: [*]align(alignment.toByteUnits()) u8 = @ptrCast(@alignCast(ptr));
62+
allocator.free(mem[0..kv.value]);
63+
}
64+
65+
pub fn init(allocator: std.mem.Allocator) Error!void {
66+
glfw_allocator = allocator;
67+
glfwInitAllocator(&.{
68+
.alloc = alloc,
69+
.realloc = realloc,
70+
.free = free,
71+
.userdata = null,
72+
});
73+
_ = glfwInit();
2374
try maybeError();
24-
unreachable;
2575
}
76+
extern fn glfwInitAllocator(vtable: *const GlfwAllocatorVtable) void;
2677
extern fn glfwInit() i32;
2778

79+
pub fn deinit() void {
80+
const allocator = glfw_allocator orelse allocatorMissing();
81+
terminate();
82+
pointer_size_map.deinit(allocator);
83+
}
84+
2885
pub const terminate = glfwTerminate;
2986
extern fn glfwTerminate() void;
3087

@@ -37,14 +94,16 @@ extern fn glfwWaitEvents() void;
3794
pub const waitEventsTimeout = glfwWaitEventsTimeout;
3895
extern fn glfwWaitEventsTimeout(timeout: f64) void;
3996

40-
pub fn isVulkanSupported() bool {
41-
return glfwVulkanSupported() == 1;
97+
pub fn isVulkanSupported() !bool {
98+
const supported = glfwVulkanSupported() == 1;
99+
try maybeError();
100+
return supported;
42101
}
43102
extern fn glfwVulkanSupported() i32;
44103

45104
pub fn getRequiredInstanceExtensions() Error![][*:0]const u8 {
46105
var count: u32 = 0;
47-
if (glfwGetRequiredInstanceExtensions(&count)) |extensions|
106+
if (glfwGetRequiredInstanceExtensions(&count)) |extensions|
48107
return extensions[0..count];
49108
try maybeError();
50109
unreachable;
@@ -102,6 +161,9 @@ pub fn maybeError() Error!void {
102161
extern fn glfwGetError(description: ?*?[*:0]const u8) i32;
103162

104163
pub const InputMode = enum(i32) {
164+
/// Not a valid enum value to pass to GLFW
165+
invalid = std.math.minInt(i32),
166+
105167
cursor = 0x00033001,
106168
sticky_keys = 0x00033002,
107169
sticky_mouse_buttons = 0x00033003,
@@ -136,9 +198,27 @@ pub fn getProcAddress(procname: [*:0]const u8) ?GlProc {
136198
}
137199
extern fn glfwGetProcAddress(procname: [*:0]const u8) ?GlProc;
138200

201+
pub const Hint = enum(i32) {
202+
/// Not a valid enum value to pass to GLFW
203+
invalid = std.math.minInt(i32),
204+
205+
joystick_hat_buttons = 0x00050001,
206+
angle_platform_type = 0x00050002,
207+
platform = 0x00050003,
208+
cocoa_chdir_resources = 0x00051001,
209+
cocoa_menubar = 0x00051002,
210+
x11_xcb_vulkan_surface = 0x00052001,
211+
wayland_libdecor = 0x00053001,
212+
213+
pub fn set(hint: Hint, value: i32) void {
214+
glfwInitHint(hint, value);
215+
}
216+
extern fn glfwInitHint(hint: Hint, value: i32) void;
217+
};
218+
139219
pub const Action = enum(i32) {
140220
/// Not a valid enum value to pass to GLFW
141-
unknown = std.math.minInt(i32),
221+
invalid = std.math.minInt(i32),
142222

143223
release = 0,
144224
press = 1,
@@ -147,7 +227,7 @@ pub const Action = enum(i32) {
147227

148228
pub const MouseButton = enum(i32) {
149229
/// Not a valid enum value to pass to GLFW
150-
unknown = std.math.minInt(i32),
230+
invalid = std.math.minInt(i32),
151231

152232
left = 0,
153233
right = 1,
@@ -161,7 +241,7 @@ pub const MouseButton = enum(i32) {
161241

162242
pub const Key = enum(i32) {
163243
/// Not a valid enum value to pass to GLFW
164-
unknown = std.math.minInt(i32),
244+
invalid = std.math.minInt(i32),
165245

166246
space = 32,
167247
apostrophe = 39,
@@ -304,6 +384,9 @@ pub const Image = extern struct {
304384

305385
pub const Cursor = opaque {
306386
pub const Shape = enum(i32) {
387+
/// Not a valid enum value to pass to GLFW
388+
invalid = std.math.minInt(i32),
389+
307390
arrow = 0x00036001,
308391
ibeam = 0x00036002,
309392
crosshair = 0x00036003,
@@ -317,6 +400,9 @@ pub const Cursor = opaque {
317400
};
318401

319402
pub const Mode = enum(i32) {
403+
/// Not a valid enum value to pass to GLFW
404+
invalid = std.math.minInt(i32),
405+
320406
normal = 0x00034001,
321407
hidden = 0x00034002,
322408
disabled = 0x00034003,
@@ -348,6 +434,9 @@ pub const Joystick = struct {
348434
pub const maximum_supported = std.math.maxInt(Id) + 1;
349435

350436
pub const ButtonAction = enum(u8) {
437+
/// Not a valid enum value to pass to GLFW
438+
invalid = std.math.maxInt(u8),
439+
351440
release = 0,
352441
press = 1,
353442
};
@@ -396,6 +485,9 @@ pub const Gamepad = struct {
396485
jid: Joystick.Id,
397486

398487
pub const Axis = enum(u8) {
488+
/// Not a valid enum value to pass to GLFW
489+
invalid = std.math.maxInt(u8),
490+
399491
left_x = 0,
400492
left_y = 1,
401493
right_x = 2,
@@ -443,10 +535,10 @@ pub const Gamepad = struct {
443535

444536
pub fn getState(self: Gamepad) State {
445537
var state: State = undefined;
446-
_ = glfwGetGamepadState(@intCast(self.jid), &state);
447-
// return value of glfwGetGamepadState is ignored as
448-
// it is expected this is guarded by glfwJoystickIsGamepad
449-
return state;
538+
if (glfwGetGamepadState(@intCast(self.jid), &state) == 1)
539+
return state;
540+
try maybeError();
541+
unreachable;
450542
}
451543
extern fn glfwGetGamepadState(jid: i32, state: *Gamepad.State) i32;
452544

@@ -511,6 +603,9 @@ pub const VideoMode = extern struct {
511603

512604
pub const Window = opaque {
513605
pub const Attribute = enum(i32) {
606+
/// Not a valid enum value to pass to GLFW
607+
invalid = std.math.minInt(i32),
608+
514609
focused = 0x00020001,
515610
iconified = 0x00020002,
516611
resizable = 0x00020003,
@@ -561,12 +656,12 @@ pub const Window = opaque {
561656
extern fn glfwSetWindowSizeLimits(window: *Window, min_w: i32, min_h: i32, max_w: i32, max_h: i32) void;
562657

563658
pub fn getContentScale(window: *Window) [2]f32 {
564-
var xscale: f32 = 0.0;
565-
var yscale: f32 = 0.0;
566-
glfwGetWindowContentScale(window, &xscale, &yscale);
567-
return .{ xscale, yscale };
659+
var x_scale: f32 = 0.0;
660+
var y_scale: f32 = 0.0;
661+
glfwGetWindowContentScale(window, &x_scale, &y_scale);
662+
return .{ x_scale, y_scale };
568663
}
569-
extern fn glfwGetWindowContentScale(window: *Window, xscale: *f32, yscale: *f32) void;
664+
extern fn glfwGetWindowContentScale(window: *Window, x_scale: *f32, y_scale: *f32) void;
570665

571666
pub const getKey = glfwGetKey;
572667
extern fn glfwGetKey(window: *Window, key: Key) Action;
@@ -575,12 +670,12 @@ pub const Window = opaque {
575670
extern fn glfwGetMouseButton(window: *Window, button: MouseButton) Action;
576671

577672
pub fn getCursorPos(window: *Window) [2]f64 {
578-
var xpos: f64 = 0.0;
579-
var ypos: f64 = 0.0;
580-
glfwGetCursorPos(window, &xpos, &ypos);
581-
return .{ xpos, ypos };
673+
var x_pos: f64 = 0.0;
674+
var y_pos: f64 = 0.0;
675+
glfwGetCursorPos(window, &x_pos, &y_pos);
676+
return .{ x_pos, y_pos };
582677
}
583-
extern fn glfwGetCursorPos(window: *Window, xpos: *f64, ypos: *f64) void;
678+
extern fn glfwGetCursorPos(window: *Window, x_pos: *f64, y_pos: *f64) void;
584679

585680
pub fn getFramebufferSize(window: *Window) [2]i32 {
586681
var width: i32 = 0.0;
@@ -602,15 +697,15 @@ pub const Window = opaque {
602697
extern fn glfwSetWindowSize(window: *Window, width: i32, height: i32) void;
603698

604699
pub fn getPos(window: *Window) [2]i32 {
605-
var xpos: i32 = 0.0;
606-
var ypos: i32 = 0.0;
607-
glfwGetWindowPos(window, &xpos, &ypos);
608-
return .{ xpos, ypos };
700+
var x_pos: i32 = 0.0;
701+
var y_pos: i32 = 0.0;
702+
glfwGetWindowPos(window, &x_pos, &y_pos);
703+
return .{ x_pos, y_pos };
609704
}
610-
extern fn glfwGetWindowPos(window: *Window, xpos: *i32, ypos: *i32) void;
705+
extern fn glfwGetWindowPos(window: *Window, x_pos: *i32, y_pos: *i32) void;
611706

612707
pub const setPos = glfwSetWindowPos;
613-
extern fn glfwSetWindowPos(window: *Window, xpos: i32, ypos: i32) void;
708+
extern fn glfwSetWindowPos(window: *Window, x_pos: i32, y_pos: i32) void;
614709

615710
pub inline fn setTitle(window: *Window, title: [:0]const u8) void {
616711
glfwSetWindowTitle(window, title);
@@ -625,10 +720,7 @@ pub const Window = opaque {
625720
pub inline fn setClipboardString(window: *Window, string: [:0]const u8) void {
626721
return glfwSetClipboardString(window, string);
627722
}
628-
extern fn glfwSetClipboardString(
629-
window: *Window,
630-
string: [*:0]const u8,
631-
) void;
723+
extern fn glfwSetClipboardString(window: *Window, string: [*:0]const u8) void;
632724

633725
pub const setFramebufferSizeCallback = glfwSetFramebufferSizeCallback;
634726
extern fn glfwSetFramebufferSizeCallback(window: *Window, callback: ?FramebufferSizeFn) ?FramebufferSizeFn;
@@ -759,6 +851,9 @@ pub const Window = opaque {
759851
};
760852

761853
pub const WindowHint = enum(i32) {
854+
/// Not a valid enum value to pass to GLFW
855+
invalid = std.math.minInt(i32),
856+
762857
focused = 0x00020001,
763858
iconified = 0x00020002,
764859
resizable = 0x00020003,
@@ -809,6 +904,7 @@ pub const WindowHint = enum(i32) {
809904

810905
fn TypeFor(window_hint: WindowHint) type {
811906
return switch (window_hint) {
907+
.invalid => @panic("Invalid WindowHint supplied"),
812908
.focused,
813909
.iconified,
814910
.resizable,
@@ -888,30 +984,45 @@ pub fn windowHintString(window_hint: WindowHint, string: [:0]const u8) void {
888984
extern fn glfwWindowHintString(WindowHint, string: [*:0]const u8) void;
889985

890986
pub const ClientApi = enum(i32) {
987+
/// Not a valid enum value to pass to GLFW
988+
invalid = std.math.minInt(i32),
989+
891990
no_api = 0,
892991
opengl_api = 0x00030001,
893992
opengl_es_api = 0x00030002,
894993
};
895994

896995
pub const OpenGLProfile = enum(i32) {
996+
/// Not a valid enum value to pass to GLFW
997+
invalid = std.math.minInt(i32),
998+
897999
opengl_any_profile = 0,
8981000
opengl_core_profile = 0x00032001,
8991001
opengl_compat_profile = 0x00032002,
9001002
};
9011003

9021004
pub const ContextRobustness = enum(i32) {
1005+
/// Not a valid enum value to pass to GLFW
1006+
invalid = std.math.minInt(i32),
1007+
9031008
no_robustness = 0,
9041009
no_reset_notification = 0x00031001,
9051010
lose_context_on_reset = 0x00031002,
9061011
};
9071012

9081013
pub const ReleaseBehaviour = enum(i32) {
1014+
/// Not a valid enum value to pass to GLFW
1015+
invalid = std.math.minInt(i32),
1016+
9091017
any = 0,
9101018
flush = 0x00035001,
9111019
none = 0x00035002,
9121020
};
9131021

9141022
pub const ContextCreationApi = enum(i32) {
1023+
/// Not a valid enum value to pass to GLFW
1024+
invalid = std.math.minInt(i32),
1025+
9151026
native = 0x00036001,
9161027
egl = 0x00036002,
9171028
osmesa = 0x00036003,

0 commit comments

Comments
 (0)