Optimised putImageData

This commit is contained in:
Fabian 2022-02-22 00:18:13 +01:00
parent e0551fcee4
commit 4eb1e5035e
4 changed files with 41 additions and 11 deletions

View file

@ -161,6 +161,9 @@ function CPU(bus, wm, next_tick_immediately)
this.reg_pdpte = v86util.view(Int32Array, memory, 968, 8);
this.svga_dirty_bitmap_min_offset = v86util.view(Uint32Array, memory, 716, 1);
this.svga_dirty_bitmap_max_offset = v86util.view(Uint32Array, memory, 720, 1);
this.fw_value = [];
this.fw_pointer = 0;
this.option_roms = [];

View file

@ -40,6 +40,10 @@ pub const instruction_counter: *mut u32 = 664 as *mut u32;
pub const sreg: *mut u16 = 668 as *mut u16;
pub const dreg: *mut i32 = 684 as *mut i32;
// filled in by svga_fill_pixel_buffer, read by javacsript for optimised putImageData calls
pub const svga_dirty_bitmap_min_offset: *mut u32 = 716 as *mut u32;
pub const svga_dirty_bitmap_max_offset: *mut u32 = 720 as *mut u32;
pub const segment_is_null: *mut bool = 724 as *mut bool;
pub const segment_offsets: *mut i32 = 736 as *mut i32;
pub const segment_limits: *mut u32 = 768 as *mut u32;

View file

@ -1,5 +1,6 @@
#![allow(non_upper_case_globals)]
use cpu::global_pointers;
use cpu::memory;
pub static mut dirty_bitmap: Vec<u64> = Vec::new();
@ -26,6 +27,9 @@ pub unsafe fn svga_mark_dirty() {
}
fn iter_dirty_pages(f: &dyn Fn(isize)) {
let mut min_off = u32::MAX;
let mut max_off = u32::MIN;
for (i, &word) in unsafe { &dirty_bitmap }.iter().enumerate() {
if word == 0 {
continue;
@ -36,13 +40,22 @@ fn iter_dirty_pages(f: &dyn Fn(isize)) {
}
let off = ((i << 6 | j) << 12) as isize;
dbg_assert!(off < unsafe { memory::vga_memory_size as isize });
if min_off == u32::MAX {
min_off = off as u32;
}
max_off = off as u32;
f(off);
}
}
unsafe {
*global_pointers::svga_dirty_bitmap_min_offset = min_off;
*global_pointers::svga_dirty_bitmap_max_offset = max_off;
}
}
#[no_mangle]
pub unsafe fn svga_fill_pixel_buffer(bpp: i32, svga_dest_offset: i32) {
pub unsafe fn svga_fill_pixel_buffer(bpp: u32, svga_dest_offset: u32) {
let debug_bounds = false;
match bpp {
@ -58,6 +71,8 @@ pub unsafe fn svga_fill_pixel_buffer(bpp: i32, svga_dest_offset: i32) {
isize::min(1024, dest_buffer.len() as isize - dest_offset)
};
dbg_assert!(src as u32 % 8 == 0);
dbg_assert!(dest as u32 % 8 == 0);
for i in 0..end {
dbg_assert!(off + i < memory::vga_memory_size as isize);
let dword = *src.offset(i);

View file

@ -2279,6 +2279,9 @@ VGAScreen.prototype.screen_fill_buffer = function()
if(this.svga_enabled)
{
let min_y = 0;
let max_y = this.svga_height - 1;
if(this.svga_bpp === 8)
{
// XXX: Slow, should be ported to rust, but it doesn't have access to vga256_palette
@ -2295,18 +2298,23 @@ VGAScreen.prototype.screen_fill_buffer = function()
else
{
this.cpu.svga_fill_pixel_buffer(this.svga_bpp, this.svga_offset);
const bytes_per_pixel = this.svga_bpp === 15 ? 2 : this.svga_bpp / 8;
const bytes_per_line = bytes_per_pixel * this.svga_width;
min_y = this.cpu.svga_dirty_bitmap_min_offset[0] / bytes_per_line | 0;
max_y = this.cpu.svga_dirty_bitmap_max_offset[0] / bytes_per_line | 0;
}
const min_y = 0;
const max_y = this.svga_height;
this.bus.send("screen-fill-buffer-end", [{
image_data: this.image_data,
screen_x: 0, screen_y: min_y,
buffer_x: 0, buffer_y: min_y,
buffer_width: this.svga_width,
buffer_height: max_y - min_y + 1,
}]);
if(min_y < max_y)
{
this.bus.send("screen-fill-buffer-end", [{
image_data: this.image_data,
screen_x: 0, screen_y: min_y,
buffer_x: 0, buffer_y: min_y,
buffer_width: this.svga_width,
buffer_height: max_y - min_y + 1,
}]);
}
}
else
{