diff --git a/src/Client.zig b/src/Client.zig index 5ffa077..b7329d7 100644 --- a/src/Client.zig +++ b/src/Client.zig @@ -69,7 +69,7 @@ pub const Window = struct { buffer_data: ?[]align(std.heap.page_size_min) u8 = null, wl_buffers: [2]?*wl.Buffer = .{ null, null }, z2d_surfaces: [2]?z2d.Surface = .{ null, null }, - selected: u1 = 0, + buffer_swapped: bool = false, /// In miliseconds. last_frame: u32 = 0, @@ -81,9 +81,18 @@ pub const Window = struct { return .init(window.alloc, &window.surfaces[window.sel]); } - // Returns the current z2d surface. - pub fn surface(window: *Window) ?*z2d.Surface { - if (window.z2d_surfaces[window.selected]) |*s| return s else return null; + // Returns a z2d surface to the window. + pub fn surface(window: *Window) ?z2d.Surface { + if (window.buffer_data) |data| { + return z2d.Surface.initBuffer( + .image_surface_rgb, + .fromClamped(1, 1, 1), + @ptrCast(@alignCast(data[window.dataOffset(true)..])), + @intCast(window.width), + @intCast(window.height), + ); + } + return null; } pub fn deinit(window: *Window) void { @@ -97,14 +106,25 @@ pub const Window = struct { } fn commit(window: *Window) void { - window.wl_surface.?.attach(window.wl_buffers[window.selected], 0, 0); + window.wl_surface.?.attach(window.wl_buffer, 0, 0); window.wl_surface.?.damage(0, 0, std.math.maxInt(i32), std.math.maxInt(i32)); window.wl_surface.?.commit(); } - pub fn submit(window: *Window) void { - window.selected +%= 1; + pub fn submit(window: *Window) !void { + window.buffer_swapped = !window.buffer_swapped; + + const buffer = try window.pool.?.createBuffer( + @intCast(window.dataOffset(false)), + @intCast(window.width), + @intCast(window.height), + @intCast(window.width * @sizeOf(z2d.pixel.RGB)), + .xrgb8888, + ); + if (window.wl_buffer) |b| b.destroy(); + window.wl_buffer = buffer; + window.commit(); window.need_redraw = false; } @@ -163,6 +183,15 @@ pub const Window = struct { window.buffer_data = data; } + /// If `next_frame` is false, it returns the frame that should currently be displayed. + /// If true, it returns the next frame's offset. + fn dataOffset(window: *Window, next_frame: bool) usize { + const size = window.buffer_data.?.len; + var b: bool = window.buffer_swapped; + if (next_frame) b = !b; + return if (b) @intCast(size / 2) else 0; + } + // Called when the window needs to be resized. // Creates a wl_shm_pool if the one the Window currently has is not big enough. // The pool is allocated enough memory for two frames, given the size. @@ -180,32 +209,19 @@ pub const Window = struct { }; const pool: *wl.ShmPool = window.pool orelse return; - const data = window.buffer_data orelse return; - window.z2d_surfaces[0] = .initBuffer( - .image_surface_rgb, - .fromClamped(1, 1, 1), - @ptrCast(data), - @intCast(width), - @intCast(height), - ); - window.z2d_surfaces[1] = .initBuffer( - .image_surface_rgb, - .fromClamped(1, 1, 1), - @ptrCast(@alignCast(data[data.len / 2 ..])), + std.log.debug("(wayland): createBuffer(s) {d}x{d} ({d})", .{ width, height, width * @sizeOf(z2d.pixel.RGB) }); + const buffer = try pool.createBuffer( + @intCast(window.dataOffset(false)), @intCast(width), @intCast(height), + @intCast(width * @sizeOf(z2d.pixel.RGB)), + .xrgb8888, ); - std.log.debug("(wayland): createBuffer(s) {d}x{d} ({d})", .{ width, height, width * @sizeOf(z2d.pixel.RGB) }); - const buffer0 = try pool.createBuffer(0, @intCast(width), @intCast(height), @intCast(width * @sizeOf(z2d.pixel.RGB)), .xrgb8888); - const buffer1 = try pool.createBuffer(@intCast(size / 2), @intCast(width), @intCast(height), @intCast(width * @sizeOf(z2d.pixel.RGB)), .xrgb8888); - - if (window.wl_buffers[1]) |b| b.destroy(); - if (window.wl_buffers[0]) |b| b.destroy(); + if (window.wl_buffer) |b| b.destroy(); - window.wl_buffers[0] = buffer0; - window.wl_buffers[1] = buffer1; + window.wl_buffer = buffer; } }; diff --git a/src/main.zig b/src/main.zig index 5156d39..f756d31 100644 --- a/src/main.zig +++ b/src/main.zig @@ -19,28 +19,27 @@ pub fn main() !void { std.log.debug("(app) Window shown", .{}); try redraw(window); - window.submit(); + try window.submit(); while (window.is_open) { std.log.info("tick", .{}); if (client.display.dispatch() != .SUCCESS) return; if (window.need_redraw) { try redraw(window); - window.submit(); } } } fn redraw(window: *Client.Window) !void { - const surface = window.surface() orelse { + var surface = window.surface() orelse { window.is_open = false; return; }; - try rect(window.alloc, surface, 0, 0, 100, 100, .rgb(1, 0, 0)); + try rect(window.alloc, &surface, 0, 0, 100, 100, .rgb(1, 0, 0)); std.log.info("(app) width: {d}", .{window.width}); try rect( window.alloc, - surface, + &surface, @as(f64, @floatFromInt(window.width)) - 100, @as(f64, @floatFromInt(window.height)) - 100, // 50, @@ -49,7 +48,7 @@ fn redraw(window: *Client.Window) !void { 100, .rgb(0, 0, 1), ); - window.submit(); + try window.submit(); } /// For converting to Wayland color space.