Hello, although I will integrate this into my patchset this not a proposed patch for qemu. This hack just shows that the current implementation of updating the emulated screen is inefficient and needs improvements.
(1) 1280 px width does not work well (16 bit only) - too slow to be usefull (2) 1024 px width for 24 bit gets faster by this patch, all other modes are not accelerated. IMPROVEMENT: - the original code almost always updates whole lines (e.g. the whole screen width). This even happens if you move the mouse. - this code monitors the min/max horizontal limits to reduce the updated area. - as a side-effect the code optimises the idle cpu time requirement (qemu checks every 30ms for screen updates). TIPS: - You can compile cirrus_vga.c with -O3 (but not the remainder of qemu!) - In win2003 enable full hw acceleration and disable write combining. KNOWN PROBLEMS: (a) for this hack: it is ugly but IT WORKS (1024 px 24 bit only). (b) other: when you try to change the screen resolution from inside win 2003 the display might get garbeld - but you can still read it. You must reboot windows to get a correct display. THIS IS NOT A PROBLEM OF THIS PATCH. I hope that some genius will do a much nicer patch that fixes also problem (b). Would be nice if a way could be found to support 1280x1024 with 24 bits. The cirrus emulator itself is quite cool. Yours Jürgen
Index: hw/cirrus_vga.c =================================================================== RCS file: /home/Cvsroot/qemu/hw/cirrus_vga.c,v retrieving revision 1.1.1.1 diff -B -b -U3 -r1.1.1.1 cirrus_vga.c --- hw/cirrus_vga.c 14 Jan 2006 13:19:59 -0000 1.1.1.1 +++ hw/cirrus_vga.c 16 Jan 2006 10:10:02 -0000 @@ -579,6 +579,20 @@ } } +// ------------------------ VGA speed hack ------------------------- +static inline void my_physical_memory_set_dirty(uint32_t uaddr) +{ + if(vga_dirty_left != 0xffff) { // only for 1024 pix width! + int jx = uaddr % 3072; // pixel*3 - will divide later + if(jx < vga_dirty_left) + vga_dirty_left = jx; + else if(jx > vga_dirty_right) + vga_dirty_right = jx; + } + cpu_physical_memory_set_dirty(uaddr); +} +// ----------------------------------------------------------------- + static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, int off_pitch, int bytesperline, int lines) @@ -587,6 +601,17 @@ int off_cur; int off_cur_end; +// ------------------------ VGA speed hack ------------------------- + if(vga_dirty_left != 0xffff) { // only for 1024 pix width! + int jx = off_begin % 3072; // pixel*3 - will divide later + if(off_pitch < 0) + jx -= bytesperline - 3; + if(jx < vga_dirty_left) vga_dirty_left = jx; + jx += bytesperline - 3; + if(jx > vga_dirty_right) vga_dirty_right = jx; + } +// ----------------------------------------------------------------- + for (y = 0; y < lines; y++) { off_cur = off_begin; off_cur_end = off_cur + bytesperline; @@ -1787,8 +1812,8 @@ val <<= 1; dst++; } - cpu_physical_memory_set_dirty(s->vram_offset + offset); - cpu_physical_memory_set_dirty(s->vram_offset + offset + 7); + my_physical_memory_set_dirty(s->vram_offset + offset); + my_physical_memory_set_dirty(s->vram_offset + offset + 7); } static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s, @@ -1812,8 +1837,8 @@ val <<= 1; dst += 2; } - cpu_physical_memory_set_dirty(s->vram_offset + offset); - cpu_physical_memory_set_dirty(s->vram_offset + offset + 15); + my_physical_memory_set_dirty(s->vram_offset + offset); + my_physical_memory_set_dirty(s->vram_offset + offset + 15); } /*************************************** @@ -1933,7 +1958,7 @@ mode = s->gr[0x05] & 0x7; if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { *(s->vram_ptr + bank_offset) = mem_value; - cpu_physical_memory_set_dirty(s->vram_offset + + my_physical_memory_set_dirty(s->vram_offset + bank_offset); } else { if ((s->gr[0x0B] & 0x14) != 0x14) { @@ -2262,7 +2287,7 @@ mode = s->gr[0x05] & 0x7; if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { *(s->vram_ptr + addr) = (uint8_t) val; - cpu_physical_memory_set_dirty(s->vram_offset + addr); + my_physical_memory_set_dirty(s->vram_offset + addr); } else { if ((s->gr[0x0B] & 0x14) != 0x14) { cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val); @@ -2321,7 +2346,7 @@ addr &= s->cirrus_addr_mask; *(s->vram_ptr + addr) = val; - cpu_physical_memory_set_dirty(s->vram_offset + addr); + my_physical_memory_set_dirty(s->vram_offset + addr); } static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr, @@ -2331,7 +2356,7 @@ addr &= s->cirrus_addr_mask; cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val); - cpu_physical_memory_set_dirty(s->vram_offset + addr); + my_physical_memory_set_dirty(s->vram_offset + addr); } static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr, @@ -2341,7 +2366,7 @@ addr &= s->cirrus_addr_mask; cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val); - cpu_physical_memory_set_dirty(s->vram_offset + addr); + my_physical_memory_set_dirty(s->vram_offset + addr); } /*************************************** Index: hw/vga.c =================================================================== RCS file: /home/Cvsroot/qemu/hw/vga.c,v retrieving revision 1.1.1.1 diff -B -b -U3 -r1.1.1.1 vga.c --- hw/vga.c 14 Jan 2006 13:19:59 -0000 1.1.1.1 +++ hw/vga.c 16 Jan 2006 10:10:18 -0000 @@ -24,6 +24,11 @@ #include "vl.h" #include "vga_int.h" +// ------------------------ VGA speed hack ------------------------- +uint16_t vga_dirty_left = 0xffff; +uint16_t vga_dirty_right; +// ----------------------------------------------------------------- + //#define DEBUG_VGA //#define DEBUG_VGA_MEM //#define DEBUG_VGA_REG @@ -1379,6 +1384,27 @@ printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]); #endif + // ------------------------ VGA speed hack ------------------------- + if(vga_dirty_left == 0xffff || full_update) { // was disabled + vga_dirty_left = 0; + vga_dirty_right = disp_width; + } + // do nothing if no update (this code is called by a timer!) + else if(vga_dirty_right == 0 && vga_dirty_left == disp_width*3) + return; + else { // has info + if(vga_dirty_left > vga_dirty_right) + vga_dirty_right = vga_dirty_left; + vga_dirty_left /= 3; + vga_dirty_right /= 3; + + vga_dirty_right -= vga_dirty_left; + vga_dirty_right += 2; + if(vga_dirty_left + vga_dirty_right > disp_width) + vga_dirty_right = disp_width - vga_dirty_left; + } + // ----------------------------------------------------------------- + addr1 = (s->start_addr * 4); bwidth = width * 4; y_start = -1; @@ -1400,14 +1427,17 @@ } page0 = s->vram_offset + (addr & TARGET_PAGE_MASK); page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK); - update = full_update | - cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) | - cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG); - if ((page1 - page0) > TARGET_PAGE_SIZE) { + update = full_update; + if(!update) { // && y >= vga_dirty_top && y <= vga_dirty_bottom) { + if( cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) | + cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG)) + update = 1; + else if((page1 - page0) > TARGET_PAGE_SIZE) { /* if wide line, can use another page */ update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, VGA_DIRTY_FLAG); } + } /* explicit invalidation for the hardware cursor */ update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; if (update) { @@ -1423,8 +1453,8 @@ } else { if (y_start >= 0) { /* flush to display */ - dpy_update(s->ds, 0, y_start, - disp_width, y - y_start); + dpy_update(s->ds, vga_dirty_left, y_start, + vga_dirty_right, y - y_start); y_start = -1; } } @@ -1444,8 +1474,8 @@ } if (y_start >= 0) { /* flush to display */ - dpy_update(s->ds, 0, y_start, - disp_width, y - y_start); + dpy_update(s->ds, vga_dirty_left, y_start, + vga_dirty_right, y - y_start); } /* reset modified pages */ if (page_max != -1) { @@ -1453,6 +1483,10 @@ VGA_DIRTY_FLAG); } memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4); +// ------------------------ VGA speed hack ------------------------- + vga_dirty_left = (disp_width == 1024) ? 3072 : 0xffff; + vga_dirty_right = 0; +// ----------------------------------------------------------------- } static void vga_draw_blank(VGAState *s, int full_update) Index: hw/vga_int.h =================================================================== RCS file: /home/Cvsroot/qemu/hw/vga_int.h,v retrieving revision 1.1.1.1 diff -B -b -U3 -r1.1.1.1 vga_int.h --- hw/vga_int.h 14 Jan 2006 13:19:59 -0000 1.1.1.1 +++ hw/vga_int.h 16 Jan 2006 10:10:20 -0000 @@ -168,3 +168,10 @@ extern const uint8_t sr_mask[8]; extern const uint8_t gr_mask[16]; + +// ------------------------ VGA speed hack ------------------------- +// limits the update region horizontally, only in some cirrus modes! +// for vga_dirty_left == 0xffff the hack becomes disabled +extern uint16_t vga_dirty_left; +extern uint16_t vga_dirty_right; +// -----------------------------------------------------------------
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel