#define PAT(x) cbswap_32(x)
#endif
-static const uint32_t dmask16[16] = {
- PAT(0x00000000),
- PAT(0x000000ff),
- PAT(0x0000ff00),
- PAT(0x0000ffff),
- PAT(0x00ff0000),
- PAT(0x00ff00ff),
- PAT(0x00ffff00),
- PAT(0x00ffffff),
- PAT(0xff000000),
- PAT(0xff0000ff),
- PAT(0xff00ff00),
- PAT(0xff00ffff),
- PAT(0xffff0000),
- PAT(0xffff00ff),
- PAT(0xffffff00),
- PAT(0xffffffff),
-};
-
-static const uint32_t dmask4[4] = {
- PAT(0x00000000),
- PAT(0x0000ffff),
- PAT(0xffff0000),
- PAT(0xffffffff),
-};
-
static uint32_t expand4[256];
static uint16_t expand2[256];
static uint8_t expand4to8[16];
size = 0x8000;
break;
}
- base += isa_mem_base;
memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram),
"vga.chain4", &s->vram, offset, size);
memory_region_add_subregion_overlap(s->legacy_address_space, base,
s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;
vbe_fixup_regs(s);
- /* clear the screen (should be done in BIOS) */
+ /* clear the screen */
if (!(val & VBE_DISPI_NOCLEARMEM)) {
memset(s->vram_ptr, 0,
s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
}
- /* we initialize the VGA graphic mode (should be done
- in BIOS) */
+ /* we initialize the VGA graphic mode */
/* graphic mode + memory map 1 */
s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
VGA_GR06_GRAPHICS_MODE;
(shift_control << 5);
s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
} else {
- /* XXX: the bios should do that */
s->bank_offset = 0;
}
s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
}
}
-typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
- const uint8_t *font_ptr, int h,
- uint32_t fgcol, uint32_t bgcol);
-typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
- const uint8_t *font_ptr, int h,
- uint32_t fgcol, uint32_t bgcol, int dup9);
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
const uint8_t *s, int width);
-#define DEPTH 8
-#include "vga_template.h"
-
-#define DEPTH 15
-#include "vga_template.h"
-
-#define BGR_FORMAT
-#define DEPTH 15
-#include "vga_template.h"
-
-#define DEPTH 16
-#include "vga_template.h"
-
-#define BGR_FORMAT
-#define DEPTH 16
-#include "vga_template.h"
-
-#define DEPTH 32
-#include "vga_template.h"
-
-#define BGR_FORMAT
-#define DEPTH 32
-#include "vga_template.h"
-
-static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel8(r, g, b);
- col |= col << 8;
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel15(r, g, b);
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
- unsigned int b)
-{
- unsigned int col;
- col = rgb_to_pixel15bgr(r, g, b);
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel16(r, g, b);
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
- unsigned int b)
-{
- unsigned int col;
- col = rgb_to_pixel16bgr(r, g, b);
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel32(r, g, b);
- return col;
-}
-
-static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel32bgr(r, g, b);
- return col;
-}
+#include "vga-helpers.h"
/* return true if the palette was modified */
static int update_palette16(VGACommonState *s)
v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
}
v = v * 3;
- col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
- c6_to_8(s->palette[v + 1]),
- c6_to_8(s->palette[v + 2]));
+ col = rgb_to_pixel32(c6_to_8(s->palette[v]),
+ c6_to_8(s->palette[v + 1]),
+ c6_to_8(s->palette[v + 2]));
if (col != palette[i]) {
full_update = 1;
palette[i] = col;
v = 0;
for(i = 0; i < 256; i++) {
if (s->dac_8bit) {
- col = s->rgb_to_pixel(s->palette[v],
- s->palette[v + 1],
- s->palette[v + 2]);
+ col = rgb_to_pixel32(s->palette[v],
+ s->palette[v + 1],
+ s->palette[v + 2]);
} else {
- col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
- c6_to_8(s->palette[v + 1]),
- c6_to_8(s->palette[v + 2]));
+ col = rgb_to_pixel32(c6_to_8(s->palette[v]),
+ c6_to_8(s->palette[v + 1]),
+ c6_to_8(s->palette[v + 2]));
}
if (col != palette[i]) {
full_update = 1;
return full_update;
}
-#define NB_DEPTHS 7
-
-static inline int get_depth_index(DisplaySurface *s)
-{
- switch (surface_bits_per_pixel(s)) {
- default:
- case 8:
- return 0;
- case 15:
- return 1;
- case 16:
- return 2;
- case 32:
- if (is_surface_bgr(s)) {
- return 4;
- } else {
- return 3;
- }
- }
-}
-
-static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
- vga_draw_glyph8_8,
- vga_draw_glyph8_16,
- vga_draw_glyph8_16,
- vga_draw_glyph8_32,
- vga_draw_glyph8_32,
- vga_draw_glyph8_16,
- vga_draw_glyph8_16,
-};
-
-static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
- vga_draw_glyph16_8,
- vga_draw_glyph16_16,
- vga_draw_glyph16_16,
- vga_draw_glyph16_32,
- vga_draw_glyph16_32,
- vga_draw_glyph16_16,
- vga_draw_glyph16_16,
-};
-
-static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
- vga_draw_glyph9_8,
- vga_draw_glyph9_16,
- vga_draw_glyph9_16,
- vga_draw_glyph9_32,
- vga_draw_glyph9_32,
- vga_draw_glyph9_16,
- vga_draw_glyph9_16,
-};
static const uint8_t cursor_glyph[32 * 4] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
*pcheight = cheight;
}
-typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
-
-static rgb_to_pixel_dup_func * const 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
* Missing:
uint32_t offset, fgcol, bgcol, v, cursor_offset;
uint8_t *d1, *d, *src, *dest, *cursor_ptr;
const uint8_t *font_ptr, *font_base[2];
- int dup9, line_offset, depth_index;
+ int dup9, line_offset;
uint32_t *palette;
uint32_t *ch_attr_ptr;
- vga_draw_glyph8_func *vga_draw_glyph8;
- vga_draw_glyph9_func *vga_draw_glyph9;
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
/* compute font data address (in plane 2) */
s->last_cw = cw;
full_update = 1;
}
- s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(surface)];
full_update |= update_palette16(s);
palette = s->last_palette;
x_incr = cw * surface_bytes_per_pixel(surface);
s->cursor_visible_phase = !s->cursor_visible_phase;
}
- depth_index = get_depth_index(surface);
- if (cw == 16)
- vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
- else
- vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
- vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
-
dest = surface_data(surface);
linesize = surface_stride(surface);
ch_attr_ptr = s->last_ch_attr;
font_ptr += 32 * 4 * ch;
bgcol = palette[cattr >> 4];
fgcol = palette[cattr & 0x0f];
- if (cw != 9) {
+ if (cw == 16) {
+ vga_draw_glyph16(d1, linesize,
+ font_ptr, cheight, fgcol, bgcol);
+ } else if (cw != 9) {
vga_draw_glyph8(d1, linesize,
font_ptr, cheight, fgcol, bgcol);
} else {
if (line_last >= line_start && line_start < cheight) {
h = line_last - line_start + 1;
d = d1 + linesize * line_start;
- if (cw != 9) {
+ if (cw == 16) {
+ vga_draw_glyph16(d, linesize,
+ cursor_glyph, h, fgcol, bgcol);
+ } else if (cw != 9) {
vga_draw_glyph8(d, linesize,
cursor_glyph, h, fgcol, bgcol);
} else {
VGA_DRAW_LINE4D2,
VGA_DRAW_LINE8D2,
VGA_DRAW_LINE8,
- VGA_DRAW_LINE15,
- VGA_DRAW_LINE16,
- VGA_DRAW_LINE24,
- VGA_DRAW_LINE32,
+ VGA_DRAW_LINE15_LE,
+ VGA_DRAW_LINE16_LE,
+ VGA_DRAW_LINE24_LE,
+ VGA_DRAW_LINE32_LE,
+ VGA_DRAW_LINE15_BE,
+ VGA_DRAW_LINE16_BE,
+ VGA_DRAW_LINE24_BE,
+ VGA_DRAW_LINE32_BE,
VGA_DRAW_LINE_NB,
};
-static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
- vga_draw_line2_8,
- vga_draw_line2_16,
- vga_draw_line2_16,
- vga_draw_line2_32,
- vga_draw_line2_32,
- vga_draw_line2_16,
- vga_draw_line2_16,
-
- vga_draw_line2d2_8,
- vga_draw_line2d2_16,
- vga_draw_line2d2_16,
- vga_draw_line2d2_32,
- vga_draw_line2d2_32,
- vga_draw_line2d2_16,
- vga_draw_line2d2_16,
-
- vga_draw_line4_8,
- vga_draw_line4_16,
- vga_draw_line4_16,
- vga_draw_line4_32,
- vga_draw_line4_32,
- vga_draw_line4_16,
- vga_draw_line4_16,
-
- vga_draw_line4d2_8,
- vga_draw_line4d2_16,
- vga_draw_line4d2_16,
- vga_draw_line4d2_32,
- vga_draw_line4d2_32,
- vga_draw_line4d2_16,
- vga_draw_line4d2_16,
-
- vga_draw_line8d2_8,
- vga_draw_line8d2_16,
- vga_draw_line8d2_16,
- vga_draw_line8d2_32,
- vga_draw_line8d2_32,
- vga_draw_line8d2_16,
- vga_draw_line8d2_16,
-
- vga_draw_line8_8,
- vga_draw_line8_16,
- vga_draw_line8_16,
- vga_draw_line8_32,
- vga_draw_line8_32,
- vga_draw_line8_16,
- vga_draw_line8_16,
-
- vga_draw_line15_8,
- vga_draw_line15_15,
- vga_draw_line15_16,
- vga_draw_line15_32,
- vga_draw_line15_32bgr,
- vga_draw_line15_15bgr,
- vga_draw_line15_16bgr,
-
- vga_draw_line16_8,
- vga_draw_line16_15,
- vga_draw_line16_16,
- vga_draw_line16_32,
- vga_draw_line16_32bgr,
- vga_draw_line16_15bgr,
- vga_draw_line16_16bgr,
-
- vga_draw_line24_8,
- vga_draw_line24_15,
- vga_draw_line24_16,
- vga_draw_line24_32,
- vga_draw_line24_32bgr,
- vga_draw_line24_15bgr,
- vga_draw_line24_16bgr,
-
- vga_draw_line32_8,
- vga_draw_line32_15,
- vga_draw_line32_16,
- vga_draw_line32_32,
- vga_draw_line32_32bgr,
- vga_draw_line32_15bgr,
- vga_draw_line32_16bgr,
+static vga_draw_line_func * const vga_draw_line_table[VGA_DRAW_LINE_NB] = {
+ vga_draw_line2,
+ vga_draw_line2d2,
+ vga_draw_line4,
+ vga_draw_line4d2,
+ vga_draw_line8d2,
+ vga_draw_line8,
+ vga_draw_line15_le,
+ vga_draw_line16_le,
+ vga_draw_line24_le,
+ vga_draw_line32_le,
+ vga_draw_line15_be,
+ vga_draw_line16_be,
+ vga_draw_line24_be,
+ vga_draw_line32_be,
};
static int vga_get_bpp(VGACommonState *s)
int disp_width, multi_scan, multi_run;
uint8_t *d;
uint32_t v, addr1, addr;
- vga_draw_line_func *vga_draw_line;
-#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
- static const bool byteswap = false;
+ vga_draw_line_func *vga_draw_line = NULL;
+ bool share_surface;
+ pixman_format_code_t format;
+#ifdef HOST_WORDS_BIGENDIAN
+ bool byteswap = !s->big_endian_fb;
#else
- static const bool byteswap = true;
+ bool byteswap = s->big_endian_fb;
#endif
full_update |= update_basic_params(s);
}
depth = s->get_bpp(s);
+
+ /*
+ * Check whether we can share the surface with the backend
+ * or whether we need a shadow surface. We share native
+ * endian surfaces for 15bpp and above and byteswapped
+ * surfaces for 24bpp and above.
+ */
+ format = qemu_default_pixman_format(depth, !byteswap);
+ if (format) {
+ share_surface = dpy_gfx_check_format(s->con, format)
+ && !s->force_shadow;
+ } else {
+ share_surface = false;
+ }
if (s->line_offset != s->last_line_offset ||
disp_width != s->last_width ||
height != s->last_height ||
- s->last_depth != depth) {
- if (depth == 32 || (depth == 16 && !byteswap)) {
+ s->last_depth != depth ||
+ s->last_byteswap != byteswap ||
+ share_surface != is_buffer_shared(surface)) {
+ if (share_surface) {
surface = qemu_create_displaysurface_from(disp_width,
- height, depth, s->line_offset,
- s->vram_ptr + (s->start_addr * 4), byteswap);
+ height, format, s->line_offset,
+ s->vram_ptr + (s->start_addr * 4));
dpy_gfx_replace_surface(s->con, surface);
+#ifdef DEBUG_VGA
+ printf("VGA: Using shared surface for depth=%d swap=%d\n",
+ depth, byteswap);
+#endif
} else {
qemu_console_resize(s->con, disp_width, height);
surface = qemu_console_surface(s->con);
+#ifdef DEBUG_VGA
+ printf("VGA: Using shadow surface for depth=%d swap=%d\n",
+ depth, byteswap);
+#endif
}
s->last_scr_width = disp_width;
s->last_scr_height = height;
s->last_height = height;
s->last_line_offset = s->line_offset;
s->last_depth = depth;
+ s->last_byteswap = byteswap;
full_update = 1;
} else if (is_buffer_shared(surface) &&
(full_update || surface_data(surface) != s->vram_ptr
+ (s->start_addr * 4))) {
+ pixman_format_code_t format =
+ qemu_default_pixman_format(depth, !byteswap);
surface = qemu_create_displaysurface_from(disp_width,
- height, depth, s->line_offset,
- s->vram_ptr + (s->start_addr * 4), byteswap);
+ height, format, s->line_offset,
+ s->vram_ptr + (s->start_addr * 4));
dpy_gfx_replace_surface(s->con, surface);
}
- s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(surface)];
-
if (shift_control == 0) {
full_update |= update_palette16(s);
if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
bits = 8;
break;
case 15:
- v = VGA_DRAW_LINE15;
+ v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
bits = 16;
break;
case 16:
- v = VGA_DRAW_LINE16;
+ v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
bits = 16;
break;
case 24:
- v = VGA_DRAW_LINE24;
+ v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
bits = 24;
break;
case 32:
- v = VGA_DRAW_LINE32;
+ v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
bits = 32;
break;
}
}
- vga_draw_line = vga_draw_line_table[v * NB_DEPTHS +
- get_depth_index(surface)];
+ vga_draw_line = vga_draw_line_table[v];
if (!is_buffer_shared(surface) && s->cursor_invalidate) {
s->cursor_invalidate(s);
static void vga_draw_blank(VGACommonState *s, int full_update)
{
DisplaySurface *surface = qemu_console_surface(s->con);
- int i, w, val;
+ int i, w;
uint8_t *d;
if (!full_update)
if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
return;
- s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(surface)];
- if (surface_bits_per_pixel(surface) == 8) {
- val = s->rgb_to_pixel(0, 0, 0);
- } else {
- val = 0;
- }
w = s->last_scr_width * surface_bytes_per_pixel(surface);
d = surface_data(surface);
for(i = 0; i < s->last_scr_height; i++) {
- memset(d, val, w);
+ memset(d, 0, w);
d += surface_stride(surface);
}
dpy_gfx_update(s->con, 0, 0,
s->cursor_start = 0;
s->cursor_end = 0;
s->cursor_offset = 0;
+ s->big_endian_fb = s->default_endian_fb;
memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
memset(s->last_palette, '\0', sizeof(s->last_palette));
memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
{
VGACommonState *s = opaque;
- return vga_mem_writeb(s, addr, data);
+ vga_mem_writeb(s, addr, data);
}
const MemoryRegionOps vga_mem_ops = {
return 0;
}
+static bool vga_endian_state_needed(void *opaque)
+{
+ VGACommonState *s = opaque;
+
+ /*
+ * Only send the endian state if it's different from the
+ * default one, thus ensuring backward compatibility for
+ * migration of the common case
+ */
+ return s->default_endian_fb != s->big_endian_fb;
+}
+
+static const VMStateDescription vmstate_vga_endian = {
+ .name = "vga.endian",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BOOL(big_endian_fb, VGACommonState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
const VMStateDescription vmstate_vga_common = {
.name = "vga",
.version_id = 2,
VMSTATE_UINT32(vbe_line_offset, VGACommonState),
VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection []) {
+ {
+ .vmsd = &vmstate_vga_endian,
+ .needed = vga_endian_state_needed,
+ }, {
+ /* empty */
+ }
}
};
.text_update = vga_update_text,
};
+static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax)
+{
+ if (val < vmin) {
+ return vmin;
+ }
+ if (val > vmax) {
+ return vmax;
+ }
+ return val;
+}
+
void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
{
int i, j, v, b;
expand4to8[i] = v;
}
- /* valid range: 1 MB -> 256 MB */
- s->vram_size = 1024 * 1024;
- while (s->vram_size < (s->vram_size_mb << 20) &&
- s->vram_size < (256 << 20)) {
- s->vram_size <<= 1;
- }
- s->vram_size_mb = s->vram_size >> 20;
+ s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512);
+ s->vram_size_mb = pow2ceil(s->vram_size_mb);
+ s->vram_size = s->vram_size_mb << 20;
+
if (!s->vbe_size) {
s->vbe_size = s->vram_size;
}
s->is_vbe_vmstate = 1;
- memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
+ memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size,
+ &error_abort);
vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
xen_register_framebuffer(&s->vram);
s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
s->update_retrace_info = vga_precise_update_retrace_info;
break;
}
+
+ /*
+ * Set default fb endian based on target, could probably be turned
+ * into a device attribute set by the machine/platform to remove
+ * all target endian dependencies from this file.
+ */
+#ifdef TARGET_WORDS_BIGENDIAN
+ s->default_endian_fb = true;
+#else
+ s->default_endian_fb = false;
+#endif
vga_dirty_log_start(s);
}
vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports);
memory_region_add_subregion_overlap(address_space,
- isa_mem_base + 0x000a0000,
+ 0x000a0000,
vga_io_memory,
1);
memory_region_set_coalescing(vga_io_memory);