diff options
Diffstat (limited to 'src/detached/wire.zig')
| -rw-r--r-- | src/detached/wire.zig | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/src/detached/wire.zig b/src/detached/wire.zig index 6903a1e8..ee8c72fb 100644 --- a/src/detached/wire.zig +++ b/src/detached/wire.zig @@ -3,6 +3,9 @@ const std = @import("std"); const pardes = @import("../pardes.zig"); const limits = @import("../memory.zig").limits; +const shader_build = @import("../shader_build.zig"); +const Scene = pardes.config.Runtime.Scene; +const ShaderAnimation = pardes.config.Runtime.ShaderAnimation; /// 7: tag layers gained the `.notice` kind, so a frame can carry a tag value /// an older frontend would reject mid-session. The greeting is where that has @@ -73,6 +76,9 @@ pub const ServerTag = enum(u8) { set_clipboard = 0x10, read_clipboard = 0x11, open_link = 0x12, + /// The post chain this frontend draws its frames through: sent on + /// attach and whenever it or a file's SPIR-V changes. + post = 0x13, }; /// Why the server hung up on a connect. Sent as a `refuse` and followed by a @@ -353,6 +359,22 @@ pub const ServerMsg = union(enum) { set_clipboard: []const u8, read_clipboard, open_link: []const u8, + post: Post, +}; + +/// The session's post chain, as a GUI attached to it draws it: its passes in +/// order, each a bundled scene at its level or a Shadertoy file's SPIR-V +/// (compiled by the session, shader_build.zig: a frontend reads no disk and +/// runs no program), and when it animates on its own. Slices borrow the +/// payload. +pub const Post = struct { + animation: ShaderAnimation = .on, + passes: [shader_build.max]shader_build.Pass = @splat(.{}), + len: u8 = 0, + + pub fn list(p: *const Post) []const shader_build.Pass { + return p.passes[0..p.len]; + } }; // --------------------------------------------------------------------------- @@ -1149,6 +1171,18 @@ pub fn encodeServer(out: []u8, msg: ServerMsg) Error![]const u8 { .set_clipboard => |t| try w.putSlice32(t), .read_clipboard => {}, .open_link => |u| try w.putSlice16(u), + .post => |p| { + try w.putByte(@intFromEnum(p.animation)); + try w.putByte(p.len); + for (p.list()) |pass| { + // 0 a file, else a bundled scene and one. + try w.putByte(if (pass.scene) |scene| @as(u8, @intFromEnum(scene)) + 1 else 0); + try w.putByte(pass.level); + try w.putU32(pass.revision); + try w.putSlice16(pass.path); + try w.putSlice32(pass.spirv); + } + }, } try finishMessage(&w, at); return w.written(); @@ -1170,6 +1204,11 @@ pub fn serverBound(msg: ServerMsg) usize { .frame => |f| frameBound(f.cols, f.rows), .set_clipboard => |t| t.len, .open_link => |u| u.len, + .post => |p| blk: { + var n: usize = 0; + for (p.list()) |pass| n += 12 + pass.path.len + pass.spirv.len; + break :blk n; + }, }; } @@ -1232,6 +1271,22 @@ pub fn decodeServer(tag: u8, payload: []const u8) Error!ServerMsg { .set_clipboard => .{ .set_clipboard = try r.getSlice32() }, .read_clipboard => .read_clipboard, .open_link => .{ .open_link = try r.getSlice16() }, + .post => blk: { + var p: Post = .{ .animation = try r.getTag(ShaderAnimation) }; + p.len = try r.getByte(); + if (p.len > shader_build.max) return error.Overlong; + for (p.passes[0..p.len]) |*pass| { + const kind = try r.getByte(); + pass.* = .{ + .scene = if (kind == 0) null else std.enums.fromInt(Scene, kind - 1) orelse return error.BadValue, + .level = try r.getByte(), + .revision = try r.getU32(), + .path = try r.getSlice16(), + .spirv = try r.getSlice32(), + }; + } + break :blk .{ .post = p }; + }, }; try r.end(); return msg; @@ -1349,6 +1404,18 @@ test "detached wire: every server message round-trips" { try testing.expectEqualStrings("yank", (try roundServer(&buf, .{ .set_clipboard = "yank" })).set_clipboard); try testing.expectEqual(ServerMsg.read_clipboard, try roundServer(&buf, .read_clipboard)); try testing.expectEqualStrings("https://x", (try roundServer(&buf, .{ .open_link = "https://x" })).open_link); + var chain: Post = .{ .animation = .always, .len = 2 }; + chain.passes[0] = .{ .scene = .bloom, .level = 3 }; + chain.passes[1] = .{ .path = "~/wave.glsl", .spirv = "\x03\x02\x23\x07spirv", .revision = 7 }; + const back = (try roundServer(&buf, .{ .post = chain })).post; + try testing.expectEqual(ShaderAnimation.always, back.animation); + try testing.expectEqual(@as(u8, 2), back.len); + try testing.expectEqual(Scene.bloom, back.passes[0].scene.?); + try testing.expectEqual(@as(u8, 3), back.passes[0].level); + try testing.expect(back.passes[1].scene == null); + try testing.expectEqualStrings("~/wave.glsl", back.passes[1].path); + try testing.expectEqualStrings("\x03\x02\x23\x07spirv", back.passes[1].spirv); + try testing.expectEqual(@as(u32, 7), back.passes[1].revision); } test "detached wire: only the display's own effects are on the wire" { @@ -1357,9 +1424,9 @@ test "detached wire: only the display's own effects are on the wire" { // is the direction that matters: it would hand a frontend work that must // outlive it. The count fails if one of the three is dropped, which would // silently leave a clipboard or a link unanswered on every frontend. - try testing.expectEqual(@as(usize, 8), std.enums.values(ServerTag).len); + try testing.expectEqual(@as(usize, 9), std.enums.values(ServerTag).len); for (std.enums.values(ServerTag)) |t| switch (t) { - .welcome, .refuse, .frame, .quit, .detach, .set_clipboard, .read_clipboard, .open_link => {}, + .welcome, .refuse, .frame, .quit, .detach, .set_clipboard, .read_clipboard, .open_link, .post => {}, }; } |
