lib/windowing/src/surface.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const sys = @import("sys");
  3 
  4 pub const Kind = enum {
  5     wayland,
  6     x11,
  7     cocoa,
  8     unsupported,
  9 };
 10 
 11 pub const Extent = struct {
 12     width: u32,
 13     height: u32,
 14     framebuffer_width: u32,
 15     framebuffer_height: u32,
 16     scale_x: f32,
 17     scale_y: f32,
 18 
 19     pub fn pixelCount(self: Extent) ?usize {
 20         return std.math.mul(usize, @as(usize, self.framebuffer_width), @as(usize, self.framebuffer_height)) catch null;
 21     }
 22 };
 23 
 24 pub const Surface = union(Kind) {
 25     wayland: Wayland,
 26     x11: X11,
 27     cocoa: Cocoa,
 28     unsupported: Unsupported,
 29 
 30     pub fn kind(self: Surface) Kind {
 31         return switch (self) {
 32             .wayland => .wayland,
 33             .x11 => .x11,
 34             .cocoa => .cocoa,
 35             .unsupported => .unsupported,
 36         };
 37     }
 38 
 39     pub fn extent(self: Surface) Extent {
 40         return switch (self) {
 41             .wayland => |value| value.extent,
 42             .x11 => |value| value.extent,
 43             .cocoa => |value| value.extent,
 44             .unsupported => |value| value.extent,
 45         };
 46     }
 47 };
 48 
 49 pub const Wayland = struct {
 50     descriptor: sys.fd.Descriptor,
 51     surface_id: u32,
 52     extent: Extent,
 53 };
 54 
 55 pub const X11 = struct {
 56     connection: *sys.x11.Connection,
 57     display: sys.x11.display.Target,
 58     window: u32,
 59     screen: u32,
 60     root: u32,
 61     visual: u32,
 62     depth: u8,
 63     red_mask: u32,
 64     green_mask: u32,
 65     blue_mask: u32,
 66     extent: Extent,
 67 };
 68 
 69 pub const Cocoa = struct {
 70     app: sys.apple.objc.Id,
 71     window: sys.apple.objc.Id,
 72     layer: sys.apple.objc.Id,
 73     extent: Extent,
 74 };
 75 
 76 pub const Unsupported = struct {
 77     extent: Extent,
 78 };
 79 
 80 pub fn extentFromSizes(
 81     width: u32,
 82     height: u32,
 83     framebuffer_width: u32,
 84     framebuffer_height: u32,
 85     scale_x: f32,
 86     scale_y: f32,
 87 ) Extent {
 88     return .{
 89         .width = width,
 90         .height = height,
 91         .framebuffer_width = framebuffer_width,
 92         .framebuffer_height = framebuffer_height,
 93         .scale_x = usableScale(scale_x),
 94         .scale_y = usableScale(scale_y),
 95     };
 96 }
 97 
 98 fn usableScale(value: f32) f32 {
 99     if (!std.math.isFinite(value) or value <= 0) return 1;
100     return value;
101 }
102 
103 test "native surface extents sanitize scale and count framebuffer pixels" {
104     const extent = extentFromSizes(320, 200, 640, 400, 2, -1);
105     try std.testing.expectEqual(@as(u32, 320), extent.width);
106     try std.testing.expectEqual(@as(u32, 400), extent.framebuffer_height);
107     try std.testing.expectEqual(@as(f32, 2), extent.scale_x);
108     try std.testing.expectEqual(@as(f32, 1), extent.scale_y);
109     try std.testing.expectEqual(@as(usize, 640 * 400), extent.pixelCount().?);
110 }
111 
112 test "native surface union exposes kind and extent" {
113     const extent = extentFromSizes(10, 20, 10, 20, 1, 1);
114     const native = Surface{ .unsupported = .{ .extent = extent } };
115     try std.testing.expectEqual(Kind.unsupported, native.kind());
116     try std.testing.expectEqual(extent, native.extent());
117 }