* [Qemu-devel] [patch] incorrect VGA initialization, can provide image
@ 2004-09-09 22:14 Piotr Krysik
2004-09-10 10:20 ` Johannes Schindelin
0 siblings, 1 reply; 9+ messages in thread
From: Piotr Krysik @ 2004-09-09 22:14 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 191 bytes --]
Hi!
This patch should fix the problem.
Piotrek
_______________________________
Do you Yahoo!?
Shop for Back-to-School deals on Yahoo! Shopping.
http://shopping.yahoo.com/backtoschool
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vga-update-1.patch --]
[-- Type: text/x-patch; name="vga-update-1.patch", Size: 2568 bytes --]
diff -ru qemu-snapshot-2004-08-04_23/hw/vga.c qemu-snapshot-2004-08-04_23-vga-update/hw/vga.c
--- qemu-snapshot-2004-08-04_23/hw/vga.c 2004-06-26 18:12:26.000000000 +0200
+++ qemu-snapshot-2004-08-04_23-vga-update/hw/vga.c 2004-09-09 23:40:51.000000000 +0200
@@ -696,10 +696,14 @@
/* chain 4 mode : simplest access */
plane = addr & 3;
if (s->sr[2] & (1 << plane)) {
- s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: chain4: [0x%x]\n", addr);
#endif
+ s->vram_ptr[addr] = val;
+ /* force full update for vga_draw_text when writing font memory */
+ if (((s->font_offsets[0] ^ addr) & ~0x7ffc) == 0 ||
+ ((s->font_offsets[1] ^ addr) & ~0x7ffc) == 0)
+ s->font_offsets[0] = -1;
cpu_physical_memory_set_dirty(s->vram_offset + addr);
}
} else if (s->gr[5] & 0x10) {
@@ -707,10 +711,14 @@
plane = (s->gr[4] & 2) | (addr & 1);
if (s->sr[2] & (1 << plane)) {
addr = ((addr & ~1) << 1) | plane;
- s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: odd/even: [0x%x]\n", addr);
#endif
+ s->vram_ptr[addr] = val;
+ /* force full update for vga_draw_text when writing font memory */
+ if (((s->font_offsets[0] ^ addr) & ~0x7ffc) == 0 ||
+ ((s->font_offsets[1] ^ addr) & ~0x7ffc) == 0)
+ s->font_offsets[0] = -1;
cpu_physical_memory_set_dirty(s->vram_offset + addr);
}
} else {
@@ -776,14 +784,19 @@
do_write:
/* mask data according to sr[2] */
write_mask = mask16[s->sr[2]];
+#ifdef DEBUG_VGA_MEM
+ printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
+ addr * 4, write_mask, val);
+#endif
((uint32_t *)s->vram_ptr)[addr] =
(((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
(val & write_mask);
-#ifdef DEBUG_VGA_MEM
- printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
- addr * 4, write_mask, val);
-#endif
- cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
+ /* force full update for vga_draw_text when writing font memory */
+ if ((s->sr[2] & 4) &&
+ (((s->font_offsets[0] ^ ((addr << 2) + 2)) & ~0x7ffc) == 0 ||
+ ((s->font_offsets[1] ^ ((addr << 2) + 2)) & ~0x7ffc) == 0))
+ s->font_offsets[0] = -1;
+ cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
}
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image
2004-09-09 22:14 [Qemu-devel] [patch] incorrect VGA initialization, can provide image Piotr Krysik
@ 2004-09-10 10:20 ` Johannes Schindelin
2004-09-10 12:26 ` Piotr Krysik
0 siblings, 1 reply; 9+ messages in thread
From: Johannes Schindelin @ 2004-09-10 10:20 UTC (permalink / raw)
To: qemu-devel
Hi,
why not consolidate those identical lines (checking if the address is in
font memory) into a function?
Just a thought,
Dscho
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image
2004-09-10 10:20 ` Johannes Schindelin
@ 2004-09-10 12:26 ` Piotr Krysik
2004-09-10 13:17 ` Fabrice Bellard
0 siblings, 1 reply; 9+ messages in thread
From: Piotr Krysik @ 2004-09-10 12:26 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 526 bytes --]
Hi,
Thanks for your comment.
I updated the patch to factor common code from
vga_mem_writeb and remove goto. The source should
be easer to read now.
Regards,
Piotrek
--- Johannes Schindelin <Johannes.Schindelin@gmx.de>
wrote:
> Hi,
>
> why not consolidate those identical lines (checking
> if the address is in
> font memory) into a function?
>
> Just a thought,
> Dscho
__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - 100MB free storage!
http://promotions.yahoo.com/new_mail
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vga-update-2.patch --]
[-- Type: text/x-patch; name="vga-update-2.patch", Size: 3762 bytes --]
diff -ru qemu-snapshot-2004-08-04_23/hw/vga.c qemu-snapshot-2004-08-04_23-vga-update/hw/vga.c
--- qemu-snapshot-2004-08-04_23/hw/vga.c 2004-06-26 18:12:26.000000000 +0200
+++ qemu-snapshot-2004-08-04_23-vga-update/hw/vga.c 2004-09-10 13:50:36.000000000 +0200
@@ -658,12 +658,47 @@
return v;
}
+/* write byte to video ram */
+static inline void vram_writeb(VGAState *s, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef DEBUG_VGA_MEM
+ printf("vga: vram: [0x%x]\n", addr);
+#endif
+ s->vram_ptr[addr] = val;
+ /* force full update for vga_draw_text when writing font memory */
+ if (((s->font_offsets[0] ^ addr) & ~0x7ffc) == 0 ||
+ ((s->font_offsets[1] ^ addr) & ~0x7ffc) == 0)
+ s->font_offsets[0] = -1;
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+/* write to video ram using mask in sr[2] register */
+static inline void vram_writel_sr2(VGAState *s, target_phys_addr_t addr, uint32_t val)
+{
+ uint32_t *ptr;
+ uint32_t write_mask;
+
+ ptr = (uint32_t *)(s->vram_ptr + addr);
+ write_mask = mask16[s->sr[2]];
+#ifdef DEBUG_VGA_MEM
+ printf("vga: vram latch: [0x%x] mask=0x%08x val=0x%08x\n",
+ addr, write_mask, val);
+#endif
+ *ptr = (*ptr & ~write_mask) | (val & write_mask);
+ /* force full update for vga_draw_text when writing font memory */
+ if ((s->sr[2] & 4) &&
+ (((s->font_offsets[0] ^ (addr + 2)) & ~0x7ffc) == 0 ||
+ ((s->font_offsets[1] ^ (addr + 2)) & ~0x7ffc) == 0))
+ s->font_offsets[0] = -1;
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
/* called for accesses between 0xa0000 and 0xc0000 */
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
VGAState *s = opaque;
int memory_map_mode, plane, write_mode, b, func_select;
- uint32_t write_mask, bit_mask, set_mask;
+ uint32_t bit_mask, set_mask;
#ifdef DEBUG_VGA_MEM
printf("vga: [0x%x] = 0x%02x\n", addr, val);
@@ -696,22 +731,14 @@
/* chain 4 mode : simplest access */
plane = addr & 3;
if (s->sr[2] & (1 << plane)) {
- s->vram_ptr[addr] = val;
-#ifdef DEBUG_VGA_MEM
- printf("vga: chain4: [0x%x]\n", addr);
-#endif
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
+ vram_writeb(s, addr, val);
}
} else if (s->gr[5] & 0x10) {
/* odd/even mode (aka text mode mapping) */
plane = (s->gr[4] & 2) | (addr & 1);
if (s->sr[2] & (1 << plane)) {
addr = ((addr & ~1) << 1) | plane;
- s->vram_ptr[addr] = val;
-#ifdef DEBUG_VGA_MEM
- printf("vga: odd/even: [0x%x]\n", addr);
-#endif
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
+ vram_writeb(s, addr, val);
}
} else {
/* standard VGA latched access */
@@ -732,7 +759,8 @@
break;
case 1:
val = s->latch;
- goto do_write;
+ vram_writel_sr2(s, addr << 2, val);
+ return;
case 2:
val = mask16[val & 0x0f];
bit_mask = s->gr[8];
@@ -773,17 +801,7 @@
bit_mask |= bit_mask << 16;
val = (val & bit_mask) | (s->latch & ~bit_mask);
- do_write:
- /* mask data according to sr[2] */
- write_mask = mask16[s->sr[2]];
- ((uint32_t *)s->vram_ptr)[addr] =
- (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
- (val & write_mask);
-#ifdef DEBUG_VGA_MEM
- printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
- addr * 4, write_mask, val);
-#endif
- cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
+ vram_writel_sr2(s, addr << 2, val);
}
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image
2004-09-10 12:26 ` Piotr Krysik
@ 2004-09-10 13:17 ` Fabrice Bellard
2004-09-10 16:15 ` [Qemu-devel] IRIX host Johannes Schindelin
2004-09-10 18:34 ` [Qemu-devel] [patch] incorrect VGA initialization, can provide image Piotr Krysik
0 siblings, 2 replies; 9+ messages in thread
From: Fabrice Bellard @ 2004-09-10 13:17 UTC (permalink / raw)
To: qemu-devel
OK for the idea, but it is not acceptable to slow down the VGA write
functions just to detect the font change. Another solution must be found.
Fabrice.
Piotr Krysik wrote:
> Hi,
>
> Thanks for your comment.
>
> I updated the patch to factor common code from
> vga_mem_writeb and remove goto. The source should
> be easer to read now.
>
>
> Regards,
>
> Piotrek
>
> --- Johannes Schindelin <Johannes.Schindelin@gmx.de>
> wrote:
>
>
>>Hi,
>>
>>why not consolidate those identical lines (checking
>>if the address is in
>>font memory) into a function?
>>
>>Just a thought,
>>Dscho
>
>
>
>
>
> __________________________________
> Do you Yahoo!?
> New and Improved Yahoo! Mail - 100MB free storage!
> http://promotions.yahoo.com/new_mail
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] IRIX host
2004-09-10 13:17 ` Fabrice Bellard
@ 2004-09-10 16:15 ` Johannes Schindelin
2004-09-10 16:33 ` Paul Brook
2004-09-10 18:34 ` [Qemu-devel] [patch] incorrect VGA initialization, can provide image Piotr Krysik
1 sibling, 1 reply; 9+ messages in thread
From: Johannes Schindelin @ 2004-09-10 16:15 UTC (permalink / raw)
To: qemu-devel
Hi,
I played around a little bit with dyngen in order to understand it. For my
own pleasure I tried to compile it on IRIX (HOST_MIPS).
For your pleasure I write down what I learnt so far:
I soon found out that gcc produces RELOCA objects, not RELOC: I added
HOST_MIPS specific code in the places where an "unsupported cpu" error
occurred - 3 places in total - , and inserted a printf to show which
relocations were found. With RELOC, there were none, with RELOCA, there
were some. I know I am lazy, probably I would have found out by RTFM.
Also, it was quite easy to do the return finding stuff. I used "objdump
--disassemble-all i386-softmmu/op.o" to find out what the code looks like,
learning a little MIPS assembly on the way. Seems that "jr ra" is the
return statement, and "nop" are used to pad up to align to 8-byte
boundaries.
But now comes the biggest task: the relocations. In order to provide the
dynamically generated assembler code with the right parameters, C
functions for each assembler instruction are compiled into op.o, where a
placeholder is passed for each possible parameter. These parameters -
identified by their placeholders - will be filled in by the dynamic
compiler, dyngen_code(). This compiler is written by dyngen in the form of
a header file, op.h.
Unfortunately this does not seem to work on IRIX as I expected it would:
If I understand correctly, and you want to reference a parameter (say
__op_param1), then the address of __op_param1 gets stored somewhere in a
global table, and the 16-bit offset in that table is actually stored in
the code.
Is there somebody with a clue of MIPS assembly who can either affirm that
or correct me?
And if I am correct, how would you go about patching those relocations?
You certainly cannot modify address in the global table everytime you want
to use that (guest) assembly instruction. BTW, I did not succeed in
convincing my gcc (v3.0.4) to not use the global table.
Ciao,
Dscho
P.S.: When I understand completely what is going on, I will write it up
and polish it so that everybuddy is able to understand it.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] IRIX host
2004-09-10 16:15 ` [Qemu-devel] IRIX host Johannes Schindelin
@ 2004-09-10 16:33 ` Paul Brook
0 siblings, 0 replies; 9+ messages in thread
From: Paul Brook @ 2004-09-10 16:33 UTC (permalink / raw)
To: qemu-devel
On Friday 10 September 2004 17:15, Johannes Schindelin wrote:
> Hi,
>
> I played around a little bit with dyngen in order to understand it. For my
> own pleasure I tried to compile it on IRIX (HOST_MIPS).
>
> For your pleasure I write down what I learnt so far:
>
> I soon found out that gcc produces RELOCA objects, not RELOC: I added
> HOST_MIPS specific code in the places where an "unsupported cpu" error
> occurred - 3 places in total - , and inserted a printf to show which
> relocations were found. With RELOC, there were none, with RELOCA, there
> were some. I know I am lazy, probably I would have found out by RTFM.
>
> Also, it was quite easy to do the return finding stuff. I used "objdump
> --disassemble-all i386-softmmu/op.o" to find out what the code looks like,
> learning a little MIPS assembly on the way. Seems that "jr ra" is the
> return statement, and "nop" are used to pad up to align to 8-byte
> boundaries.
IIRC MIPS has "branch delay slots", so these may not just be padding.
> But now comes the biggest task: the relocations. In order to provide the
> dynamically generated assembler code with the right parameters, C
> functions for each assembler instruction are compiled into op.o, where a
> placeholder is passed for each possible parameter. These parameters -
> identified by their placeholders - will be filled in by the dynamic
> compiler, dyngen_code(). This compiler is written by dyngen in the form of
> a header file, op.h.
>
> Unfortunately this does not seem to work on IRIX as I expected it would:
> If I understand correctly, and you want to reference a parameter (say
> __op_param1), then the address of __op_param1 gets stored somewhere in a
> global table, and the 16-bit offset in that table is actually stored in
> the code.
This sounds like you're generating PIC code. A few options spring to mind:
- Generate non-pic code. I don't know if MIPS/IRIX has a non-pic option.
- Change the definition of __op_param1 so it generates a more convenient
relocation.
- Do something clever with the GOT-indirect relocation. eg. turn it into a
pc-relative reference to a constant pool.
Paul
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image
2004-09-10 13:17 ` Fabrice Bellard
2004-09-10 16:15 ` [Qemu-devel] IRIX host Johannes Schindelin
@ 2004-09-10 18:34 ` Piotr Krysik
2004-09-13 21:29 ` Fabrice Bellard
1 sibling, 1 reply; 9+ messages in thread
From: Piotr Krysik @ 2004-09-10 18:34 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 558 bytes --]
Update of font memory is now detected during
vga_draw_text. I also added time-to-live for
font cache to limit memory bandwidth required
for cache validation (overkill?).
Please review.
Piotrek
--- Fabrice Bellard <fabrice@bellard.org> wrote:
> OK for the idea, but it is not acceptable to slow
> down the VGA write functions just to detect the
> font change. Another solution must be found.
>
> Fabrice.
__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - Send 10MB messages!
http://promotions.yahoo.com/new_mail
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vga-update-3.patch --]
[-- Type: text/x-patch; name="vga-update-3.patch", Size: 5789 bytes --]
diff -ru qemu-snapshot-2004-08-04_23/hw/vga.c qemu-snapshot-2004-08-04_23-vga-update/hw/vga.c
--- qemu-snapshot-2004-08-04_23/hw/vga.c 2004-06-26 18:12:26.000000000 +0200
+++ qemu-snapshot-2004-08-04_23-vga-update/hw/vga.c 2004-09-10 20:11:00.000000000 +0200
@@ -935,6 +935,60 @@
return full_update;
}
+/* return true if the font was modified */
+static int update_font_cache(uint8_t *font_ptr, uint8_t *vram_font_ptr)
+{
+ int full_update;
+ uint8_t *font_end;
+
+ full_update = 0;
+ font_end = font_ptr + 0x2000;
+ while (font_ptr < font_end) {
+ if (*font_ptr != *vram_font_ptr) {
+ *font_ptr = *vram_font_ptr;
+ full_update = 1;
+ }
+ font_ptr ++;
+ vram_font_ptr += 4;
+ }
+ return full_update;
+}
+
+/* return true if any of the font 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 = update_font_cache(s->font[0], s->vram_ptr + offset);
+ /* font B */
+ offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
+ full_update |= update_font_cache(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 for next update */
+ } else {
+ s->font_ttl = s->font_age;
+ s->font_age += s->font_ttl; /* age for next update */
+ if (s->font_age > 16)
+ s->font_age = 16; /* limit ttl for next update */
+ }
+#if defined(DEBUG_VGA)
+ printf("vga: font cache 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 +1116,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 +1127,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 +1218,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 +1636,8 @@
s->cr[0x30] = 0xe1;
#endif
s->graphic_mode = -1; /* force full update */
+ s->font_age = 0;
+ s->font_ttl = 0;
}
static CPUReadMemoryFunc *vga_mem_read[3] = {
diff -ru qemu-snapshot-2004-08-04_23/hw/vga_int.h qemu-snapshot-2004-08-04_23-vga-update/hw/vga_int.h
--- qemu-snapshot-2004-08-04_23/hw/vga_int.h 2004-06-08 02:59:19.000000000 +0200
+++ qemu-snapshot-2004-08-04_23-vga-update/hw/vga_int.h 2004-09-10 19:29:19.000000000 +0200
@@ -109,8 +109,10 @@
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_age; \
+ uint8_t font_ttl; \
uint8_t shift_control; \
uint8_t double_scan; \
uint32_t line_offset; \
diff -ru qemu-snapshot-2004-08-04_23/hw/vga_template.h qemu-snapshot-2004-08-04_23-vga-update/hw/vga_template.h
--- qemu-snapshot-2004-08-04_23/hw/vga_template.h 2004-06-21 18:56:45.000000000 +0200
+++ qemu-snapshot-2004-08-04_23-vga-update/hw/vga_template.h 2004-09-10 17:58:31.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);
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image
2004-09-10 18:34 ` [Qemu-devel] [patch] incorrect VGA initialization, can provide image Piotr Krysik
@ 2004-09-13 21:29 ` Fabrice Bellard
2004-10-11 7:40 ` Piotr Krysik
0 siblings, 1 reply; 9+ messages in thread
From: Fabrice Bellard @ 2004-09-13 21:29 UTC (permalink / raw)
To: qemu-devel
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.
Piotr Krysik wrote:
> Update of font memory is now detected during
> vga_draw_text. I also added time-to-live for
> font cache to limit memory bandwidth required
> for cache validation (overkill?).
>
> Please review.
>
>
> Piotrek
>
> --- Fabrice Bellard <fabrice@bellard.org> wrote:
>
>
>>OK for the idea, but it is not acceptable to slow
>>down the VGA write functions just to detect the
>>font change. Another solution must be found.
>>
>>Fabrice.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [patch] incorrect VGA initialization, can provide image
2004-09-13 21:29 ` Fabrice Bellard
@ 2004-10-11 7:40 ` Piotr Krysik
0 siblings, 0 replies; 9+ messages in thread
From: Piotr Krysik @ 2004-10-11 7:40 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 432 bytes --]
Hi!
Done. Sorry for the delay - I was quite busy last
weeks.
Piotrek
--- Fabrice Bellard <fabrice@bellard.org> 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
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vga-update-5.patch --]
[-- Type: text/x-patch; name="vga-update-5.patch", Size: 11079 bytes --]
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 {
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2004-10-11 7:48 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-09 22:14 [Qemu-devel] [patch] incorrect VGA initialization, can provide image Piotr Krysik
2004-09-10 10:20 ` Johannes Schindelin
2004-09-10 12:26 ` Piotr Krysik
2004-09-10 13:17 ` Fabrice Bellard
2004-09-10 16:15 ` [Qemu-devel] IRIX host Johannes Schindelin
2004-09-10 16:33 ` Paul Brook
2004-09-10 18:34 ` [Qemu-devel] [patch] incorrect VGA initialization, can provide image Piotr Krysik
2004-09-13 21:29 ` Fabrice Bellard
2004-10-11 7:40 ` Piotr Krysik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).