Revision 799e709b hw/vga.c

b/hw/vga.c
36 36

  
37 37
//#define DEBUG_BOCHS_VBE
38 38

  
39
#define GMODE_TEXT     0
40
#define GMODE_GRAPH    1
41
#define GMODE_BLANK 2
42

  
43 39
/* force some bits to zero */
44 40
const uint8_t sr_mask[8] = {
45 41
    0x03,
......
397 393
        if (s->ar_flip_flop == 0) {
398 394
            val &= 0x3f;
399 395
            s->ar_index = val;
400
            vga_update_resolution(s);
401 396
        } else {
402 397
            index = s->ar_index & 0x1f;
403 398
            switch(index) {
......
438 433
#endif
439 434
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
440 435
        if (s->sr_index == 1) s->update_retrace_info(s);
441
        vga_update_resolution(s);
442 436
        break;
443 437
    case 0x3c7:
444 438
        s->dac_read_index = val;
......
466 460
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
467 461
#endif
468 462
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
469
        vga_update_resolution(s);
470 463
        break;
471 464
    case 0x3b4:
472 465
    case 0x3d4:
......
482 475
            /* can always write bit 4 of CR7 */
483 476
            if (s->cr_index == 7)
484 477
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
485
            vga_update_resolution(s);
486 478
            return;
487 479
        }
488 480
        switch(s->cr_index) {
......
510 502
            s->update_retrace_info(s);
511 503
            break;
512 504
        }
513
        vga_update_resolution(s);
514 505
        break;
515 506
    case 0x3ba:
516 507
    case 0x3da:
......
590 581
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
591 582
                s->vbe_regs[s->vbe_index] = val;
592 583
            }
593
            vga_update_resolution(s);
594 584
            break;
595 585
        case VBE_DISPI_INDEX_YRES:
596 586
            if (val <= VBE_DISPI_MAX_YRES) {
597 587
                s->vbe_regs[s->vbe_index] = val;
598 588
            }
599
            vga_update_resolution(s);
600 589
            break;
601 590
        case VBE_DISPI_INDEX_BPP:
602 591
            if (val == 0)
......
605 594
                val == 16 || val == 24 || val == 32) {
606 595
                s->vbe_regs[s->vbe_index] = val;
607 596
            }
608
            vga_update_resolution(s);
609 597
            break;
610 598
        case VBE_DISPI_INDEX_BANK:
611 599
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
......
674 662
            }
675 663
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
676 664
            s->vbe_regs[s->vbe_index] = val;
677
            vga_update_resolution(s);
678 665
            break;
679 666
        case VBE_DISPI_INDEX_VIRT_WIDTH:
680 667
            {
......
695 682
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
696 683
                s->vbe_line_offset = line_offset;
697 684
            }
698
            vga_update_resolution(s);
699 685
            break;
700 686
        case VBE_DISPI_INDEX_X_OFFSET:
701 687
        case VBE_DISPI_INDEX_Y_OFFSET:
......
710 696
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
711 697
                s->vbe_start_addr >>= 2;
712 698
            }
713
            vga_update_resolution(s);
714 699
            break;
715 700
        default:
716 701
            break;
......
1317 1302
        s->plane_updated = 0;
1318 1303
        full_update = 1;
1319 1304
    }
1305
    full_update |= update_basic_params(s);
1320 1306

  
1321 1307
    line_offset = s->line_offset;
1322 1308
    s1 = s->vram_ptr + (s->start_addr * 4);
......
1328 1314
        return;
1329 1315
    }
1330 1316

  
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
    }
1331 1329
    s->rgb_to_pixel =
1332 1330
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1333 1331
    full_update |= update_palette16(s);
......
1584 1582
    vga_dirty_log_start(s);
1585 1583
}
1586 1584

  
1587
static void vga_update_resolution_graphics(VGAState *s)
1585
/*
1586
 * graphic modes
1587
 */
1588
static void vga_draw_graphic(VGAState *s, int full_update)
1588 1589
{
1589
    int depth = s->get_bpp(s);
1590
    int width, height, shift_control, double_scan;
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;
1591 1592
    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);
1592 1601

  
1593 1602
    s->get_resolution(s, &width, &height);
1594 1603
    disp_width = width;
1595 1604

  
1596 1605
    shift_control = (s->gr[0x05] >> 5) & 3;
1597 1606
    double_scan = (s->cr[0x09] >> 7);
1598

  
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;
1599 1615
    if (shift_control != s->shift_control ||
1600 1616
        double_scan != s->double_scan) {
1601
        s->want_full_update = 1;
1617
        full_update = 1;
1602 1618
        s->shift_control = shift_control;
1603 1619
        s->double_scan = double_scan;
1604 1620
    }
......
1612 1628
            disp_width <<= 1;
1613 1629
        }
1614 1630
    }
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;
1626 1631

  
1632
    depth = s->get_bpp(s);
1627 1633
    if (s->line_offset != s->last_line_offset ||
1628 1634
        disp_width != s->last_width ||
1629 1635
        height != s->last_height ||
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
        }
1636
        s->last_depth != depth) {
1637 1637
#if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1638 1638
        if (depth == 16 || depth == 32) {
1639 1639
#else
......
1650 1650
        } else {
1651 1651
            qemu_console_resize(s->ds, disp_width, height);
1652 1652
        }
1653
    dont_touch_display_surface:
1654 1653
        s->last_scr_width = disp_width;
1655 1654
        s->last_scr_height = height;
1656 1655
        s->last_width = disp_width;
1657 1656
        s->last_height = height;
1658 1657
        s->last_line_offset = s->line_offset;
1659 1658
        s->last_depth = depth;
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) &&
1659
        full_update = 1;
1660
    } else if (is_buffer_shared(s->ds->surface) &&
1738 1661
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1739 1662
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1740 1663
        dpy_setdata(s->ds);
......
1743 1666
    s->rgb_to_pixel =
1744 1667
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1745 1668

  
1746
    if (s->shift_control == 0) {
1669
    if (shift_control == 0) {
1747 1670
        full_update |= update_palette16(s);
1748 1671
        if (s->sr[0x01] & 8) {
1749 1672
            v = VGA_DRAW_LINE4D2;
......
1751 1674
            v = VGA_DRAW_LINE4;
1752 1675
        }
1753 1676
        bits = 4;
1754
    } else if (s->shift_control == 1) {
1677
    } else if (shift_control == 1) {
1755 1678
        full_update |= update_palette16(s);
1756 1679
        if (s->sr[0x01] & 8) {
1757 1680
            v = VGA_DRAW_LINE2D2;
......
1847 1770
            if (y_start >= 0) {
1848 1771
                /* flush to display */
1849 1772
                dpy_update(s->ds, 0, y_start,
1850
                           s->last_width, y - y_start);
1773
                           disp_width, y - y_start);
1851 1774
                y_start = -1;
1852 1775
            }
1853 1776
        }
......
1856 1779
            if ((y1 & mask) == mask)
1857 1780
                addr1 += line_offset;
1858 1781
            y1++;
1859
            multi_run = s->multi_scan;
1782
            multi_run = multi_scan;
1860 1783
        } else {
1861 1784
            multi_run--;
1862 1785
        }
......
1868 1791
    if (y_start >= 0) {
1869 1792
        /* flush to display */
1870 1793
        dpy_update(s->ds, 0, y_start,
1871
                   s->last_width, y - y_start);
1794
                   disp_width, y - y_start);
1872 1795
    }
1873 1796
    /* reset modified pages */
1874 1797
    if (page_max != -1) {
......
1905 1828
               s->last_scr_width, s->last_scr_height);
1906 1829
}
1907 1830

  
1831
#define GMODE_TEXT     0
1832
#define GMODE_GRAPH    1
1833
#define GMODE_BLANK 2
1834

  
1908 1835
static void vga_update_display(void *opaque)
1909 1836
{
1910 1837
    VGAState *s = (VGAState *)opaque;
1911
    int full_update;
1838
    int full_update, graphic_mode;
1912 1839

  
1913 1840
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1914 1841
        /* nothing to do */
1915 1842
    } else {
1916
        full_update = s->want_full_update;
1917
        s->want_full_update = 0;
1918
        switch(s->graphic_mode) {
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) {
1919 1854
        case GMODE_TEXT:
1920 1855
            vga_draw_text(s, full_update);
1921 1856
            break;
......
1935 1870
{
1936 1871
    VGAState *s = (VGAState *)opaque;
1937 1872

  
1938
    vga_update_resolution(s);
1939
    s->want_full_update = 1;
1873
    s->last_width = -1;
1874
    s->last_height = -1;
1940 1875
}
1941 1876

  
1942 1877
void vga_reset(void *opaque)
......
1980 1915
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1981 1916
#endif
1982 1917
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1918
    s->graphic_mode = -1; /* force full update */
1983 1919
    s->shift_control = 0;
1984 1920
    s->double_scan = 0;
1985 1921
    s->line_offset = 0;
......
2005 1941
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
2006 1942
        break;
2007 1943
    }
2008
    vga_update_resolution(s);
2009 1944
}
2010 1945

  
2011 1946
#define TEXTMODE_X(x)	((x) % width)
......
2017 1952
static void vga_update_text(void *opaque, console_ch_t *chardata)
2018 1953
{
2019 1954
    VGAState *s = (VGAState *) opaque;
2020
    int i, cursor_offset, cursor_visible;
1955
    int graphic_mode, i, cursor_offset, cursor_visible;
2021 1956
    int cw, cheight, width, height, size, c_min, c_max;
2022 1957
    uint32_t *src;
2023 1958
    console_ch_t *dst, val;
2024 1959
    char msg_buffer[80];
2025
    int full_update = s->want_full_update;
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
    }
2026 1975

  
2027
    s->want_full_update = 0;
2028
    switch (s->graphic_mode) {
1976
    switch (graphic_mode) {
2029 1977
    case GMODE_TEXT:
2030 1978
        /* TODO: update palette */
1979
        full_update |= update_basic_params(s);
2031 1980

  
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);
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;
2039 1997
        }
2040 1998

  
2041
        /* total width & height */
2042 1999
        size = (height * width);
2043 2000
        if (size > CH_ATTR_SIZE) {
2044 2001
            if (!full_update)
......
2049 2006
            break;
2050 2007
        }
2051 2008

  
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

  
2052 2023
        /* Update "hardware" cursor */
2053 2024
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2054 2025
        if (cursor_offset != s->cursor_offset ||
......
2247 2218
#endif
2248 2219

  
2249 2220
    /* force refresh */
2250
    vga_update_resolution(s);
2251
    s->want_full_update = 1;
2221
    s->graphic_mode = -1;
2252 2222
    return 0;
2253 2223
}
2254 2224

  
......
2671 2641
    ds->surface = qemu_create_displaysurface(ds, w, h);
2672 2642

  
2673 2643
    s->ds = ds;
2674
    vga_update_resolution(s);
2675
    s->want_full_update = 1;
2644
    s->graphic_mode = -1;
2676 2645
    vga_update_display(s);
2677 2646

  
2678 2647
    ppm_save(filename, ds->surface);
......
2703 2672
{
2704 2673
    VGAState *s = (VGAState *)opaque;
2705 2674

  
2706
    switch (s->graphic_mode) {
2707
    case GMODE_TEXT:
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:
2675
    if (!(s->ar_index & 0x20))
2715 2676
        vga_screen_dump_blank(s, filename);
2716
        break;
2717
    }
2677
    else if (s->gr[6] & 1)
2678
        vga_screen_dump_graphic(s, filename);
2679
    else
2680
        vga_screen_dump_text(s, filename);
2718 2681
}

Also available in: Unified diff