Skip to content

Commit 08730ee

Browse files
zbalatonelmarco
authored andcommitted
ati-vga: Implement fallback for pixman routines
Pixman routines can fail if no implementation is available and it will become optional soon so add fallbacks when pixman does not work. Signed-off-by: BALATON Zoltan <[email protected]> Acked-by: Marc-André Lureau <[email protected]> Message-ID: <ed0fba3f74e48143f02228b83bf8796ca49f3e7d.1698871239.git.balaton@eik.bme.hu>
1 parent bf9ac62 commit 08730ee

File tree

3 files changed

+62
-22
lines changed

3 files changed

+62
-22
lines changed

hw/display/ati.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,7 @@ static Property ati_vga_properties[] = {
10331033
DEFINE_PROP_UINT16("x-device-id", ATIVGAState, dev_id,
10341034
PCI_DEVICE_ID_ATI_RAGE128_PF),
10351035
DEFINE_PROP_BOOL("guest_hwcursor", ATIVGAState, cursor_guest_mode, false),
1036+
DEFINE_PROP_UINT8("x-pixman", ATIVGAState, use_pixman, 3),
10361037
DEFINE_PROP_END_OF_LIST()
10371038
};
10381039

@@ -1054,11 +1055,18 @@ static void ati_vga_class_init(ObjectClass *klass, void *data)
10541055
k->exit = ati_vga_exit;
10551056
}
10561057

1058+
static void ati_vga_init(Object *o)
1059+
{
1060+
object_property_set_description(o, "x-pixman", "Use pixman for: "
1061+
"1: fill, 2: blit");
1062+
}
1063+
10571064
static const TypeInfo ati_vga_info = {
10581065
.name = TYPE_ATI_VGA,
10591066
.parent = TYPE_PCI_DEVICE,
10601067
.instance_size = sizeof(ATIVGAState),
10611068
.class_init = ati_vga_class_init,
1069+
.instance_init = ati_vga_init,
10621070
.interfaces = (InterfaceInfo[]) {
10631071
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
10641072
{ },

hw/display/ati_2d.c

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ void ati_2d_blt(ATIVGAState *s)
9292
switch (s->regs.dp_mix & GMC_ROP3_MASK) {
9393
case ROP3_SRCCOPY:
9494
{
95+
bool fallback = false;
9596
unsigned src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
9697
s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width);
9798
unsigned src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
@@ -122,27 +123,50 @@ void ati_2d_blt(ATIVGAState *s)
122123
src_bits, dst_bits, src_stride, dst_stride, bpp, bpp,
123124
src_x, src_y, dst_x, dst_y,
124125
s->regs.dst_width, s->regs.dst_height);
125-
if (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT &&
126+
if ((s->use_pixman & BIT(1)) &&
127+
s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT &&
126128
s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) {
127-
pixman_blt((uint32_t *)src_bits, (uint32_t *)dst_bits,
128-
src_stride, dst_stride, bpp, bpp,
129-
src_x, src_y, dst_x, dst_y,
130-
s->regs.dst_width, s->regs.dst_height);
131-
} else {
129+
fallback = !pixman_blt((uint32_t *)src_bits, (uint32_t *)dst_bits,
130+
src_stride, dst_stride, bpp, bpp,
131+
src_x, src_y, dst_x, dst_y,
132+
s->regs.dst_width, s->regs.dst_height);
133+
} else if (s->use_pixman & BIT(1)) {
132134
/* FIXME: We only really need a temporary if src and dst overlap */
133135
int llb = s->regs.dst_width * (bpp / 8);
134136
int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t));
135137
uint32_t *tmp = g_malloc(tmp_stride * sizeof(uint32_t) *
136138
s->regs.dst_height);
137-
pixman_blt((uint32_t *)src_bits, tmp,
138-
src_stride, tmp_stride, bpp, bpp,
139-
src_x, src_y, 0, 0,
140-
s->regs.dst_width, s->regs.dst_height);
141-
pixman_blt(tmp, (uint32_t *)dst_bits,
142-
tmp_stride, dst_stride, bpp, bpp,
143-
0, 0, dst_x, dst_y,
144-
s->regs.dst_width, s->regs.dst_height);
139+
fallback = !pixman_blt((uint32_t *)src_bits, tmp,
140+
src_stride, tmp_stride, bpp, bpp,
141+
src_x, src_y, 0, 0,
142+
s->regs.dst_width, s->regs.dst_height);
143+
if (!fallback) {
144+
fallback = !pixman_blt(tmp, (uint32_t *)dst_bits,
145+
tmp_stride, dst_stride, bpp, bpp,
146+
0, 0, dst_x, dst_y,
147+
s->regs.dst_width, s->regs.dst_height);
148+
}
145149
g_free(tmp);
150+
} else {
151+
fallback = true;
152+
}
153+
if (fallback) {
154+
unsigned int y, i, j, bypp = bpp / 8;
155+
unsigned int src_pitch = src_stride * sizeof(uint32_t);
156+
unsigned int dst_pitch = dst_stride * sizeof(uint32_t);
157+
158+
for (y = 0; y < s->regs.dst_height; y++) {
159+
i = dst_x * bypp;
160+
j = src_x * bypp;
161+
if (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) {
162+
i += (dst_y + y) * dst_pitch;
163+
j += (src_y + y) * src_pitch;
164+
} else {
165+
i += (dst_y + s->regs.dst_height - 1 - y) * dst_pitch;
166+
j += (src_y + s->regs.dst_height - 1 - y) * src_pitch;
167+
}
168+
memmove(&dst_bits[i], &src_bits[j], s->regs.dst_width * bypp);
169+
}
146170
}
147171
if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr &&
148172
dst_bits < s->vga.vram_ptr + s->vga.vbe_start_addr +
@@ -180,14 +204,21 @@ void ati_2d_blt(ATIVGAState *s)
180204

181205
dst_stride /= sizeof(uint32_t);
182206
DPRINTF("pixman_fill(%p, %d, %d, %d, %d, %d, %d, %x)\n",
183-
dst_bits, dst_stride, bpp,
184-
dst_x, dst_y,
185-
s->regs.dst_width, s->regs.dst_height,
186-
filler);
187-
pixman_fill((uint32_t *)dst_bits, dst_stride, bpp,
188-
dst_x, dst_y,
189-
s->regs.dst_width, s->regs.dst_height,
190-
filler);
207+
dst_bits, dst_stride, bpp, dst_x, dst_y,
208+
s->regs.dst_width, s->regs.dst_height, filler);
209+
if (!(s->use_pixman & BIT(0)) ||
210+
!pixman_fill((uint32_t *)dst_bits, dst_stride, bpp, dst_x, dst_y,
211+
s->regs.dst_width, s->regs.dst_height, filler)) {
212+
/* fallback when pixman failed or we don't want to call it */
213+
unsigned int x, y, i, bypp = bpp / 8;
214+
unsigned int dst_pitch = dst_stride * sizeof(uint32_t);
215+
for (y = 0; y < s->regs.dst_height; y++) {
216+
i = dst_x * bypp + (dst_y + y) * dst_pitch;
217+
for (x = 0; x < s->regs.dst_width; x++, i += bypp) {
218+
stn_he_p(&dst_bits[i], bypp, filler);
219+
}
220+
}
221+
}
191222
if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr &&
192223
dst_bits < s->vga.vram_ptr + s->vga.vbe_start_addr +
193224
s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] * s->vga.vbe_line_offset) {

hw/display/ati_int.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ struct ATIVGAState {
9090
char *model;
9191
uint16_t dev_id;
9292
uint8_t mode;
93+
uint8_t use_pixman;
9394
bool cursor_guest_mode;
9495
uint16_t cursor_size;
9596
uint32_t cursor_offset;

0 commit comments

Comments
 (0)