Files
RedBear-OS/graphics/vesad/src/screen.rs
T
bjorn3 d2f1af9ca7 Add driver-graphics crate
This unifies the driver interface handling between graphics drivers and
makes it easier to change all graphics drivers in lockstep when adding
new features.
2024-12-27 12:47:43 +01:00

130 lines
3.9 KiB
Rust

use std::convert::TryInto;
use std::{cmp, ptr};
use driver_graphics::Resource;
use inputd::Damage;
use crate::display::OffscreenBuffer;
use crate::framebuffer::FrameBuffer;
pub struct GraphicScreen {
pub width: usize,
pub height: usize,
pub offscreen: OffscreenBuffer,
}
impl GraphicScreen {
pub fn new(width: usize, height: usize) -> GraphicScreen {
GraphicScreen {
width,
height,
offscreen: OffscreenBuffer::new(width * height),
}
}
}
impl Resource for GraphicScreen {
fn width(&self) -> u32 {
self.width as u32
}
fn height(&self) -> u32 {
self.height as u32
}
}
impl GraphicScreen {
pub fn resize(&mut self, width: usize, height: usize) {
//TODO: Fix issue with mapped screens
if width != self.width || height != self.height {
println!("Resize display to {}, {}", width, height);
let size = width * height;
let mut offscreen = OffscreenBuffer::new(size);
let mut old_ptr = self.offscreen.as_ptr();
let mut new_ptr = offscreen.as_mut_ptr();
for _y in 0..cmp::min(height, self.height) {
unsafe {
ptr::copy(old_ptr, new_ptr, cmp::min(width, self.width));
if width > self.width {
ptr::write_bytes(
new_ptr.offset(self.width as isize),
0,
width - self.width,
);
}
old_ptr = old_ptr.offset(self.width as isize);
new_ptr = new_ptr.offset(width as isize);
}
}
if height > self.height {
for _y in self.height..height {
unsafe {
ptr::write_bytes(new_ptr, 0, width);
new_ptr = new_ptr.offset(width as isize);
}
}
}
self.width = width;
self.height = height;
self.offscreen = offscreen;
} else {
println!("Display is already {}, {}", width, height);
};
}
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.offscreen.as_ptr();
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,
}],
);
}
}