From 907c0d0dd44cfe72846533a11a88ef3623afdc59 Mon Sep 17 00:00:00 2001 From: koniifer Date: Thu, 14 Nov 2024 21:28:21 +0000 Subject: [PATCH] multi-client support and demo --- Cargo.lock | 6 +- repbuild/src/dev.rs | 23 +++++- sysdata/libraries/sunset_proto/src/client.hb | 12 ++- sysdata/libraries/sunset_proto/src/lib.hb | 11 ++- sysdata/libraries/sunset_proto/src/server.hb | 82 ++++++++++++++------ sysdata/programs/sunset_client/src/main.hb | 11 ++- sysdata/programs/sunset_client_2/meta.toml | 11 +++ sysdata/programs/sunset_client_2/src/main.hb | 29 +++++++ sysdata/system_config.toml | 3 + 9 files changed, 140 insertions(+), 48 deletions(-) create mode 100644 sysdata/programs/sunset_client_2/meta.toml create mode 100644 sysdata/programs/sunset_client_2/src/main.hb diff --git a/Cargo.lock b/Cargo.lock index 5dc6c134..ddd7fea3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -228,12 +228,12 @@ dependencies = [ [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d01e31b2034e53098f92dfb07b183a21857ded1e" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#81cf39b602a64242f2bfb22b0d18ef113e578dd8" [[package]] name = "hblang" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d01e31b2034e53098f92dfb07b183a21857ded1e" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#81cf39b602a64242f2bfb22b0d18ef113e578dd8" dependencies = [ "hashbrown 0.15.1", "hbbytecode", @@ -245,7 +245,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d01e31b2034e53098f92dfb07b183a21857ded1e" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#81cf39b602a64242f2bfb22b0d18ef113e578dd8" dependencies = [ "hbbytecode", ] diff --git a/repbuild/src/dev.rs b/repbuild/src/dev.rs index 91c46447..ab300ef2 100644 --- a/repbuild/src/dev.rs +++ b/repbuild/src/dev.rs @@ -1,5 +1,6 @@ #![allow(unused)] use std::{ + collections::HashMap, fmt::format, fs::{read_to_string, File}, io::{BufWriter, Write}, @@ -13,6 +14,7 @@ pub struct Package { name: String, binaries: Vec, build_cmd: String, + args: HashMap, } impl Package { @@ -46,26 +48,36 @@ impl Package { let mut binaries = vec![]; for (count, (name, table)) in bin_table.into_iter().enumerate() { - // if count != 0 { binaries.push(name.clone()); - // } } let build_table = data.get("build").unwrap(); let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into(); build_cmd.remove(0); - // build_cmd.pop(); + let mut args: HashMap = match build_table.get("args") { + None => HashMap::new(), + Some(v) => v + .as_table() + .unwrap() + .into_iter() + .map(|(k, v)| (k.clone(), v.to_string())) + .collect::>(), + }; Self { name, binaries, build_cmd, + args, } } pub fn build(&self, out: &mut Vec) -> std::io::Result<()> { if self.binaries.contains(&"hblang".to_string()) { let file = self.build_cmd.split_ascii_whitespace().last().unwrap(); - + let in_house_regalloc = self + .args + .get("use_new_regalloc") + .map_or(false, |str| str.parse().expect("must be a boolean")); let path = format!("sysdata/programs/{}/{}", self.name, file); // compile here @@ -73,6 +85,7 @@ impl Package { &path, Options { fmt: true, + in_house_regalloc, ..Default::default() }, out, @@ -87,6 +100,7 @@ impl Package { hblang::run_compiler( &path, Options { + in_house_regalloc, ..Default::default() }, out, @@ -98,6 +112,7 @@ impl Package { &path, Options { dump_asm: true, + in_house_regalloc, ..Default::default() }, out, diff --git a/sysdata/libraries/sunset_proto/src/client.hb b/sysdata/libraries/sunset_proto/src/client.hb index d47f5a80..01d57628 100644 --- a/sysdata/libraries/sunset_proto/src/client.hb +++ b/sysdata/libraries/sunset_proto/src/client.hb @@ -7,7 +7,7 @@ channel := Channel.(0, 0) find_server := fn(): void { log.info("client: locating server\0") - channel2 := await_channel(channel) + channel2 := await_channel() channel.server = channel2.server channel.client = channel2.client log.info("client: server located\0") @@ -51,15 +51,13 @@ update_permissions := fn(client: Window): bool { } send_frame := fn(client: Window): bool { - server_id := client.data.channel.server - client_id := client.data.channel.client - send_header(message.frame_ready, server_id) - response := await_message(uint, client_id) + send_header(message.frame_ready, client.data.channel.server) + response := await_message(uint, client.data.channel.client) if response.header.kind != message.ack { return false } // ! FOR NOW, server will ALWAYS be local, // ! so we can send pointer to surface. - send_message(^Color, message.ack, client.surface.buf, server_id) - return await_header(client_id).kind == message.ack + send_message(^Color, message.ack, client.surface.buf, client.data.channel.server) + return true } \ No newline at end of file diff --git a/sysdata/libraries/sunset_proto/src/lib.hb b/sysdata/libraries/sunset_proto/src/lib.hb index f5df7b62..f75dfb28 100644 --- a/sysdata/libraries/sunset_proto/src/lib.hb +++ b/sysdata/libraries/sunset_proto/src/lib.hb @@ -14,11 +14,11 @@ server := @use("./server.hb") message := @use("./message.hb") permissions := @use("./permissions.hb") -$send_message := fn($Expr: type, kind: uint, msg: Expr, buffer_id: uint): void { +$send_message := fn($Expr: type, kind: MessageKind, msg: Expr, buffer_id: uint): void { buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg))) } -$send_header := fn(kind: uint, buffer_id: uint): void { +$send_header := fn(kind: MessageKind, buffer_id: uint): void { buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind))) } @@ -34,7 +34,8 @@ $recv_header := fn(buffer_id: uint): ?MessageHeader { return response } -await_channel := fn(channel: Channel): Channel { +await_channel := fn(): Channel { + channel := Channel.(0, 0) loop if channel.server != 0 break else { channel.server = buffer.search(BUFFER_SERVER) } @@ -64,8 +65,10 @@ await_header := fn(buffer_id: uint): MessageHeader { } } +MessageKind := u8 + MessageHeader := packed struct { - kind: uint, + kind: MessageKind, } Message := fn($Expr: type): type { diff --git a/sysdata/libraries/sunset_proto/src/server.hb b/sysdata/libraries/sunset_proto/src/server.hb index 6737a406..0b0319a9 100644 --- a/sysdata/libraries/sunset_proto/src/server.hb +++ b/sysdata/libraries/sunset_proto/src/server.hb @@ -21,7 +21,12 @@ start := fn(): void { log.error("server: failed to load asset\0") return } - server = .(0, .{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)}, .(null, null, null, null, null, null, null, null, null, null), @as(text.Font, font)) + server = .( + 0, + .{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)}, + .(null, null, null, null, null, null, null, null, null, null), + @as(text.Font, font), + ) log.info("server: started server\0") } @@ -43,9 +48,12 @@ incoming := fn(): bool { data := WindowData.(props.body, channel, permissions.default) send_message(WindowData, message.ack, data, channel.client) surface := new_window_decorations(data.props.dimensions) - put_filled_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM), DECO_COLOUR) - put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH, DECO_HEIGHT_TOP), DECO_COLOUR) - put_text(surface, server.font, .(2, 1), .(0, 0, 0, 255), data.props.title) + // decorations + { + put_filled_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM), DECO_COLOUR) + put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH, DECO_HEIGHT_TOP), DECO_COLOUR) + put_text(surface, server.font, .(2, 1), .(0, 0, 0, 255), data.props.title) + } server.windows[server.window_count] = .(data, surface) server.window_count += 1 } @@ -58,35 +66,61 @@ $DECO_HEIGHT_BOTTOM := 1 $DECO_COLOUR := Color.(100, 200, 255, 255) new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface { - return new_surface(dimensions.x + DECO_WIDTH, dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM) + return new_surface( + dimensions.x + DECO_WIDTH, + dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM, + ) } // ! compositor code. this currently disallows tearing. collect_frames := fn(): void { - window := server.windows[0] - if window == null { - return + i := 0 + loop if i == 10 break else { + window := server.windows[i] + if window == null { + i += 1 + continue + } + header := recv_header(window.data.channel.server) + if header == null { + i += 1 + continue + } + if header.kind != message.frame_ready { + i += 1 + continue + } + send_header(message.ack, window.data.channel.client) + ptr := await_message(^Color, window.data.channel.server) + if ptr.header.kind != message.ack { + return + } + put_surface( + window.surface, + Surface.( + ptr.body, + window.data.props.dimensions.x, + window.data.props.dimensions.y, + window.data.props.dimensions.x * window.data.props.dimensions.y, + ), + .(DECO_WIDTH / 2, DECO_HEIGHT_TOP), + false, + ) + i += 1 } - header := recv_header(window.data.channel.server) - if header == null | @unwrap(header).kind != message.frame_ready { - return - } - send_header(message.ack, window.data.channel.client) - ptr := await_message(^Color, window.data.channel.server) - // ! weird compiler error - // if ptr.header.kind != message.ack { - // return - // } - put_surface(window.surface, Surface.(ptr.body, window.data.props.dimensions.x, window.data.props.dimensions.y, window.data.props.dimensions.x * window.data.props.dimensions.y), .(DECO_WIDTH / 2, DECO_HEIGHT_TOP), false) - send_header(message.ack, window.data.channel.client) } render_clients := fn(screen: Surface): void { - window := server.windows[0] - if window == null { - return + i := 0 + loop if i == 10 break else { + window := server.windows[i] + if window == null { + i += 1 + continue + } + put_surface(screen, window.surface, window.data.props.position, false) + i += 1 } - put_surface(screen, window.surface, window.data.props.position, false) sync(screen) } \ No newline at end of file diff --git a/sysdata/programs/sunset_client/src/main.hb b/sysdata/programs/sunset_client/src/main.hb index a4cb5f62..a52ee3f3 100644 --- a/sysdata/programs/sunset_client/src/main.hb +++ b/sysdata/programs/sunset_client/src/main.hb @@ -7,24 +7,23 @@ bmp := @embed("../../../assets/mini.bmp") main := fn(): void { sunset.client.find_server() - image := render.image.from(@bitcast(&bmp)) + image := render.image.bmp.from(@bitcast(&bmp)) if image == null { log.error("got no image\0") return } - window := sunset.client.new(.(.(100, 100), .(480, 200), "sunset windowing demo paddingpaddingpadding\0")) + window := sunset.client.new(.(.(100, 100), .(200, 200), "Hello,\0")) + if window == null { log.error("got no window\0") return } x := 0 loop { - render.clear(window.surface, render.cyan) + render.clear(window.surface, render.black) render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 20), false) - if sunset.client.send_frame(window) == false { - log.error("did not send frame\0") - } + _ = sunset.client.send_frame(window) x += 1 } } \ No newline at end of file diff --git a/sysdata/programs/sunset_client_2/meta.toml b/sysdata/programs/sunset_client_2/meta.toml new file mode 100644 index 00000000..399214f0 --- /dev/null +++ b/sysdata/programs/sunset_client_2/meta.toml @@ -0,0 +1,11 @@ +[package] +name = "sunset_client_2" +authors = ["koniifer"] + +[dependants.libraries] + +[dependants.binaries] +hblang.version = "1.0.0" + +[build] +command = "hblang src/main.hb" diff --git a/sysdata/programs/sunset_client_2/src/main.hb b/sysdata/programs/sunset_client_2/src/main.hb new file mode 100644 index 00000000..3fcf1c1a --- /dev/null +++ b/sysdata/programs/sunset_client_2/src/main.hb @@ -0,0 +1,29 @@ +.{log} := @use("../../../libraries/stn/src/lib.hb") +sunset := @use("../../../libraries/sunset_proto/src/lib.hb") +render := @use("../../../libraries/render/src/lib.hb") + +bmp := @embed("../../../assets/able.bmp") + +main := fn(): void { + sunset.client.find_server() + + image := render.image.bmp.from(@bitcast(&bmp)) + if image == null { + log.error("got no image\0") + return + } + + window := sunset.client.new(.(.(400, 300), .(400, 240), "Sunset!\0")) + + if window == null { + log.error("got no window\0") + return + } + x := 0 + loop { + render.clear(window.surface, render.black) + render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 40), false) + _ = sunset.client.send_frame(window) + x += 1 + } +} \ No newline at end of file diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml index da9cbd07..b4fe6705 100644 --- a/sysdata/system_config.toml +++ b/sysdata/system_config.toml @@ -37,5 +37,8 @@ resolution = "1024x768x24" [boot.limine.ableos.modules.sunset_client] path = "boot:///sunset_client.hbf" +[boot.limine.ableos.modules.sunset_client_2] +path = "boot:///sunset_client_2.hbf" + [boot.limine.ableos.modules.sunset_server] path = "boot:///sunset_server.hbf"