summaryrefslogtreecommitdiff
path: root/src/gui/gui.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/gui.zig')
-rw-r--r--src/gui/gui.zig58
1 files changed, 41 insertions, 17 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index 127f9b5d..2d31416b 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -11,6 +11,7 @@ const config = @import("../config.zig");
const look = @import("../look.zig");
const message = pardes.Messages.Message;
const file_watch = @import("../file_watch.zig");
+const shader_build = @import("../shader_build.zig");
const deck = @import("deck.zig");
const Post = @import("Post.zig");
const pet = @import("pet.zig");
@@ -2693,6 +2694,7 @@ fn localSession(
.test_hz = if (std.c.getenv("PARDES_TEST_HZ")) |hz| @max(1, std.fmt.parseInt(u64, std.mem.span(hz), 10) catch 60) else 60,
};
defer shell.shutdownPtys();
+ defer shell.shaders.deinit(gpa, inotify_fd, &watches);
// A virtual clock never blinks: goldens and feel series hold still.
g.no_blink = shell.test_clock != null;
const host = shell.host();
@@ -2862,6 +2864,7 @@ fn attachedLoop(gpa: std.mem.Allocator, g: *Gui, client: *detached_client.Client
in.post(.{ .paste = text });
},
.open_link => |url| look.openLink(url),
+ .post => dirty = true,
}
}
try link;
@@ -2877,7 +2880,15 @@ fn attachedLoop(gpa: std.mem.Allocator, g: *Gui, client: *detached_client.Client
geom = now;
try attachedResize(client, g, now.cols, now.rows);
}
- if (!dirty) continue;
+ // The session's chain, its files compiled there.
+ g.post.sync(gpa, g.device, g.swapchain_format, client.post.list(), client.post_key, null);
+ if (!dirty) {
+ // As a local window does: a chain that moves on its own redraws
+ // alone, once a refresh.
+ if (g.post.animating(client.post.animation) and g.scene_tex != null and
+ c.SDL_GetTicksNS() -| g.post.last_ns + std.time.ns_per_ms >= refreshNs(g)) redrawPost(g, gpa);
+ continue;
+ }
dirty = false;
paintAttached(g, gpa, client);
}
@@ -3993,6 +4004,8 @@ const Shell = struct {
pipe_tasks: *PipeTasks,
inotify_fd: c_int,
watches: *file_watch.Table,
+ /// The post chain's files as SPIR-V.
+ shaders: shader_build = .{},
threads_ok: bool = false,
test_mode: bool = false,
feed: StdinFeed = .{},
@@ -4209,11 +4222,19 @@ const Shell = struct {
.files_changed => check_files = true,
.fs_ready => {},
};
+ if (check_files) s.shaders.recheck();
if (check_files and file_watch.reloadChanged(s.core, s.io, s.gpa, s.watches))
s.queue.push(.files_changed);
}
};
+/// A post chain compile is done (shader_build.zig): the loop's SDL wait ends.
+fn wakeSdl(_: ?*anyopaque) void {
+ var event = std.mem.zeroes(c.SDL_Event);
+ event.type = c.SDL_EVENT_USER;
+ _ = c.SDL_PushEvent(&event);
+}
+
fn wakeFs(ctx: ?*anyopaque) void {
const q: *Queue = @ptrCast(@alignCast(ctx.?));
q.push(.fs_ready);
@@ -4356,7 +4377,11 @@ fn pollFrame(ctx: ?*anyopaque) void {
const geom = windowCells(g);
if (updateCoreResize(core, geom.cols, geom.rows, g.cell_w, g.cell_h, g.tagline_width, g.tagline_height)) resetScroll(g);
stepScroll(g, core, s.gpa);
- g.post.sync(s.gpa, s.io, g.device, g.swapchain_format, core);
+ _ = s.shaders.sync(s.gpa, s.io, core, s.inotify_fd, s.watches, .{ .call = wakeSdl });
+ {
+ var passes: [Post.max]shader_build.Pass = undefined;
+ g.post.sync(s.gpa, g.device, g.swapchain_format, s.shaders.view(&core.settings.post, &passes), s.shaders.revision, core);
+ }
if (s.test_mode) writeTestStatus(g, core, s.presented);
// Between the core's frames, a chain that moves on its own redraws
// alone, once a refresh of the display the window is on (a millisecond
@@ -5805,8 +5830,9 @@ fn renderFrame(
const win_w: f32 = @floatFromInt(sw);
const win_h: f32 = @floatFromInt(sh);
- // The post chain runs over a local frame, from the scene texture.
- var scene_on = core != null and g.post.ready();
+ // The post chain runs from the scene texture, over a local frame or an
+ // attached session's alike.
+ var scene_on = g.post.ready();
if (scene_on) ensureSceneTexture(g, sw, sh) catch {
g.scene_target_failed = true;
scene_on = false;
@@ -6179,19 +6205,17 @@ fn renderFrame(
c.SDL_EndGPURenderPass(rp);
if (scene_on) {
- if (core) |p| {
- var boxes: [max_cursors]CursorBox = undefined;
- const cursors = if (cursors_shown) cursorBoxes(g, surface, layout, win_h, &boxes) else 0;
- var spare: [Post.max_spare][4]f32 = undefined;
- g.post.describe(.{
- .cursor = if (cursors > 0) boxes[0] else null,
- .spare = spare[0..postSpare(surface, layout, &spare)],
- .background = chrome.page orelse bg_default,
- .foreground = chrome.fg orelse fg_default,
- .selection_foreground = p.theme().sel_fg,
- .selection_background = p.theme().sel_bg,
- });
- }
+ var boxes: [max_cursors]CursorBox = undefined;
+ const cursors = if (cursors_shown) cursorBoxes(g, surface, layout, win_h, &boxes) else 0;
+ var spare: [Post.max_spare][4]f32 = undefined;
+ g.post.describe(.{
+ .cursor = if (cursors > 0) boxes[0] else null,
+ .spare = spare[0..postSpare(surface, layout, &spare)],
+ .background = chrome.page orelse bg_default,
+ .foreground = chrome.fg orelse fg_default,
+ .selection_foreground = if (core) |p| p.theme().sel_fg else chrome.sel_fg,
+ .selection_background = if (core) |p| p.theme().sel_bg else chrome.sel_bg,
+ });
const chain_zone = tracy.zone(@src(), "post chain");
defer chain_zone.end();
g.post.scale = display_scale;