multi-client support and demo

This commit is contained in:
koniifer 2024-11-14 21:28:21 +00:00
parent 95b4a921dc
commit 907c0d0dd4
9 changed files with 140 additions and 48 deletions

6
Cargo.lock generated
View file

@ -228,12 +228,12 @@ dependencies = [
[[package]] [[package]]
name = "hbbytecode" name = "hbbytecode"
version = "0.1.0" 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]] [[package]]
name = "hblang" name = "hblang"
version = "0.1.0" 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 = [ dependencies = [
"hashbrown 0.15.1", "hashbrown 0.15.1",
"hbbytecode", "hbbytecode",
@ -245,7 +245,7 @@ dependencies = [
[[package]] [[package]]
name = "hbvm" name = "hbvm"
version = "0.1.0" 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 = [ dependencies = [
"hbbytecode", "hbbytecode",
] ]

View file

@ -1,5 +1,6 @@
#![allow(unused)] #![allow(unused)]
use std::{ use std::{
collections::HashMap,
fmt::format, fmt::format,
fs::{read_to_string, File}, fs::{read_to_string, File},
io::{BufWriter, Write}, io::{BufWriter, Write},
@ -13,6 +14,7 @@ pub struct Package {
name: String, name: String,
binaries: Vec<String>, binaries: Vec<String>,
build_cmd: String, build_cmd: String,
args: HashMap<String, String>,
} }
impl Package { impl Package {
@ -46,26 +48,36 @@ impl Package {
let mut binaries = vec![]; let mut binaries = vec![];
for (count, (name, table)) in bin_table.into_iter().enumerate() { for (count, (name, table)) in bin_table.into_iter().enumerate() {
// if count != 0 {
binaries.push(name.clone()); binaries.push(name.clone());
// }
} }
let build_table = data.get("build").unwrap(); let build_table = data.get("build").unwrap();
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into(); let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
build_cmd.remove(0); build_cmd.remove(0);
// build_cmd.pop(); let mut args: HashMap<String, String> = 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::<HashMap<String, String>>(),
};
Self { Self {
name, name,
binaries, binaries,
build_cmd, build_cmd,
args,
} }
} }
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> { pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
if self.binaries.contains(&"hblang".to_string()) { if self.binaries.contains(&"hblang".to_string()) {
let file = self.build_cmd.split_ascii_whitespace().last().unwrap(); 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); let path = format!("sysdata/programs/{}/{}", self.name, file);
// compile here // compile here
@ -73,6 +85,7 @@ impl Package {
&path, &path,
Options { Options {
fmt: true, fmt: true,
in_house_regalloc,
..Default::default() ..Default::default()
}, },
out, out,
@ -87,6 +100,7 @@ impl Package {
hblang::run_compiler( hblang::run_compiler(
&path, &path,
Options { Options {
in_house_regalloc,
..Default::default() ..Default::default()
}, },
out, out,
@ -98,6 +112,7 @@ impl Package {
&path, &path,
Options { Options {
dump_asm: true, dump_asm: true,
in_house_regalloc,
..Default::default() ..Default::default()
}, },
out, out,

View file

@ -7,7 +7,7 @@ channel := Channel.(0, 0)
find_server := fn(): void { find_server := fn(): void {
log.info("client: locating server\0") log.info("client: locating server\0")
channel2 := await_channel(channel) channel2 := await_channel()
channel.server = channel2.server channel.server = channel2.server
channel.client = channel2.client channel.client = channel2.client
log.info("client: server located\0") log.info("client: server located\0")
@ -51,15 +51,13 @@ update_permissions := fn(client: Window): bool {
} }
send_frame := fn(client: Window): bool { send_frame := fn(client: Window): bool {
server_id := client.data.channel.server send_header(message.frame_ready, client.data.channel.server)
client_id := client.data.channel.client response := await_message(uint, client.data.channel.client)
send_header(message.frame_ready, server_id)
response := await_message(uint, client_id)
if response.header.kind != message.ack { if response.header.kind != message.ack {
return false return false
} }
// ! FOR NOW, server will ALWAYS be local, // ! FOR NOW, server will ALWAYS be local,
// ! so we can send pointer to surface. // ! so we can send pointer to surface.
send_message(^Color, message.ack, client.surface.buf, server_id) send_message(^Color, message.ack, client.surface.buf, client.data.channel.server)
return await_header(client_id).kind == message.ack return true
} }

View file

@ -14,11 +14,11 @@ server := @use("./server.hb")
message := @use("./message.hb") message := @use("./message.hb")
permissions := @use("./permissions.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))) 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))) buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind)))
} }
@ -34,7 +34,8 @@ $recv_header := fn(buffer_id: uint): ?MessageHeader {
return response return response
} }
await_channel := fn(channel: Channel): Channel { await_channel := fn(): Channel {
channel := Channel.(0, 0)
loop if channel.server != 0 break else { loop if channel.server != 0 break else {
channel.server = buffer.search(BUFFER_SERVER) channel.server = buffer.search(BUFFER_SERVER)
} }
@ -64,8 +65,10 @@ await_header := fn(buffer_id: uint): MessageHeader {
} }
} }
MessageKind := u8
MessageHeader := packed struct { MessageHeader := packed struct {
kind: uint, kind: MessageKind,
} }
Message := fn($Expr: type): type { Message := fn($Expr: type): type {

View file

@ -21,7 +21,12 @@ start := fn(): void {
log.error("server: failed to load asset\0") log.error("server: failed to load asset\0")
return 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") log.info("server: started server\0")
} }
@ -43,9 +48,12 @@ incoming := fn(): bool {
data := WindowData.(props.body, channel, permissions.default) data := WindowData.(props.body, channel, permissions.default)
send_message(WindowData, message.ack, data, channel.client) send_message(WindowData, message.ack, data, channel.client)
surface := new_window_decorations(data.props.dimensions) 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) // decorations
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) 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.windows[server.window_count] = .(data, surface)
server.window_count += 1 server.window_count += 1
} }
@ -58,35 +66,61 @@ $DECO_HEIGHT_BOTTOM := 1
$DECO_COLOUR := Color.(100, 200, 255, 255) $DECO_COLOUR := Color.(100, 200, 255, 255)
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface { 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. // ! compositor code. this currently disallows tearing.
collect_frames := fn(): void { collect_frames := fn(): void {
window := server.windows[0] i := 0
if window == null { loop if i == 10 break else {
return 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 { render_clients := fn(screen: Surface): void {
window := server.windows[0] i := 0
if window == null { loop if i == 10 break else {
return 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) sync(screen)
} }

View file

@ -7,24 +7,23 @@ bmp := @embed("../../../assets/mini.bmp")
main := fn(): void { main := fn(): void {
sunset.client.find_server() sunset.client.find_server()
image := render.image.from(@bitcast(&bmp)) image := render.image.bmp.from(@bitcast(&bmp))
if image == null { if image == null {
log.error("got no image\0") log.error("got no image\0")
return 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 { if window == null {
log.error("got no window\0") log.error("got no window\0")
return return
} }
x := 0 x := 0
loop { 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) render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 20), false)
if sunset.client.send_frame(window) == false { _ = sunset.client.send_frame(window)
log.error("did not send frame\0")
}
x += 1 x += 1
} }
} }

View file

@ -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"

View file

@ -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
}
}

View file

@ -37,5 +37,8 @@ resolution = "1024x768x24"
[boot.limine.ableos.modules.sunset_client] [boot.limine.ableos.modules.sunset_client]
path = "boot:///sunset_client.hbf" path = "boot:///sunset_client.hbf"
[boot.limine.ableos.modules.sunset_client_2]
path = "boot:///sunset_client_2.hbf"
[boot.limine.ableos.modules.sunset_server] [boot.limine.ableos.modules.sunset_server]
path = "boot:///sunset_server.hbf" path = "boot:///sunset_server.hbf"