Skip to content

Commit 584acf3

Browse files
zbalatonkraxel
authored andcommitted
ati-vga: Fix reverse bit blts
The pixman library only supports blts with left to right, top to bottom order but the ATI VGA engine can also do different directions. Fix support for these via a temporary buffer for now. This fixes rendering issues related to such blts (such as moving windows) but some other glitches still remain. Signed-off-by: BALATON Zoltan <[email protected]> Message-id: e21855faaeb30d7b1771f084f283f6a30bedb1a3.1562227303.git.balaton@eik.bme.hu Signed-off-by: Gerd Hoffmann <[email protected]>
1 parent a381274 commit 584acf3

File tree

1 file changed

+40
-15
lines changed

1 file changed

+40
-15
lines changed

hw/display/ati_2d.c

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ void ati_2d_blt(ATIVGAState *s)
5353
s->vga.vbe_start_addr, surface_data(ds), surface_stride(ds),
5454
surface_bits_per_pixel(ds),
5555
(s->regs.dp_mix & GMC_ROP3_MASK) >> 16);
56+
int dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
57+
s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width);
58+
int dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
59+
s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height);
5660
int bpp = ati_bpp_from_datatype(s);
5761
int dst_stride = DEFAULT_CNTL ? s->regs.dst_pitch : s->regs.default_pitch;
5862
uint8_t *dst_bits = s->vga.vram_ptr + (DEFAULT_CNTL ?
@@ -63,20 +67,25 @@ void ati_2d_blt(ATIVGAState *s)
6367
dst_stride *= bpp;
6468
}
6569
uint8_t *end = s->vga.vram_ptr + s->vga.vram_size;
66-
if (dst_bits >= end ||
67-
dst_bits + s->regs.dst_x + (s->regs.dst_y + s->regs.dst_height) *
70+
if (dst_bits >= end || dst_bits + dst_x + (dst_y + s->regs.dst_height) *
6871
dst_stride >= end) {
6972
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
7073
return;
7174
}
72-
DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d\n",
75+
DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c\n",
7376
s->regs.src_offset, s->regs.dst_offset, s->regs.default_offset,
7477
s->regs.src_pitch, s->regs.dst_pitch, s->regs.default_pitch,
7578
s->regs.src_x, s->regs.src_y, s->regs.dst_x, s->regs.dst_y,
76-
s->regs.dst_width, s->regs.dst_height);
79+
s->regs.dst_width, s->regs.dst_height,
80+
(s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? '>' : '<'),
81+
(s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? 'v' : '^'));
7782
switch (s->regs.dp_mix & GMC_ROP3_MASK) {
7883
case ROP3_SRCCOPY:
7984
{
85+
int src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
86+
s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width);
87+
int src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
88+
s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height);
8089
int src_stride = DEFAULT_CNTL ?
8190
s->regs.src_pitch : s->regs.default_pitch;
8291
uint8_t *src_bits = s->vga.vram_ptr + (DEFAULT_CNTL ?
@@ -86,9 +95,8 @@ void ati_2d_blt(ATIVGAState *s)
8695
src_bits += s->regs.crtc_offset & 0x07ffffff;
8796
src_stride *= bpp;
8897
}
89-
if (src_bits >= end ||
90-
src_bits + s->regs.src_x + (s->regs.src_y + s->regs.dst_height) *
91-
src_stride >= end) {
98+
if (src_bits >= end || src_bits + src_x +
99+
(src_y + s->regs.dst_height) * src_stride >= end) {
92100
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
93101
return;
94102
}
@@ -97,19 +105,36 @@ void ati_2d_blt(ATIVGAState *s)
97105
dst_stride /= sizeof(uint32_t);
98106
DPRINTF("pixman_blt(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)\n",
99107
src_bits, dst_bits, src_stride, dst_stride, bpp, bpp,
100-
s->regs.src_x, s->regs.src_y, s->regs.dst_x, s->regs.dst_y,
108+
src_x, src_y, dst_x, dst_y,
101109
s->regs.dst_width, s->regs.dst_height);
102-
pixman_blt((uint32_t *)src_bits, (uint32_t *)dst_bits,
103-
src_stride, dst_stride, bpp, bpp,
104-
s->regs.src_x, s->regs.src_y,
105-
s->regs.dst_x, s->regs.dst_y,
106-
s->regs.dst_width, s->regs.dst_height);
110+
if (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT &&
111+
s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) {
112+
pixman_blt((uint32_t *)src_bits, (uint32_t *)dst_bits,
113+
src_stride, dst_stride, bpp, bpp,
114+
src_x, src_y, dst_x, dst_y,
115+
s->regs.dst_width, s->regs.dst_height);
116+
} else {
117+
/* FIXME: We only really need a temporary if src and dst overlap */
118+
int llb = s->regs.dst_width * (bpp / 8);
119+
int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t));
120+
uint32_t *tmp = g_malloc(tmp_stride * sizeof(uint32_t) *
121+
s->regs.dst_height);
122+
pixman_blt((uint32_t *)src_bits, tmp,
123+
src_stride, tmp_stride, bpp, bpp,
124+
src_x, src_y, 0, 0,
125+
s->regs.dst_width, s->regs.dst_height);
126+
pixman_blt(tmp, (uint32_t *)dst_bits,
127+
tmp_stride, dst_stride, bpp, bpp,
128+
0, 0, dst_x, dst_y,
129+
s->regs.dst_width, s->regs.dst_height);
130+
g_free(tmp);
131+
}
107132
if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr &&
108133
dst_bits < s->vga.vram_ptr + s->vga.vbe_start_addr +
109134
s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] * s->vga.vbe_line_offset) {
110135
memory_region_set_dirty(&s->vga.vram, s->vga.vbe_start_addr +
111136
s->regs.dst_offset +
112-
s->regs.dst_y * surface_stride(ds),
137+
dst_y * surface_stride(ds),
113138
s->regs.dst_height * surface_stride(ds));
114139
}
115140
s->regs.dst_x += s->regs.dst_width;
@@ -151,7 +176,7 @@ void ati_2d_blt(ATIVGAState *s)
151176
s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] * s->vga.vbe_line_offset) {
152177
memory_region_set_dirty(&s->vga.vram, s->vga.vbe_start_addr +
153178
s->regs.dst_offset +
154-
s->regs.dst_y * surface_stride(ds),
179+
dst_y * surface_stride(ds),
155180
s->regs.dst_height * surface_stride(ds));
156181
}
157182
s->regs.dst_y += s->regs.dst_height;

0 commit comments

Comments
 (0)