qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide imag


From: Piotr Krysik
Subject: Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image
Date: Mon, 11 Oct 2004 00:40:18 -0700 (PDT)

Hi!

Done. Sorry for the delay - I was quite busy last 
weeks.


Piotrek

--- Fabrice Bellard <address@hidden> wrote:

> This is better, but maybe a heuristic could do 
> even better (for example by tracking access to 
> registers which map plans 2 and 3 ?).
> 
> Fabrice.

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
diff -ru qemu-snapshot-2004-10-05_23/hw/cirrus_vga.c 
qemu-snapshot-2004-10-05_23-vga-update/hw/cirrus_vga.c
--- qemu-snapshot-2004-10-05_23/hw/cirrus_vga.c 2004-07-10 15:41:46.000000000 
+0200
+++ qemu-snapshot-2004-10-05_23-vga-update/hw/cirrus_vga.c      2004-10-11 
09:19:11.000000000 +0200
@@ -2568,12 +2568,20 @@
        s->sr_index = val;
        break;
     case 0x3c5:
-       if (cirrus_hook_write_sr(s, s->sr_index, val))
-           break;
+       if (!cirrus_hook_write_sr(s, s->sr_index, val)) {
 #ifdef DEBUG_VGA_REG
-       printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
+           printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
 #endif
-       s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+           s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+       }
+       if (s->sr_index == 2 ||
+           s->sr_index == 4) {
+           vga_notify_font_reg((VGAState *)s);
+       } else if (s->sr_index == 3) {
+           /* writing sr[3]; even if the register value didn't change,
+              it's possible that fonts were updated or will be updated soon */
+           vga_invalidate_font((VGAState *)s);
+       }
        break;
     case 0x3c6:
        cirrus_write_hidden_dac(s, val);
@@ -2602,12 +2610,16 @@
        s->gr_index = val;
        break;
     case 0x3cf:
-       if (cirrus_hook_write_gr(s, s->gr_index, val))
-           break;
+       if (!cirrus_hook_write_gr(s, s->gr_index, val)) {
 #ifdef DEBUG_VGA_REG
-       printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
+           printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
 #endif
-       s->gr[s->gr_index] = val & gr_mask[s->gr_index];
+           s->gr[s->gr_index] = val & gr_mask[s->gr_index];
+       }
+       if (s->gr_index == 4 ||
+           s->gr_index == 5) {
+           vga_notify_font_reg((VGAState *)s);
+       }
        break;
     case 0x3b4:
     case 0x3d4:
diff -ru qemu-snapshot-2004-10-05_23/hw/vga.c 
qemu-snapshot-2004-10-05_23-vga-update/hw/vga.c
--- qemu-snapshot-2004-10-05_23/hw/vga.c        2004-06-26 18:12:26.000000000 
+0200
+++ qemu-snapshot-2004-10-05_23-vga-update/hw/vga.c     2004-10-11 
09:18:32.000000000 +0200
@@ -306,6 +306,14 @@
         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
 #endif
         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+        if (s->sr_index == 2 ||
+            s->sr_index == 4) {
+            vga_notify_font_reg(s);
+        } else if (s->sr_index == 3) {
+            /* writing sr[3]; even if the register value didn't change,
+               it's possible that fonts were updated or will be updated soon */
+            vga_invalidate_font(s);
+        }
         break;
     case 0x3c7:
         s->dac_read_index = val;
@@ -333,6 +341,10 @@
         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
 #endif
         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
+        if (s->gr_index == 4 ||
+            s->gr_index == 5) {
+            vga_notify_font_reg(s);
+        }
         break;
     case 0x3b4:
     case 0x3d4:
@@ -935,6 +947,106 @@
     return full_update;
 }
 
+/* invalidate the font cache */
+void vga_invalidate_font(VGAState *s)
+{
+    s->font_age = 0;
+    s->font_ttl = 0;
+#if defined(DEBUG_VGA)
+    printf("vga: invalidate_font\n");
+#endif
+}
+
+/* notify the font cache when updating register sr[2], sr[4], gr[4] or gr[5] */
+void vga_notify_font_reg(VGAState *s)
+{
+    int writable;
+
+    /* check if font area if writable (based on vga_mem_writeb) */
+    /* XXX: assume no font updating via framebuffer */
+    writable = 0;
+    if (s->sr[4] & 0x08) {
+        /* chain 4 mode */
+        if (s->sr[2] & 0x04)
+            writable = 1;
+    } else if (s->gr[5] & 0x10) {
+        /* odd/even mode (aka text mode mapping) */
+        if (s->gr[4] & 0x02)
+            writable = 1;
+    } else {
+        /* standard VGA latched access */
+        if (s->sr[2] & 0x04)
+            writable = 1;
+    }
+
+#if defined(DEBUG_VGA)
+    printf("vga: notify_font_regs old=%d new=%d\n", s->font_writable, 
writable);
+#endif
+    if (s->font_writable != writable) {
+        s->font_writable = writable;
+        /* expect updates when unprotecting; otherwise don't play with 
font_age */
+        if (writable) {
+            s->font_age = 0;
+        }
+        s->font_ttl = 0; /* force refresh */
+    }
+}
+
+/* return true if the font was modified */
+static int refresh_font(uint8_t *font_ptr, uint8_t *vram_font_ptr)
+{
+    int modified;
+    uint8_t *font_end;
+
+    modified = 0;
+    font_end = font_ptr + 0x2000;
+    while (font_ptr < font_end) {
+        if (*font_ptr != *vram_font_ptr) {
+            *font_ptr = *vram_font_ptr;
+            modified = 1;
+        }
+        font_ptr ++;
+        vram_font_ptr += 4;
+    }
+    return modified;
+}
+
+/* return true if any of the fonts was modified */
+static int update_font(VGAState *s)
+{
+    int full_update;
+    uint32_t v, offset;
+
+    if (s->font_ttl > 0) {
+        s->font_ttl --;
+        return 0;
+    }
+
+    v = s->sr[3];
+    /* font A */
+    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
+    full_update = refresh_font(s->font[0], s->vram_ptr + offset);
+    /* font B */
+    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
+    full_update |= refresh_font(s->font[1], s->vram_ptr + offset);
+
+    if (full_update) {
+        s->font_ttl = s->font_age >> 1;
+        s->font_age = s->font_ttl + 1; /* age at next refresh */
+    } else {
+        s->font_ttl = s->font_age;
+        s->font_age += s->font_ttl + 1; /* age at next refresh */
+        /* limit ttl for next refresh and prevent age overflow */
+        if (s->font_age > VGA_FONT_REFRESH_INTERVAL / GUI_REFRESH_INTERVAL)
+            s->font_age = VGA_FONT_REFRESH_INTERVAL / GUI_REFRESH_INTERVAL;
+    }
+#if defined(DEBUG_VGA)
+    printf("vga: update_font full_update=%d age=%d ttl=%d\n",
+           full_update, s->font_age, s->font_ttl);
+#endif
+    return full_update;
+}
+
 static void vga_get_offsets(VGAState *s, 
                             uint32_t *pline_offset, 
                             uint32_t *pstart_addr)
@@ -1062,7 +1174,7 @@
 {
     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
     int cx_min, cx_max, linesize, x_incr;
-    uint32_t offset, fgcol, bgcol, v, cursor_offset;
+    uint32_t fgcol, bgcol, cursor_offset;
     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
     const uint8_t *font_ptr, *font_base[2];
     int dup9, line_offset, depth_index;
@@ -1073,22 +1185,10 @@
 
     full_update |= update_palette16(s);
     palette = s->last_palette;
-    
-    /* compute font data address (in plane 2) */
-    v = s->sr[3];
-    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
-    if (offset != s->font_offsets[0]) {
-        s->font_offsets[0] = offset;
-        full_update = 1;
-    }
-    font_base[0] = s->vram_ptr + offset;
 
-    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
-    font_base[1] = s->vram_ptr + offset;
-    if (offset != s->font_offsets[1]) {
-        s->font_offsets[1] = offset;
-        full_update = 1;
-    }
+    full_update |= update_font(s);
+    font_base[0] = s->font[0];
+    font_base[1] = s->font[1];
 
     full_update |= update_basic_params(s);
 
@@ -1176,7 +1276,7 @@
                 cattr = ch_attr >> 8;
 #endif
                 font_ptr = font_base[(cattr >> 3) & 1];
-                font_ptr += 32 * 4 * ch;
+                font_ptr += 32 * ch;
                 bgcol = palette[cattr >> 4];
                 fgcol = palette[cattr & 0x0f];
                 if (cw != 9) {
@@ -1594,6 +1694,7 @@
     s->cr[0x30] = 0xe1;
 #endif
     s->graphic_mode = -1; /* force full update */
+    vga_invalidate_font(s);
 }
 
 static CPUReadMemoryFunc *vga_mem_read[3] = {
diff -ru qemu-snapshot-2004-10-05_23/hw/vga_int.h 
qemu-snapshot-2004-10-05_23-vga-update/hw/vga_int.h
--- qemu-snapshot-2004-10-05_23/hw/vga_int.h    2004-06-08 02:59:19.000000000 
+0200
+++ qemu-snapshot-2004-10-05_23-vga-update/hw/vga_int.h 2004-10-11 
09:18:32.000000000 +0200
@@ -109,8 +109,11 @@
     VGA_STATE_COMMON_BOCHS_VBE                                          \
     /* display refresh support */                                       \
     DisplayState *ds;                                                   \
-    uint32_t font_offsets[2];                                           \
     int graphic_mode;                                                   \
+    uint8_t font[2][0x2000];                                            \
+    uint8_t font_writable;                                              \
+    uint8_t font_age;                                                   \
+    uint8_t font_ttl;                                                   \
     uint8_t shift_control;                                              \
     uint8_t double_scan;                                                \
     uint32_t line_offset;                                               \
@@ -149,6 +152,8 @@
 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
 void vga_invalidate_scanlines(VGAState *s, int y1, int y2);
+void vga_invalidate_font(VGAState *s); 
+void vga_notify_font_reg(VGAState *s);
 
 void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, 
                             int poffset, int w, 
diff -ru qemu-snapshot-2004-10-05_23/hw/vga_template.h 
qemu-snapshot-2004-10-05_23-vga-update/hw/vga_template.h
--- qemu-snapshot-2004-10-05_23/hw/vga_template.h       2004-06-21 
18:56:45.000000000 +0200
+++ qemu-snapshot-2004-10-05_23-vga-update/hw/vga_template.h    2004-10-11 
09:18:32.000000000 +0200
@@ -72,7 +72,7 @@
     do {
         font_data = font_ptr[0];
         glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
-        font_ptr += 4;
+        font_ptr ++;
         d += linesize;
     } while (--h);
 }
@@ -92,7 +92,7 @@
         glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP, 
                                           expand4to8[font_data & 0x0f], 
                                           xorcol, bgcol);
-        font_ptr += 4;
+        font_ptr ++;
         d += linesize;
     } while (--h);
 }
@@ -141,7 +141,7 @@
         else
             ((uint32_t *)d)[8] = bgcol;
 #endif
-        font_ptr += 4;
+        font_ptr ++;
         d += linesize;
     } while (--h);
 }
diff -ru qemu-snapshot-2004-10-05_23/vl.c 
qemu-snapshot-2004-10-05_23-vga-update/vl.c
--- qemu-snapshot-2004-10-05_23/vl.c    2004-10-03 15:29:03.000000000 +0200
+++ qemu-snapshot-2004-10-05_23-vga-update/vl.c 2004-10-11 09:18:32.000000000 
+0200
@@ -94,8 +94,6 @@
 #else
 #define DEFAULT_RAM_SIZE 128
 #endif
-/* in ms */
-#define GUI_REFRESH_INTERVAL 30
 
 /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536
diff -ru qemu-snapshot-2004-10-05_23/vl.h 
qemu-snapshot-2004-10-05_23-vga-update/vl.h
--- qemu-snapshot-2004-10-05_23/vl.h    2004-10-04 23:23:09.000000000 +0200
+++ qemu-snapshot-2004-10-05_23-vga-update/vl.h 2004-10-11 09:18:32.000000000 
+0200
@@ -503,6 +503,9 @@
 
 /* vga.c */
 
+#define GUI_REFRESH_INTERVAL 30 /* ms */
+#define VGA_FONT_REFRESH_INTERVAL 500 /* ms */
+
 #define VGA_RAM_SIZE (4096 * 1024)
 
 struct DisplayState {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]