Optimize graphical debug scrolling

This commit is contained in:
Wildan M
2025-08-09 18:30:51 +07:00
parent 6bf8c0c26c
commit 39cb82d91d
2 changed files with 56 additions and 14 deletions
+25 -10
View File
@@ -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);
}
}
}
}
+31 -4
View File
@@ -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,
);
}
}
}