perf(display): present copies window rows as-is (scanout R8G8B8X8 = window byte order, Host hands out row bytes, Framebuffer::write_rgba_row); Window copy_from/copy_to one fenced memcpy; full present ~65ms -> ~3ms
This commit is contained in:
@@ -3,13 +3,10 @@
|
||||
//! the display's memory has a fixed ceiling whatever apps do.
|
||||
|
||||
use libkos::syscall;
|
||||
use libkos::window::Window;
|
||||
use types::address::{ByteOffset, VirtualAddress};
|
||||
use types::address::VirtualAddress;
|
||||
use types::badge::Badge;
|
||||
use types::bounded::{CapSlot, PageCount};
|
||||
use types::display::Color;
|
||||
use types::display::window::PIXEL_BYTES;
|
||||
use types::mapping::PagePerms;
|
||||
use types::permission::{Permission, PermissionSet};
|
||||
|
||||
use crate::server::Host;
|
||||
@@ -26,12 +23,13 @@ pub struct KernelHost {
|
||||
/// from.
|
||||
ep: CapSlot,
|
||||
input: Option<CapSlot>,
|
||||
buffers: [Option<(CapSlot, Window)>; MAX_WINDOWS],
|
||||
/// Each slot's region and its pixels, mapped here as plain memory.
|
||||
buffers: [Option<(CapSlot, &'static mut [u8])>; MAX_WINDOWS],
|
||||
}
|
||||
|
||||
impl KernelHost {
|
||||
pub fn new(ep: CapSlot, input: Option<CapSlot>) -> Self {
|
||||
Self { ep, input, buffers: [None; MAX_WINDOWS] }
|
||||
Self { ep, input, buffers: [const { None }; MAX_WINDOWS] }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +41,8 @@ impl Host for KernelHost {
|
||||
let pages = PageCount::new(u16::try_from(bytes.div_ceil(PAGE)).ok()?)?;
|
||||
let region = syscall::create_region(pages).ok()?;
|
||||
let va = VirtualAddress::from_raw(BUFFERS_VA + index * BUFFER_SPAN);
|
||||
match libkos::window::map(region, va, PagePerms::ReadWrite) {
|
||||
Ok(window) => *slot = Some((region, window)),
|
||||
match libkos::window::map_buffer(region, va) {
|
||||
Ok(pixels) => *slot = Some((region, pixels)),
|
||||
Err(_) => {
|
||||
syscall::drop_cap(region);
|
||||
return None;
|
||||
@@ -55,20 +53,16 @@ impl Host for KernelHost {
|
||||
}
|
||||
|
||||
fn blank(&mut self, index: usize) {
|
||||
if let Some((_, window)) = self.buffers.get(index).and_then(Option::as_ref) {
|
||||
window.fill_u32(ByteOffset::ZERO, window.len() / PIXEL_BYTES, 0);
|
||||
if let Some((_, pixels)) = self.buffers.get_mut(index).and_then(Option::as_mut) {
|
||||
pixels.fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
fn read(&self, index: usize, from: usize, out: &mut [Color]) {
|
||||
let Some((_, window)) = self.buffers.get(index).and_then(Option::as_ref) else { return };
|
||||
for (i, px) in out.iter_mut().enumerate() {
|
||||
let at = (from + i) * PIXEL_BYTES;
|
||||
if at + PIXEL_BYTES > window.len() {
|
||||
return;
|
||||
}
|
||||
*px = Color::from_rgba(window.read::<u32>(ByteOffset::new(at)).to_le_bytes());
|
||||
}
|
||||
fn pixels(&self, index: usize, from: usize, count: usize) -> &[u8] {
|
||||
let Some((_, pixels)) = self.buffers.get(index).and_then(Option::as_ref) else { return &[] };
|
||||
let start = (from * PIXEL_BYTES).min(pixels.len());
|
||||
let end = from.saturating_add(count).saturating_mul(PIXEL_BYTES).min(pixels.len());
|
||||
&pixels[start..end]
|
||||
}
|
||||
|
||||
fn reclaim(&mut self, index: usize) {
|
||||
|
||||
Reference in New Issue
Block a user