Optimize graphical debug scrolling
This commit is contained in:
@@ -38,8 +38,7 @@ impl DebugDisplay {
|
||||
self.scroll(d_y * 16);
|
||||
|
||||
unsafe {
|
||||
self.display
|
||||
.sync(0, 0, self.display.width, self.display.height);
|
||||
self.display.sync_screen();
|
||||
}
|
||||
|
||||
self.y = new_y;
|
||||
@@ -65,7 +64,12 @@ impl DebugDisplay {
|
||||
/// Draw a character
|
||||
fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
|
||||
if x + 8 <= self.display.width && y + 16 <= self.display.height {
|
||||
let mut dst = unsafe { self.display.data_mut().add(y * self.display.stride + x) };
|
||||
let phys_y = (self.display.offset_y + y) % self.display.height;
|
||||
let mut dst = unsafe {
|
||||
self.display
|
||||
.data_mut()
|
||||
.add(phys_y * self.display.stride + x)
|
||||
};
|
||||
|
||||
let font_i = 16 * (character as usize);
|
||||
if font_i + 16 <= FONT.len() {
|
||||
@@ -78,7 +82,13 @@ impl DebugDisplay {
|
||||
}
|
||||
}
|
||||
}
|
||||
dst = unsafe { dst.add(self.display.stride) };
|
||||
|
||||
let next_phys_y = (phys_y + row + 1) % self.display.height;
|
||||
dst = unsafe {
|
||||
self.display
|
||||
.data_mut()
|
||||
.add(next_phys_y * self.display.stride + x)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,12 +96,17 @@ impl DebugDisplay {
|
||||
|
||||
/// Scroll the screen
|
||||
fn scroll(&mut self, lines: usize) {
|
||||
let offset = cmp::min(self.display.height, lines) * self.display.stride;
|
||||
let size = (self.display.stride * self.display.height) - offset;
|
||||
unsafe {
|
||||
let ptr = self.display.data_mut();
|
||||
ptr::copy(ptr.add(offset), ptr, size);
|
||||
ptr::write_bytes(ptr.add(size), 0, offset);
|
||||
let lines = cmp::min(self.h * 16, lines); // clamp
|
||||
self.display.offset_y = (self.display.offset_y + lines) % self.display.height;
|
||||
|
||||
// clear the new lines
|
||||
let start_y = (self.display.offset_y + self.h * 16 - lines) % self.display.height;
|
||||
for row in 0..lines {
|
||||
let y = (start_y + row) % self.display.height;
|
||||
unsafe {
|
||||
let ptr = self.display.data_mut().add(y * self.display.stride);
|
||||
ptr::write_bytes(ptr, 0, self.display.stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ pub(super) struct Display {
|
||||
pub(super) stride: usize,
|
||||
onscreen_ptr: *mut u32,
|
||||
offscreen: Option<Box<[u32]>>,
|
||||
pub(super) offset_y: usize,
|
||||
}
|
||||
|
||||
unsafe impl Send for Display {}
|
||||
@@ -28,6 +29,7 @@ impl Display {
|
||||
stride,
|
||||
onscreen_ptr,
|
||||
offscreen: None,
|
||||
offset_y: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,16 +49,41 @@ impl Display {
|
||||
/// Sync from offscreen to onscreen, unsafe because it trusts provided x, y, w, h
|
||||
pub(super) unsafe fn sync(&mut self, x: usize, y: usize, w: usize, mut h: usize) {
|
||||
if let Some(offscreen) = &self.offscreen {
|
||||
let mut offset = y * self.stride + x;
|
||||
let mut y = y;
|
||||
while h > 0 {
|
||||
let src_y = (self.offset_y + y) % self.height;
|
||||
let src_offset = src_y * self.stride + x;
|
||||
let dst_offset = y * self.stride + x;
|
||||
|
||||
ptr::copy(
|
||||
offscreen.as_ptr().add(offset),
|
||||
self.onscreen_ptr.add(offset),
|
||||
offscreen.as_ptr().add(src_offset),
|
||||
self.onscreen_ptr.add(dst_offset),
|
||||
w,
|
||||
);
|
||||
offset += self.stride;
|
||||
|
||||
y += 1;
|
||||
h -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sync the whole screen (faster)
|
||||
pub(super) unsafe fn sync_screen(&mut self) {
|
||||
if let Some(offscreen) = &self.offscreen {
|
||||
let stride_bytes = self.stride;
|
||||
let first_part_len = (self.height - self.offset_y) * stride_bytes;
|
||||
let second_part_len = self.offset_y * stride_bytes;
|
||||
|
||||
ptr::copy(
|
||||
offscreen.as_ptr().add(self.offset_y * stride_bytes),
|
||||
self.onscreen_ptr,
|
||||
first_part_len,
|
||||
);
|
||||
ptr::copy(
|
||||
offscreen.as_ptr(),
|
||||
self.onscreen_ptr.add(first_part_len),
|
||||
second_part_len,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user