More efficient iteration in graphics functions

This commit is contained in:
Jeremy Soller 2016-09-01 15:31:39 -06:00
parent 0ccfd2125a
commit ff4d06f678
3 changed files with 76 additions and 30 deletions

View file

@ -3,6 +3,9 @@ ARCH?=x86_64
QEMU=qemu-system-$(ARCH) QEMU=qemu-system-$(ARCH)
QEMUFLAGS=-serial mon:stdio -d guest_errors QEMUFLAGS=-serial mon:stdio -d guest_errors
RUSTCFLAGS=--target $(ARCH)-unknown-none.json -O -C soft-float
CARGOFLAGS=--target $(ARCH)-unknown-none.json -- -O -C soft-float
ifeq ($(ARCH),arm) ifeq ($(ARCH),arm)
LD=$(ARCH)-none-eabi-ld LD=$(ARCH)-none-eabi-ld
QEMUFLAGS+=-cpu arm1176 -machine integratorcp QEMUFLAGS+=-cpu arm1176 -machine integratorcp
@ -34,23 +37,23 @@ FORCE:
build/libcore.rlib: rust/src/libcore/lib.rs build/libcore.rlib: rust/src/libcore/lib.rs
mkdir -p build mkdir -p build
./rustc.sh --target $(ARCH)-unknown-none.json -C soft-float -o $@ $< ./rustc.sh $(RUSTCFLAGS) -o $@ $<
build/liballoc.rlib: rust/src/liballoc/lib.rs build/libcore.rlib build/liballoc.rlib: rust/src/liballoc/lib.rs build/libcore.rlib
mkdir -p build mkdir -p build
./rustc.sh --target $(ARCH)-unknown-none.json -C soft-float -o $@ $< ./rustc.sh $(RUSTCFLAGS) -o $@ $<
build/librustc_unicode.rlib: rust/src/librustc_unicode/lib.rs build/libcore.rlib build/librustc_unicode.rlib: rust/src/librustc_unicode/lib.rs build/libcore.rlib
mkdir -p build mkdir -p build
./rustc.sh --target $(ARCH)-unknown-none.json -C soft-float -o $@ $< ./rustc.sh $(RUSTCFLAGS) -o $@ $<
build/libcollections.rlib: rust/src/libcollections/lib.rs build/libcore.rlib build/liballoc.rlib build/librustc_unicode.rlib build/libcollections.rlib: rust/src/libcollections/lib.rs build/libcore.rlib build/liballoc.rlib build/librustc_unicode.rlib
mkdir -p build mkdir -p build
./rustc.sh --target $(ARCH)-unknown-none.json -C soft-float -o $@ $< ./rustc.sh $(RUSTCFLAGS) -o $@ $<
build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.rlib FORCE build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.rlib FORCE
mkdir -p build mkdir -p build
RUSTC="./rustc.sh" cargo rustc --target $(ARCH)-unknown-none.json -- -C soft-float -o $@ RUSTC="./rustc.sh" cargo rustc $(CARGOFLAGS) -o $@
build/kernel.bin: build/libkernel.a build/kernel.bin: build/libkernel.a
$(LD) --gc-sections -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $< $(LD) --gc-sections -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $<

View file

@ -8,6 +8,7 @@ use paging::{ActivePageTable, PhysicalAddress, entry};
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[allow(unused_assignments)] #[allow(unused_assignments)]
#[inline(always)] #[inline(always)]
#[cold]
unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) { unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) {
asm!("cld asm!("cld
rep movsq" rep movsq"
@ -20,6 +21,7 @@ unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[allow(unused_assignments)] #[allow(unused_assignments)]
#[inline(always)] #[inline(always)]
#[cold]
unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) { unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) {
asm!("cld asm!("cld
rep stosd" rep stosd"
@ -32,6 +34,7 @@ unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[allow(unused_assignments)] #[allow(unused_assignments)]
#[inline(always)] #[inline(always)]
#[cold]
unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) { unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) {
asm!("cld asm!("cld
rep stosq" rep stosq"
@ -81,7 +84,7 @@ pub struct VBEModeInfo {
pub static CONSOLE: Mutex<Option<Console>> = Mutex::new(None); pub static CONSOLE: Mutex<Option<Console>> = Mutex::new(None);
pub static DISPLAY: Mutex<Option<Display<'static>>> = Mutex::new(None); pub static DISPLAY: Mutex<Option<Display>> = Mutex::new(None);
static FONT: &'static [u8] = include_bytes!("../../../../res/unifont.font"); static FONT: &'static [u8] = include_bytes!("../../../../res/unifont.font");
@ -105,8 +108,14 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
fast_set64(onscreen as *mut u64, 0, size/2); fast_set64(onscreen as *mut u64, 0, size/2);
let offscreen = ::allocator::__rust_allocate(size * 4, 8);
fast_set64(offscreen as *mut u64, 0, size/2);
*CONSOLE.lock() = Some(Console::new(width/8, height/16)); *CONSOLE.lock() = Some(Console::new(width/8, height/16));
*DISPLAY.lock() = Some(Display::new(width, height, slice::from_raw_parts_mut(onscreen as *mut u32, size))); *DISPLAY.lock() = Some(Display::new(width, height,
slice::from_raw_parts_mut(onscreen as *mut u32, size),
slice::from_raw_parts_mut(offscreen as *mut u32, size)
));
} }
} }
@ -131,18 +140,20 @@ pub unsafe fn init_ap(active_table: &mut ActivePageTable) {
} }
/// A display /// A display
pub struct Display<'a> { pub struct Display {
pub width: usize, pub width: usize,
pub height: usize, pub height: usize,
pub data: &'a mut [u32], pub onscreen: &'static mut [u32],
pub offscreen: &'static mut [u32],
} }
impl<'a> Display<'a> { impl Display {
fn new<'data>(width: usize, height: usize, data: &'data mut [u32]) -> Display<'data> { fn new(width: usize, height: usize, onscreen: &'static mut [u32], offscreen: &'static mut [u32]) -> Display {
Display { Display {
width: width, width: width,
height: height, height: height,
data: data, onscreen: onscreen,
offscreen: offscreen,
} }
} }
@ -151,35 +162,65 @@ impl<'a> Display<'a> {
let start_y = cmp::min(self.height - 1, y); let start_y = cmp::min(self.height - 1, y);
let end_y = cmp::min(self.height, y + h); let end_y = cmp::min(self.height, y + h);
let mut start_x = cmp::min(self.width - 1, x); let start_x = cmp::min(self.width - 1, x);
let mut len = cmp::min(self.width, x + w) - start_x; let len = cmp::min(self.width, x + w) - start_x;
let width = self.width; let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
let data_ptr = self.data.as_mut_ptr(); let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
for y in start_y..end_y {
let offset = y * self.width + start_x; let stride = self.width * 4;
let offset = y * stride + start_x * 4;
offscreen_ptr += offset;
onscreen_ptr += offset;
let mut rows = end_y - start_y;
while rows > 0 {
unsafe { unsafe {
fast_set(data_ptr.offset(offset as isize), color, len); fast_set(offscreen_ptr as *mut u32, color, len);
fast_set(onscreen_ptr as *mut u32, color, len);
} }
offscreen_ptr += stride;
onscreen_ptr += stride;
rows -= 1;
} }
} }
/// Draw a character /// Draw a character
fn char(&mut self, x: usize, y: usize, character: char, color: u32) { fn char(&mut self, x: usize, y: usize, character: char, color: u32) {
if x + 8 <= self.width && y + 16 <= self.height { if x + 8 <= self.width && y + 16 <= self.height {
let mut offset = y * self.width + x; let mut font_i = 16 * (character as usize);
let font_end = font_i + 16;
if font_end <= FONT.len() {
let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize;
let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize;
let font_i = 16 * (character as usize); let stride = self.width * 4;
if font_i + 16 <= FONT.len() {
for row in 0..16 { let offset = y * stride + x * 4;
let row_data = FONT[font_i + row]; offscreen_ptr += offset;
for col in 0..8 { onscreen_ptr += offset;
if (row_data >> (7 - col)) & 1 == 1 {
self.data[offset + col] = color; while font_i < font_end {
let mut row_data = FONT[font_i];
let mut col = 8;
while col > 0 {
col -= 1;
if row_data & 1 == 1 {
unsafe {
*((offscreen_ptr + col * 4) as *mut u32) = color;
} }
} }
row_data = row_data >> 1;
}
offset += self.width; unsafe {
fast_copy64(onscreen_ptr as *mut u64, offscreen_ptr as *const u64, 4);
}
offscreen_ptr += stride;
onscreen_ptr += stride;
font_i += 1;
} }
} }
} }
@ -195,9 +236,11 @@ impl<'a> Display<'a> {
let off1 = rows * width; let off1 = rows * width;
let off2 = height * width - off1; let off2 = height * width - off1;
unsafe { unsafe {
let data_ptr = self.data.as_mut_ptr() as *mut u64; let data_ptr = self.offscreen.as_mut_ptr() as *mut u64;
fast_copy64(data_ptr, data_ptr.offset(off1 as isize), off2); fast_copy64(data_ptr, data_ptr.offset(off1 as isize), off2);
fast_set64(data_ptr.offset(off2 as isize), data, off1); fast_set64(data_ptr.offset(off2 as isize), data, off1);
fast_copy64(self.onscreen.as_mut_ptr() as *mut u64, data_ptr, off1 + off2);
} }
} }
} }

View file

@ -297,7 +297,7 @@ impl Ps2 {
self.mouse_x = cmp::max(0, cmp::min(display.width as isize - 1, self.mouse_x as isize + dx)) as usize; self.mouse_x = cmp::max(0, cmp::min(display.width as isize - 1, self.mouse_x as isize + dx)) as usize;
self.mouse_y = cmp::max(0, cmp::min(display.height as isize - 1, self.mouse_y as isize - dy)) as usize; self.mouse_y = cmp::max(0, cmp::min(display.height as isize - 1, self.mouse_y as isize - dy)) as usize;
let offset = self.mouse_y * display.width + self.mouse_x; let offset = self.mouse_y * display.width + self.mouse_x;
display.data[offset as usize] = 0xFF0000; display.onscreen[offset as usize] = 0xFF0000;
} }
} }
} }