peterdelevoryas / rpms / qemu

Forked from rpms/qemu 2 years ago
Clone

Blame qemu-fix-display-breakage.patch

Mark McLoughlin 910c5e
From 8ad63a93a482d5c3354b97463633394456a157d5 Mon Sep 17 00:00:00 2001
Mark McLoughlin 910c5e
From: Avi Kivity <avi@redhat.com>
Mark McLoughlin 910c5e
Date: Thu, 2 Apr 2009 22:17:50 +0300
Mark McLoughlin 910c5e
Subject: [PATCH 1/1] kvm: qemu: Fix display breakage when resizing the screen
Mark McLoughlin 910c5e
Mark McLoughlin 910c5e
When the vga resolution changes, a new display surface is not allocated
Mark McLoughlin 910c5e
immediately; instead that is deferred until the next update.  However,
Mark McLoughlin 910c5e
if we're running without a display client attached, that won't happen
Mark McLoughlin 910c5e
and the next bitblt is likely to cause a segfault by overflowing the
Mark McLoughlin 910c5e
display surface.
Mark McLoughlin 910c5e
Mark McLoughlin 910c5e
Fix by reallocating the display immediately when the resolution changes.
Mark McLoughlin 910c5e
Mark McLoughlin 910c5e
Signed-off-by: Avi Kivity <avi@redhat.com>
Mark McLoughlin 910c5e
---
Mark McLoughlin 910c5e
 qemu/hw/cirrus_vga.c |   10 ++-
Mark McLoughlin 910c5e
 qemu/hw/vga.c        |  205 +++++++++++++++++++++++++++++--------------------
Mark McLoughlin 910c5e
 qemu/hw/vga_int.h    |    4 +
Mark McLoughlin 910c5e
 3 files changed, 134 insertions(+), 85 deletions(-)
Mark McLoughlin 910c5e
Mark McLoughlin 910c5e
diff --git a/qemu/hw/cirrus_vga.c b/qemu/hw/cirrus_vga.c
Mark McLoughlin 910c5e
index 0ab0f14..7bd0482 100644
Mark McLoughlin 910c5e
--- a/qemu/hw/cirrus_vga.c
Mark McLoughlin 910c5e
+++ b/qemu/hw/cirrus_vga.c
Mark McLoughlin 910c5e
@@ -1399,6 +1399,8 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
Mark McLoughlin 910c5e
 	break;
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
+    vga_update_resolution((VGAState *)s);
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
     return CIRRUS_HOOK_HANDLED;
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
@@ -1426,6 +1428,7 @@ static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
Mark McLoughlin 910c5e
 #endif
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
     s->cirrus_hidden_dac_lockindex = 0;
Mark McLoughlin 910c5e
+    vga_update_resolution((VGAState *)s);
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
 /***************************************
Mark McLoughlin 910c5e
@@ -1712,6 +1715,8 @@ cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
Mark McLoughlin 910c5e
 	break;
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
+    vga_update_resolution((VGAState *)s);
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
     return CIRRUS_HOOK_HANDLED;
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
@@ -2839,6 +2844,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
 	if (s->ar_flip_flop == 0) {
Mark McLoughlin 910c5e
 	    val &= 0x3f;
Mark McLoughlin 910c5e
 	    s->ar_index = val;
Mark McLoughlin 910c5e
+            vga_update_resolution((VGAState *)s);
Mark McLoughlin 910c5e
 	} else {
Mark McLoughlin 910c5e
 	    index = s->ar_index & 0x1f;
Mark McLoughlin 910c5e
 	    switch (index) {
Mark McLoughlin 910c5e
@@ -2932,6 +2938,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
 	    /* can always write bit 4 of CR7 */
Mark McLoughlin 910c5e
 	    if (s->cr_index == 7)
Mark McLoughlin 910c5e
 		s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
Mark McLoughlin 910c5e
+            vga_update_resolution((VGAState *)s);
Mark McLoughlin 910c5e
 	    return;
Mark McLoughlin 910c5e
 	}
Mark McLoughlin 910c5e
 	switch (s->cr_index) {
Mark McLoughlin 910c5e
@@ -3166,7 +3173,8 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     cirrus_update_memory_access(s);
Mark McLoughlin 910c5e
     /* force refresh */
Mark McLoughlin 910c5e
-    s->graphic_mode = -1;
Mark McLoughlin 910c5e
+    vga_update_resolution((VGAState *)s);
Mark McLoughlin 910c5e
+    s->want_full_update = 1;
Mark McLoughlin 910c5e
     cirrus_update_bank_ptr(s, 0);
Mark McLoughlin 910c5e
     cirrus_update_bank_ptr(s, 1);
Mark McLoughlin 910c5e
     return 0;
Mark McLoughlin 910c5e
diff --git a/qemu/hw/vga.c b/qemu/hw/vga.c
Mark McLoughlin 910c5e
index d4fddf9..9a950d3 100644
Mark McLoughlin 910c5e
--- a/qemu/hw/vga.c
Mark McLoughlin 910c5e
+++ b/qemu/hw/vga.c
Mark McLoughlin 910c5e
@@ -37,6 +37,10 @@
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
 //#define DEBUG_BOCHS_VBE
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
+#define GMODE_TEXT     0
Mark McLoughlin 910c5e
+#define GMODE_GRAPH    1
Mark McLoughlin 910c5e
+#define GMODE_BLANK 2
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
 /* force some bits to zero */
Mark McLoughlin 910c5e
 const uint8_t sr_mask[8] = {
Mark McLoughlin 910c5e
     (uint8_t)~0xfc,
Mark McLoughlin 910c5e
@@ -394,6 +398,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
         if (s->ar_flip_flop == 0) {
Mark McLoughlin 910c5e
             val &= 0x3f;
Mark McLoughlin 910c5e
             s->ar_index = val;
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
         } else {
Mark McLoughlin 910c5e
             index = s->ar_index & 0x1f;
Mark McLoughlin 910c5e
             switch(index) {
Mark McLoughlin 910c5e
@@ -434,6 +439,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
 #endif
Mark McLoughlin 910c5e
         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
Mark McLoughlin 910c5e
         if (s->sr_index == 1) s->update_retrace_info(s);
Mark McLoughlin 910c5e
+        vga_update_resolution(s);
Mark McLoughlin 910c5e
         break;
Mark McLoughlin 910c5e
     case 0x3c7:
Mark McLoughlin 910c5e
         s->dac_read_index = val;
Mark McLoughlin 910c5e
@@ -461,6 +467,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
Mark McLoughlin 910c5e
 #endif
Mark McLoughlin 910c5e
         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
Mark McLoughlin 910c5e
+        vga_update_resolution(s);
Mark McLoughlin 910c5e
         break;
Mark McLoughlin 910c5e
     case 0x3b4:
Mark McLoughlin 910c5e
     case 0x3d4:
Mark McLoughlin 910c5e
@@ -476,6 +483,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
             /* can always write bit 4 of CR7 */
Mark McLoughlin 910c5e
             if (s->cr_index == 7)
Mark McLoughlin 910c5e
                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
             return;
Mark McLoughlin 910c5e
         }
Mark McLoughlin 910c5e
         switch(s->cr_index) {
Mark McLoughlin 910c5e
@@ -503,6 +511,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
             s->update_retrace_info(s);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
         }
Mark McLoughlin 910c5e
+        vga_update_resolution(s);
Mark McLoughlin 910c5e
         break;
Mark McLoughlin 910c5e
     case 0x3ba:
Mark McLoughlin 910c5e
     case 0x3da:
Mark McLoughlin 910c5e
@@ -582,11 +591,13 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
Mark McLoughlin 910c5e
                 s->vbe_regs[s->vbe_index] = val;
Mark McLoughlin 910c5e
             }
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
         case VBE_DISPI_INDEX_YRES:
Mark McLoughlin 910c5e
             if (val <= VBE_DISPI_MAX_YRES) {
Mark McLoughlin 910c5e
                 s->vbe_regs[s->vbe_index] = val;
Mark McLoughlin 910c5e
             }
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
         case VBE_DISPI_INDEX_BPP:
Mark McLoughlin 910c5e
             if (val == 0)
Mark McLoughlin 910c5e
@@ -595,6 +606,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
                 val == 16 || val == 24 || val == 32) {
Mark McLoughlin 910c5e
                 s->vbe_regs[s->vbe_index] = val;
Mark McLoughlin 910c5e
             }
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
         case VBE_DISPI_INDEX_BANK:
Mark McLoughlin 910c5e
             if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
Mark McLoughlin 910c5e
@@ -663,6 +675,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
             }
Mark McLoughlin 910c5e
             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
Mark McLoughlin 910c5e
             s->vbe_regs[s->vbe_index] = val;
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
         case VBE_DISPI_INDEX_VIRT_WIDTH:
Mark McLoughlin 910c5e
             {
Mark McLoughlin 910c5e
@@ -683,6 +696,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
Mark McLoughlin 910c5e
                 s->vbe_line_offset = line_offset;
Mark McLoughlin 910c5e
             }
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
         case VBE_DISPI_INDEX_X_OFFSET:
Mark McLoughlin 910c5e
         case VBE_DISPI_INDEX_Y_OFFSET:
Mark McLoughlin 910c5e
@@ -697,6 +711,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
Mark McLoughlin 910c5e
                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
Mark McLoughlin 910c5e
                 s->vbe_start_addr >>= 2;
Mark McLoughlin 910c5e
             }
Mark McLoughlin 910c5e
+            vga_update_resolution(s);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
         default:
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
@@ -1300,7 +1315,6 @@ static void vga_draw_text(VGAState *s, int full_update)
Mark McLoughlin 910c5e
         s->plane_updated = 0;
Mark McLoughlin 910c5e
         full_update = 1;
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
-    full_update |= update_basic_params(s);
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     line_offset = s->line_offset;
Mark McLoughlin 910c5e
     s1 = s->vram_ptr + (s->start_addr * 4);
Mark McLoughlin 910c5e
@@ -1312,18 +1326,6 @@ static void vga_draw_text(VGAState *s, int full_update)
Mark McLoughlin 910c5e
         return;
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
-    if (width != s->last_width || height != s->last_height ||
Mark McLoughlin 910c5e
-        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
Mark McLoughlin 910c5e
-        s->last_scr_width = width * cw;
Mark McLoughlin 910c5e
-        s->last_scr_height = height * cheight;
Mark McLoughlin 910c5e
-        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
Mark McLoughlin 910c5e
-        s->last_depth = 0;
Mark McLoughlin 910c5e
-        s->last_width = width;
Mark McLoughlin 910c5e
-        s->last_height = height;
Mark McLoughlin 910c5e
-        s->last_ch = cheight;
Mark McLoughlin 910c5e
-        s->last_cw = cw;
Mark McLoughlin 910c5e
-        full_update = 1;
Mark McLoughlin 910c5e
-    }
Mark McLoughlin 910c5e
     s->rgb_to_pixel =
Mark McLoughlin 910c5e
         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
Mark McLoughlin 910c5e
     full_update |= update_palette16(s);
Mark McLoughlin 910c5e
@@ -1580,40 +1582,20 @@ static void vga_sync_dirty_bitmap(VGAState *s)
Mark McLoughlin 910c5e
     vga_dirty_log_start(s);
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
-/*
Mark McLoughlin 910c5e
- * graphic modes
Mark McLoughlin 910c5e
- */
Mark McLoughlin 910c5e
-static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
+static void vga_update_resolution_graphics(VGAState *s)
Mark McLoughlin 910c5e
 {
Mark McLoughlin 910c5e
-    int y1, y, update, linesize, y_start, double_scan, mask, depth;
Mark McLoughlin 910c5e
-    int width, height, shift_control, line_offset, bwidth, bits;
Mark McLoughlin 910c5e
+    int depth = s->get_bpp(s);
Mark McLoughlin 910c5e
+    int width, height, shift_control, double_scan;
Mark McLoughlin 910c5e
     int disp_width, multi_scan, multi_run;
Mark McLoughlin 910c5e
-    uint8_t *d;
Mark McLoughlin 910c5e
-    uint32_t v, addr1, addr;
Mark McLoughlin 910c5e
-    long page0, page1, page_min, page_max;
Mark McLoughlin 910c5e
-    vga_draw_line_func *vga_draw_line;
Mark McLoughlin 910c5e
-
Mark McLoughlin 910c5e
-    full_update |= update_basic_params(s);
Mark McLoughlin 910c5e
-
Mark McLoughlin 910c5e
-    if (!full_update)
Mark McLoughlin 910c5e
-        vga_sync_dirty_bitmap(s);
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     s->get_resolution(s, &width, &height);
Mark McLoughlin 910c5e
-    disp_width = width;
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     shift_control = (s->gr[0x05] >> 5) & 3;
Mark McLoughlin 910c5e
     double_scan = (s->cr[0x09] >> 7);
Mark McLoughlin 910c5e
-    if (shift_control != 1) {
Mark McLoughlin 910c5e
-        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
Mark McLoughlin 910c5e
-    } else {
Mark McLoughlin 910c5e
-        /* in CGA modes, multi_scan is ignored */
Mark McLoughlin 910c5e
-        /* XXX: is it correct ? */
Mark McLoughlin 910c5e
-        multi_scan = double_scan;
Mark McLoughlin 910c5e
-    }
Mark McLoughlin 910c5e
-    multi_run = multi_scan;
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
     if (shift_control != s->shift_control ||
Mark McLoughlin 910c5e
         double_scan != s->double_scan) {
Mark McLoughlin 910c5e
-        full_update = 1;
Mark McLoughlin 910c5e
+        s->want_full_update = 1;
Mark McLoughlin 910c5e
         s->shift_control = shift_control;
Mark McLoughlin 910c5e
         s->double_scan = double_scan;
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
@@ -1627,12 +1609,25 @@ static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
             disp_width <<= 1;
Mark McLoughlin 910c5e
         }
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
+    disp_width = width;
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+    if (shift_control != 1) {
Mark McLoughlin 910c5e
+        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
Mark McLoughlin 910c5e
+    } else {
Mark McLoughlin 910c5e
+        /* in CGA modes, multi_scan is ignored */
Mark McLoughlin 910c5e
+        /* XXX: is it correct ? */
Mark McLoughlin 910c5e
+        multi_scan = double_scan;
Mark McLoughlin 910c5e
+    }
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+    multi_run = multi_scan;
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
-    depth = s->get_bpp(s);
Mark McLoughlin 910c5e
     if (s->line_offset != s->last_line_offset ||
Mark McLoughlin 910c5e
         disp_width != s->last_width ||
Mark McLoughlin 910c5e
         height != s->last_height ||
Mark McLoughlin 910c5e
-        s->last_depth != depth) {
Mark McLoughlin 910c5e
+        s->last_depth != depth ||
Mark McLoughlin 910c5e
+        s->multi_run != multi_run ||
Mark McLoughlin 910c5e
+        s->multi_scan != multi_scan ||
Mark McLoughlin 910c5e
+        s->want_full_update) {
Mark McLoughlin 910c5e
 #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
Mark McLoughlin 910c5e
         if (depth == 16 || depth == 32) {
Mark McLoughlin 910c5e
 #else
Mark McLoughlin 910c5e
@@ -1659,8 +1654,74 @@ static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
         s->last_height = height;
Mark McLoughlin 910c5e
         s->last_line_offset = s->line_offset;
Mark McLoughlin 910c5e
         s->last_depth = depth;
Mark McLoughlin 910c5e
-        full_update = 1;
Mark McLoughlin 910c5e
-    } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) &&
Mark McLoughlin 910c5e
+        s->multi_run = multi_run;
Mark McLoughlin 910c5e
+        s->multi_scan = multi_scan;
Mark McLoughlin 910c5e
+        s->want_full_update = 1;
Mark McLoughlin 910c5e
+    }
Mark McLoughlin 910c5e
+}
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+static void vga_update_resolution_text(VGAState *s)
Mark McLoughlin 910c5e
+{
Mark McLoughlin 910c5e
+    int width, height, cw, cheight;
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
Mark McLoughlin 910c5e
+    if (width != s->last_width || height != s->last_height ||
Mark McLoughlin 910c5e
+        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
Mark McLoughlin 910c5e
+        s->last_scr_width = width * cw;
Mark McLoughlin 910c5e
+        s->last_scr_height = height * cheight;
Mark McLoughlin 910c5e
+        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
Mark McLoughlin 910c5e
+        s->last_depth = 0;
Mark McLoughlin 910c5e
+        s->last_width = width;
Mark McLoughlin 910c5e
+        s->last_height = height;
Mark McLoughlin 910c5e
+        s->last_ch = cheight;
Mark McLoughlin 910c5e
+        s->last_cw = cw;
Mark McLoughlin 910c5e
+        s->want_full_update = 1;
Mark McLoughlin 910c5e
+    }
Mark McLoughlin 910c5e
+}
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+void vga_update_resolution(VGAState *s)
Mark McLoughlin 910c5e
+{
Mark McLoughlin 910c5e
+    int graphic_mode;
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+    if (!(s->ar_index & 0x20)) {
Mark McLoughlin 910c5e
+        graphic_mode = GMODE_BLANK;
Mark McLoughlin 910c5e
+    } else {
Mark McLoughlin 910c5e
+        graphic_mode = s->gr[6] & 1;
Mark McLoughlin 910c5e
+    }
Mark McLoughlin 910c5e
+    if (graphic_mode != s->graphic_mode) {
Mark McLoughlin 910c5e
+        s->graphic_mode = graphic_mode;
Mark McLoughlin 910c5e
+        s->want_full_update = 1;
Mark McLoughlin 910c5e
+    }
Mark McLoughlin 910c5e
+    s->want_full_update |= update_basic_params(s);
Mark McLoughlin 910c5e
+    switch (graphic_mode) {
Mark McLoughlin 910c5e
+    case GMODE_TEXT:
Mark McLoughlin 910c5e
+        vga_update_resolution_text(s);
Mark McLoughlin 910c5e
+        break;
Mark McLoughlin 910c5e
+    case GMODE_GRAPH:
Mark McLoughlin 910c5e
+        vga_update_resolution_graphics(s);
Mark McLoughlin 910c5e
+        break;
Mark McLoughlin 910c5e
+    }
Mark McLoughlin 910c5e
+}
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+/*
Mark McLoughlin 910c5e
+ * graphic modes
Mark McLoughlin 910c5e
+ */
Mark McLoughlin 910c5e
+static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
+{
Mark McLoughlin 910c5e
+    int y1, y, update, linesize, y_start, mask;
Mark McLoughlin 910c5e
+    int width, height, line_offset, bwidth, bits;
Mark McLoughlin 910c5e
+    int multi_run;
Mark McLoughlin 910c5e
+    uint8_t *d;
Mark McLoughlin 910c5e
+    uint32_t v, addr1, addr;
Mark McLoughlin 910c5e
+    long page0, page1, page_min, page_max;
Mark McLoughlin 910c5e
+    vga_draw_line_func *vga_draw_line;
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+    if (!full_update)
Mark McLoughlin 910c5e
+        vga_sync_dirty_bitmap(s);
Mark McLoughlin 910c5e
+
Mark McLoughlin 910c5e
+    s->get_resolution(s, &width, &height);
Mark McLoughlin 910c5e
+    multi_run = s->multi_run;
Mark McLoughlin 910c5e
+    if (is_graphic_console() && is_buffer_shared(s->ds->surface) &&
Mark McLoughlin 910c5e
                (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
Mark McLoughlin 910c5e
         s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
Mark McLoughlin 910c5e
         dpy_setdata(s->ds);
Mark McLoughlin 910c5e
@@ -1669,7 +1730,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
     s->rgb_to_pixel =
Mark McLoughlin 910c5e
         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
-    if (shift_control == 0) {
Mark McLoughlin 910c5e
+    if (s->shift_control == 0) {
Mark McLoughlin 910c5e
         full_update |= update_palette16(s);
Mark McLoughlin 910c5e
         if (s->sr[0x01] & 8) {
Mark McLoughlin 910c5e
             v = VGA_DRAW_LINE4D2;
Mark McLoughlin 910c5e
@@ -1677,7 +1738,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
             v = VGA_DRAW_LINE4;
Mark McLoughlin 910c5e
         }
Mark McLoughlin 910c5e
         bits = 4;
Mark McLoughlin 910c5e
-    } else if (shift_control == 1) {
Mark McLoughlin 910c5e
+    } else if (s->shift_control == 1) {
Mark McLoughlin 910c5e
         full_update |= update_palette16(s);
Mark McLoughlin 910c5e
         if (s->sr[0x01] & 8) {
Mark McLoughlin 910c5e
             v = VGA_DRAW_LINE2D2;
Mark McLoughlin 910c5e
@@ -1773,7 +1834,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
             if (y_start >= 0) {
Mark McLoughlin 910c5e
                 /* flush to display */
Mark McLoughlin 910c5e
                 dpy_update(s->ds, 0, y_start,
Mark McLoughlin 910c5e
-                           disp_width, y - y_start);
Mark McLoughlin 910c5e
+                           s->last_width, y - y_start);
Mark McLoughlin 910c5e
                 y_start = -1;
Mark McLoughlin 910c5e
             }
Mark McLoughlin 910c5e
         }
Mark McLoughlin 910c5e
@@ -1782,7 +1843,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
             if ((y1 & mask) == mask)
Mark McLoughlin 910c5e
                 addr1 += line_offset;
Mark McLoughlin 910c5e
             y1++;
Mark McLoughlin 910c5e
-            multi_run = multi_scan;
Mark McLoughlin 910c5e
+            multi_run = s->multi_scan;
Mark McLoughlin 910c5e
         } else {
Mark McLoughlin 910c5e
             multi_run--;
Mark McLoughlin 910c5e
         }
Mark McLoughlin 910c5e
@@ -1794,7 +1855,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
Mark McLoughlin 910c5e
     if (y_start >= 0) {
Mark McLoughlin 910c5e
         /* flush to display */
Mark McLoughlin 910c5e
         dpy_update(s->ds, 0, y_start,
Mark McLoughlin 910c5e
-                   disp_width, y - y_start);
Mark McLoughlin 910c5e
+                   s->last_width, y - y_start);
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
     /* reset modified pages */
Mark McLoughlin 910c5e
     if (page_max != -1) {
Mark McLoughlin 910c5e
@@ -1831,29 +1892,17 @@ static void vga_draw_blank(VGAState *s, int full_update)
Mark McLoughlin 910c5e
                s->last_scr_width, s->last_scr_height);
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
-#define GMODE_TEXT     0
Mark McLoughlin 910c5e
-#define GMODE_GRAPH    1
Mark McLoughlin 910c5e
-#define GMODE_BLANK 2
Mark McLoughlin 910c5e
-
Mark McLoughlin 910c5e
 static void vga_update_display(void *opaque)
Mark McLoughlin 910c5e
 {
Mark McLoughlin 910c5e
     VGAState *s = (VGAState *)opaque;
Mark McLoughlin 910c5e
-    int full_update, graphic_mode;
Mark McLoughlin 910c5e
+    int full_update;
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     if (ds_get_bits_per_pixel(s->ds) == 0) {
Mark McLoughlin 910c5e
         /* nothing to do */
Mark McLoughlin 910c5e
     } else {
Mark McLoughlin 910c5e
-        full_update = 0;
Mark McLoughlin 910c5e
-        if (!(s->ar_index & 0x20)) {
Mark McLoughlin 910c5e
-            graphic_mode = GMODE_BLANK;
Mark McLoughlin 910c5e
-        } else {
Mark McLoughlin 910c5e
-            graphic_mode = s->gr[6] & 1;
Mark McLoughlin 910c5e
-        }
Mark McLoughlin 910c5e
-        if (graphic_mode != s->graphic_mode) {
Mark McLoughlin 910c5e
-            s->graphic_mode = graphic_mode;
Mark McLoughlin 910c5e
-            full_update = 1;
Mark McLoughlin 910c5e
-        }
Mark McLoughlin 910c5e
-        switch(graphic_mode) {
Mark McLoughlin 910c5e
+        full_update = s->want_full_update;
Mark McLoughlin 910c5e
+        s->want_full_update = 0;
Mark McLoughlin 910c5e
+        switch(s->graphic_mode) {
Mark McLoughlin 910c5e
         case GMODE_TEXT:
Mark McLoughlin 910c5e
             vga_draw_text(s, full_update);
Mark McLoughlin 910c5e
             break;
Mark McLoughlin 910c5e
@@ -1876,8 +1925,8 @@ static void vga_invalidate_display(void *opaque)
Mark McLoughlin 910c5e
 {
Mark McLoughlin 910c5e
     VGAState *s = (VGAState *)opaque;
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
-    s->last_width = -1;
Mark McLoughlin 910c5e
-    s->last_height = -1;
Mark McLoughlin 910c5e
+    vga_update_resolution(s);
Mark McLoughlin 910c5e
+    s->want_full_update = 1;
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
 void vga_reset(void *opaque)
Mark McLoughlin 910c5e
@@ -1921,7 +1970,6 @@ void vga_reset(void *opaque)
Mark McLoughlin 910c5e
     s->vbe_bank_mask = (s->vram_size >> 16) - 1;
Mark McLoughlin 910c5e
 #endif
Mark McLoughlin 910c5e
     memset(s->font_offsets, '\0', sizeof(s->font_offsets));
Mark McLoughlin 910c5e
-    s->graphic_mode = -1; /* force full update */
Mark McLoughlin 910c5e
     s->shift_control = 0;
Mark McLoughlin 910c5e
     s->double_scan = 0;
Mark McLoughlin 910c5e
     s->line_offset = 0;
Mark McLoughlin 910c5e
@@ -1947,6 +1995,7 @@ void vga_reset(void *opaque)
Mark McLoughlin 910c5e
         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
Mark McLoughlin 910c5e
         break;
Mark McLoughlin 910c5e
     }
Mark McLoughlin 910c5e
+    vga_update_resolution(s);
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
 #define TEXTMODE_X(x)	((x) % width)
Mark McLoughlin 910c5e
@@ -1965,24 +2014,9 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
Mark McLoughlin 910c5e
     char msg_buffer[80];
Mark McLoughlin 910c5e
     int full_update = 0;
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
-    if (!(s->ar_index & 0x20)) {
Mark McLoughlin 910c5e
-        graphic_mode = GMODE_BLANK;
Mark McLoughlin 910c5e
-    } else {
Mark McLoughlin 910c5e
-        graphic_mode = s->gr[6] & 1;
Mark McLoughlin 910c5e
-    }
Mark McLoughlin 910c5e
-    if (graphic_mode != s->graphic_mode) {
Mark McLoughlin 910c5e
-        s->graphic_mode = graphic_mode;
Mark McLoughlin 910c5e
-        full_update = 1;
Mark McLoughlin 910c5e
-    }
Mark McLoughlin 910c5e
-    if (s->last_width == -1) {
Mark McLoughlin 910c5e
-        s->last_width = 0;
Mark McLoughlin 910c5e
-        full_update = 1;
Mark McLoughlin 910c5e
-    }
Mark McLoughlin 910c5e
-
Mark McLoughlin 910c5e
     switch (graphic_mode) {
Mark McLoughlin 910c5e
     case GMODE_TEXT:
Mark McLoughlin 910c5e
         /* TODO: update palette */
Mark McLoughlin 910c5e
-        full_update |= update_basic_params(s);
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
         /* total width & height */
Mark McLoughlin 910c5e
         cheight = (s->cr[9] & 0x1f) + 1;
Mark McLoughlin 910c5e
@@ -2224,7 +2258,8 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
Mark McLoughlin 910c5e
 #endif
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     /* force refresh */
Mark McLoughlin 910c5e
-    s->graphic_mode = -1;
Mark McLoughlin 910c5e
+    vga_update_resolution(s);
Mark McLoughlin 910c5e
+    s->want_full_update = 1;
Mark McLoughlin 910c5e
     return 0;
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
@@ -2418,7 +2453,8 @@ void vga_bios_init(VGAState *s)
Mark McLoughlin 910c5e
     memcpy(s->palette, palette_model, 192);
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     s->bank_offset = 0;
Mark McLoughlin 910c5e
-    s->graphic_mode = -1;
Mark McLoughlin 910c5e
+    vga_update_resolution(s);
Mark McLoughlin 910c5e
+    s->want_full_update = 1;
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     /* TODO: add vbe support if enabled */
Mark McLoughlin 910c5e
 }
Mark McLoughlin 910c5e
@@ -2803,7 +2839,8 @@ static void vga_screen_dump_common(VGAState *s, const char *filename,
Mark McLoughlin 910c5e
     ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w);
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     s->ds = ds;
Mark McLoughlin 910c5e
-    s->graphic_mode = -1;
Mark McLoughlin 910c5e
+    vga_update_resolution(s);
Mark McLoughlin 910c5e
+    s->want_full_update = 1;
Mark McLoughlin 910c5e
     vga_update_display(s);
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
     ppm_save(filename, ds->surface);
Mark McLoughlin 910c5e
diff --git a/qemu/hw/vga_int.h b/qemu/hw/vga_int.h
Mark McLoughlin 910c5e
index 8ba8a60..71ffeb5 100644
Mark McLoughlin 910c5e
--- a/qemu/hw/vga_int.h
Mark McLoughlin 910c5e
+++ b/qemu/hw/vga_int.h
Mark McLoughlin 910c5e
@@ -147,8 +147,11 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
Mark McLoughlin 910c5e
     DisplayState *ds;                                                   \
Mark McLoughlin 910c5e
     uint32_t font_offsets[2];                                           \
Mark McLoughlin 910c5e
     int graphic_mode;                                                   \
Mark McLoughlin 910c5e
+    int want_full_update;                                               \
Mark McLoughlin 910c5e
     uint8_t shift_control;                                              \
Mark McLoughlin 910c5e
     uint8_t double_scan;                                                \
Mark McLoughlin 910c5e
+    uint8_t multi_run;                                                  \
Mark McLoughlin 910c5e
+    uint8_t multi_scan;                                                 \
Mark McLoughlin 910c5e
     uint32_t line_offset;                                               \
Mark McLoughlin 910c5e
     uint32_t line_compare;                                              \
Mark McLoughlin 910c5e
     uint32_t start_addr;                                                \
Mark McLoughlin 910c5e
@@ -195,6 +198,7 @@ void vga_common_init(VGAState *s, uint8_t *vga_ram_base,
Mark McLoughlin 910c5e
                      ram_addr_t vga_ram_offset, int vga_ram_size);
Mark McLoughlin 910c5e
 void vga_init(VGAState *s);
Mark McLoughlin 910c5e
 void vga_reset(void *s);
Mark McLoughlin 910c5e
+void vga_update_resolution(VGAState *s);
Mark McLoughlin 910c5e
 
Mark McLoughlin 910c5e
 void vga_dirty_log_start(VGAState *s);
Mark McLoughlin 910c5e
 void vga_dirty_log_stop(VGAState *s);
Mark McLoughlin 910c5e
-- 
Mark McLoughlin 910c5e
1.6.0.6
Mark McLoughlin 910c5e