summaryrefslogtreecommitdiff
path: root/src/detached/server.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/detached/server.zig')
-rw-r--r--src/detached/server.zig36
1 files changed, 35 insertions, 1 deletions
diff --git a/src/detached/server.zig b/src/detached/server.zig
index 13cf4488..99a2afc2 100644
--- a/src/detached/server.zig
+++ b/src/detached/server.zig
@@ -11,6 +11,7 @@ const host_io = @import("../host_io.zig");
const selection_pipe = @import("../selection_pipe.zig");
const file_watch = @import("../file_watch.zig");
+const shader_build = @import("../shader_build.zig");
const ninep_io = @import("../9p_io.zig");
@@ -63,6 +64,8 @@ const Client = struct {
mirror: std.ArrayListUnmanaged(pardes.Cell) = .empty,
need_full: bool = true,
accepted_ms: i64 = 0,
+ /// The post chain last sent (Session.sendPost); null: none yet.
+ post_sent: ?u64 = null,
};
const Pty = struct {
@@ -173,6 +176,8 @@ pub const Session = struct {
/// the next poll returns at once, to draw it.
ninep_wake: std.atomic.Value(bool) = .init(false),
watches: file_watch.Table = @splat(null),
+ /// The post chain's files, compiled here for the GUIs attached.
+ shaders: shader_build = .{},
check_files: bool = false,
in_loop: bool = false,
greet_deadline_ms: u32 = greet_deadline_default_ms,
@@ -254,6 +259,8 @@ pub const Session = struct {
for (0..pardes.MAX_PANES) |pane|
file_watch.watchPane(s.inotify_fd, &s.watches, @intCast(pane), null, 0, .{ .text = 0 });
_ = file_watch.applyThemeEffect(s.core, s.gpa, s.inotify_fd, &s.watches, 0, false, false);
+ // The new core's chain generations are its own.
+ s.shaders.generation = null;
s.check_files = false;
if (s.ninep) |listener| listener.reset(replacement);
s.ninep_pending = false;
@@ -267,6 +274,8 @@ pub const Session = struct {
}
pub fn deinit(s: *Session) void {
+ // First: its compile thread wakes the mailbox, closed below.
+ s.shaders.deinit(s.gpa, s.inotify_fd, &s.watches);
if (s.mailbox.wake[0] >= 0) pardes.lsp.setStatusSink(null, null);
if (s.mailbox.wake[0] >= 0) host_io.setExitWake(null, null);
s.cancelWorkers();
@@ -766,6 +775,7 @@ pub const Session = struct {
fn reloadWatched(s: *Session) void {
if (!s.check_files) return;
s.check_files = false;
+ s.shaders.recheck();
for (0..reload_retries) |_| {
if (!file_watch.reloadChanged(s.core, s.io, s.gpa, &s.watches)) return;
}
@@ -823,6 +833,8 @@ pub const Session = struct {
const completed = s.ninep_wake.swap(false, .acq_rel) or drained;
for (&s.clients) |*c| if (c.fd >= 0) s.flush(c);
const regridded = s.reconcile();
+ // After the greeting reconcile sends: a chain before it is refused.
+ const compiled = s.sendPost();
// Nobody attached, nobody to dismiss a message: the loop expires
// them itself, between the editor's steps (expireUnattended).
s.core.unattended = s.primary() == null;
@@ -891,7 +903,7 @@ pub const Session = struct {
}
var timeout: c_int = if (timeout_ms == 0) -1 else @intCast(@min(timeout_ms, std.math.maxInt(c_int)));
if (s.nextWake(now)) |due| timeout = if (timeout < 0) due else @min(timeout, due);
- if (completed or s.check_files or regridded or s.ninep_pending) timeout = 0;
+ if (completed or compiled or s.check_files or regridded or s.ninep_pending) timeout = 0;
pardes.turn.rest();
const ready = libc.poll(&fds, @intCast(n), timeout);
pardes.turn.wake();
@@ -1102,6 +1114,28 @@ pub const Session = struct {
return regridded;
}
+ /// Compiles the post chain's files (a finished compile wakes the loop
+ /// through the mailbox) and sends each attached frontend the chain it
+ /// has not seen: on attach, and when it or a file's SPIR-V changes. True
+ /// when a compile was taken in, so the loop draws what it said.
+ /// ponytail: a terminal frontend is sent it too and drops it; a hello
+ /// saying which frontend it is would spare those bytes.
+ fn sendPost(s: *Session) bool {
+ const files = for (s.core.settings.post.list()) |entry| {
+ if (entry.scene == null) break true;
+ } else false;
+ const compiled = s.shaders.sync(s.gpa, s.io, s.core, if (files) s.inotify() else s.inotify_fd, &s.watches, .{ .ctx = &s.mailbox, .call = wakeForExit });
+ const key = @as(u64, s.shaders.revision) << 8 | @intFromEnum(s.core.settings.shader_animation);
+ var chain: wire.Post = .{ .animation = s.core.settings.shader_animation, .len = s.core.settings.post.len };
+ _ = s.shaders.view(&s.core.settings.post, &chain.passes);
+ for (&s.clients) |*c| {
+ if (!c.attached or c.greet or c.post_sent == key) continue;
+ c.post_sent = key;
+ s.send(c, .{ .post = chain });
+ }
+ return compiled;
+ }
+
fn send(s: *Session, c: *Client, msg: wire.ServerMsg) void {
const want = wire.serverBound(msg);
s.scratch.ensureTotalCapacity(s.gpa, want) catch return s.close(c, .oom);