Skip to content

Commit 7351d68

Browse files
committed
Add Redox/Orbital support
1 parent 939bcc4 commit 7351d68

File tree

4 files changed

+116
-1
lines changed

4 files changed

+116
-1
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ wasm-bindgen = "0.2.78"
3737
version = "0.3.55"
3838
features = ["CanvasRenderingContext2d", "Document", "Element", "HtmlCanvasElement", "ImageData", "Window"]
3939

40+
[target.'cfg(target_os = "redox")'.dependencies]
41+
redox_syscall = "0.3"
42+
4043
[dev-dependencies]
4144
instant = "0.1.12"
4245
winit = "0.27.2"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ For now, the priority for new platforms is:
4343
✅: Present | ❌: Absent
4444
- AndroidNdk ❌
4545
- AppKit ✅ (Thanks to [Seo Sanghyeon](https://github.com/sanxiyn) and [lunixbochs](https://github.com/lunixbochs)!)
46-
- Orbital
46+
- Orbital
4747
- UiKit ❌
4848
- Wayland ✅ (Wayland support in winit is immature at the moment, so it might be wise to force X11 if you're using winit)
4949
- Web ✅ (Thanks to [Liamolucko](https://github.com/Liamolucko)!)

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ mod x11;
1515
mod wayland;
1616
#[cfg(target_arch = "wasm32")]
1717
mod web;
18+
#[cfg(target_os = "redox")]
19+
mod orbital;
1820

1921
mod error;
2022

@@ -52,6 +54,8 @@ impl<W: HasRawWindowHandle + HasRawDisplayHandle> GraphicsContext<W> {
5254
(RawWindowHandle::AppKit(appkit_handle), _) => Box::new(cg::CGImpl::new(appkit_handle)?),
5355
#[cfg(target_arch = "wasm32")]
5456
(RawWindowHandle::Web(web_handle), _) => Box::new(web::WebImpl::new(web_handle)?),
57+
#[cfg(target_os = "redox")]
58+
(RawWindowHandle::Orbital(orbital_handle), _) => Box::new(orbital::OrbitalImpl::new(orbital_handle)?),
5559
(unimplemented_window_handle, unimplemented_display_handle) => return Err(SoftBufferError::UnsupportedPlatform {
5660
window,
5761
human_readable_window_platform_name: window_handle_type_name(&unimplemented_window_handle),

src/orbital.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use raw_window_handle::HasRawWindowHandle;
2+
use raw_window_handle::OrbitalWindowHandle;
3+
use std::{
4+
cmp,
5+
slice,
6+
str,
7+
};
8+
9+
use crate::GraphicsContextImpl;
10+
use crate::SoftBufferError;
11+
12+
struct OrbitalMap {
13+
address: usize,
14+
size: usize,
15+
}
16+
17+
impl OrbitalMap {
18+
unsafe fn new(fd: usize, size_unaligned: usize) -> syscall::Result<Self> {
19+
// Page align size
20+
let pages = (size_unaligned + syscall::PAGE_SIZE - 1) / syscall::PAGE_SIZE;
21+
let size = pages * syscall::PAGE_SIZE;
22+
23+
// Map window buffer
24+
let address = syscall::fmap(fd, &syscall::Map {
25+
offset: 0,
26+
size,
27+
flags: syscall::PROT_READ | syscall::PROT_WRITE,
28+
address: 0,
29+
})?;
30+
31+
Ok(Self { address, size })
32+
}
33+
}
34+
35+
impl Drop for OrbitalMap {
36+
fn drop(&mut self) {
37+
unsafe {
38+
// Unmap window buffer on drop
39+
syscall::funmap(self.address, self.size)
40+
.expect("failed to unmap orbital window");
41+
}
42+
}
43+
}
44+
45+
pub struct OrbitalImpl {
46+
handle: OrbitalWindowHandle,
47+
}
48+
49+
impl OrbitalImpl {
50+
pub fn new<W: HasRawWindowHandle>(handle: OrbitalWindowHandle) -> Result<Self, SoftBufferError<W>> {
51+
Ok(Self { handle })
52+
}
53+
}
54+
55+
impl GraphicsContextImpl for OrbitalImpl {
56+
unsafe fn set_buffer(&mut self, buffer: &[u32], width_u16: u16, height_u16: u16) {
57+
let window_fd = self.handle.window as usize;
58+
59+
// Read the current width and size
60+
let mut window_width = 0;
61+
let mut window_height = 0;
62+
{
63+
let mut buf: [u8; 4096] = [0; 4096];
64+
let count = syscall::fpath(window_fd, &mut buf).unwrap();
65+
let path = str::from_utf8(&buf[..count]).unwrap();
66+
// orbital:/x/y/w/h/t
67+
let mut parts = path.split('/').skip(3);
68+
if let Some(w) = parts.next() {
69+
window_width = w.parse::<usize>().unwrap_or(0);
70+
}
71+
if let Some(h) = parts.next() {
72+
window_height = h.parse::<usize>().unwrap_or(0);
73+
}
74+
}
75+
76+
{
77+
// Map window buffer
78+
let window_map = OrbitalMap::new(
79+
window_fd,
80+
window_width * window_height * 4
81+
).expect("failed to map orbital window");
82+
83+
// Window buffer is u32 color data in 0xAABBGGRR format
84+
let window_data = slice::from_raw_parts_mut(
85+
window_map.address as *mut u32,
86+
window_width * window_height
87+
);
88+
89+
// Copy each line, cropping to fit
90+
let width = width_u16 as usize;
91+
let height = height_u16 as usize;
92+
let min_width = cmp::min(width, window_width);
93+
let min_height = cmp::min(height, window_height);
94+
for y in 0..min_height {
95+
let offset_buffer = y * width;
96+
let offset_data = y * window_width;
97+
window_data[offset_data..offset_data + min_width].copy_from_slice(
98+
&buffer[offset_buffer..offset_buffer + min_width]
99+
);
100+
}
101+
102+
// Window buffer map is dropped here
103+
}
104+
105+
// Tell orbital to show the latest window data
106+
syscall::fsync(window_fd).expect("failed to sync orbital window");
107+
}
108+
}

0 commit comments

Comments
 (0)