Merge branch 'graphics_improvements' into 'master'

Various graphics subsystem improvements

See merge request redox-os/drivers!241
This commit is contained in:
Jeremy Soller
2025-03-01 20:41:40 +00:00
10 changed files with 163 additions and 177 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
log = "0.4"
redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" }
redox_syscall = "0.5"
redox_syscall = { version = "0.5", features = ["std"] }
libredox = "0.1.3"
common = { path = "../../common" }
-5
View File
@@ -96,11 +96,6 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
}
}
VtEventKind::Deactivate => {
log::info!("deactivate {}", vt_event.vt);
// nothing to do :)
}
VtEventKind::Resize => {
log::warn!("driver-graphics: resize is not implemented yet")
}
+29 -13
View File
@@ -41,18 +41,26 @@ enum DisplayCommand {
pub struct Display {
cmd_tx: Sender<DisplayCommand>,
pub map: Arc<Mutex<DisplayMap>>,
pub map: Arc<Mutex<Option<DisplayMap>>>,
}
impl Display {
pub fn open_first_vt() -> io::Result<Self> {
let input_handle = ConsumerHandle::for_vt(1)?;
let display_handle = LegacyGraphicsHandle::from_file(input_handle.open_display()?)?;
let map = Arc::new(Mutex::new(
display_fd_map(display_handle).unwrap_or_else(|e| panic!("failed to map display: {e}")),
));
let map = match input_handle.open_display() {
Ok(display) => {
let display_handle = LegacyGraphicsHandle::from_file(display)?;
Arc::new(Mutex::new(Some(
display_fd_map(display_handle)
.unwrap_or_else(|e| panic!("failed to map display: {e}")),
)))
}
Err(err) => {
println!("fbbootlogd: No display present yet: {err}");
Arc::new(Mutex::new(None))
}
};
let map_clone = map.clone();
std::thread::spawn(move || {
@@ -68,7 +76,7 @@ impl Display {
Ok(Self { cmd_tx, map })
}
fn handle_input_events(map: Arc<Mutex<DisplayMap>>, input_handle: ConsumerHandle) {
fn handle_input_events(map: Arc<Mutex<Option<DisplayMap>>>, input_handle: ConsumerHandle) {
let event_queue = EventQueue::new().expect("fbbootlogd: failed to create event queue");
user_data! {
@@ -93,13 +101,17 @@ impl Display {
Err(err) if err.errno() == ESTALE => {
eprintln!("fbbootlogd: handoff requested");
let new_display_handle =
LegacyGraphicsHandle::from_file(input_handle.open_display().unwrap())
.unwrap();
let new_display_handle = match input_handle.open_display() {
Ok(display) => LegacyGraphicsHandle::from_file(display).unwrap(),
Err(err) => {
println!("fbbootlogd: No display present yet: {err}");
continue;
}
};
match display_fd_map(new_display_handle) {
Ok(ok) => {
*map.lock().unwrap() = ok;
*map.lock().unwrap() = Some(ok);
eprintln!("fbbootlogd: handoff finished");
}
@@ -117,13 +129,17 @@ impl Display {
}
}
fn handle_sync_rect(map: Arc<Mutex<DisplayMap>>, cmd_rx: Receiver<DisplayCommand>) {
fn handle_sync_rect(map: Arc<Mutex<Option<DisplayMap>>>, cmd_rx: Receiver<DisplayCommand>) {
while let Ok(cmd) = cmd_rx.recv() {
match cmd {
DisplayCommand::SyncRects(sync_rects) => {
// We may not hold this lock across the write call to avoid deadlocking if the
// graphics driver tries to write to the bootlog.
let display_handle = map.lock().unwrap().display_handle.clone();
let display_handle = if let Some(map) = &*map.lock().unwrap() {
map.display_handle.clone()
} else {
continue;
};
display_handle.sync_rects(&sync_rects).unwrap();
}
}
+14 -12
View File
@@ -55,19 +55,21 @@ impl Scheme for FbbootlogScheme {
}
fn write(&mut self, _id: usize, buf: &[u8], _offset: u64, _fcntl_flags: u32) -> Result<usize> {
let mut map = self.display.map.lock().unwrap();
let damage = self.text_screen.write(
&mut console_draw::DisplayMap {
offscreen: map.inner.ptr_mut(),
width: map.inner.width(),
height: map.inner.height(),
},
buf,
&mut VecDeque::new(),
);
drop(map);
let mut map_guard = self.display.map.lock().unwrap();
if let Some(map) = &mut *map_guard {
let damage = self.text_screen.write(
&mut console_draw::DisplayMap {
offscreen: map.inner.ptr_mut(),
width: map.inner.width(),
height: map.inner.height(),
},
buf,
&mut VecDeque::new(),
);
drop(map_guard);
self.display.sync_rects(damage);
self.display.sync_rects(damage);
}
Ok(buf.len())
}
+6 -1
View File
@@ -13,7 +13,6 @@ use crate::scheme::FbAdapter;
mod framebuffer;
mod scheme;
mod screen;
fn main() {
let mut spec = Vec::new();
@@ -22,6 +21,11 @@ fn main() {
spec.push(());
}
if env::var("FRAMEBUFFER_WIDTH").is_err() {
println!("vesad: No boot framebuffer");
return;
}
let width = usize::from_str_radix(
&env::var("FRAMEBUFFER_WIDTH").expect("FRAMEBUFFER_WIDTH not set"),
16,
@@ -49,6 +53,7 @@ fn main() {
);
if phys == 0 {
println!("vesad: Boot framebuffer at address 0");
return;
}
+95 -6
View File
@@ -1,7 +1,12 @@
use driver_graphics::GraphicsAdapter;
use graphics_ipc::legacy::Damage;
use std::alloc::{self, Layout};
use std::convert::TryInto;
use std::ptr::{self, NonNull};
use crate::{framebuffer::FrameBuffer, screen::GraphicScreen};
use driver_graphics::{GraphicsAdapter, Resource};
use graphics_ipc::legacy::Damage;
use syscall::PAGE_SIZE;
use crate::framebuffer::FrameBuffer;
pub struct FbAdapter {
pub framebuffers: Vec<FrameBuffer>,
@@ -26,11 +31,11 @@ impl GraphicsAdapter for FbAdapter {
}
fn map_resource(&mut self, resource: &Self::Resource) -> *mut u8 {
resource.ptr()
resource.ptr.as_ptr().cast::<u8>()
}
fn set_scanout(&mut self, display_id: usize, resource: &Self::Resource) {
resource.redraw(&mut self.framebuffers[display_id]);
self.flush_resource(display_id, resource, None);
}
fn flush_resource(
@@ -42,7 +47,91 @@ impl GraphicsAdapter for FbAdapter {
if let Some(damage) = damage {
resource.sync(&mut self.framebuffers[display_id], damage)
} else {
resource.redraw(&mut self.framebuffers[display_id])
let framebuffer: &mut FrameBuffer = &mut self.framebuffers[display_id];
let width = resource.width.try_into().unwrap();
let height = resource.height.try_into().unwrap();
resource.sync(
framebuffer,
&[Damage {
x: 0,
y: 0,
width,
height,
}],
);
}
}
}
pub struct GraphicScreen {
width: usize,
height: usize,
ptr: NonNull<[u32]>,
}
impl GraphicScreen {
fn new(width: usize, height: usize) -> GraphicScreen {
let len = width * height;
let layout = Self::layout(len);
let ptr = unsafe { alloc::alloc_zeroed(layout) };
let ptr = ptr::slice_from_raw_parts_mut(ptr.cast(), len);
let ptr = NonNull::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout));
GraphicScreen { width, height, ptr }
}
#[inline]
fn layout(len: usize) -> Layout {
// optimizes to an integer mul
Layout::array::<u32>(len)
.unwrap()
.align_to(PAGE_SIZE)
.unwrap()
}
}
impl Drop for GraphicScreen {
fn drop(&mut self) {
let layout = Self::layout(self.ptr.len());
unsafe { alloc::dealloc(self.ptr.as_ptr().cast(), layout) };
}
}
impl Resource for GraphicScreen {
fn width(&self) -> u32 {
self.width as u32
}
fn height(&self) -> u32 {
self.height as u32
}
}
impl GraphicScreen {
fn sync(&self, framebuffer: &mut FrameBuffer, sync_rects: &[Damage]) {
for sync_rect in sync_rects {
let sync_rect = sync_rect.clip(
self.width.try_into().unwrap(),
self.height.try_into().unwrap(),
);
let start_x: usize = sync_rect.x.try_into().unwrap_or(0);
let start_y: usize = sync_rect.y.try_into().unwrap_or(0);
let w: usize = sync_rect.width.try_into().unwrap_or(0);
let h: usize = sync_rect.height.try_into().unwrap_or(0);
let offscreen_ptr = self.ptr.as_ptr() as *mut u32;
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
for row in start_y..start_y + h {
unsafe {
ptr::copy(
offscreen_ptr.add(row * self.width + start_x),
onscreen_ptr.add(row * framebuffer.stride + start_x),
w,
);
}
}
}
}
}
-107
View File
@@ -1,107 +0,0 @@
use std::alloc::{self, Layout};
use std::convert::TryInto;
use std::ptr::{self, NonNull};
use driver_graphics::Resource;
use graphics_ipc::legacy::Damage;
use syscall::PAGE_SIZE;
use crate::framebuffer::FrameBuffer;
pub struct GraphicScreen {
pub width: usize,
pub height: usize,
ptr: NonNull<[u32]>,
}
impl GraphicScreen {
pub fn new(width: usize, height: usize) -> GraphicScreen {
let len = width * height;
let layout = Self::layout(len);
let ptr = unsafe { alloc::alloc_zeroed(layout) };
let ptr = ptr::slice_from_raw_parts_mut(ptr.cast(), len);
let ptr = NonNull::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout));
GraphicScreen { width, height, ptr }
}
#[inline]
fn layout(len: usize) -> Layout {
// optimizes to an integer mul
Layout::array::<u32>(len)
.unwrap()
.align_to(PAGE_SIZE)
.unwrap()
}
}
impl Drop for GraphicScreen {
fn drop(&mut self) {
let layout = Self::layout(self.ptr.len());
unsafe { alloc::dealloc(self.ptr.as_ptr().cast(), layout) };
}
}
impl Resource for GraphicScreen {
fn width(&self) -> u32 {
self.width as u32
}
fn height(&self) -> u32 {
self.height as u32
}
}
impl GraphicScreen {
pub fn ptr(&self) -> *mut u8 {
self.ptr.as_ptr().cast::<u8>()
}
pub fn sync(&self, framebuffer: &mut FrameBuffer, sync_rects: &[Damage]) {
for sync_rect in sync_rects {
let sync_rect = sync_rect.clip(
self.width.try_into().unwrap(),
self.height.try_into().unwrap(),
);
let start_x: usize = sync_rect.x.try_into().unwrap_or(0);
let start_y: usize = sync_rect.y.try_into().unwrap_or(0);
let w: usize = sync_rect.width.try_into().unwrap_or(0);
let h: usize = sync_rect.height.try_into().unwrap_or(0);
let end_y = start_y + h;
let row_pixel_count = w;
let mut offscreen_ptr = self.ptr.as_ptr() as *mut u32;
let mut onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
unsafe {
offscreen_ptr = offscreen_ptr.add(start_y * self.width + start_x);
onscreen_ptr = onscreen_ptr.add(start_y * framebuffer.stride + start_x);
let mut rows = end_y - start_y;
while rows > 0 {
ptr::copy(offscreen_ptr, onscreen_ptr, row_pixel_count);
offscreen_ptr = offscreen_ptr.add(self.width);
onscreen_ptr = onscreen_ptr.add(framebuffer.stride);
rows -= 1;
}
}
}
}
pub fn redraw(&self, framebuffer: &mut FrameBuffer) {
let width = self.width.try_into().unwrap();
let height = self.height.try_into().unwrap();
self.sync(
framebuffer,
&[Damage {
x: 0,
y: 0,
width,
height,
}],
);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ authors = ["Anhad Singh <andypython@protonmail.com>"]
anyhow = "1.0.71"
log = "0.4.19"
redox-daemon = "0.1.2"
redox_syscall = "0.5"
redox_syscall = { version = "0.5", features = ["std"] }
orbclient = "0.3.27"
libredox = "0.1.3"
+1 -3
View File
@@ -32,8 +32,7 @@ impl ConsumerHandle {
pub fn open_display(&self) -> Result<File, Error> {
let mut buffer = [0; 1024];
let fd = self.0.as_raw_fd();
let written = libredox::call::fpath(fd as usize, &mut buffer)
.expect("init: failed to get the path to the display device");
let written = libredox::call::fpath(fd as usize, &mut buffer)?;
assert!(written <= buffer.len());
@@ -119,7 +118,6 @@ impl ControlHandle {
#[repr(usize)]
pub enum VtEventKind {
Activate,
Deactivate,
Resize,
}
+16 -28
View File
@@ -120,19 +120,6 @@ impl InputScheme {
device,
..
} => {
if let Some(active_vt) = self.active_vt {
if &self.vts[&active_vt].display == &*device {
pending.push(VtEvent {
kind: VtEventKind::Deactivate,
vt: self.active_vt.unwrap(),
width: 0,
height: 0,
stride: 0,
});
*notified = false;
}
}
if &self.vts[&new_active].display == &*device {
pending.push(VtEvent {
kind: VtEventKind::Activate,
@@ -420,23 +407,24 @@ impl Scheme for InputScheme {
let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?;
assert!(handle.is_producer());
let active_vt = self.active_vt.unwrap();
for handle in self.handles.values_mut() {
match handle {
Handle::Consumer {
pending,
notified,
vt,
..
} => {
if *vt != active_vt {
continue;
}
if let Some(active_vt) = self.active_vt {
for handle in self.handles.values_mut() {
match handle {
Handle::Consumer {
pending,
notified,
vt,
..
} => {
if *vt != active_vt {
continue;
}
pending.extend_from_slice(buf);
*notified = false;
pending.extend_from_slice(buf);
*notified = false;
}
_ => continue,
}
_ => continue,
}
}