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

Reply via email to