]> Git Repo - qemu.git/blobdiff - hw/vga.c
generic hardware cursor support
[qemu.git] / hw / vga.c
index 8d8ad9baf854b12d5a3287795177b3d778977afd..23695f506d56afcfc579678ea0908abe8a805b7d 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include "vga_int.h"
 
 //#define DEBUG_VGA
 //#define DEBUG_VGA_MEM
 /* S3 VGA is deprecated - another graphic card will be emulated */
 //#define CONFIG_S3VGA
 
-#define MSR_COLOR_EMULATION 0x01
-#define MSR_PAGE_SELECT     0x20
-
-#define ST01_V_RETRACE      0x08
-#define ST01_DISP_ENABLE    0x01
-
-/* bochs VBE support */
-#define CONFIG_BOCHS_VBE
-
-#define VBE_DISPI_MAX_XRES              1024
-#define VBE_DISPI_MAX_YRES              768
-
-#define VBE_DISPI_INDEX_ID              0x0
-#define VBE_DISPI_INDEX_XRES            0x1
-#define VBE_DISPI_INDEX_YRES            0x2
-#define VBE_DISPI_INDEX_BPP             0x3
-#define VBE_DISPI_INDEX_ENABLE          0x4
-#define VBE_DISPI_INDEX_BANK            0x5
-#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
-#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
-#define VBE_DISPI_INDEX_X_OFFSET        0x8
-#define VBE_DISPI_INDEX_Y_OFFSET        0x9
-#define VBE_DISPI_INDEX_NB              0xa
-      
-#define VBE_DISPI_ID0                   0xB0C0
-#define VBE_DISPI_ID1                   0xB0C1
-#define VBE_DISPI_ID2                   0xB0C2
-  
-#define VBE_DISPI_DISABLED              0x00
-#define VBE_DISPI_ENABLED               0x01
-#define VBE_DISPI_LFB_ENABLED           0x40
-#define VBE_DISPI_NOCLEARMEM            0x80
-  
-#define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
-
-typedef struct VGAState {
-    uint8_t *vram_ptr;
-    unsigned long vram_offset;
-    unsigned int vram_size;
-    uint32_t latch;
-    uint8_t sr_index;
-    uint8_t sr[8];
-    uint8_t gr_index;
-    uint8_t gr[16];
-    uint8_t ar_index;
-    uint8_t ar[21];
-    int ar_flip_flop;
-    uint8_t cr_index;
-    uint8_t cr[256]; /* CRT registers */
-    uint8_t msr; /* Misc Output Register */
-    uint8_t fcr; /* Feature Control Register */
-    uint8_t st00; /* status 0 */
-    uint8_t st01; /* status 1 */
-    uint8_t dac_state;
-    uint8_t dac_sub_index;
-    uint8_t dac_read_index;
-    uint8_t dac_write_index;
-    uint8_t dac_cache[3]; /* used when writing */
-    uint8_t palette[768];
-    int32_t bank_offset;
-#ifdef CONFIG_BOCHS_VBE
-    uint16_t vbe_index;
-    uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
-    uint32_t vbe_start_addr;
-    uint32_t vbe_line_offset;
-    uint32_t vbe_bank_mask;
-#endif
-    /* display refresh support */
-    DisplayState *ds;
-    uint32_t font_offsets[2];
-    int graphic_mode;
-    uint8_t shift_control;
-    uint8_t double_scan;
-    uint32_t line_offset;
-    uint32_t line_compare;
-    uint32_t start_addr;
-    uint8_t last_cw, last_ch;
-    uint32_t last_width, last_height; /* in chars or pixels */
-    uint32_t last_scr_width, last_scr_height; /* in pixels */
-    uint8_t cursor_start, cursor_end;
-    uint32_t cursor_offset;
-    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
-    /* tell for each page if it has been updated since the last time */
-    uint32_t last_palette[256];
-#define CH_ATTR_SIZE (160 * 100)
-    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
-} VGAState;
-
 /* force some bits to zero */
-static const uint8_t sr_mask[8] = {
+const uint8_t sr_mask[8] = {
     (uint8_t)~0xfc,
     (uint8_t)~0xc2,
     (uint8_t)~0xf0,
@@ -133,7 +46,7 @@ static const uint8_t sr_mask[8] = {
     (uint8_t)~0x00,
 };
 
-static const uint8_t gr_mask[16] = {
+const uint8_t gr_mask[16] = {
     (uint8_t)~0xf0, /* 0x00 */
     (uint8_t)~0xf0, /* 0x01 */
     (uint8_t)~0xf0, /* 0x02 */
@@ -234,7 +147,7 @@ static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
 
-VGAState vga_state;
+VGAState *vga_state;
 int vga_io_memory;
 
 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
@@ -656,7 +569,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
 #endif
 
 /* called for accesses between 0xa0000 and 0xc0000 */
-static uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
+uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
 {
     VGAState *s = opaque;
     int memory_map_mode, plane;
@@ -743,7 +656,7 @@ static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
 }
 
 /* called for accesses between 0xa0000 and 0xc0000 */
-static void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     VGAState *s = opaque;
     int memory_map_mode, plane, write_mode, b, func_select;
@@ -939,14 +852,6 @@ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsign
 #define DEPTH 32
 #include "vga_template.h"
 
-static inline int c6_to_8(int v)
-{
-    int b;
-    v &= 0x3f;
-    b = v & 1;
-    return (v << 2) | (b << 1) | b;
-}
-
 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
 {
     unsigned int col;
@@ -1027,14 +932,11 @@ static int update_palette256(VGAState *s)
     return full_update;
 }
 
-/* update start_addr and line_offset. Return TRUE if modified */
-static int update_basic_params(VGAState *s)
+static void vga_get_offsets(VGAState *s, 
+                            uint32_t *pline_offset, 
+                            uint32_t *pstart_addr)
 {
-    int full_update;
-    uint32_t start_addr, line_offset, line_compare;
-    
-    full_update = 0;
-
+    uint32_t start_addr, line_offset;
 #ifdef CONFIG_BOCHS_VBE
     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
         line_offset = s->vbe_line_offset;
@@ -1061,7 +963,19 @@ static int update_basic_params(VGAState *s)
         start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
 #endif
     }
+    *pline_offset = line_offset;
+    *pstart_addr = start_addr;
+}
+
+/* update start_addr and line_offset. Return TRUE if modified */
+static int update_basic_params(VGAState *s)
+{
+    int full_update;
+    uint32_t start_addr, line_offset, line_compare;
     
+    full_update = 0;
+
+    s->get_offsets(s, &line_offset, &start_addr);
     /* line compare */
     line_compare = s->cr[0x18] | 
         ((s->cr[0x07] & 0x10) << 4) |
@@ -1373,11 +1287,34 @@ static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
     vga_draw_line32_32,
 };
 
+static int vga_get_bpp(VGAState *s)
+{
+    int ret;
+#ifdef CONFIG_BOCHS_VBE
+    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
+    } else 
+#endif
+    {
+        ret = 0;
+    }
+    return ret;
+}
+
+void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
+{
+    int y;
+    if (y1 >= VGA_MAX_HEIGHT)
+        return;
+    if (y2 >= VGA_MAX_HEIGHT)
+        y2 = VGA_MAX_HEIGHT;
+    for(y = y1; y < y2; y++) {
+        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
+    }
+}
+
 /* 
  * graphic modes
- * Missing:
- * - double scan
- * - double width 
  */
 static void vga_draw_graphic(VGAState *s, int full_update)
 {
@@ -1429,32 +1366,28 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             v = VGA_DRAW_LINE2;
         }
     } else {
-#ifdef CONFIG_BOCHS_VBE
-        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
-            switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) {
-            default:
-            case 8:
-                full_update |= update_palette256(s);
-                v = VGA_DRAW_LINE8;
-                break;
-            case 15:
-                v = VGA_DRAW_LINE15;
-                break;
-            case 16:
-                v = VGA_DRAW_LINE16;
-                break;
-            case 24:
-                v = VGA_DRAW_LINE24;
-                break;
-            case 32:
-                v = VGA_DRAW_LINE32;
-                break;
-            }
-        } else 
-#endif
-        {
+        switch(s->get_bpp(s)) {
+        default:
+        case 0:
             full_update |= update_palette256(s);
             v = VGA_DRAW_LINE8D2;
+            break;
+        case 8:
+            full_update |= update_palette256(s);
+            v = VGA_DRAW_LINE8;
+            break;
+        case 15:
+            v = VGA_DRAW_LINE15;
+            break;
+        case 16:
+            v = VGA_DRAW_LINE16;
+            break;
+        case 24:
+            v = VGA_DRAW_LINE24;
+            break;
+        case 32:
+            v = VGA_DRAW_LINE32;
+            break;
         }
     }
     vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
@@ -1468,7 +1401,9 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         s->last_height = height;
         full_update = 1;
     }
-
+    if (s->cursor_invalidate)
+        s->cursor_invalidate(s);
+    
     line_offset = s->line_offset;
 #if 0
     printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
@@ -1501,6 +1436,8 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             /* if wide line, can use another page */
             update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
         }
+        /* explicit invalidation for the hardware cursor */
+        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
         if (update) {
             if (y_start < 0)
                 y_start = y;
@@ -1509,6 +1446,8 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             if (page1 > page_max)
                 page_max = page1;
             vga_draw_line(s, d, s->vram_ptr + addr, width);
+            if (s->cursor_draw_line)
+                s->cursor_draw_line(s, d, y);
         } else {
             if (y_start >= 0) {
                 /* flush to display */
@@ -1544,6 +1483,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     if (page_max != -1) {
         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
     }
+    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 }
 
 static void vga_draw_blank(VGAState *s, int full_update)
@@ -1575,7 +1515,7 @@ static void vga_draw_blank(VGAState *s, int full_update)
 
 void vga_update_display(void)
 {
-    VGAState *s = &vga_state;
+    VGAState *s = vga_state;
     int full_update, graphic_mode;
 
     if (s->ds->depth == 0) {
@@ -1742,16 +1682,14 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
 static void vga_map(PCIDevice *pci_dev, int region_num, 
                     uint32_t addr, uint32_t size, int type)
 {
-    VGAState *s = &vga_state;
+    VGAState *s = vga_state;
 
     cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
 }
 
-int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
-                   unsigned long vga_ram_offset, int vga_ram_size, 
-                   int is_pci)
+void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
+                     unsigned long vga_ram_offset, int vga_ram_size)
 {
-    VGAState *s = &vga_state;
     int i, j, v, b;
 
     for(i = 0;i < 256; i++) {
@@ -1783,6 +1721,24 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base,
     s->vram_offset = vga_ram_offset;
     s->vram_size = vga_ram_size;
     s->ds = ds;
+    s->get_bpp = vga_get_bpp;
+    s->get_offsets = vga_get_offsets;
+    /* XXX: currently needed for display */
+    vga_state = s;
+}
+
+
+int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
+                   unsigned long vga_ram_offset, int vga_ram_size, 
+                   int is_pci)
+{
+    VGAState *s;
+
+    s = qemu_mallocz(sizeof(VGAState));
+    if (!s)
+        return -1;
+
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
 
     register_savevm("vga", 0, 1, vga_save, vga_load, s);
 
@@ -1915,7 +1871,7 @@ static int ppm_save(const char *filename, uint8_t *data,
    available */
 void vga_screen_dump(const char *filename)
 {
-    VGAState *s = &vga_state;
+    VGAState *s = vga_state;
     DisplayState *saved_ds, ds1, *ds = &ds1;
     
     /* XXX: this is a little hackish */
This page took 0.032153 seconds and 4 git commands to generate.