diff options
-rw-r--r-- | hw/vga.c | 58 | ||||
-rw-r--r-- | hw/vga_template.h | 12 |
2 files changed, 38 insertions, 32 deletions
@@ -82,7 +82,6 @@ typedef struct VGAState { uint8_t palette[768]; /* display refresh support */ - /* tell for each page if it has been updated since the last time */ DisplayState *ds; uint32_t font_offsets[2]; int graphic_mode; @@ -94,6 +93,7 @@ typedef struct VGAState { uint32_t last_width, last_height; uint8_t cursor_start, cursor_end; uint32_t cursor_offset; + /* tell for each page if it has been updated since the last time */ uint8_t vram_updated[VGA_RAM_SIZE / 4096]; uint32_t last_palette[256]; #define CH_ATTR_SIZE (132 * 60) @@ -763,13 +763,7 @@ static int update_basic_params(VGAState *s) v = (s->cr[0x43] >> 2) & 1; /* S3 extension */ line_offset = s->cr[0x13] | (v << 8); line_offset <<= 3; -#if 0 - /* XXX: check this - inconsistent with some VGA docs */ - if (s->cr[0x14] & 0x40) - line_offset <<= 2; - else if (!(s->cr[0x17] & 0x40)) - line_offset <<= 1; -#endif + /* starting address */ start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8); start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */ @@ -917,7 +911,7 @@ static void vga_draw_text(VGAState *s, int full_update) s->cursor_start = s->cr[0xa]; s->cursor_end = s->cr[0xb]; } - cursor_ptr = s->vram_ptr + cursor_offset * 4; + cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4; depth_index = get_depth_index(s->ds->depth); vga_draw_glyph8 = vga_draw_glyph8_table[depth_index]; @@ -1035,18 +1029,17 @@ static vga_draw_line_func *vga_draw_line_table[4 * 6] = { */ static void vga_draw_graphic(VGAState *s, int full_update) { - int y, update, y_min, y_max, page_min, page_max, linesize; - int width, height, shift_control, line_offset, page0, page1; + int y, update, page_min, page_max, linesize, y_start; + int width, height, shift_control, line_offset, page0, page1, bwidth; uint8_t *d; - uint32_t v, *palette, addr1, addr; + uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line; full_update |= update_palette16(s); - palette = s->last_palette; full_update |= update_basic_params(s); - width = (s->cr[0x01] + 1); + width = (s->cr[0x01] + 1) * 8; height = s->cr[0x12] | ((s->cr[0x07] & 0x02) << 7) | ((s->cr[0x07] & 0x40) << 3); @@ -1054,6 +1047,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) if (width != s->last_width || height != s->last_height) { + dpy_resize(s->ds, width, height); s->last_width = width; s->last_height = height; full_update = 1; @@ -1066,44 +1060,52 @@ static void vga_draw_graphic(VGAState *s, int full_update) } if (shift_control == 0) - v = 1; /* 4 bit/pxeil */ + v = 1; /* 4 bit/pixel */ else if (shift_control == 1) v = 0; /* 2 bit/pixel */ else v = 2; /* 8 bit/pixel */ - vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)]; line_offset = s->line_offset; addr1 = (s->start_addr * 4); - y_min = height; - y_max = -1; + bwidth = width * 4; + y_start = -1; page_min = 0x7fffffff; page_max = -1; d = s->ds->data; linesize = s->ds->linesize; for(y = 0; y < height; y++) { addr = addr1; - if (s->cr[0x17] & 1) { + if (!(s->cr[0x17] & 1)) { /* CGA compatibility handling */ addr = (addr & ~0x2000) | ((y & 1) << 13); } - if (s->cr[0x17] & 2) { + if (!(s->cr[0x17] & 2)) { addr = (addr & ~0x4000) | ((y & 2) << 13); } page0 = addr >> 12; - page1 = (addr + width - 1) >> 12; + page1 = (addr + bwidth - 1) >> 12; update = full_update | s->vram_updated[page0] | s->vram_updated[page1]; + if ((page1 - page0) > 1) { + /* if wide line, can use another page */ + update |= s->vram_updated[page0 + 1]; + } if (update) { - if (y < y_min) - y_min = y; - if (y > y_max) - y_max = y; + if (y_start < 0) + y_start = y; if (page0 < page_min) page_min = page0; if (page1 > page_max) page_max = page1; vga_draw_line(s, d, s->vram_ptr + addr, width); + } else { + if (y_start >= 0) { + /* flush to display */ + dpy_update(s->ds, 0, y_start, + width, y - y_start); + y_start = -1; + } } if (y == s->line_compare) { addr1 = 0; @@ -1112,7 +1114,11 @@ static void vga_draw_graphic(VGAState *s, int full_update) } d += linesize; } - + if (y_start >= 0) { + /* flush to display */ + dpy_update(s->ds, 0, y_start, + width, y - y_start); + } /* reset modified pages */ if (page_max != -1) { memset(s->vram_updated + page_min, 0, page_max - page_min + 1); diff --git a/hw/vga_template.h b/hw/vga_template.h index dd6581e37d..2f658b4d15 100644 --- a/hw/vga_template.h +++ b/hw/vga_template.h @@ -84,9 +84,9 @@ static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize, v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; ((uint32_t *)d)[3] = v; if (dup9) - *(uint8_t *)(d + 8) = v >> (24 * (1 - BIG)); + ((uint8_t *)d)[8] = v >> (24 * (1 - BIG)); else - *(uint8_t *)(d + 8) = bgcol; + ((uint8_t *)d)[8] = bgcol; #elif BPP == 2 ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; @@ -95,9 +95,9 @@ static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize, v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; ((uint32_t *)d)[3] = v; if (dup9) - *(uint16_t *)(d + 8) = v >> (16 * (1 - BIG)); + ((uint16_t *)d)[8] = v >> (16 * (1 - BIG)); else - *(uint16_t *)(d + 8) = bgcol; + ((uint16_t *)d)[8] = bgcol; #else ((uint32_t *)d)[0] = ((-(font_data >> 7)) & xorcol) ^ bgcol; ((uint32_t *)d)[1] = ((-(font_data >> 6) & 1) & xorcol) ^ bgcol; @@ -109,9 +109,9 @@ static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize, v = ((-(font_data >> 0) & 1) & xorcol) ^ bgcol; ((uint32_t *)d)[7] = v; if (dup9) - *(uint32_t *)(d + 8) = v; + ((uint32_t *)d)[8] = v; else - *(uint32_t *)(d + 8) = bgcol; + ((uint32_t *)d)[8] = bgcol; #endif font_ptr += 4; d += linesize; |