use super::{Framebuffer, Error, BlankingLevel};
use memmap::MmapMut;
#[derive(Debug)]
enum State {
DrawToFirst,
DrawToSecond,
}
impl State {
fn flip(&mut self) -> &Self {
*self = match self {
State::DrawToFirst => State::DrawToSecond,
State::DrawToSecond => State::DrawToFirst,
};
self
}
}
pub struct Buffer {
pub width: u32,
pub height: u32,
fb: Framebuffer,
map: MmapMut,
state: State,
}
impl Buffer {
pub fn new(mut fb: Framebuffer) -> Result<Self, Error> {
let (width, height) = fb.get_size();
let (virtual_width, virtual_height) = fb.get_virtual_size();
if virtual_width != width || virtual_height != (height * 2) {
fb.set_virtual_size(width, height * 2)?;
}
let (offset_x, mut offset_y) = fb.get_offset();
if offset_x != 0 || (offset_y != 0 && offset_y != height) {
fb.set_offset(0, 0)?;
offset_y = 0;
}
let map = fb.map()?;
let state = if offset_y == height {
State::DrawToFirst
} else {
State::DrawToSecond
};
Ok(Self { width, height, fb, map, state })
}
pub fn as_mut_slice(&mut self) -> &mut[u8] {
let page_size = (self.fb.get_bytes_per_pixel() * self.height * self.width) as usize;
let (start, end) = match self.state {
State::DrawToFirst => (0, page_size),
State::DrawToSecond => (page_size, page_size * 2),
};
&mut self.map[start..end]
}
pub fn flip(&mut self) -> Result<(), Error> {
match self.state.flip() {
State::DrawToFirst => self.fb.set_offset(0, self.height),
State::DrawToSecond => self.fb.set_offset(0, 0),
}
}
pub fn blank(&self, level: BlankingLevel) -> Result<(), Error>{
self.fb.blank(level)
}
}