/* force some bits to zero */
const uint8_t sr_mask[8] = {
- (uint8_t)~0xfc,
- (uint8_t)~0xc2,
- (uint8_t)~0xf0,
- (uint8_t)~0xc0,
- (uint8_t)~0xf1,
- (uint8_t)~0xff,
- (uint8_t)~0xff,
- (uint8_t)~0x00,
+ 0x03,
+ 0x3d,
+ 0x0f,
+ 0x3f,
+ 0x0e,
+ 0x00,
+ 0x00,
+ 0xff,
};
const uint8_t gr_mask[16] = {
- (uint8_t)~0xf0, /* 0x00 */
- (uint8_t)~0xf0, /* 0x01 */
- (uint8_t)~0xf0, /* 0x02 */
- (uint8_t)~0xe0, /* 0x03 */
- (uint8_t)~0xfc, /* 0x04 */
- (uint8_t)~0x84, /* 0x05 */
- (uint8_t)~0xf0, /* 0x06 */
- (uint8_t)~0xf0, /* 0x07 */
- (uint8_t)~0x00, /* 0x08 */
- (uint8_t)~0xff, /* 0x09 */
- (uint8_t)~0xff, /* 0x0a */
- (uint8_t)~0xff, /* 0x0b */
- (uint8_t)~0xff, /* 0x0c */
- (uint8_t)~0xff, /* 0x0d */
- (uint8_t)~0xff, /* 0x0e */
- (uint8_t)~0xff, /* 0x0f */
+ 0x0f, /* 0x00 */
+ 0x0f, /* 0x01 */
+ 0x0f, /* 0x02 */
+ 0x1f, /* 0x03 */
+ 0x03, /* 0x04 */
+ 0x7b, /* 0x05 */
+ 0x0f, /* 0x06 */
+ 0x0f, /* 0x07 */
+ 0xff, /* 0x08 */
+ 0x00, /* 0x09 */
+ 0x00, /* 0x0a */
+ 0x00, /* 0x0b */
+ 0x00, /* 0x0c */
+ 0x00, /* 0x0d */
+ 0x00, /* 0x0e */
+ 0x00, /* 0x0f */
};
#define cbswap_32(__x) \
case 16:
return 2;
case 32:
- return 3;
+ if (is_surface_bgr(s->surface))
+ return 4;
+ else
+ return 3;
}
}
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
-static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS];
+static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
+ rgb_to_pixel8_dup,
+ rgb_to_pixel15_dup,
+ rgb_to_pixel16_dup,
+ rgb_to_pixel32_dup,
+ rgb_to_pixel32bgr_dup,
+ rgb_to_pixel15bgr_dup,
+ rgb_to_pixel16bgr_dup,
+};
/*
* Text mode update
vga_draw_glyph8_func *vga_draw_glyph8;
vga_draw_glyph9_func *vga_draw_glyph9;
- vga_dirty_log_stop(s);
-
/* compute font data address (in plane 2) */
v = s->sr[3];
offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
s->last_scr_width = width * cw;
s->last_scr_height = height * cheight;
- qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
+ qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
s->last_depth = 0;
s->last_width = width;
s->last_height = height;
vga_draw_line32_16bgr,
};
-static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
- rgb_to_pixel8_dup,
- rgb_to_pixel15_dup,
- rgb_to_pixel16_dup,
- rgb_to_pixel32_dup,
- rgb_to_pixel32bgr_dup,
- rgb_to_pixel15bgr_dup,
- rgb_to_pixel16bgr_dup,
-};
-
static int vga_get_bpp(VGAState *s)
{
int ret;
cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
}
- vga_dirty_log_start(s);
}
/*
*/
static void vga_draw_graphic(VGAState *s, int full_update)
{
- int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth;
- int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
+ int y1, y, update, linesize, y_start, double_scan, mask, depth;
+ int width, height, shift_control, line_offset, bwidth, bits;
+ ram_addr_t page0, page1, page_min, page_max;
int disp_width, multi_scan, multi_run;
uint8_t *d;
uint32_t v, addr1, addr;
s->double_scan = double_scan;
}
+ if (shift_control == 0) {
+ if (s->sr[0x01] & 8) {
+ disp_width <<= 1;
+ }
+ } else if (shift_control == 1) {
+ if (s->sr[0x01] & 8) {
+ disp_width <<= 1;
+ }
+ }
+
+ depth = s->get_bpp(s);
+ if (s->line_offset != s->last_line_offset ||
+ disp_width != s->last_width ||
+ height != s->last_height ||
+ s->last_depth != depth) {
+#if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+ if (depth == 16 || depth == 32) {
+#else
+ if (depth == 32) {
+#endif
+ qemu_free_displaysurface(s->ds);
+ s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
+ s->line_offset,
+ s->vram_ptr + (s->start_addr * 4));
+#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+ s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
+#endif
+ dpy_resize(s->ds);
+ } else {
+ qemu_console_resize(s->ds, disp_width, height);
+ }
+ s->last_scr_width = disp_width;
+ s->last_scr_height = height;
+ s->last_width = disp_width;
+ s->last_height = height;
+ s->last_line_offset = s->line_offset;
+ s->last_depth = depth;
+ full_update = 1;
+ } else if (is_buffer_shared(s->ds->surface) &&
+ (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
+ s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
+ dpy_setdata(s->ds);
+ }
+
+ s->rgb_to_pixel =
+ rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+
if (shift_control == 0) {
full_update |= update_palette16(s);
if (s->sr[0x01] & 8) {
v = VGA_DRAW_LINE4D2;
- disp_width <<= 1;
} else {
v = VGA_DRAW_LINE4;
}
full_update |= update_palette16(s);
if (s->sr[0x01] & 8) {
v = VGA_DRAW_LINE2D2;
- disp_width <<= 1;
} else {
v = VGA_DRAW_LINE2;
}
}
vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
- depth = s->get_bpp(s);
- if (s->line_offset != s->last_line_offset ||
- disp_width != s->last_width ||
- height != s->last_height ||
- s->last_depth != depth) {
- if (depth == 16 || depth == 32) {
- if (is_graphic_console()) {
- qemu_free_displaysurface(s->ds->surface);
- s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
- s->line_offset,
- s->vram_ptr + (s->start_addr * 4));
- dpy_resize(s->ds);
- } else {
- qemu_console_resize(s->console, disp_width, height);
- }
- } else {
- qemu_console_resize(s->console, disp_width, height);
- }
- s->last_scr_width = disp_width;
- s->last_scr_height = height;
- s->last_width = disp_width;
- s->last_height = height;
- s->last_line_offset = s->line_offset;
- s->last_depth = depth;
- full_update = 1;
- } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) &&
- (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
- s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
- dpy_setdata(s->ds);
- }
-
- s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(s->ds)];
-
if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
s->cursor_invalidate(s);
addr1 = (s->start_addr * 4);
bwidth = (width * bits + 7) / 8;
y_start = -1;
- page_min = 0x7fffffff;
- page_max = -1;
+ page_min = -1;
+ page_max = 0;
d = ds_get_data(s->ds);
linesize = ds_get_linesize(s->ds);
y1 = 0;
disp_width, y - y_start);
}
/* reset modified pages */
- if (page_max != -1) {
+ if (page_max >= page_min) {
cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
VGA_DIRTY_FLAG);
}
return;
if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
return;
- vga_dirty_log_stop(s);
s->rgb_to_pixel =
rgb_to_pixel_dup_table[get_depth_index(s->ds)];
}
}
-void vga_dirty_log_stop(VGAState *s)
-{
- if (kvm_enabled() && s->map_addr)
- kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
-
- if (kvm_enabled() && s->lfb_vram_mapped) {
- kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
- kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
- }
-}
-
static void vga_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
} else {
cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+ s->map_addr = addr;
+ s->map_end = addr + s->vram_size;
+ vga_dirty_log_start(s);
}
-
- s->map_addr = addr;
- s->map_end = addr + VGA_RAM_SIZE;
-
- vga_dirty_log_start(s);
}
-void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
- ram_addr_t vga_ram_offset, int vga_ram_size)
+void vga_common_init(VGAState *s, int vga_ram_size)
{
int i, j, v, b;
expand4to8[i] = v;
}
- s->vram_ptr = vga_ram_base;
- s->vram_offset = vga_ram_offset;
+ s->vram_offset = qemu_ram_alloc(vga_ram_size);
+ s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
s->vram_size = vga_ram_size;
- s->ds = ds;
s->get_bpp = vga_get_bpp;
s->get_offsets = vga_get_offsets;
s->get_resolution = vga_get_resolution;
{
int vga_io_memory;
- qemu_register_reset(vga_reset, s);
+ qemu_register_reset(vga_reset, 0, s);
register_savevm("vga", 0, 2, vga_save, vga_load, s);
register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
}
-int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size)
+int isa_vga_init(void)
{
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);
+ vga_common_init(s, VGA_RAM_SIZE);
vga_init(s);
- s->console = graphic_console_init(s->ds, s->update, s->invalidate,
- s->screen_dump, s->text_update, s);
+ s->ds = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
#ifdef CONFIG_BOCHS_VBE
/* XXX: use optimized standard vga accesses */
cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
- vga_ram_size, vga_ram_offset);
+ VGA_RAM_SIZE, s->vram_offset);
#endif
return 0;
}
-int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size,
- target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
- int it_shift)
+int isa_vga_mm_init(target_phys_addr_t vram_base,
+ target_phys_addr_t ctrl_base, int it_shift)
{
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);
+ vga_common_init(s, VGA_RAM_SIZE);
vga_mm_init(s, vram_base, ctrl_base, it_shift);
- s->console = graphic_console_init(s->ds, s->update, s->invalidate,
- s->screen_dump, s->text_update, s);
+ s->ds = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
#ifdef CONFIG_BOCHS_VBE
/* XXX: use optimized standard vga accesses */
cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
- vga_ram_size, vga_ram_offset);
+ VGA_RAM_SIZE, s->vram_offset);
#endif
return 0;
}
-int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size,
+static void pci_vga_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len)
+{
+ PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
+ VGAState *s = &pvs->vga_state;
+
+ pci_default_write_config(d, address, val, len);
+ if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
+ s->map_addr = 0;
+}
+
+int pci_vga_init(PCIBus *bus,
unsigned long vga_bios_offset, int vga_bios_size)
{
PCIVGAState *d;
d = (PCIVGAState *)pci_register_device(bus, "VGA",
sizeof(PCIVGAState),
- -1, NULL, NULL);
+ -1, NULL, pci_vga_write_config);
if (!d)
return -1;
s = &d->vga_state;
- vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+ vga_common_init(s, VGA_RAM_SIZE);
vga_init(s);
- s->console = graphic_console_init(s->ds, s->update, s->invalidate,
- s->screen_dump, s->text_update, s);
+ s->ds = graphic_console_init(s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
s->pci_dev = &d->dev;
pci_conf = d->dev.config;
- pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
- pci_conf[0x01] = 0x12;
- pci_conf[0x02] = 0x11;
- pci_conf[0x03] = 0x11;
- pci_conf[0x0a] = 0x00; // VGA controller
- pci_conf[0x0b] = 0x03;
- pci_conf[0x0e] = 0x00; // header_type
-
- /* XXX: vga_ram_size must be a power of two */
- pci_register_io_region(&d->dev, 0, vga_ram_size,
+ // dummy VGA (same as Bochs ID)
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
+ pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+
+ /* XXX: VGA_RAM_SIZE must be a power of two */
+ pci_register_io_region(&d->dev, 0, VGA_RAM_SIZE,
PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
if (vga_bios_size != 0) {
unsigned int bios_total_size;
/********************************************************/
/* vga screen dump */
-static int vga_save_w, vga_save_h;
-
static void vga_save_dpy_update(DisplayState *s,
int x, int y, int w, int h)
{
{
}
-int ppm_save(const char *filename, uint8_t *data,
- int w, int h, int linesize)
+int ppm_save(const char *filename, struct DisplaySurface *ds)
{
FILE *f;
uint8_t *d, *d1;
- unsigned int v;
+ uint32_t v;
int y, x;
+ uint8_t r, g, b;
f = fopen(filename, "wb");
if (!f)
return -1;
fprintf(f, "P6\n%d %d\n%d\n",
- w, h, 255);
- d1 = data;
- for(y = 0; y < h; y++) {
+ ds->width, ds->height, 255);
+ d1 = ds->data;
+ for(y = 0; y < ds->height; y++) {
d = d1;
- for(x = 0; x < w; x++) {
- v = *(uint32_t *)d;
- fputc((v >> 16) & 0xff, f);
- fputc((v >> 8) & 0xff, f);
- fputc((v) & 0xff, f);
- d += 4;
+ for(x = 0; x < ds->width; x++) {
+ if (ds->pf.bits_per_pixel == 32)
+ v = *(uint32_t *)d;
+ else
+ v = (uint32_t) (*(uint16_t *)d);
+ r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
+ (ds->pf.rmax + 1);
+ g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
+ (ds->pf.gmax + 1);
+ b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
+ (ds->pf.bmax + 1);
+ fputc(r, f);
+ fputc(g, f);
+ fputc(b, f);
+ d += ds->pf.bytes_per_pixel;
}
- d1 += linesize;
+ d1 += ds->linesize;
}
fclose(f);
return 0;
dcl.dpy_resize = vga_save_dpy_resize;
dcl.dpy_refresh = vga_save_dpy_refresh;
register_displaychangelistener(ds, &dcl);
- ds->surface = qemu_create_displaysurface(ds_get_width(saved_ds),
- ds_get_height(saved_ds), 32, 4 * ds_get_width(saved_ds));
+ ds->allocator = &default_allocator;
+ ds->surface = qemu_create_displaysurface(ds, w, h);
s->ds = ds;
s->graphic_mode = -1;
vga_update_display(s);
- ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h,
- ds_get_linesize(ds));
+ ppm_save(filename, ds->surface);
- qemu_free_displaysurface(ds->surface);
+ qemu_free_displaysurface(ds);
s->ds = saved_ds;
}
vga_screen_dump_graphic(s, filename);
else
vga_screen_dump_text(s, filename);
+ vga_invalidate_display(s);
}