@@ -3,28 +3,85 @@ const builtin = @import("builtin");
33
44const 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 ;
2677extern 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+
2885pub const terminate = glfwTerminate ;
2986extern fn glfwTerminate () void ;
3087
@@ -37,14 +94,16 @@ extern fn glfwWaitEvents() void;
3794pub const waitEventsTimeout = glfwWaitEventsTimeout ;
3895extern 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}
43102extern fn glfwVulkanSupported () i32 ;
44103
45104pub 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 {
102161extern fn glfwGetError (description : ? * ? [* :0 ]const u8 ) i32 ;
103162
104163pub 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}
137199extern 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+
139219pub 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
148228pub 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
162242pub 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
305385pub 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
512604pub 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
761853pub 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 {
888984extern fn glfwWindowHintString (WindowHint , string : [* :0 ]const u8 ) void ;
889985
890986pub 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
896995pub 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
9021004pub 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
9081013pub 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
9141022pub 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