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]]
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",
]

View file

@ -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<String>,
build_cmd: String,
args: HashMap<String, String>,
}
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<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 {
name,
binaries,
build_cmd,
args,
}
}
pub fn build(&self, out: &mut Vec<u8>) -> 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,

View file

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

View file

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

View file

@ -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)
// 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]
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
return
i += 1
continue
}
header := recv_header(window.data.channel.server)
if header == null | @unwrap(header).kind != message.frame_ready {
return
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)
// ! 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)
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
}
}
render_clients := fn(screen: Surface): void {
window := server.windows[0]
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
return
i += 1
continue
}
put_surface(screen, window.surface, window.data.props.position, false)
i += 1
}
sync(screen)
}

View file

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

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