Smooth rendering!

This commit is contained in:
2026-05-05 22:45:41 +02:00
parent 10365c135b
commit 10cbf61e52
+73 -62
View File
@@ -51,10 +51,14 @@ const WaylandState = struct {
surface: ?*c.wl_surface, surface: ?*c.wl_surface,
buffer: ?*c.wl_buffer, buffer: ?*c.wl_buffer,
shared_memory_pool_data: []u8,
xkb_context: ?*c.xkb_context, xkb_context: ?*c.xkb_context,
xkb_keymap: ?*c.xkb_keymap, xkb_keymap: ?*c.xkb_keymap,
xkb_state: ?*c.xkb_state, xkb_state: ?*c.xkb_state,
io: std.Io,
clock: std.Io.Clock,
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
resize: bool, resize: bool,
@@ -66,6 +70,7 @@ const WaylandState = struct {
pointer_event: WlPointerEvent, pointer_event: WlPointerEvent,
app_memory: puzzle.platform.AppMemory,
app_input: puzzle.platform.AppInput, app_input: puzzle.platform.AppInput,
}; };
@@ -124,6 +129,42 @@ fn wlFrameHandleDone(data: ?*anyopaque, callback: ?*c.wl_callback, callback_data
std.debug.print("[Wayland] Frame ready\n", .{}); std.debug.print("[Wayland] Frame ready\n", .{});
const render_start_time = wl_state.clock.now(wl_state.io);
wl_state.app_input.delta_time = 1.0 / 30.0;
const app_offscreen_buffer: puzzle.platform.OffscreenBuffer = .{
.width = wl_state.window_width,
.height = wl_state.window_height,
.stride = wl_state.window_width * 4,
.data = wl_state.shared_memory_pool_data,
};
// wl_state.app_input.controls = puzzle.platform.Controls{ .key = old_key };
puzzle.updateAndRender(wl_state.io, &wl_state.app_memory, app_offscreen_buffer, &wl_state.app_input);
const render_end_time = wl_state.clock.now(wl_state.io);
const render_time = render_start_time.durationTo(render_end_time);
std.debug.print("[Wayland] Render: {f}.\n", .{render_time});
// if (render_time.toNanoseconds() < frame_target_time_ns.toNanoseconds()) {
// const sleep_duration: std.Io.Clock.Duration = .{
// .raw = .{ .nanoseconds = frame_target_time.nanoseconds - render_time.nanoseconds },
// .clock = clock,
// };
// std.debug.print("[Wayland] Sleeping: {f}.\n", .{sleep_duration.raw});
// sleep_duration.sleep(io) catch {
// std.debug.print("[Wayland] Error sleeping\n", .{});
// return 1;
// };
// } else {
// std.debug.print("[Wayland] MISSED FRAME\n", .{});
// }
c.wl_surface_attach(wl_state.surface, wl_state.buffer, 0, 0);
c.wl_surface_damage_buffer(wl_state.surface, 0, 0, wl_state.window_width, wl_state.window_height);
c.wl_surface_commit(wl_state.surface);
wl_state.frame_commited = true; wl_state.frame_commited = true;
} }
@@ -146,12 +187,14 @@ fn xdg_surface_handle_configure(data: ?*anyopaque, xdg_surface: ?*c.xdg_surface,
var wl_state: *WaylandState = @ptrCast(@alignCast(data)); var wl_state: *WaylandState = @ptrCast(@alignCast(data));
c.xdg_surface_ack_configure(xdg_surface, serial); c.xdg_surface_ack_configure(xdg_surface, serial);
c.wl_surface_commit(wl_state.surface);
// TODO: Ready to resize? // TODO: Ready to resize?
if (wl_state.window_resized) { if (wl_state.window_resized) {
wl_state.resize = true; wl_state.resize = true;
} }
std.debug.print("[Wayland] Configured.\n", .{});
wl_state.configured = true; wl_state.configured = true;
} }
@@ -856,13 +899,19 @@ fn pollEvents(wl_state: *WaylandState, fds: *[1]linux.pollfd) void {
pub fn main(init: std.process.Init) u8 { pub fn main(init: std.process.Init) u8 {
const io = init.io; const io = init.io;
const clock = std.Io.Clock.awake;
const clock_resolution = clock.resolution(io) catch {
std.debug.print("[Wayland] ERROR: awake clock resoultion not supported.\n", .{});
return 1;
};
const display = c.wl_display_connect(null); const display = c.wl_display_connect(null);
if (display == null) { if (display == null) {
std.debug.print("Error connecting to wayland display.\n", .{}); std.debug.print("Error connecting to wayland display.\n", .{});
return 1; return 1;
} }
const wl_fd = c.wl_display_get_fd(display); // const wl_fd = c.wl_display_get_fd(display);
std.debug.print("[Wayland] Connection established.\n", .{}); std.debug.print("[Wayland] Connection established.\n", .{});
@@ -871,6 +920,8 @@ pub fn main(init: std.process.Init) u8 {
wl_state.xkb_context = null; wl_state.xkb_context = null;
wl_state.xkb_state = null; wl_state.xkb_state = null;
wl_state.xkb_keymap = null; wl_state.xkb_keymap = null;
wl_state.io = io;
wl_state.clock = clock;
const registry = c.wl_display_get_registry(display); const registry = c.wl_display_get_registry(display);
if (registry == null) { if (registry == null) {
@@ -927,11 +978,6 @@ pub fn main(init: std.process.Init) u8 {
wl_state.window_width = 1280; wl_state.window_width = 1280;
wl_state.window_height = 960; wl_state.window_height = 960;
const clock = std.Io.Clock.awake;
const clock_resolution = clock.resolution(io) catch {
std.debug.print("[Wayland] ERROR: awake clock resoultion not supported.\n", .{});
return 1;
};
{ {
var buf: [34]u8 = undefined; var buf: [34]u8 = undefined;
var w: std.Io.Writer = .fixed(&buf); var w: std.Io.Writer = .fixed(&buf);
@@ -943,11 +989,10 @@ pub fn main(init: std.process.Init) u8 {
} }
var shared_memory_pool: ?*c.wl_shm_pool = undefined; var shared_memory_pool: ?*c.wl_shm_pool = undefined;
var shared_memory_pool_data: []u8 = undefined;
const monitor_update_hz: f64 = 30; // const monitor_update_hz: f64 = 30;
const game_update_hz: f64 = monitor_update_hz; // const game_update_hz: f64 = monitor_update_hz;
const frame_target_time_s: f64 = 1.0 / game_update_hz; // const frame_target_time_s: f64 = 1.0 / game_update_hz;
// const frame_target_time_ms: f64 = std.time.ms_per_s * frame_target_time_s; // const frame_target_time_ms: f64 = std.time.ms_per_s * frame_target_time_s;
// const frame_target_time_ns = std.Io.Duration.fromNanoseconds(std.time.ns_per_ms * @as(u64, @intFromFloat(frame_target_time_ms))); // const frame_target_time_ns = std.Io.Duration.fromNanoseconds(std.time.ns_per_ms * @as(u64, @intFromFloat(frame_target_time_ms)));
// const frame_target_time = std.Io.Duration.fromNanoseconds(@intFromFloat(std.time.ns_per_s * frame_target_time_s)); // const frame_target_time = std.Io.Duration.fromNanoseconds(@intFromFloat(std.time.ns_per_s * frame_target_time_s));
@@ -963,7 +1008,7 @@ pub fn main(init: std.process.Init) u8 {
return 1; return 1;
}; };
var app_memory: puzzle.platform.AppMemory = .{ wl_state.app_memory = .{
.initialized = false, .initialized = false,
.permanent_storage = app_permanent_storage, .permanent_storage = app_permanent_storage,
}; };
@@ -974,25 +1019,11 @@ pub fn main(init: std.process.Init) u8 {
std.debug.print("[Wayland] Added frame callback with ret {d}.\n", .{ret}); std.debug.print("[Wayland] Added frame callback with ret {d}.\n", .{ret});
} }
var start = clock.now(io);
var frame_count: u32 = 0;
var fds: [1]linux.pollfd = .{
.{
.fd = wl_fd,
.events = std.posix.POLL.IN,
.revents = 0,
},
};
while (wl_state.running) {
pollEvents(&wl_state, &fds);
if (wl_state.resize) { if (wl_state.resize) {
const new_pool = createSharedMemoryPool(wl_state) catch { const new_pool = createSharedMemoryPool(wl_state) catch {
std.debug.print("[Wayland] Error creating memory pool!\n", .{}); std.debug.print("[Wayland] Error creating memory pool!\n", .{});
wl_state.running = false; wl_state.running = false;
break; return 1;
}; };
std.debug.print( std.debug.print(
@@ -1001,7 +1032,7 @@ pub fn main(init: std.process.Init) u8 {
); );
shared_memory_pool = new_pool.pool; shared_memory_pool = new_pool.pool;
shared_memory_pool_data = new_pool.data; wl_state.shared_memory_pool_data = new_pool.data;
const stride = wl_state.window_width * 4; const stride = wl_state.window_width * 4;
const buffer = c.wl_shm_pool_create_buffer( const buffer = c.wl_shm_pool_create_buffer(
@@ -1017,7 +1048,7 @@ pub fn main(init: std.process.Init) u8 {
} else { } else {
std.debug.print("[Wayland] Error creating buffer!\n", .{}); std.debug.print("[Wayland] Error creating buffer!\n", .{});
wl_state.running = false; wl_state.running = false;
break; return 1;
} }
wl_state.resize = false; wl_state.resize = false;
@@ -1028,43 +1059,23 @@ pub fn main(init: std.process.Init) u8 {
c.wl_surface_commit(wl_state.surface); c.wl_surface_commit(wl_state.surface);
} }
const render_start_time = clock.now(io); var start = clock.now(io);
wl_state.app_input.delta_time = frame_target_time_s; var frame_count: u32 = 0;
const app_offscreen_buffer: puzzle.platform.OffscreenBuffer = .{ // var fds: [1]linux.pollfd = .{
.width = wl_state.window_width, // .{
.height = wl_state.window_height, // .fd = wl_fd,
.stride = wl_state.window_width * 4, // .events = std.posix.POLL.IN,
.data = shared_memory_pool_data, // .revents = 0,
}; // },
// wl_state.app_input.controls = puzzle.platform.Controls{ .key = old_key };
puzzle.updateAndRender(io, &app_memory, app_offscreen_buffer, &wl_state.app_input);
const render_end_time = clock.now(io);
const render_time = render_start_time.durationTo(render_end_time);
std.debug.print("[Wayland] Render: {f}.\n", .{render_time});
// if (render_time.toNanoseconds() < frame_target_time_ns.toNanoseconds()) {
// const sleep_duration: std.Io.Clock.Duration = .{
// .raw = .{ .nanoseconds = frame_target_time.nanoseconds - render_time.nanoseconds },
// .clock = clock,
// }; // };
// std.debug.print("[Wayland] Sleeping: {f}.\n", .{sleep_duration.raw}); while (wl_state.running) {
// sleep_duration.sleep(io) catch { const ret = c.wl_display_dispatch(wl_state.display);
// std.debug.print("[Wayland] Error sleeping\n", .{}); if (ret == -1) {
// return 1; std.debug.print("[Wayland] Dispatch failed: exiting.\n", .{});
// }; wl_state.running = false;
// } else { }
// std.debug.print("[Wayland] MISSED FRAME\n", .{});
// }
c.wl_surface_attach(wl_state.surface, wl_state.buffer, 0, 0);
c.wl_surface_damage_buffer(wl_state.surface, 0, 0, wl_state.window_width, wl_state.window_height);
c.wl_surface_commit(wl_state.surface);
_ = c.wl_display_roundtrip(wl_state.display);
wl_state.frame_commited = false; wl_state.frame_commited = false;