Skip to content

Commit ca24815

Browse files
committed
Image rendering ("show" command) demo
1 parent d7c60e1 commit ca24815

8 files changed

Lines changed: 186 additions & 0 deletions

File tree

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ members = [
1515
"crates/kernel",
1616
"crates/lz4",
1717
"crates/shell",
18+
"crates/show",
1819
"crates/ulib",
1920
]
2021

crates/kernel/scripts/compile-init.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ FS_PATH="../../disk-image"
88
DESTDIR="$FS_PATH" ../shell/build.sh
99
DESTDIR="$FS_PATH" ../console/build.sh
1010
DESTDIR="$FS_PATH" ../display-server/build.sh
11+
DESTDIR="$FS_PATH" ../show/build.sh
1112
../init/build.sh

crates/show/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.elf

crates/show/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "show"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
bytemuck = { version = "1.19.0", default-features = false }
8+
display-client = { path = "../display-client" }
9+
lz4 = { path = "../lz4" }
10+
ulib = { path = "../ulib", features = ["heap-impl"] }
11+
gfx = { path = "../gfx" }
12+
13+
[dev-dependencies]
14+
ulib = { path = "../ulib", features = ["test"] }

crates/show/build.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
let crate_root = std::env::var("CARGO_MANIFEST_DIR").unwrap();
3+
println!("cargo::rerun-if-changed=../ulib/script.ld");
4+
println!("cargo::rustc-link-arg-bins=-T{crate_root}/../ulib/script.ld");
5+
println!("cargo::rustc-link-arg-bins=-n");
6+
}

crates/show/build.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
3+
set -ex
4+
cd "$(dirname "$0")"
5+
6+
BIN="show"
7+
TARGET=aarch64-unknown-none-softfloat
8+
PROFILE=${PROFILE-"release"}
9+
10+
cargo rustc --profile="${PROFILE}" \
11+
--target="${TARGET}" \
12+
--bin="${BIN}" \
13+
-- -C relocation-model=static
14+
15+
if test "$PROFILE" = "dev" ; then
16+
BINARY=../../target/${TARGET}/debug/${BIN}
17+
else
18+
BINARY=../../target/${TARGET}/${PROFILE}/${BIN}
19+
fi
20+
21+
cp "${BINARY}" "${BIN}".elf
22+
23+
if test -n "$DESTDIR" ; then
24+
cp "${BINARY}" "$DESTDIR/"
25+
fi

crates/show/src/main.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#![no_std]
2+
#![cfg_attr(not(test), no_main)]
3+
4+
extern crate alloc;
5+
extern crate display_client;
6+
7+
#[macro_use]
8+
extern crate ulib;
9+
10+
use display_client::proto;
11+
12+
use ulib::sys::FileDesc;
13+
14+
// TODO: stat for file length
15+
fn read_all(fd: FileDesc) -> alloc::vec::Vec<u8> {
16+
let mut out = alloc::vec::Vec::new();
17+
let mut buf = [0u8; 512];
18+
let mut offset = 0;
19+
loop {
20+
match ulib::sys::pread(fd, &mut buf, offset) {
21+
Ok(0) => break,
22+
Ok(len) => {
23+
out.extend(&buf[..len]);
24+
offset += len as u64;
25+
}
26+
Err(e) => {
27+
println!("Error reading file: {e}");
28+
ulib::sys::exit(1);
29+
}
30+
}
31+
}
32+
out
33+
}
34+
35+
#[no_mangle]
36+
fn main(argc: usize, argv: *const *const u8) {
37+
let argv_array = unsafe { core::slice::from_raw_parts(argv, argc) };
38+
let args = argv_array
39+
.iter()
40+
.copied()
41+
.map(|arg| unsafe { core::ffi::CStr::from_ptr(arg) }.to_bytes())
42+
.map(|arg| core::str::from_utf8(arg).unwrap())
43+
.collect::<alloc::vec::Vec<_>>();
44+
45+
let file = args[1];
46+
47+
let img_data;
48+
let img_width;
49+
let img_height;
50+
51+
if file.ends_with("qoi") {
52+
let Ok(file) = ulib::sys::openat(3, file.as_bytes(), 0, 0) else {
53+
println!("Error opening file {}", file);
54+
ulib::sys::exit(1);
55+
};
56+
57+
let img = read_all(file);
58+
let (header, data) = gfx::format::qoi::read_qoi_header(&img).unwrap();
59+
let width = header.width as usize;
60+
let height = header.height as usize;
61+
let mut output = alloc::vec![0u32; width * height];
62+
gfx::format::qoi::decode_qoi(&header, data, &mut output, width);
63+
64+
img_width = width;
65+
img_height = height;
66+
img_data = output;
67+
} else {
68+
println!("Unknown file format, exiting.");
69+
ulib::sys::exit(1);
70+
}
71+
72+
let mut buf = display_client::connect(img_width as u16, img_height as u16);
73+
buf.set_title(alloc::format!("show - {}", file).as_bytes());
74+
75+
let (width, height) = (
76+
buf.video_meta.width as usize,
77+
buf.video_meta.height as usize,
78+
);
79+
let row_stride = buf.video_meta.row_stride as usize / 4;
80+
81+
'outer: loop {
82+
while let Some(ev) = buf.server_to_client_queue().try_recv() {
83+
match ev.kind {
84+
proto::EventKind::INPUT => {
85+
use proto::EventData;
86+
let data = proto::InputEvent::parse(&ev).expect("TODO");
87+
if data.kind == proto::InputEvent::KIND_KEY {
88+
match proto::ScanCode(data.data2) {
89+
proto::ScanCode::ESCAPE | proto::ScanCode::Q => {
90+
break 'outer;
91+
}
92+
_ => (),
93+
}
94+
}
95+
}
96+
proto::EventKind::REQUEST_CLOSE => {
97+
break 'outer;
98+
}
99+
_ => (),
100+
}
101+
}
102+
103+
let fb = buf.video_mem();
104+
gfx::blit_buffer(
105+
fb, width, height, row_stride, 0, 0, &img_data, img_width, img_height, img_width,
106+
);
107+
108+
buf.client_to_server_queue()
109+
.try_send(proto::Event {
110+
kind: proto::EventKind::PRESENT,
111+
data: [0; 7],
112+
})
113+
.ok();
114+
115+
// signal(video)? for sync
116+
ulib::sys::sem_down(buf.get_sem_fd(buf.present_sem)).unwrap();
117+
118+
unsafe { ulib::sys::sys_sleep_ms(1000) };
119+
}
120+
121+
buf.client_to_server_queue()
122+
.try_send(proto::Event {
123+
kind: proto::EventKind::DISCONNECT,
124+
data: [0; 7],
125+
})
126+
.ok();
127+
}

0 commit comments

Comments
 (0)