Commit 9586fefefe383a9aa25ad99bde9a6b240309ca33

Authored by aliguori
1 parent b9e82a59

Fix display breakage when resizing the screen (v2) (Avi Kivity)

When the vga resolution changes, a new display surface is not allocated
immediately; instead that is deferred until the next update.  However,
if we're running without a display client attached, that won't happen
and the next bitblt is likely to cause a segfault by overflowing the
display surface.

Fix by reallocating the display immediately when the resolution changes.

Tested with (Windows|Linux) x (cirrus|std) x (curses|sdl).

Changes from v1:
 - fix segfault when switching virtual consoles with curses

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6989 c046a42c-6fe2-441c-8c8c-71466251a162
hw/cirrus_vga.c
@@ -1392,6 +1392,8 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) @@ -1392,6 +1392,8 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1392 break; 1392 break;
1393 } 1393 }
1394 1394
  1395 + vga_update_resolution((VGAState *)s);
  1396 +
1395 return CIRRUS_HOOK_HANDLED; 1397 return CIRRUS_HOOK_HANDLED;
1396 } 1398 }
1397 1399
@@ -1419,6 +1421,7 @@ static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value) @@ -1419,6 +1421,7 @@ static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1419 #endif 1421 #endif
1420 } 1422 }
1421 s->cirrus_hidden_dac_lockindex = 0; 1423 s->cirrus_hidden_dac_lockindex = 0;
  1424 + vga_update_resolution((VGAState *)s);
1422 } 1425 }
1423 1426
1424 /*************************************** 1427 /***************************************
@@ -1705,6 +1708,8 @@ cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value) @@ -1705,6 +1708,8 @@ cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1705 break; 1708 break;
1706 } 1709 }
1707 1710
  1711 + vga_update_resolution((VGAState *)s);
  1712 +
1708 return CIRRUS_HOOK_HANDLED; 1713 return CIRRUS_HOOK_HANDLED;
1709 } 1714 }
1710 1715
@@ -2830,6 +2835,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -2830,6 +2835,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2830 if (s->ar_flip_flop == 0) { 2835 if (s->ar_flip_flop == 0) {
2831 val &= 0x3f; 2836 val &= 0x3f;
2832 s->ar_index = val; 2837 s->ar_index = val;
  2838 + vga_update_resolution((VGAState *)s);
2833 } else { 2839 } else {
2834 index = s->ar_index & 0x1f; 2840 index = s->ar_index & 0x1f;
2835 switch (index) { 2841 switch (index) {
@@ -2923,6 +2929,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -2923,6 +2929,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2923 /* can always write bit 4 of CR7 */ 2929 /* can always write bit 4 of CR7 */
2924 if (s->cr_index == 7) 2930 if (s->cr_index == 7)
2925 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); 2931 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
  2932 + vga_update_resolution((VGAState *)s);
2926 return; 2933 return;
2927 } 2934 }
2928 switch (s->cr_index) { 2935 switch (s->cr_index) {
@@ -2951,6 +2958,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -2951,6 +2958,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2951 s->update_retrace_info((VGAState *) s); 2958 s->update_retrace_info((VGAState *) s);
2952 break; 2959 break;
2953 } 2960 }
  2961 + vga_update_resolution((VGAState *)s);
2954 break; 2962 break;
2955 case 0x3ba: 2963 case 0x3ba:
2956 case 0x3da: 2964 case 0x3da:
@@ -3157,7 +3165,8 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) @@ -3157,7 +3165,8 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
3157 3165
3158 cirrus_update_memory_access(s); 3166 cirrus_update_memory_access(s);
3159 /* force refresh */ 3167 /* force refresh */
3160 - s->graphic_mode = -1; 3168 + vga_update_resolution((VGAState *)s);
  3169 + s->want_full_update = 1;
3161 cirrus_update_bank_ptr(s, 0); 3170 cirrus_update_bank_ptr(s, 0);
3162 cirrus_update_bank_ptr(s, 1); 3171 cirrus_update_bank_ptr(s, 1);
3163 return 0; 3172 return 0;
hw/vga.c
@@ -36,6 +36,10 @@ @@ -36,6 +36,10 @@
36 36
37 //#define DEBUG_BOCHS_VBE 37 //#define DEBUG_BOCHS_VBE
38 38
  39 +#define GMODE_TEXT 0
  40 +#define GMODE_GRAPH 1
  41 +#define GMODE_BLANK 2
  42 +
39 /* force some bits to zero */ 43 /* force some bits to zero */
40 const uint8_t sr_mask[8] = { 44 const uint8_t sr_mask[8] = {
41 0x03, 45 0x03,
@@ -393,6 +397,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -393,6 +397,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
393 if (s->ar_flip_flop == 0) { 397 if (s->ar_flip_flop == 0) {
394 val &= 0x3f; 398 val &= 0x3f;
395 s->ar_index = val; 399 s->ar_index = val;
  400 + vga_update_resolution(s);
396 } else { 401 } else {
397 index = s->ar_index & 0x1f; 402 index = s->ar_index & 0x1f;
398 switch(index) { 403 switch(index) {
@@ -433,6 +438,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -433,6 +438,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
433 #endif 438 #endif
434 s->sr[s->sr_index] = val & sr_mask[s->sr_index]; 439 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
435 if (s->sr_index == 1) s->update_retrace_info(s); 440 if (s->sr_index == 1) s->update_retrace_info(s);
  441 + vga_update_resolution(s);
436 break; 442 break;
437 case 0x3c7: 443 case 0x3c7:
438 s->dac_read_index = val; 444 s->dac_read_index = val;
@@ -460,6 +466,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -460,6 +466,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
460 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); 466 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
461 #endif 467 #endif
462 s->gr[s->gr_index] = val & gr_mask[s->gr_index]; 468 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
  469 + vga_update_resolution(s);
463 break; 470 break;
464 case 0x3b4: 471 case 0x3b4:
465 case 0x3d4: 472 case 0x3d4:
@@ -475,6 +482,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -475,6 +482,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
475 /* can always write bit 4 of CR7 */ 482 /* can always write bit 4 of CR7 */
476 if (s->cr_index == 7) 483 if (s->cr_index == 7)
477 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); 484 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
  485 + vga_update_resolution(s);
478 return; 486 return;
479 } 487 }
480 switch(s->cr_index) { 488 switch(s->cr_index) {
@@ -502,6 +510,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -502,6 +510,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
502 s->update_retrace_info(s); 510 s->update_retrace_info(s);
503 break; 511 break;
504 } 512 }
  513 + vga_update_resolution(s);
505 break; 514 break;
506 case 0x3ba: 515 case 0x3ba:
507 case 0x3da: 516 case 0x3da:
@@ -581,11 +590,13 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) @@ -581,11 +590,13 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
581 if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) { 590 if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
582 s->vbe_regs[s->vbe_index] = val; 591 s->vbe_regs[s->vbe_index] = val;
583 } 592 }
  593 + vga_update_resolution(s);
584 break; 594 break;
585 case VBE_DISPI_INDEX_YRES: 595 case VBE_DISPI_INDEX_YRES:
586 if (val <= VBE_DISPI_MAX_YRES) { 596 if (val <= VBE_DISPI_MAX_YRES) {
587 s->vbe_regs[s->vbe_index] = val; 597 s->vbe_regs[s->vbe_index] = val;
588 } 598 }
  599 + vga_update_resolution(s);
589 break; 600 break;
590 case VBE_DISPI_INDEX_BPP: 601 case VBE_DISPI_INDEX_BPP:
591 if (val == 0) 602 if (val == 0)
@@ -594,6 +605,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) @@ -594,6 +605,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
594 val == 16 || val == 24 || val == 32) { 605 val == 16 || val == 24 || val == 32) {
595 s->vbe_regs[s->vbe_index] = val; 606 s->vbe_regs[s->vbe_index] = val;
596 } 607 }
  608 + vga_update_resolution(s);
597 break; 609 break;
598 case VBE_DISPI_INDEX_BANK: 610 case VBE_DISPI_INDEX_BANK:
599 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { 611 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
@@ -662,6 +674,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) @@ -662,6 +674,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
662 } 674 }
663 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0; 675 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
664 s->vbe_regs[s->vbe_index] = val; 676 s->vbe_regs[s->vbe_index] = val;
  677 + vga_update_resolution(s);
665 break; 678 break;
666 case VBE_DISPI_INDEX_VIRT_WIDTH: 679 case VBE_DISPI_INDEX_VIRT_WIDTH:
667 { 680 {
@@ -682,6 +695,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) @@ -682,6 +695,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
682 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h; 695 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
683 s->vbe_line_offset = line_offset; 696 s->vbe_line_offset = line_offset;
684 } 697 }
  698 + vga_update_resolution(s);
685 break; 699 break;
686 case VBE_DISPI_INDEX_X_OFFSET: 700 case VBE_DISPI_INDEX_X_OFFSET:
687 case VBE_DISPI_INDEX_Y_OFFSET: 701 case VBE_DISPI_INDEX_Y_OFFSET:
@@ -696,6 +710,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) @@ -696,6 +710,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
696 s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); 710 s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
697 s->vbe_start_addr >>= 2; 711 s->vbe_start_addr >>= 2;
698 } 712 }
  713 + vga_update_resolution(s);
699 break; 714 break;
700 default: 715 default:
701 break; 716 break;
@@ -1302,7 +1317,6 @@ static void vga_draw_text(VGAState *s, int full_update) @@ -1302,7 +1317,6 @@ static void vga_draw_text(VGAState *s, int full_update)
1302 s->plane_updated = 0; 1317 s->plane_updated = 0;
1303 full_update = 1; 1318 full_update = 1;
1304 } 1319 }
1305 - full_update |= update_basic_params(s);  
1306 1320
1307 line_offset = s->line_offset; 1321 line_offset = s->line_offset;
1308 s1 = s->vram_ptr + (s->start_addr * 4); 1322 s1 = s->vram_ptr + (s->start_addr * 4);
@@ -1314,18 +1328,6 @@ static void vga_draw_text(VGAState *s, int full_update) @@ -1314,18 +1328,6 @@ static void vga_draw_text(VGAState *s, int full_update)
1314 return; 1328 return;
1315 } 1329 }
1316 1330
1317 - if (width != s->last_width || height != s->last_height ||  
1318 - cw != s->last_cw || cheight != s->last_ch || s->last_depth) {  
1319 - s->last_scr_width = width * cw;  
1320 - s->last_scr_height = height * cheight;  
1321 - qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);  
1322 - s->last_depth = 0;  
1323 - s->last_width = width;  
1324 - s->last_height = height;  
1325 - s->last_ch = cheight;  
1326 - s->last_cw = cw;  
1327 - full_update = 1;  
1328 - }  
1329 s->rgb_to_pixel = 1331 s->rgb_to_pixel =
1330 rgb_to_pixel_dup_table[get_depth_index(s->ds)]; 1332 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1331 full_update |= update_palette16(s); 1333 full_update |= update_palette16(s);
@@ -1582,39 +1584,21 @@ static void vga_sync_dirty_bitmap(VGAState *s) @@ -1582,39 +1584,21 @@ static void vga_sync_dirty_bitmap(VGAState *s)
1582 vga_dirty_log_start(s); 1584 vga_dirty_log_start(s);
1583 } 1585 }
1584 1586
1585 -/*  
1586 - * graphic modes  
1587 - */  
1588 -static void vga_draw_graphic(VGAState *s, int full_update) 1587 +static void vga_update_resolution_graphics(VGAState *s)
1589 { 1588 {
1590 - int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth;  
1591 - int width, height, shift_control, line_offset, page0, page1, bwidth, bits; 1589 + int depth = s->get_bpp(s);
  1590 + int width, height, shift_control, double_scan;
1592 int disp_width, multi_scan, multi_run; 1591 int disp_width, multi_scan, multi_run;
1593 - uint8_t *d;  
1594 - uint32_t v, addr1, addr;  
1595 - vga_draw_line_func *vga_draw_line;  
1596 -  
1597 - full_update |= update_basic_params(s);  
1598 -  
1599 - if (!full_update)  
1600 - vga_sync_dirty_bitmap(s);  
1601 1592
1602 s->get_resolution(s, &width, &height); 1593 s->get_resolution(s, &width, &height);
1603 disp_width = width; 1594 disp_width = width;
1604 1595
1605 shift_control = (s->gr[0x05] >> 5) & 3; 1596 shift_control = (s->gr[0x05] >> 5) & 3;
1606 double_scan = (s->cr[0x09] >> 7); 1597 double_scan = (s->cr[0x09] >> 7);
1607 - if (shift_control != 1) {  
1608 - multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;  
1609 - } else {  
1610 - /* in CGA modes, multi_scan is ignored */  
1611 - /* XXX: is it correct ? */  
1612 - multi_scan = double_scan;  
1613 - }  
1614 - multi_run = multi_scan; 1598 +
1615 if (shift_control != s->shift_control || 1599 if (shift_control != s->shift_control ||
1616 double_scan != s->double_scan) { 1600 double_scan != s->double_scan) {
1617 - full_update = 1; 1601 + s->want_full_update = 1;
1618 s->shift_control = shift_control; 1602 s->shift_control = shift_control;
1619 s->double_scan = double_scan; 1603 s->double_scan = double_scan;
1620 } 1604 }
@@ -1628,12 +1612,28 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1628,12 +1612,28 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1628 disp_width <<= 1; 1612 disp_width <<= 1;
1629 } 1613 }
1630 } 1614 }
  1615 + disp_width = width;
  1616 +
  1617 + if (shift_control != 1) {
  1618 + multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
  1619 + } else {
  1620 + /* in CGA modes, multi_scan is ignored */
  1621 + /* XXX: is it correct ? */
  1622 + multi_scan = double_scan;
  1623 + }
  1624 +
  1625 + multi_run = multi_scan;
1631 1626
1632 - depth = s->get_bpp(s);  
1633 if (s->line_offset != s->last_line_offset || 1627 if (s->line_offset != s->last_line_offset ||
1634 disp_width != s->last_width || 1628 disp_width != s->last_width ||
1635 height != s->last_height || 1629 height != s->last_height ||
1636 - s->last_depth != depth) { 1630 + s->last_depth != depth ||
  1631 + s->multi_run != multi_run ||
  1632 + s->multi_scan != multi_scan ||
  1633 + s->want_full_update) {
  1634 + if (s->ds->surface->pf.depth == 0) {
  1635 + goto dont_touch_display_surface;
  1636 + }
1637 #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) 1637 #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1638 if (depth == 16 || depth == 32) { 1638 if (depth == 16 || depth == 32) {
1639 #else 1639 #else
@@ -1650,14 +1650,91 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1650,14 +1650,91 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1650 } else { 1650 } else {
1651 qemu_console_resize(s->ds, disp_width, height); 1651 qemu_console_resize(s->ds, disp_width, height);
1652 } 1652 }
  1653 + dont_touch_display_surface:
1653 s->last_scr_width = disp_width; 1654 s->last_scr_width = disp_width;
1654 s->last_scr_height = height; 1655 s->last_scr_height = height;
1655 s->last_width = disp_width; 1656 s->last_width = disp_width;
1656 s->last_height = height; 1657 s->last_height = height;
1657 s->last_line_offset = s->line_offset; 1658 s->last_line_offset = s->line_offset;
1658 s->last_depth = depth; 1659 s->last_depth = depth;
1659 - full_update = 1;  
1660 - } else if (is_buffer_shared(s->ds->surface) && 1660 + s->multi_run = multi_run;
  1661 + s->multi_scan = multi_scan;
  1662 + s->want_full_update = 1;
  1663 + }
  1664 +}
  1665 +
  1666 +static void vga_update_resolution_text(VGAState *s)
  1667 +{
  1668 + int width, height, cw, cheight;
  1669 +
  1670 + vga_get_text_resolution(s, &width, &height, &cw, &cheight);
  1671 + if (width != s->last_width || height != s->last_height ||
  1672 + cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
  1673 + s->last_scr_width = width * cw;
  1674 + s->last_scr_height = height * cheight;
  1675 + if (s->ds->surface->pf.depth != 0) {
  1676 + qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
  1677 + } else {
  1678 + /*
  1679 + * curses expects width and height to be in character cell
  1680 + * dimensions, not pixels.
  1681 + */
  1682 + s->ds->surface->width = width;
  1683 + s->ds->surface->height = height;
  1684 + dpy_resize(s->ds);
  1685 + }
  1686 + s->last_depth = 0;
  1687 + s->last_width = width;
  1688 + s->last_height = height;
  1689 + s->last_ch = cheight;
  1690 + s->last_cw = cw;
  1691 + s->want_full_update = 1;
  1692 + }
  1693 +}
  1694 +
  1695 +void vga_update_resolution(VGAState *s)
  1696 +{
  1697 + int graphic_mode;
  1698 +
  1699 + if (!(s->ar_index & 0x20)) {
  1700 + graphic_mode = GMODE_BLANK;
  1701 + } else {
  1702 + graphic_mode = s->gr[6] & 1;
  1703 + }
  1704 + if (graphic_mode != s->graphic_mode) {
  1705 + s->graphic_mode = graphic_mode;
  1706 + s->want_full_update = 1;
  1707 + }
  1708 + s->want_full_update |= update_basic_params(s);
  1709 + switch (graphic_mode) {
  1710 + case GMODE_TEXT:
  1711 + vga_update_resolution_text(s);
  1712 + break;
  1713 + case GMODE_GRAPH:
  1714 + vga_update_resolution_graphics(s);
  1715 + break;
  1716 + }
  1717 +}
  1718 +
  1719 +/*
  1720 + * graphic modes
  1721 + */
  1722 +static void vga_draw_graphic(VGAState *s, int full_update)
  1723 +{
  1724 + int y1, y, update, linesize, y_start, mask;
  1725 + int width, height, line_offset, bwidth, bits;
  1726 + int multi_run;
  1727 + uint8_t *d;
  1728 + uint32_t v, addr1, addr;
  1729 + long page0, page1, page_min, page_max;
  1730 + vga_draw_line_func *vga_draw_line;
  1731 +
  1732 + if (!full_update)
  1733 + vga_sync_dirty_bitmap(s);
  1734 +
  1735 + s->get_resolution(s, &width, &height);
  1736 + multi_run = s->multi_run;
  1737 + if (is_buffer_shared(s->ds->surface) &&
1661 (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) { 1738 (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1662 s->ds->surface->data = s->vram_ptr + (s->start_addr * 4); 1739 s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1663 dpy_setdata(s->ds); 1740 dpy_setdata(s->ds);
@@ -1666,7 +1743,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1666,7 +1743,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1666 s->rgb_to_pixel = 1743 s->rgb_to_pixel =
1667 rgb_to_pixel_dup_table[get_depth_index(s->ds)]; 1744 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1668 1745
1669 - if (shift_control == 0) { 1746 + if (s->shift_control == 0) {
1670 full_update |= update_palette16(s); 1747 full_update |= update_palette16(s);
1671 if (s->sr[0x01] & 8) { 1748 if (s->sr[0x01] & 8) {
1672 v = VGA_DRAW_LINE4D2; 1749 v = VGA_DRAW_LINE4D2;
@@ -1674,7 +1751,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1674,7 +1751,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1674 v = VGA_DRAW_LINE4; 1751 v = VGA_DRAW_LINE4;
1675 } 1752 }
1676 bits = 4; 1753 bits = 4;
1677 - } else if (shift_control == 1) { 1754 + } else if (s->shift_control == 1) {
1678 full_update |= update_palette16(s); 1755 full_update |= update_palette16(s);
1679 if (s->sr[0x01] & 8) { 1756 if (s->sr[0x01] & 8) {
1680 v = VGA_DRAW_LINE2D2; 1757 v = VGA_DRAW_LINE2D2;
@@ -1770,7 +1847,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1770,7 +1847,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1770 if (y_start >= 0) { 1847 if (y_start >= 0) {
1771 /* flush to display */ 1848 /* flush to display */
1772 dpy_update(s->ds, 0, y_start, 1849 dpy_update(s->ds, 0, y_start,
1773 - disp_width, y - y_start); 1850 + s->last_width, y - y_start);
1774 y_start = -1; 1851 y_start = -1;
1775 } 1852 }
1776 } 1853 }
@@ -1779,7 +1856,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1779,7 +1856,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1779 if ((y1 & mask) == mask) 1856 if ((y1 & mask) == mask)
1780 addr1 += line_offset; 1857 addr1 += line_offset;
1781 y1++; 1858 y1++;
1782 - multi_run = multi_scan; 1859 + multi_run = s->multi_scan;
1783 } else { 1860 } else {
1784 multi_run--; 1861 multi_run--;
1785 } 1862 }
@@ -1791,7 +1868,7 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1791,7 +1868,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1791 if (y_start >= 0) { 1868 if (y_start >= 0) {
1792 /* flush to display */ 1869 /* flush to display */
1793 dpy_update(s->ds, 0, y_start, 1870 dpy_update(s->ds, 0, y_start,
1794 - disp_width, y - y_start); 1871 + s->last_width, y - y_start);
1795 } 1872 }
1796 /* reset modified pages */ 1873 /* reset modified pages */
1797 if (page_max != -1) { 1874 if (page_max != -1) {
@@ -1828,29 +1905,17 @@ static void vga_draw_blank(VGAState *s, int full_update) @@ -1828,29 +1905,17 @@ static void vga_draw_blank(VGAState *s, int full_update)
1828 s->last_scr_width, s->last_scr_height); 1905 s->last_scr_width, s->last_scr_height);
1829 } 1906 }
1830 1907
1831 -#define GMODE_TEXT 0  
1832 -#define GMODE_GRAPH 1  
1833 -#define GMODE_BLANK 2  
1834 -  
1835 static void vga_update_display(void *opaque) 1908 static void vga_update_display(void *opaque)
1836 { 1909 {
1837 VGAState *s = (VGAState *)opaque; 1910 VGAState *s = (VGAState *)opaque;
1838 - int full_update, graphic_mode; 1911 + int full_update;
1839 1912
1840 if (ds_get_bits_per_pixel(s->ds) == 0) { 1913 if (ds_get_bits_per_pixel(s->ds) == 0) {
1841 /* nothing to do */ 1914 /* nothing to do */
1842 } else { 1915 } else {
1843 - full_update = 0;  
1844 - if (!(s->ar_index & 0x20)) {  
1845 - graphic_mode = GMODE_BLANK;  
1846 - } else {  
1847 - graphic_mode = s->gr[6] & 1;  
1848 - }  
1849 - if (graphic_mode != s->graphic_mode) {  
1850 - s->graphic_mode = graphic_mode;  
1851 - full_update = 1;  
1852 - }  
1853 - switch(graphic_mode) { 1916 + full_update = s->want_full_update;
  1917 + s->want_full_update = 0;
  1918 + switch(s->graphic_mode) {
1854 case GMODE_TEXT: 1919 case GMODE_TEXT:
1855 vga_draw_text(s, full_update); 1920 vga_draw_text(s, full_update);
1856 break; 1921 break;
@@ -1870,8 +1935,8 @@ static void vga_invalidate_display(void *opaque) @@ -1870,8 +1935,8 @@ static void vga_invalidate_display(void *opaque)
1870 { 1935 {
1871 VGAState *s = (VGAState *)opaque; 1936 VGAState *s = (VGAState *)opaque;
1872 1937
1873 - s->last_width = -1;  
1874 - s->last_height = -1; 1938 + vga_update_resolution(s);
  1939 + s->want_full_update = 1;
1875 } 1940 }
1876 1941
1877 void vga_reset(void *opaque) 1942 void vga_reset(void *opaque)
@@ -1915,7 +1980,6 @@ void vga_reset(void *opaque) @@ -1915,7 +1980,6 @@ void vga_reset(void *opaque)
1915 s->vbe_bank_mask = (s->vram_size >> 16) - 1; 1980 s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1916 #endif 1981 #endif
1917 memset(s->font_offsets, '\0', sizeof(s->font_offsets)); 1982 memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1918 - s->graphic_mode = -1; /* force full update */  
1919 s->shift_control = 0; 1983 s->shift_control = 0;
1920 s->double_scan = 0; 1984 s->double_scan = 0;
1921 s->line_offset = 0; 1985 s->line_offset = 0;
@@ -1941,6 +2005,7 @@ void vga_reset(void *opaque) @@ -1941,6 +2005,7 @@ void vga_reset(void *opaque)
1941 memset(&s->retrace_info, 0, sizeof (s->retrace_info)); 2005 memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1942 break; 2006 break;
1943 } 2007 }
  2008 + vga_update_resolution(s);
1944 } 2009 }
1945 2010
1946 #define TEXTMODE_X(x) ((x) % width) 2011 #define TEXTMODE_X(x) ((x) % width)
@@ -1952,50 +2017,28 @@ void vga_reset(void *opaque) @@ -1952,50 +2017,28 @@ void vga_reset(void *opaque)
1952 static void vga_update_text(void *opaque, console_ch_t *chardata) 2017 static void vga_update_text(void *opaque, console_ch_t *chardata)
1953 { 2018 {
1954 VGAState *s = (VGAState *) opaque; 2019 VGAState *s = (VGAState *) opaque;
1955 - int graphic_mode, i, cursor_offset, cursor_visible; 2020 + int i, cursor_offset, cursor_visible;
1956 int cw, cheight, width, height, size, c_min, c_max; 2021 int cw, cheight, width, height, size, c_min, c_max;
1957 uint32_t *src; 2022 uint32_t *src;
1958 console_ch_t *dst, val; 2023 console_ch_t *dst, val;
1959 char msg_buffer[80]; 2024 char msg_buffer[80];
1960 - int full_update = 0;  
1961 -  
1962 - if (!(s->ar_index & 0x20)) {  
1963 - graphic_mode = GMODE_BLANK;  
1964 - } else {  
1965 - graphic_mode = s->gr[6] & 1;  
1966 - }  
1967 - if (graphic_mode != s->graphic_mode) {  
1968 - s->graphic_mode = graphic_mode;  
1969 - full_update = 1;  
1970 - }  
1971 - if (s->last_width == -1) {  
1972 - s->last_width = 0;  
1973 - full_update = 1;  
1974 - } 2025 + int full_update = s->want_full_update;
1975 2026
1976 - switch (graphic_mode) { 2027 + s->want_full_update = 0;
  2028 + switch (s->graphic_mode) {
1977 case GMODE_TEXT: 2029 case GMODE_TEXT:
1978 /* TODO: update palette */ 2030 /* TODO: update palette */
1979 - full_update |= update_basic_params(s);  
1980 2031
1981 - /* total width & height */  
1982 - cheight = (s->cr[9] & 0x1f) + 1;  
1983 - cw = 8;  
1984 - if (!(s->sr[1] & 0x01))  
1985 - cw = 9;  
1986 - if (s->sr[1] & 0x08)  
1987 - cw = 16; /* NOTE: no 18 pixel wide */  
1988 - width = (s->cr[0x01] + 1);  
1989 - if (s->cr[0x06] == 100) {  
1990 - /* ugly hack for CGA 160x100x16 - explain me the logic */  
1991 - height = 100;  
1992 - } else {  
1993 - height = s->cr[0x12] |  
1994 - ((s->cr[0x07] & 0x02) << 7) |  
1995 - ((s->cr[0x07] & 0x40) << 3);  
1996 - height = (height + 1) / cheight; 2032 + vga_get_text_resolution(s, &width, &height, &cw, &cheight);
  2033 +
  2034 + if (s->ds->surface->width != width
  2035 + || s->ds->surface->height != height) {
  2036 + s->ds->surface->width = width;
  2037 + s->ds->surface->height = height;
  2038 + dpy_resize(s->ds);
1997 } 2039 }
1998 2040
  2041 + /* total width & height */
1999 size = (height * width); 2042 size = (height * width);
2000 if (size > CH_ATTR_SIZE) { 2043 if (size > CH_ATTR_SIZE) {
2001 if (!full_update) 2044 if (!full_update)
@@ -2006,20 +2049,6 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) @@ -2006,20 +2049,6 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
2006 break; 2049 break;
2007 } 2050 }
2008 2051
2009 - if (width != s->last_width || height != s->last_height ||  
2010 - cw != s->last_cw || cheight != s->last_ch) {  
2011 - s->last_scr_width = width * cw;  
2012 - s->last_scr_height = height * cheight;  
2013 - s->ds->surface->width = width;  
2014 - s->ds->surface->height = height;  
2015 - dpy_resize(s->ds);  
2016 - s->last_width = width;  
2017 - s->last_height = height;  
2018 - s->last_ch = cheight;  
2019 - s->last_cw = cw;  
2020 - full_update = 1;  
2021 - }  
2022 -  
2023 /* Update "hardware" cursor */ 2052 /* Update "hardware" cursor */
2024 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; 2053 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2025 if (cursor_offset != s->cursor_offset || 2054 if (cursor_offset != s->cursor_offset ||
@@ -2218,7 +2247,8 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id) @@ -2218,7 +2247,8 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
2218 #endif 2247 #endif
2219 2248
2220 /* force refresh */ 2249 /* force refresh */
2221 - s->graphic_mode = -1; 2250 + vga_update_resolution(s);
  2251 + s->want_full_update = 1;
2222 return 0; 2252 return 0;
2223 } 2253 }
2224 2254
@@ -2641,7 +2671,8 @@ static void vga_screen_dump_common(VGAState *s, const char *filename, @@ -2641,7 +2671,8 @@ static void vga_screen_dump_common(VGAState *s, const char *filename,
2641 ds->surface = qemu_create_displaysurface(ds, w, h); 2671 ds->surface = qemu_create_displaysurface(ds, w, h);
2642 2672
2643 s->ds = ds; 2673 s->ds = ds;
2644 - s->graphic_mode = -1; 2674 + vga_update_resolution(s);
  2675 + s->want_full_update = 1;
2645 vga_update_display(s); 2676 vga_update_display(s);
2646 2677
2647 ppm_save(filename, ds->surface); 2678 ppm_save(filename, ds->surface);
@@ -2672,10 +2703,16 @@ static void vga_screen_dump(void *opaque, const char *filename) @@ -2672,10 +2703,16 @@ static void vga_screen_dump(void *opaque, const char *filename)
2672 { 2703 {
2673 VGAState *s = (VGAState *)opaque; 2704 VGAState *s = (VGAState *)opaque;
2674 2705
2675 - if (!(s->ar_index & 0x20))  
2676 - vga_screen_dump_blank(s, filename);  
2677 - else if (s->gr[6] & 1)  
2678 - vga_screen_dump_graphic(s, filename);  
2679 - else 2706 + switch (s->graphic_mode) {
  2707 + case GMODE_TEXT:
2680 vga_screen_dump_text(s, filename); 2708 vga_screen_dump_text(s, filename);
  2709 + break;
  2710 + case GMODE_GRAPH:
  2711 + vga_screen_dump_graphic(s, filename);
  2712 + break;
  2713 + case GMODE_BLANK:
  2714 + default:
  2715 + vga_screen_dump_blank(s, filename);
  2716 + break;
  2717 + }
2681 } 2718 }
hw/vga_int.h
@@ -147,8 +147,11 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s); @@ -147,8 +147,11 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
147 DisplayState *ds; \ 147 DisplayState *ds; \
148 uint32_t font_offsets[2]; \ 148 uint32_t font_offsets[2]; \
149 int graphic_mode; \ 149 int graphic_mode; \
  150 + int want_full_update; \
150 uint8_t shift_control; \ 151 uint8_t shift_control; \
151 uint8_t double_scan; \ 152 uint8_t double_scan; \
  153 + uint8_t multi_run; \
  154 + uint8_t multi_scan; \
152 uint32_t line_offset; \ 155 uint32_t line_offset; \
153 uint32_t line_compare; \ 156 uint32_t line_compare; \
154 uint32_t start_addr; \ 157 uint32_t start_addr; \
@@ -195,6 +198,7 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base, @@ -195,6 +198,7 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base,
195 ram_addr_t vga_ram_offset, int vga_ram_size); 198 ram_addr_t vga_ram_offset, int vga_ram_size);
196 void vga_init(VGAState *s); 199 void vga_init(VGAState *s);
197 void vga_reset(void *s); 200 void vga_reset(void *s);
  201 +void vga_update_resolution(VGAState *s);
198 202
199 void vga_dirty_log_start(VGAState *s); 203 void vga_dirty_log_start(VGAState *s);
200 void vga_dirty_log_stop(VGAState *s); 204 void vga_dirty_log_stop(VGAState *s);