VirtualBox

Changeset 37770 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jul 4, 2011 5:43:06 PM (14 years ago)
Author:
vboxsync
Message:

vga: workaround invalid vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT]: re-calculate its value on saved state restore

Location:
trunk/src/VBox/Devices/Graphics
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA.cpp

    r37769 r37770  
    899899
    900900    return width;
     901}
     902
     903static void recaltulate_data(VGAState *s, bool fVirtHeightOnly)
     904{
     905    uint16_t cBPP        = s->vbe_regs[VBE_DISPI_INDEX_BPP];
     906    uint16_t cVirtWidth  = s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH];
     907    uint16_t cX          = s->vbe_regs[VBE_DISPI_INDEX_XRES];
     908    if (!cBPP || !cX)
     909        return;  /* Not enough data has been set yet. */
     910    uint32_t cbLinePitch = calc_line_pitch(cBPP, cVirtWidth);
     911    if (!cbLinePitch)
     912        cbLinePitch      = calc_line_pitch(cBPP, cX);
     913    Assert(cbLinePitch != 0);
     914    uint32_t cVirtHeight = s->vram_size / cbLinePitch;
     915    if (!fVirtHeightOnly)
     916    {
     917        uint16_t offX        = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
     918        uint16_t offY        = s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
     919        uint32_t offStart    = cbLinePitch * offY;
     920        if (cBPP == 4)
     921            offStart += offX >> 1;
     922        else
     923            offStart += offX * ((cBPP + 7) >> 3);
     924        offStart >>= 2;
     925        s->vbe_line_offset = RT_MIN(cbLinePitch, s->vram_size);
     926        s->vbe_start_addr  = RT_MIN(offStart, s->vram_size);
     927    }
     928
     929    /* The VBE_DISPI_INDEX_VIRT_HEIGHT is used to prevent setting resolution bigger than VRAM permits
     930     * it is used instead of VBE_DISPI_INDEX_YRES *only* in case
     931     * s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] < s->vbe_regs[VBE_DISPI_INDEX_YRES]
     932     * We can not simply do s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = cVirtHeight since
     933     * the cVirtHeight we calculated can exceed the 16bit value range
     934     * instead we'll check if it's bigger than s->vbe_regs[VBE_DISPI_INDEX_YRES], and if yes,
     935     * assign the s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] with a dummy UINT16_MAX value
     936     * that is always bigger than s->vbe_regs[VBE_DISPI_INDEX_YRES]
     937     * to just ensure the s->vbe_regs[VBE_DISPI_INDEX_YRES] is always used */
     938    s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = (cVirtHeight >= (uint32_t)s->vbe_regs[VBE_DISPI_INDEX_YRES]) ? UINT16_MAX : (uint16_t)cVirtHeight;
    901939}
    902940
     
    11151153        if (fRecalculate)
    11161154        {
    1117             uint16_t cBPP        = s->vbe_regs[VBE_DISPI_INDEX_BPP];
    1118             uint16_t cVirtWidth  = s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH];
    1119             uint16_t cX          = s->vbe_regs[VBE_DISPI_INDEX_XRES];
    1120             uint16_t offX        = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
    1121             uint16_t offY        = s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
    1122             if (!cBPP || !cX)
    1123                 return VINF_SUCCESS;  /* Not enough data has been set yet. */
    1124             uint32_t cbLinePitch = calc_line_pitch(cBPP, cVirtWidth);
    1125             if (!cbLinePitch)
    1126                 cbLinePitch      = calc_line_pitch(cBPP, cX);
    1127             Assert(cbLinePitch != 0);
    1128             uint32_t cVirtHeight = s->vram_size / cbLinePitch;
    1129             uint32_t offStart    = cbLinePitch * offY;
    1130             if (cBPP == 4)
    1131                 offStart += offX >> 1;
    1132             else
    1133                 offStart += offX * ((cBPP + 7) >> 3);
    1134             offStart >>= 2;
    1135             s->vbe_line_offset = RT_MIN(cbLinePitch, s->vram_size);
    1136             s->vbe_start_addr  = RT_MIN(offStart, s->vram_size);
    1137 
    1138             /* The VBE_DISPI_INDEX_VIRT_HEIGHT is used to prevent setting resolution bigger than VRAM permits
    1139              * it is used instead of VBE_DISPI_INDEX_YRES *only* in case
    1140              * s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] < s->vbe_regs[VBE_DISPI_INDEX_YRES]
    1141              * We can not simply do s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = cVirtHeight since
    1142              * the cVirtHeight we calculated can exceed the 16bit value range
    1143              * instead we'll check if it's bigger than s->vbe_regs[VBE_DISPI_INDEX_YRES], and if yes,
    1144              * assign the s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] with a dummy UINT16_MAX value
    1145              * that is always bigger than s->vbe_regs[VBE_DISPI_INDEX_YRES]
    1146              * to just ensure the s->vbe_regs[VBE_DISPI_INDEX_YRES] is always used */
    1147             s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = (cVirtHeight >= (uint32_t)s->vbe_regs[VBE_DISPI_INDEX_YRES]) ? UINT16_MAX : (uint16_t)cVirtHeight;
     1155            recaltulate_data(s, false);
    11481156        }
    11491157    }
     
    24402448    for(i = 0; i < VBE_DISPI_INDEX_NB_SAVED; i++)
    24412449        qemu_get_be16s(f, &s->vbe_regs[i]);
     2450    if (version_id <= VGA_SAVEDSTATE_VERSION_INV_VHEIGHT)
     2451        recaltulate_data(s, false); /* <- re-calculate the s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] since it might be invalid */
    24422452    qemu_get_be32s(f, &s->vbe_start_addr);
    24432453    qemu_get_be32s(f, &s->vbe_line_offset);
  • trunk/src/VBox/Devices/Graphics/DevVGASavedState.h

    r34140 r37770  
    2424
    2525#define VGA_SAVEDSTATE_VERSION              8
     26#define VGA_SAVEDSTATE_VERSION_INV_VHEIGHT  8 /* <- states upto and including this version may contain invalid vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] value */
    2627#define VGA_SAVEDSTATE_VERSION_WDDM         7
    2728#define VGA_SAVEDSTATE_VERSION_PRE_WDDM     6
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette