[Top][All Lists]
[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 {
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image,
Piotr Krysik <=