diff --git a/hw/vga.c b/hw/vga.c index 4adba3cdd7..23695f506d 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -852,14 +852,6 @@ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsign #define DEPTH 32 #include "vga_template.h" -static inline int c6_to_8(int v) -{ - int b; - v &= 0x3f; - b = v & 1; - return (v << 2) | (b << 1) | b; -} - static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b) { unsigned int col; @@ -1309,11 +1301,20 @@ static int vga_get_bpp(VGAState *s) return ret; } +void vga_invalidate_scanlines(VGAState *s, int y1, int y2) +{ + int y; + if (y1 >= VGA_MAX_HEIGHT) + return; + if (y2 >= VGA_MAX_HEIGHT) + y2 = VGA_MAX_HEIGHT; + for(y = y1; y < y2; y++) { + s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); + } +} + /* * graphic modes - * Missing: - * - double scan - * - double width */ static void vga_draw_graphic(VGAState *s, int full_update) { @@ -1400,7 +1401,9 @@ static void vga_draw_graphic(VGAState *s, int full_update) s->last_height = height; full_update = 1; } - + if (s->cursor_invalidate) + s->cursor_invalidate(s); + line_offset = s->line_offset; #if 0 printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n", @@ -1433,6 +1436,8 @@ static void vga_draw_graphic(VGAState *s, int full_update) /* if wide line, can use another page */ update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE); } + /* explicit invalidation for the hardware cursor */ + update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; if (update) { if (y_start < 0) y_start = y; @@ -1441,6 +1446,8 @@ static void vga_draw_graphic(VGAState *s, int full_update) if (page1 > page_max) page_max = page1; vga_draw_line(s, d, s->vram_ptr + addr, width); + if (s->cursor_draw_line) + s->cursor_draw_line(s, d, y); } else { if (y_start >= 0) { /* flush to display */ @@ -1476,6 +1483,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) if (page_max != -1) { cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE); } + memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4); } static void vga_draw_blank(VGAState *s, int full_update) diff --git a/hw/vga_int.h b/hw/vga_int.h index 8fb78a0df7..0d0f3edee1 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -72,6 +72,7 @@ #endif /* !CONFIG_BOCHS_VBE */ #define CH_ATTR_SIZE (160 * 100) +#define VGA_MAX_HEIGHT 1024 #define VGA_STATE_COMMON \ uint8_t *vram_ptr; \ @@ -119,6 +120,10 @@ uint32_t cursor_offset; \ unsigned int (*rgb_to_pixel)(unsigned int r, \ unsigned int g, unsigned b); \ + /* hardware mouse cursor support */ \ + uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \ + void (*cursor_invalidate)(struct VGAState *s); \ + void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \ /* tell for each page if it has been updated since the last time */ \ uint32_t last_palette[256]; \ uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ @@ -128,10 +133,32 @@ typedef struct VGAState { VGA_STATE_COMMON } VGAState; +static inline int c6_to_8(int v) +{ + int b; + v &= 0x3f; + b = v & 1; + return (v << 2) | (b << 1) | b; +} + void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size); 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_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); +void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); +void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); extern const uint8_t sr_mask[8]; extern const uint8_t gr_mask[16]; diff --git a/hw/vga_template.h b/hw/vga_template.h index 766257c09e..721abcb828 100644 --- a/hw/vga_template.h +++ b/hw/vga_template.h @@ -434,6 +434,74 @@ static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d, #endif } +#if DEPTH != 15 +void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, + const uint8_t *src1, + int poffset, int w, + unsigned int color0, + unsigned int color1, + unsigned int color_xor) +{ + const uint8_t *plane0, *plane1; + int x, b0, b1; + uint8_t *d; + + d = d1; + plane0 = src1; + plane1 = src1 + poffset; + for(x = 0; x < w; x++) { + b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; + b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; +#if DEPTH == 8 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + d[0] ^= color_xor; + break; + case 2: + d[0] = color0; + break; + case 3: + d[0] = color1; + break; + } +#elif DEPTH == 16 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint16_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint16_t *)d)[0] = color0; + break; + case 3: + ((uint16_t *)d)[0] = color1; + break; + } +#elif DEPTH == 32 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint32_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint32_t *)d)[0] = color0; + break; + case 3: + ((uint32_t *)d)[0] = color1; + break; + } +#else +#error unsupported depth +#endif + d += (DEPTH / 8); + } +} +#endif + #undef PUT_PIXEL2 #undef DEPTH #undef BPP