diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 27252646bc7817aa8b79c4fd2042769f6627b7cc..3a53f2039241ad459d7db8d6787dfd271a8f361b 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -202,8 +202,6 @@ typedef struct CirrusVGAState { uint32_t cirrus_bank_base[2]; uint32_t cirrus_bank_limit[2]; uint8_t cirrus_hidden_palette[48]; - uint32_t hw_cursor_x; - uint32_t hw_cursor_y; int cirrus_blt_pixelwidth; int cirrus_blt_width; int cirrus_blt_height; @@ -1328,7 +1326,7 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val) case 0xd0: case 0xf0: // Graphics Cursor X s->vga.sr[0x10] = val; - s->hw_cursor_x = (val << 3) | (s->vga.sr_index >> 5); + s->vga.hw_cursor_x = (val << 3) | (s->vga.sr_index >> 5); break; case 0x11: case 0x31: @@ -1339,7 +1337,7 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val) case 0xd1: case 0xf1: // Graphics Cursor Y s->vga.sr[0x11] = val; - s->hw_cursor_y = (val << 3) | (s->vga.sr_index >> 5); + s->vga.hw_cursor_y = (val << 3) | (s->vga.sr_index >> 5); break; case 0x07: // Extended Sequencer Mode cirrus_update_memory_access(s); @@ -1351,7 +1349,6 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val) case 0x0d: // VCLK 2 case 0x0e: // VCLK 3 case 0x0f: // DRAM Control - case 0x12: // Graphics Cursor Attribute case 0x13: // Graphics Cursor Pattern Address case 0x14: // Scratch Register 2 case 0x15: // Scratch Register 3 @@ -1370,6 +1367,14 @@ static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val) s->vga.sr_index, val); #endif break; + case 0x12: // Graphics Cursor Attribute + s->vga.sr[0x12] = val; + s->vga.force_shadow = !!(val & CIRRUS_CURSOR_SHOW); +#ifdef DEBUG_CIRRUS + printf("cirrus: cursor ctl SR12=%02x (force shadow: %d)\n", + val, s->vga.force_shadow); +#endif + break; case 0x17: // Configuration Readback and Extended Control s->vga.sr[s->vga.sr_index] = (s->vga.sr[s->vga.sr_index] & 0x38) | (val & 0xc7); @@ -2188,14 +2193,14 @@ static void cirrus_cursor_invalidate(VGACommonState *s1) } /* invalidate last cursor and new cursor if any change */ if (s->last_hw_cursor_size != size || - s->last_hw_cursor_x != s->hw_cursor_x || - s->last_hw_cursor_y != s->hw_cursor_y) { + s->last_hw_cursor_x != s->vga.hw_cursor_x || + s->last_hw_cursor_y != s->vga.hw_cursor_y) { invalidate_cursor1(s); s->last_hw_cursor_size = size; - s->last_hw_cursor_x = s->hw_cursor_x; - s->last_hw_cursor_y = s->hw_cursor_y; + s->last_hw_cursor_x = s->vga.hw_cursor_x; + s->last_hw_cursor_y = s->vga.hw_cursor_y; /* compute the real cursor min and max y */ cirrus_cursor_compute_yrange(s); invalidate_cursor1(s); @@ -2252,14 +2257,15 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) } else { h = 32; } - if (scr_y < s->hw_cursor_y || - scr_y >= (s->hw_cursor_y + h)) + if (scr_y < s->vga.hw_cursor_y || + scr_y >= (s->vga.hw_cursor_y + h)) { return; + } src = s->vga.vram_ptr + s->real_vram_size - 16 * 1024; if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) { src += (s->vga.sr[0x13] & 0x3c) * 256; - src += (scr_y - s->hw_cursor_y) * 16; + src += (scr_y - s->vga.hw_cursor_y) * 16; poffset = 8; content = ((uint32_t *)src)[0] | ((uint32_t *)src)[1] | @@ -2267,7 +2273,7 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) ((uint32_t *)src)[3]; } else { src += (s->vga.sr[0x13] & 0x3f) * 256; - src += (scr_y - s->hw_cursor_y) * 4; + src += (scr_y - s->vga.hw_cursor_y) * 4; poffset = 128; @@ -2279,10 +2285,10 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y) return; w = h; - x1 = s->hw_cursor_x; + x1 = s->vga.hw_cursor_x; if (x1 >= s->vga.last_scr_width) return; - x2 = s->hw_cursor_x + w; + x2 = s->vga.hw_cursor_x + w; if (x2 > s->vga.last_scr_width) x2 = s->vga.last_scr_width; w = x2 - x1; @@ -2771,8 +2777,8 @@ static const VMStateDescription vmstate_cirrus_vga = { VMSTATE_INT32(vga.bank_offset, CirrusVGAState), VMSTATE_UINT8(cirrus_hidden_dac_lockindex, CirrusVGAState), VMSTATE_UINT8(cirrus_hidden_dac_data, CirrusVGAState), - VMSTATE_UINT32(hw_cursor_x, CirrusVGAState), - VMSTATE_UINT32(hw_cursor_y, CirrusVGAState), + VMSTATE_UINT32(vga.hw_cursor_x, CirrusVGAState), + VMSTATE_UINT32(vga.hw_cursor_y, CirrusVGAState), /* XXX: we do not save the bitblt state - we assume we do not save the state when the blitter is active */ VMSTATE_END_OF_LIST() diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index db922f1843a7b1892666580aae5a1d8171cd0184..53739e4f792c05d4ef4d305c0c4499a1758cde6b 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -321,6 +321,7 @@ static void secondary_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_vga_pci; dc->props = secondary_pci_properties; dc->reset = pci_secondary_vga_reset; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } static const TypeInfo vga_info = { diff --git a/hw/display/vga.c b/hw/display/vga.c index 52eaf056594dbb9fb1f35fb3141685ff4224d650..a620c0786492d4fc6781b1b0964613bc9d978190 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1436,6 +1436,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line = NULL; + bool share_surface; #ifdef HOST_WORDS_BIGENDIAN bool byteswap = !s->big_endian_fb; #else @@ -1479,21 +1480,33 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) } depth = s->get_bpp(s); + + share_surface = (!s->force_shadow) && + ( depth == 32 || (depth == 16 && !byteswap) ); if (s->line_offset != s->last_line_offset || disp_width != s->last_width || height != s->last_height || s->last_depth != depth || - s->last_byteswap != byteswap) { - if (depth == 32 || (depth == 16 && !byteswap)) { + s->last_byteswap != byteswap || + share_surface != is_buffer_shared(surface)) { + if (share_surface) { pixman_format_code_t format = qemu_default_pixman_format(depth, !byteswap); surface = qemu_create_displaysurface_from(disp_width, height, format, s->line_offset, s->vram_ptr + (s->start_addr * 4)); dpy_gfx_replace_surface(s->con, surface); +#ifdef DEBUG_VGA + printf("VGA: Using shared surface for depth=%d swap=%d\n", + depth, byteswap); +#endif } else { qemu_console_resize(s->con, disp_width, height); surface = qemu_console_surface(s->con); +#ifdef DEBUG_VGA + printf("VGA: Using shadow surface for depth=%d swap=%d\n", + depth, byteswap); +#endif } s->last_scr_width = disp_width; s->last_scr_height = height; diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index ed69e064a8a4631af81ac702bf8721807bc27edd..fcfcc5f431b69f66016bf01b8b0170dc890a8595 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -151,6 +151,7 @@ typedef struct VGACommonState { uint32_t last_scr_width, last_scr_height; /* in pixels */ uint32_t last_depth; /* in bits */ bool last_byteswap; + bool force_shadow; uint8_t cursor_start, cursor_end; bool cursor_visible_phase; int64_t cursor_blink_time; @@ -162,6 +163,8 @@ typedef struct VGACommonState { bool default_endian_fb; /* hardware mouse cursor support */ uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; + uint32_t hw_cursor_x; + uint32_t hw_cursor_y; void (*cursor_invalidate)(struct VGACommonState *s); void (*cursor_draw_line)(struct VGACommonState *s, uint8_t *d, int y); /* tell for each page if it has been updated since the last time */