aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/display/cirrus_vga.c4
-rw-r--r--hw/display/vga-helpers.h100
-rw-r--r--hw/display/vga.c36
-rw-r--r--hw/display/vga_int.h3
4 files changed, 111 insertions, 32 deletions
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index e637e5a816..150883a971 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -43,6 +43,7 @@
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "ui/pixel_ops.h"
+#include "vga_regs.h"
#include "cirrus_vga_internal.h"
#include "qom/object.h"
#include "ui/console.h"
@@ -1121,6 +1122,9 @@ static void cirrus_get_params(VGACommonState *s1,
params->line_compare = s->vga.cr[0x18] |
((s->vga.cr[0x07] & 0x10) << 4) |
((s->vga.cr[0x09] & 0x40) << 3);
+
+ params->hpel = s->vga.ar[VGA_ATC_PEL];
+ params->hpel_split = s->vga.ar[VGA_ATC_MODE] & 0x20;
}
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h
index 83b9a15604..29933562c4 100644
--- a/hw/display/vga-helpers.h
+++ b/hw/display/vga-helpers.h
@@ -98,14 +98,19 @@ static void vga_draw_glyph9(uint8_t *d, int linesize,
/*
* 4 color mode
*/
-static void vga_draw_line2(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line2(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
uint32_t plane_mask, *palette, data, v;
int x;
palette = vga->last_palette;
plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ hpel &= 7;
+ if (hpel) {
+ width += 8;
+ d = vga->panning_buf;
+ }
width >>= 3;
for(x = 0; x < width; x++) {
data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
@@ -126,6 +131,7 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d,
d += 32;
addr += 4;
}
+ return hpel ? vga->panning_buf + 4 * hpel : NULL;
}
#define PUT_PIXEL2(d, n, v) \
@@ -134,14 +140,19 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d,
/*
* 4 color mode, dup2 horizontal
*/
-static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
uint32_t plane_mask, *palette, data, v;
int x;
palette = vga->last_palette;
plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ hpel &= 7;
+ if (hpel) {
+ width += 8;
+ d = vga->panning_buf;
+ }
width >>= 3;
for(x = 0; x < width; x++) {
data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
@@ -162,19 +173,25 @@ static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
d += 64;
addr += 4;
}
+ return hpel ? vga->panning_buf + 8 * hpel : NULL;
}
/*
* 16 color mode
*/
-static void vga_draw_line4(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line4(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
uint32_t plane_mask, data, v, *palette;
int x;
palette = vga->last_palette;
plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ hpel &= 7;
+ if (hpel) {
+ width += 8;
+ d = vga->panning_buf;
+ }
width >>= 3;
for(x = 0; x < width; x++) {
data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
@@ -194,19 +211,25 @@ static void vga_draw_line4(VGACommonState *vga, uint8_t *d,
d += 32;
addr += 4;
}
+ return hpel ? vga->panning_buf + 4 * hpel : NULL;
}
/*
* 16 color mode, dup2 horizontal
*/
-static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
uint32_t plane_mask, data, v, *palette;
int x;
palette = vga->last_palette;
plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
+ hpel &= 7;
+ if (hpel) {
+ width += 8;
+ d = vga->panning_buf;
+ }
width >>= 3;
for(x = 0; x < width; x++) {
data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
@@ -226,6 +249,7 @@ static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
d += 64;
addr += 4;
}
+ return hpel ? vga->panning_buf + 8 * hpel : NULL;
}
/*
@@ -233,13 +257,18 @@ static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
*
* XXX: add plane_mask support (never used in standard VGA modes)
*/
-static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
uint32_t *palette;
int x;
palette = vga->last_palette;
+ hpel = (hpel >> 1) & 3;
+ if (hpel) {
+ width += 8;
+ d = vga->panning_buf;
+ }
width >>= 3;
for(x = 0; x < width; x++) {
addr &= VGA_VRAM_SIZE - 1;
@@ -250,6 +279,7 @@ static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
d += 32;
addr += 4;
}
+ return hpel ? vga->panning_buf + 8 * hpel : NULL;
}
/*
@@ -257,13 +287,18 @@ static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
*
* XXX: add plane_mask support (never used in standard VGA modes)
*/
-static void vga_draw_line8(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line8(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
uint32_t *palette;
int x;
palette = vga->last_palette;
+ hpel = (hpel >> 1) & 3;
+ if (hpel) {
+ width += 8;
+ d = vga->panning_buf;
+ }
width >>= 3;
for(x = 0; x < width; x++) {
((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)];
@@ -277,13 +312,14 @@ static void vga_draw_line8(VGACommonState *vga, uint8_t *d,
d += 32;
addr += 8;
}
+ return hpel ? vga->panning_buf + 4 * hpel : NULL;
}
/*
* 15 bit color
*/
-static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t v, r, g, b;
@@ -298,10 +334,11 @@ static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
addr += 2;
d += 4;
} while (--w != 0);
+ return NULL;
}
-static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t v, r, g, b;
@@ -316,13 +353,14 @@ static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
addr += 2;
d += 4;
} while (--w != 0);
+ return NULL;
}
/*
* 16 bit color
*/
-static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t v, r, g, b;
@@ -337,10 +375,11 @@ static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
addr += 2;
d += 4;
} while (--w != 0);
+ return NULL;
}
-static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t v, r, g, b;
@@ -355,13 +394,14 @@ static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
addr += 2;
d += 4;
} while (--w != 0);
+ return NULL;
}
/*
* 24 bit color
*/
-static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t r, g, b;
@@ -375,10 +415,11 @@ static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
addr += 3;
d += 4;
} while (--w != 0);
+ return NULL;
}
-static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t r, g, b;
@@ -392,13 +433,14 @@ static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
addr += 3;
d += 4;
} while (--w != 0);
+ return NULL;
}
/*
* 32 bit color
*/
-static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t r, g, b;
@@ -412,10 +454,11 @@ static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
addr += 4;
d += 4;
} while (--w != 0);
+ return NULL;
}
-static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
- uint32_t addr, int width)
+static void *vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
+ uint32_t addr, int width, int hpel)
{
int w;
uint32_t r, g, b;
@@ -429,4 +472,5 @@ static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
addr += 4;
d += 4;
} while (--w != 0);
+ return NULL;
}
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 5bf4d14f34..a39f802ab7 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -50,6 +50,13 @@ bool have_vga = true;
/* Address mask for non-VESA modes. */
#define VGA_VRAM_SIZE (256 * KiB)
+/* This value corresponds to a shift of zero pixels
+ * in 9-dot text mode. In other modes, bit 3 is undefined;
+ * we just ignore it, so that 8 corresponds to zero pixels
+ * in all modes.
+ */
+#define VGA_HPEL_NEUTRAL 8
+
/*
* Video Graphics Array (VGA)
*
@@ -984,8 +991,8 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
}
}
-typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
- uint32_t srcaddr, int width);
+typedef void *vga_draw_line_func(VGACommonState *s1, uint8_t *d,
+ uint32_t srcaddr, int width, int hpel);
#include "vga-access.h"
#include "vga-helpers.h"
@@ -1052,6 +1059,8 @@ static void vga_get_params(VGACommonState *s,
params->line_offset = s->vbe_line_offset;
params->start_addr = s->vbe_start_addr;
params->line_compare = 65535;
+ params->hpel = VGA_HPEL_NEUTRAL;
+ params->hpel_split = false;
} else {
/* compute line_offset in bytes */
params->line_offset = s->cr[VGA_CRTC_OFFSET] << 3;
@@ -1064,6 +1073,9 @@ static void vga_get_params(VGACommonState *s,
params->line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
+
+ params->hpel = s->ar[VGA_ATC_PEL];
+ params->hpel_split = s->ar[VGA_ATC_MODE] & 0x20;
}
}
@@ -1435,6 +1447,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
ram_addr_t page0, page1, region_start, region_end;
DirtyBitmapSnapshot *snap = NULL;
int disp_width, multi_scan, multi_run;
+ int hpel;
uint8_t *d;
uint32_t v, addr1, addr;
vga_draw_line_func *vga_draw_line = NULL;
@@ -1534,6 +1547,9 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->last_line_offset = s->params.line_offset;
s->last_depth = depth;
s->last_byteswap = byteswap;
+ /* 16 extra pixels are needed for double-width planar modes. */
+ s->panning_buf = g_realloc(s->panning_buf,
+ (disp_width + 16) * sizeof(uint32_t));
full_update = 1;
}
if (surface_data(surface) != s->vram_ptr + (s->params.start_addr * 4)
@@ -1613,8 +1629,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
s->params.line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
#endif
+ hpel = bits <= 8 ? s->params.hpel : 0;
addr1 = (s->params.start_addr * 4);
bwidth = DIV_ROUND_UP(width * bits, 8);
+ if (hpel) {
+ bwidth += 4;
+ }
y_start = -1;
d = surface_data(surface);
linesize = surface_stride(surface);
@@ -1662,7 +1682,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
if (y_start < 0)
y_start = y;
if (!(is_buffer_shared(surface))) {
- vga_draw_line(s, d, addr, width);
+ uint8_t *p;
+ p = vga_draw_line(s, d, addr, width, hpel);
+ if (p) {
+ memcpy(d, p, disp_width * sizeof(uint32_t));
+ }
if (s->cursor_draw_line)
s->cursor_draw_line(s, d, y);
}
@@ -1684,8 +1708,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
multi_run--;
}
/* line compare acts on the displayed lines */
- if (y == s->params.line_compare)
+ if (y == s->params.line_compare) {
+ if (s->params.hpel_split) {
+ hpel = VGA_HPEL_NEUTRAL;
+ }
addr1 = 0;
+ }
d += linesize;
}
if (y_start >= 0) {
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index 6be61e0428..876a1d3697 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -60,6 +60,8 @@ typedef struct VGADisplayParams {
uint32_t line_offset;
uint32_t start_addr;
uint32_t line_compare;
+ uint8_t hpel;
+ bool hpel_split;
} VGADisplayParams;
typedef struct VGACommonState {
@@ -111,6 +113,7 @@ typedef struct VGACommonState {
/* display refresh support */
QemuConsole *con;
uint32_t font_offsets[2];
+ uint8_t *panning_buf;
int graphic_mode;
uint8_t shift_control;
uint8_t double_scan;