From ff4d06f678ced2753df28173312891721d50fe01 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 1 Sep 2016 15:31:39 -0600 Subject: [PATCH] More efficient iteration in graphics functions --- Makefile | 13 +++-- arch/x86_64/src/device/display.rs | 91 +++++++++++++++++++++++-------- arch/x86_64/src/device/ps2.rs | 2 +- 3 files changed, 76 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 2a0f1d2..0bf1ea1 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,9 @@ ARCH?=x86_64 QEMU=qemu-system-$(ARCH) 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) LD=$(ARCH)-none-eabi-ld QEMUFLAGS+=-cpu arm1176 -machine integratorcp @@ -34,23 +37,23 @@ FORCE: build/libcore.rlib: rust/src/libcore/lib.rs 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 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 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 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 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 $(LD) --gc-sections -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $< diff --git a/arch/x86_64/src/device/display.rs b/arch/x86_64/src/device/display.rs index c5af5bf..25cc299 100644 --- a/arch/x86_64/src/device/display.rs +++ b/arch/x86_64/src/device/display.rs @@ -8,6 +8,7 @@ use paging::{ActivePageTable, PhysicalAddress, entry}; #[cfg(target_arch = "x86_64")] #[allow(unused_assignments)] #[inline(always)] +#[cold] unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) { asm!("cld rep movsq" @@ -20,6 +21,7 @@ unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) { #[cfg(target_arch = "x86_64")] #[allow(unused_assignments)] #[inline(always)] +#[cold] unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) { asm!("cld rep stosd" @@ -32,6 +34,7 @@ unsafe fn fast_set(dst: *mut u32, src: u32, len: usize) { #[cfg(target_arch = "x86_64")] #[allow(unused_assignments)] #[inline(always)] +#[cold] unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) { asm!("cld rep stosq" @@ -81,7 +84,7 @@ pub struct VBEModeInfo { pub static CONSOLE: Mutex> = Mutex::new(None); -pub static DISPLAY: Mutex>> = Mutex::new(None); +pub static DISPLAY: Mutex> = Mutex::new(None); 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); + 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)); - *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 -pub struct Display<'a> { +pub struct Display { pub width: usize, pub height: usize, - pub data: &'a mut [u32], + pub onscreen: &'static mut [u32], + pub offscreen: &'static mut [u32], } -impl<'a> Display<'a> { - fn new<'data>(width: usize, height: usize, data: &'data mut [u32]) -> Display<'data> { +impl Display { + fn new(width: usize, height: usize, onscreen: &'static mut [u32], offscreen: &'static mut [u32]) -> Display { Display { width: width, 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 end_y = cmp::min(self.height, y + h); - let mut start_x = cmp::min(self.width - 1, x); - let mut len = cmp::min(self.width, x + w) - start_x; + let start_x = cmp::min(self.width - 1, x); + let len = cmp::min(self.width, x + w) - start_x; - let width = self.width; - let data_ptr = self.data.as_mut_ptr(); - for y in start_y..end_y { - let offset = y * self.width + start_x; + let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; + let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize; + + 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 { - 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 fn char(&mut self, x: usize, y: usize, character: char, color: u32) { 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); - if font_i + 16 <= FONT.len() { - for row in 0..16 { - let row_data = FONT[font_i + row]; - for col in 0..8 { - if (row_data >> (7 - col)) & 1 == 1 { - self.data[offset + col] = color; + let stride = self.width * 4; + + let offset = y * stride + x * 4; + offscreen_ptr += offset; + onscreen_ptr += offset; + + 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 off2 = height * width - off1; 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_set64(data_ptr.offset(off2 as isize), data, off1); + + fast_copy64(self.onscreen.as_mut_ptr() as *mut u64, data_ptr, off1 + off2); } } } diff --git a/arch/x86_64/src/device/ps2.rs b/arch/x86_64/src/device/ps2.rs index 38a4f71..4c1c502 100644 --- a/arch/x86_64/src/device/ps2.rs +++ b/arch/x86_64/src/device/ps2.rs @@ -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_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; - display.data[offset as usize] = 0xFF0000; + display.onscreen[offset as usize] = 0xFF0000; } } }