forked from AbleOS/ableos
multi-client support and demo
This commit is contained in:
parent
95b4a921dc
commit
907c0d0dd4
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
11
sysdata/programs/sunset_client_2/meta.toml
Normal file
11
sysdata/programs/sunset_client_2/meta.toml
Normal 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"
|
29
sysdata/programs/sunset_client_2/src/main.hb
Normal file
29
sysdata/programs/sunset_client_2/src/main.hb
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in a new issue