Add graphics from kernel (text and primitives) and adapt to the new
windowing system by removing framebuffer drawing code and adding a WindowFramebuffer as well as methods to request and manage a window, add IPC for communication with rust helpers and SHM support (also with rust helpers) to draw into the window, move I/O code to a separate io folder.
This commit is contained in:
parent
e029139d65
commit
a6448bc1f2
17 changed files with 659 additions and 51 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
|
@ -2,10 +2,24 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
||||
|
||||
[[package]]
|
||||
name = "font8x8"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "875488b8711a968268c7cf5d139578713097ca4635a76044e8fe8eedf831d07e"
|
||||
|
||||
[[package]]
|
||||
name = "libxunil"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"font8x8",
|
||||
"spin",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ panic = "abort"
|
|||
opt-level = "s"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "2.11.1"
|
||||
font8x8 = { version = "0.3.1", default-features = false }
|
||||
spin = "0.10.0"
|
||||
|
||||
[profile.dev]
|
||||
|
|
|
|||
21
include/window.h
Normal file
21
include/window.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct Window {
|
||||
size_t width;
|
||||
size_t height;
|
||||
size_t x;
|
||||
size_t y;
|
||||
uint64_t shm_id;
|
||||
} Window;
|
||||
|
||||
Window request_window(void);
|
||||
|
||||
int draw_buffer_to_window(
|
||||
const uint32_t* buffer,
|
||||
uint64_t shm_id,
|
||||
size_t src_width,
|
||||
size_t src_height,
|
||||
size_t window_width,
|
||||
size_t window_height
|
||||
);
|
||||
57
src/graphics/font_render.rs
Normal file
57
src/graphics/font_render.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
extern crate font8x8;
|
||||
|
||||
use crate::graphics::framebuffer::WindowFrameBuffer;
|
||||
use crate::graphics::primitives::rectangle_filled;
|
||||
use font8x8::legacy::BASIC_LEGACY;
|
||||
|
||||
pub fn render_char(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
start_x: usize,
|
||||
start_y: usize,
|
||||
char: usize,
|
||||
font_size: usize,
|
||||
color: u32,
|
||||
) {
|
||||
if let Some(glyph) = BASIC_LEGACY.get(char) {
|
||||
for (row, row_bits) in glyph.iter().enumerate() {
|
||||
for bit in 0..8 {
|
||||
if (row_bits & (1 << bit)) != 0 {
|
||||
rectangle_filled(
|
||||
framebuffer,
|
||||
start_x + bit * font_size,
|
||||
start_y + row * font_size,
|
||||
font_size,
|
||||
font_size,
|
||||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_text(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
start_x: usize,
|
||||
start_y: usize,
|
||||
text: &str,
|
||||
font_size: usize,
|
||||
color: u32,
|
||||
margin_left: usize,
|
||||
) -> (usize, usize) {
|
||||
let mut x = start_x;
|
||||
let mut y = start_y;
|
||||
|
||||
for b in text.bytes() {
|
||||
if b == b'\n' {
|
||||
y += 12 * font_size;
|
||||
x = margin_left;
|
||||
continue;
|
||||
}
|
||||
|
||||
render_char(framebuffer, x, y, b as usize, font_size, color);
|
||||
x += 8 * font_size;
|
||||
}
|
||||
|
||||
(x, y)
|
||||
}
|
||||
|
|
@ -1,45 +1,53 @@
|
|||
use crate::syscall::{MAP_FRAMEBUFFER, syscall0};
|
||||
use crate::{
|
||||
io::window::Window,
|
||||
shm::{SHM_SLOT_SIZE, USER_SHM_BASE},
|
||||
};
|
||||
|
||||
pub const USER_FB_BASE: u64 = 0x0000_7F00_0000_0000;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct UserFrameBuffer {
|
||||
pub buf_virt: *mut u32,
|
||||
pub struct WindowFrameBuffer {
|
||||
pub ptr: *mut u32,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub pitch: usize,
|
||||
}
|
||||
|
||||
impl UserFrameBuffer {
|
||||
pub unsafe fn load_from_ptr(
|
||||
&mut self,
|
||||
src_ptr: *const u32,
|
||||
src_width: usize,
|
||||
src_height: usize,
|
||||
) {
|
||||
let _buf = unsafe { core::ptr::read_volatile(&self.buf_virt) };
|
||||
for dy in 0..self.height {
|
||||
let sy = dy * src_height / self.height;
|
||||
impl WindowFrameBuffer {
|
||||
pub fn from_window(window: &Window) -> Self {
|
||||
let ptr = (USER_SHM_BASE + window.shm_id * SHM_SLOT_SIZE) as *mut u32;
|
||||
WindowFrameBuffer {
|
||||
ptr,
|
||||
width: window.width,
|
||||
height: window.height,
|
||||
}
|
||||
}
|
||||
|
||||
for dx in 0..self.width {
|
||||
let sx = dx * src_width / self.width;
|
||||
#[inline(always)]
|
||||
pub fn put_pixel(&mut self, x: usize, y: usize, color: u32) {
|
||||
if x >= self.width || y >= self.height {
|
||||
return;
|
||||
}
|
||||
let idx = y * self.width + x;
|
||||
if idx >= self.width * self.height {
|
||||
return;
|
||||
}
|
||||
unsafe { self.ptr.add(idx).write(color) };
|
||||
}
|
||||
|
||||
let src_pixel = unsafe { *src_ptr.add(sy * src_width + sx) };
|
||||
#[inline(always)]
|
||||
pub fn fill_span(&mut self, x: usize, y: usize, len: usize, color: u32) {
|
||||
if y >= self.height || x >= self.width || len == 0 {
|
||||
return;
|
||||
}
|
||||
let len = core::cmp::min(len, self.width - x);
|
||||
let start = y * self.width + x;
|
||||
unsafe {
|
||||
let slice = core::slice::from_raw_parts_mut(self.ptr.add(start), len);
|
||||
slice.fill(color);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { *self.buf_virt.add(dy * self.pitch + dx) = src_pixel };
|
||||
}
|
||||
pub fn clear(&mut self, color: u32) {
|
||||
unsafe {
|
||||
let slice = core::slice::from_raw_parts_mut(self.ptr, self.width * self.height);
|
||||
slice.fill(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn map_framebuffer() {
|
||||
unsafe { syscall0(MAP_FRAMEBUFFER) };
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn draw_buffer(buffer: *const u32, width: u32, height: u32) -> i32 {
|
||||
let fb_ptr = USER_FB_BASE as *mut UserFrameBuffer;
|
||||
unsafe { (*fb_ptr).load_from_ptr(buffer, width as usize, height as usize) };
|
||||
|
||||
0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,7 @@
|
|||
pub mod font_render;
|
||||
pub mod framebuffer;
|
||||
pub mod primitives;
|
||||
|
||||
pub fn rgb(r: u8, g: u8, b: u8) -> u32 {
|
||||
((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||
}
|
||||
|
|
|
|||
185
src/graphics/primitives.rs
Normal file
185
src/graphics/primitives.rs
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
use crate::graphics::framebuffer::WindowFrameBuffer;
|
||||
|
||||
pub fn line(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
x0: usize,
|
||||
y0: usize,
|
||||
x1: usize,
|
||||
y1: usize,
|
||||
color: u32,
|
||||
) {
|
||||
if y0 == y1 {
|
||||
let (xa, xb) = if x0 <= x1 { (x0, x1) } else { (x1, x0) };
|
||||
framebuffer.fill_span(xa, y0, xb - xa + 1, color);
|
||||
return;
|
||||
}
|
||||
if x0 == x1 {
|
||||
let (ya, yb) = if y0 <= y1 { (y0, y1) } else { (y1, y0) };
|
||||
for yy in ya..=yb {
|
||||
framebuffer.put_pixel(x0, yy, color);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let mut x0 = x0 as isize;
|
||||
let mut y0 = y0 as isize;
|
||||
let x1 = x1 as isize;
|
||||
let y1 = y1 as isize;
|
||||
|
||||
let mut dx: isize = x1 - x0;
|
||||
let mut dy: isize = y1 - y0;
|
||||
|
||||
if dx < 0 {
|
||||
dx = -dx;
|
||||
}
|
||||
if dy < 0 {
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
let step_x: isize = if x0 < x1 { 1 } else { -1 };
|
||||
let step_y: isize = if y0 < y1 { 1 } else { -1 };
|
||||
|
||||
let mut error: isize = dx - dy;
|
||||
|
||||
loop {
|
||||
framebuffer.put_pixel(x0 as usize, y0 as usize, color);
|
||||
|
||||
let e2: isize = 2 * error;
|
||||
if e2 > -dy {
|
||||
error -= dy;
|
||||
x0 += step_x;
|
||||
}
|
||||
if e2 < dx {
|
||||
error += dx;
|
||||
y0 += step_y;
|
||||
}
|
||||
|
||||
if x0 == x1 && y0 == y1 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn triangle_outline(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
x1: usize,
|
||||
y1: usize,
|
||||
x2: usize,
|
||||
y2: usize,
|
||||
x3: usize,
|
||||
y3: usize,
|
||||
color: u32,
|
||||
) {
|
||||
line(framebuffer, x1, y1, x2, y2, color);
|
||||
line(framebuffer, x1, y1, x3, y3, color);
|
||||
line(framebuffer, x2, y2, x3, y3, color);
|
||||
}
|
||||
|
||||
pub fn circle_outline(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
cx: usize,
|
||||
cy: usize,
|
||||
radius: usize,
|
||||
color: u32,
|
||||
) {
|
||||
let mut x = radius as isize;
|
||||
let mut y: isize = 0;
|
||||
let mut d = 1 - x;
|
||||
let cx = cx as isize;
|
||||
let cy = cy as isize;
|
||||
|
||||
#[inline(always)]
|
||||
fn plot_points(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
cx: isize,
|
||||
cy: isize,
|
||||
x: isize,
|
||||
y: isize,
|
||||
color: u32,
|
||||
) {
|
||||
framebuffer.put_pixel((cx + x) as usize, (cy + y) as usize, color);
|
||||
framebuffer.put_pixel((cx + y) as usize, (cy + x) as usize, color);
|
||||
framebuffer.put_pixel((cx - y) as usize, (cy + x) as usize, color);
|
||||
framebuffer.put_pixel((cx - x) as usize, (cy + y) as usize, color);
|
||||
framebuffer.put_pixel((cx - x) as usize, (cy - y) as usize, color);
|
||||
framebuffer.put_pixel((cx - y) as usize, (cy - x) as usize, color);
|
||||
framebuffer.put_pixel((cx + y) as usize, (cy - x) as usize, color);
|
||||
framebuffer.put_pixel((cx + x) as usize, (cy - y) as usize, color);
|
||||
}
|
||||
|
||||
while y <= x {
|
||||
plot_points(framebuffer, cx, cy, x, y, color);
|
||||
y += 1;
|
||||
|
||||
if d <= 0 {
|
||||
d += 2 * y + 1;
|
||||
} else {
|
||||
x -= 1;
|
||||
d += 2 * (y - x) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn circle_filled(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
x0: usize,
|
||||
y0: usize,
|
||||
radius: usize,
|
||||
color: u32,
|
||||
) {
|
||||
let mut x = radius as isize;
|
||||
let mut y: isize = 0;
|
||||
let mut x_change: isize = 1 - (radius as isize * 2);
|
||||
let mut y_change: isize = 0;
|
||||
let mut radius_error: isize = 0;
|
||||
|
||||
while x >= y {
|
||||
let mut i = x0 as isize - x;
|
||||
while i <= x0 as isize + x {
|
||||
framebuffer.put_pixel(i as usize, (y0 as isize + y) as usize, color);
|
||||
framebuffer.put_pixel(i as usize, (y0 as isize - y) as usize, color);
|
||||
i += 1;
|
||||
}
|
||||
let mut i = x0 as isize - y;
|
||||
while i <= x0 as isize + y {
|
||||
framebuffer.put_pixel(i as usize, (y0 as isize + x) as usize, color);
|
||||
framebuffer.put_pixel(i as usize, (y0 as isize - x) as usize, color);
|
||||
i += 1;
|
||||
}
|
||||
y += 1;
|
||||
radius_error += y_change;
|
||||
y_change += 2;
|
||||
if (radius_error * 2) + x_change > 0 {
|
||||
x -= 1;
|
||||
radius_error += x_change;
|
||||
x_change += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rectangle_filled(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
color: u32,
|
||||
) {
|
||||
for yy in y..y + height {
|
||||
framebuffer.fill_span(x, yy, width, color);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rectangle_outline(
|
||||
framebuffer: &mut WindowFrameBuffer,
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
color: u32,
|
||||
) {
|
||||
line(framebuffer, x, y, x + width, y, color); // bottomleft -> bottomright
|
||||
line(framebuffer, x, y + height, x + width, y + height, color); // topleft -> topright
|
||||
line(framebuffer, x, y, x, y + height, color); // bottomleft -> topleft
|
||||
line(framebuffer, x + width, y, x + width, y + height, color); // bottomright -> topright
|
||||
}
|
||||
138
src/io/ipc.rs
Normal file
138
src/io/ipc.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
use core::ffi::c_char;
|
||||
|
||||
use alloc::{ffi::CString, string::String};
|
||||
use bitflags::bitflags;
|
||||
|
||||
use crate::{
|
||||
mem::malloc,
|
||||
syscall::{IPC_CREATE, IPC_MANAGE, IPC_READ, IPC_WRITE, syscall2, syscall3},
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug)]
|
||||
pub struct Permissions: u32 {
|
||||
const READ = 1 << 0;
|
||||
const WRITE = 1 << 1;
|
||||
const MANAGE = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn create_port(name_ptr: *const u8, default_permissions: u32) -> isize {
|
||||
if name_ptr.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return unsafe { syscall2(IPC_CREATE, name_ptr as isize, default_permissions as isize) };
|
||||
}
|
||||
|
||||
pub fn create_port_rust(name: String, default_permissions: Permissions) -> bool {
|
||||
let name_cstring_opt = CString::new(name);
|
||||
if let Ok(name_cstring) = name_cstring_opt {
|
||||
match create_port(
|
||||
name_cstring.as_ptr() as *const u8,
|
||||
default_permissions.bits(),
|
||||
) {
|
||||
-1 => false,
|
||||
_ => true,
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn read_port(name_ptr: *const u8, output_ptr: *mut u8, from: i64) -> isize {
|
||||
if name_ptr.is_null() || output_ptr.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return unsafe {
|
||||
syscall3(
|
||||
IPC_READ,
|
||||
name_ptr as isize,
|
||||
output_ptr as isize,
|
||||
from as isize,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn read_port_rust(name: String, from: i64) -> Option<(u64, String)> {
|
||||
let name_cstring_opt = CString::new(name);
|
||||
if let Ok(name_cstring) = name_cstring_opt {
|
||||
let output_ptr = malloc(256);
|
||||
return match read_port(name_cstring.as_ptr() as *const u8, output_ptr, from) {
|
||||
-1 => None,
|
||||
sender if sender > 0 => {
|
||||
match unsafe { CString::from_raw(output_ptr as *mut c_char) }.into_string() {
|
||||
Ok(rust_string) => Some((sender as u64, rust_string)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn write_port(name_ptr: *const u8, message: *const u8) -> isize {
|
||||
if name_ptr.is_null() || message.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return unsafe { syscall2(IPC_WRITE, name_ptr as isize, message as isize) };
|
||||
}
|
||||
|
||||
pub fn write_port_rust(name: String, message: String) -> bool {
|
||||
let name_cstring_opt = CString::new(name);
|
||||
if let Ok(name_cstring) = name_cstring_opt {
|
||||
let message_cstring_opt = CString::new(message);
|
||||
if let Ok(message_cstring) = message_cstring_opt {
|
||||
match write_port(
|
||||
name_cstring.as_ptr() as *const u8,
|
||||
message_cstring.as_ptr() as *const u8,
|
||||
) {
|
||||
-1 => false,
|
||||
_ => true,
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn manage_port(name_ptr: *const u8, pid_to_set: u64, new_permissions: u32) -> isize {
|
||||
if name_ptr.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return unsafe {
|
||||
syscall3(
|
||||
IPC_MANAGE,
|
||||
name_ptr as isize,
|
||||
pid_to_set as isize,
|
||||
new_permissions as isize,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn manage_port_rust(name: String, pid_to_set: u64, new_permissions: Permissions) -> bool {
|
||||
let name_cstring_opt = CString::new(name);
|
||||
if let Ok(name_cstring) = name_cstring_opt {
|
||||
match manage_port(
|
||||
name_cstring.as_ptr() as *const u8,
|
||||
pid_to_set,
|
||||
new_permissions.bits(),
|
||||
) {
|
||||
-1 => false,
|
||||
_ => true,
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
5
src/io/mod.rs
Normal file
5
src/io/mod.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
pub mod file;
|
||||
pub mod ipc;
|
||||
pub mod keyboard;
|
||||
pub mod time;
|
||||
pub mod window;
|
||||
118
src/io/window.rs
Normal file
118
src/io/window.rs
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
getpid,
|
||||
io::{
|
||||
ipc::{read_port_rust, write_port_rust},
|
||||
time::sleep_ms,
|
||||
},
|
||||
println,
|
||||
shm::{SHM_SLOT_SIZE, USER_SHM_BASE, shm_open_rust},
|
||||
};
|
||||
|
||||
pub static mut PRIV_IPC_NAME: Option<String> = None;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Window {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
pub shm_id: u64,
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn request_window() -> Window {
|
||||
write_port_rust("window_manager".to_string(), "request_priv_ipc".to_string());
|
||||
let pid = getpid();
|
||||
let priv_ipc_name = loop {
|
||||
if let Some((sender, msg)) = read_port_rust("window_manager".to_string(), -1) {
|
||||
println!("{}: {}", sender, msg);
|
||||
|
||||
if msg.starts_with("ack_request_priv_ipc") {
|
||||
let parts = msg.split_whitespace().collect::<Vec<&str>>();
|
||||
|
||||
println!("{}", parts[1].trim().parse::<isize>().unwrap_or(-1) == pid);
|
||||
|
||||
if parts[1].trim().parse::<isize>().unwrap_or(-1) == pid {
|
||||
break parts[2].to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { sleep_ms(1) };
|
||||
};
|
||||
|
||||
println!("Private IPC Name: {}", priv_ipc_name);
|
||||
|
||||
unsafe {
|
||||
PRIV_IPC_NAME = Some(priv_ipc_name.clone());
|
||||
}
|
||||
|
||||
write_port_rust(priv_ipc_name.clone(), "request_window_buf".to_string());
|
||||
|
||||
let (width, height, x, y, shm_name, shm_id) = loop {
|
||||
if let Some((_, msg)) = read_port_rust(priv_ipc_name.clone(), -1) {
|
||||
if msg.starts_with("ack_request_window_buf") {
|
||||
let parts = msg.split_whitespace().collect::<Vec<&str>>();
|
||||
let width = parts[1].parse::<usize>().unwrap_or(0);
|
||||
let height = parts[2].parse::<usize>().unwrap_or(0);
|
||||
let x = parts[3].parse::<usize>().unwrap_or(0);
|
||||
let y = parts[4].parse::<usize>().unwrap_or(0);
|
||||
let shm_id = parts[6].parse::<u64>().unwrap_or(0);
|
||||
break (width, height, x, y, parts[5].to_string(), shm_id);
|
||||
}
|
||||
};
|
||||
unsafe { sleep_ms(1) };
|
||||
};
|
||||
|
||||
shm_open_rust(
|
||||
shm_name.clone(),
|
||||
(width * height * size_of::<u32>() + 1) as u64,
|
||||
);
|
||||
|
||||
Window {
|
||||
width,
|
||||
height,
|
||||
x,
|
||||
y,
|
||||
shm_id,
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn draw_buffer_to_window(
|
||||
buffer: *const u32,
|
||||
shm_id: u64,
|
||||
src_width: usize,
|
||||
src_height: usize,
|
||||
window_width: usize,
|
||||
window_height: usize,
|
||||
) -> i32 {
|
||||
let ptr = (USER_SHM_BASE + shm_id * SHM_SLOT_SIZE) as *mut u32;
|
||||
|
||||
for wy in 0..window_height {
|
||||
for wx in 0..window_width {
|
||||
let src_x = wx * src_width / window_width;
|
||||
let src_y = wy * src_height / window_height;
|
||||
|
||||
let src_pixel = unsafe { *buffer.add(src_y * src_width + src_x) };
|
||||
unsafe { *ptr.add(wy * window_width + wx) = src_pixel };
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
pub fn set_dirty() {
|
||||
write_port_rust(
|
||||
#[allow(static_mut_refs)]
|
||||
unsafe {
|
||||
PRIV_IPC_NAME.as_ref().unwrap().clone()
|
||||
},
|
||||
"set_dirty".to_string(),
|
||||
);
|
||||
}
|
||||
24
src/lib.rs
24
src/lib.rs
|
|
@ -12,19 +12,17 @@ use core::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
graphics::framebuffer::map_framebuffer,
|
||||
heap::init_heap,
|
||||
mem::{malloc, memcpy},
|
||||
syscall::{EXIT, FRAMEBUFFER_SWAP, WRITE, syscall0, syscall3},
|
||||
syscall::{EXIT, GETPID, WRITE, syscall0, syscall3},
|
||||
};
|
||||
|
||||
pub mod file;
|
||||
pub mod graphics;
|
||||
pub mod heap;
|
||||
pub mod keyboard;
|
||||
pub mod io;
|
||||
pub mod mem;
|
||||
pub mod shm;
|
||||
pub mod syscall;
|
||||
pub mod time;
|
||||
pub mod util;
|
||||
|
||||
static mut ERRNO: core::ffi::c_int = 0;
|
||||
|
|
@ -389,9 +387,6 @@ pub extern "C" fn _start() -> ! {
|
|||
exit(-1);
|
||||
};
|
||||
|
||||
print("Mapping Framebuffer...\n");
|
||||
unsafe { map_framebuffer() };
|
||||
|
||||
let code = unsafe { main(0, null()) };
|
||||
|
||||
exit(code as i32);
|
||||
|
|
@ -540,13 +535,6 @@ pub unsafe extern "C" fn strncmp(str_1: *const u8, str_2: *const u8, n: usize) -
|
|||
compare_str(str_1, str_2, false, n)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn framebuffer_swap() -> i32 {
|
||||
unsafe {
|
||||
return syscall0(FRAMEBUFFER_SWAP) as i32;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn strncpy(dest: *mut u8, source: *const u8, n: usize) -> *mut u8 {
|
||||
let mut i = 0usize;
|
||||
|
|
@ -676,6 +664,12 @@ pub unsafe extern "C" fn tolower(char: i32) -> i32 {
|
|||
pub extern "C" fn system(cmd: *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn getpid() -> isize {
|
||||
unsafe { syscall0(GETPID) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn __ctype_toupper_loc() -> *const *const i32 {
|
||||
unsafe {
|
||||
|
|
|
|||
24
src/shm.rs
Normal file
24
src/shm.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use alloc::{ffi::CString, string::String};
|
||||
|
||||
use crate::syscall::{SHM_OPEN, syscall2};
|
||||
|
||||
pub const USER_SHM_BASE: u64 = 0x0000_7000_0000_0000;
|
||||
pub const SHM_SLOT_SIZE: u64 = 64 * 1024 * 1024;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn shm_open(name_ptr: *const u8, size: u64) -> isize {
|
||||
if name_ptr.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return unsafe { syscall2(SHM_OPEN, name_ptr as isize, size as isize) };
|
||||
}
|
||||
|
||||
pub fn shm_open_rust(name: String, size: u64) -> isize {
|
||||
let name_cstring_opt = CString::new(name);
|
||||
if let Ok(name_cstring) = name_cstring_opt {
|
||||
return shm_open(name_cstring.as_ptr() as *const u8, size);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,11 @@ pub const CLOCK_GETTIME: usize = 228;
|
|||
pub const EXIT_GROUP: usize = 231;
|
||||
pub const KBD_READ: usize = 666;
|
||||
pub const SLEEP: usize = 909090; // zzz haha
|
||||
pub const IPC_CREATE: usize = 500;
|
||||
pub const IPC_READ: usize = 501;
|
||||
pub const IPC_WRITE: usize = 502;
|
||||
pub const IPC_MANAGE: usize = 503;
|
||||
pub const SHM_OPEN: usize = 600;
|
||||
pub const MAP_FRAMEBUFFER: usize = 5555;
|
||||
pub const FRAMEBUFFER_SWAP: usize = 6666;
|
||||
|
||||
|
|
|
|||
35
src/util.rs
35
src/util.rs
|
|
@ -1,15 +1,46 @@
|
|||
use spin::{MutexGuard, mutex::Mutex};
|
||||
|
||||
pub struct U64Buf {
|
||||
buf: [u8; 20],
|
||||
start: usize,
|
||||
}
|
||||
|
||||
impl U64Buf {
|
||||
pub fn new(n: u64) -> Self {
|
||||
let mut buf = [0u8; 20];
|
||||
let mut pos = 20;
|
||||
let mut val = n;
|
||||
|
||||
if val == 0 {
|
||||
buf[19] = b'0';
|
||||
return Self { buf, start: 19 };
|
||||
}
|
||||
|
||||
while val > 0 {
|
||||
pos -= 1;
|
||||
buf[pos] = b'0' + (val % 10) as u8;
|
||||
val /= 10;
|
||||
}
|
||||
|
||||
Self { buf, start: pos }
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
unsafe { core::str::from_utf8_unchecked(&self.buf[self.start..]) }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn align_down(addr: usize, align: usize) -> usize {
|
||||
pub fn align_down(addr: usize, align: usize) -> usize {
|
||||
assert!(align.is_power_of_two(), "`align` must be a power of two");
|
||||
addr & !(align - 1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn align_up(addr: usize, align: usize) -> usize {
|
||||
pub fn align_up(addr: usize, align: usize) -> usize {
|
||||
assert!(align.is_power_of_two(), "`align` must be a power of two");
|
||||
let align_mask = align - 1;
|
||||
|
||||
if addr & align_mask == 0 {
|
||||
addr
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue