d2f1af9ca7
This unifies the driver interface handling between graphics drivers and makes it easier to change all graphics drivers in lockstep when adding new features.
130 lines
3.9 KiB
Rust
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,
|
|
}],
|
|
);
|
|
}
|
|
}
|