From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020926797154.43142937536368; Sun, 8 Mar 2026 18:48:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjN-0005p3-48; Sun, 08 Mar 2026 21:48:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiw-0005lL-6U for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:01 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiq-0001HM-9g for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:47:55 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id 801E15969ED; Mon, 09 Mar 2026 02:47:46 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id 7_kKrN1MRwWp; Mon, 9 Mar 2026 02:47:44 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 4A7135969E8; Mon, 09 Mar 2026 02:47:44 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <7ab2227b96b73a63cb4fc61d0e6921e01900a4ee.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 1/9] ati-vga: Remove src and dst stride mutation in ati_2d_blt MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:44 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020929840158500 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski Pixman requires stride in words. So over the course of the ati_2d_blt function both src and dst stride were mutated before being passed to pixman and then back afterwards. This creates local variables holding src and dst stride in words avoiding the potentially confusing mutation. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati_2d.c | 48 +++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index 980cdd6ac0..8a7dcdf6e9 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -125,34 +125,34 @@ void ati_2d_blt(ATIVGAState *s) return; } =20 - src_stride /=3D sizeof(uint32_t); - dst_stride /=3D sizeof(uint32_t); - DPRINTF("pixman_blt(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d= )\n", - src_bits, dst_bits, src_stride, dst_stride, bpp, bpp, - src_x, src_y, dst_x, dst_y, - s->regs.dst_width, s->regs.dst_height); + DPRINTF("pixman_blt(%p, %p, %ld, %ld, %d, %d, %d, %d, %d, %d, %d, = %d)\n", + src_bits, dst_bits, src_stride / sizeof(uint32_t), + dst_stride / sizeof(uint32_t), bpp, bpp, src_x, src_y, dst= _x, + dst_y, s->regs.dst_width, s->regs.dst_height); #ifdef CONFIG_PIXMAN + int src_stride_words =3D src_stride / sizeof(uint32_t); + int dst_stride_words =3D dst_stride / sizeof(uint32_t); if ((s->use_pixman & BIT(1)) && s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT && s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) { fallback =3D !pixman_blt((uint32_t *)src_bits, (uint32_t *)dst= _bits, - src_stride, dst_stride, bpp, bpp, + src_stride_words, dst_stride_words, bpp= , bpp, src_x, src_y, dst_x, dst_y, s->regs.dst_width, s->regs.dst_height); } else if (s->use_pixman & BIT(1)) { /* FIXME: We only really need a temporary if src and dst overl= ap */ int llb =3D s->regs.dst_width * (bpp / 8); - int tmp_stride =3D DIV_ROUND_UP(llb, sizeof(uint32_t)); - uint32_t *tmp =3D g_malloc(tmp_stride * sizeof(uint32_t) * + int tmp_stride_words =3D DIV_ROUND_UP(llb, sizeof(uint32_t)); + uint32_t *tmp =3D g_malloc(tmp_stride_words * sizeof(uint32_t)= * s->regs.dst_height); fallback =3D !pixman_blt((uint32_t *)src_bits, tmp, - src_stride, tmp_stride, bpp, bpp, + src_stride_words, tmp_stride_words, bpp= , bpp, src_x, src_y, 0, 0, s->regs.dst_width, s->regs.dst_height); if (!fallback) { fallback =3D !pixman_blt(tmp, (uint32_t *)dst_bits, - tmp_stride, dst_stride, bpp, bpp, - 0, 0, dst_x, dst_y, + tmp_stride_words, dst_stride_words, + bpp, bpp, 0, 0, dst_x, dst_y, s->regs.dst_width, s->regs.dst_heig= ht); } g_free(tmp); @@ -163,18 +163,15 @@ void ati_2d_blt(ATIVGAState *s) } if (fallback) { unsigned int y, i, j, bypp =3D bpp / 8; - unsigned int src_pitch =3D src_stride * sizeof(uint32_t); - unsigned int dst_pitch =3D dst_stride * sizeof(uint32_t); - for (y =3D 0; y < s->regs.dst_height; y++) { i =3D dst_x * bypp; j =3D src_x * bypp; if (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) { - i +=3D (dst_y + y) * dst_pitch; - j +=3D (src_y + y) * src_pitch; + i +=3D (dst_y + y) * dst_stride; + j +=3D (src_y + y) * src_stride; } else { - i +=3D (dst_y + s->regs.dst_height - 1 - y) * dst_pitc= h; - j +=3D (src_y + s->regs.dst_height - 1 - y) * src_pitc= h; + i +=3D (dst_y + s->regs.dst_height - 1 - y) * dst_stri= de; + j +=3D (src_y + s->regs.dst_height - 1 - y) * src_stri= de; } memmove(&dst_bits[i], &src_bits[j], s->regs.dst_width * by= pp); } @@ -201,21 +198,20 @@ void ati_2d_blt(ATIVGAState *s) break; } =20 - dst_stride /=3D sizeof(uint32_t); - DPRINTF("pixman_fill(%p, %d, %d, %d, %d, %d, %d, %x)\n", - dst_bits, dst_stride, bpp, dst_x, dst_y, + DPRINTF("pixman_fill(%p, %ld, %d, %d, %d, %d, %d, %x)\n", + dst_bits, dst_stride / sizeof(uint32_t), bpp, dst_x, dst_y, s->regs.dst_width, s->regs.dst_height, filler); #ifdef CONFIG_PIXMAN if (!(s->use_pixman & BIT(0)) || - !pixman_fill((uint32_t *)dst_bits, dst_stride, bpp, dst_x, dst= _y, - s->regs.dst_width, s->regs.dst_height, filler)) + !pixman_fill((uint32_t *)dst_bits, dst_stride / sizeof(uint32_= t), + bpp, dst_x, dst_y, s->regs.dst_width, + s->regs.dst_height, filler)) #endif { /* fallback when pixman failed or we don't want to call it */ unsigned int x, y, i, bypp =3D bpp / 8; - unsigned int dst_pitch =3D dst_stride * sizeof(uint32_t); for (y =3D 0; y < s->regs.dst_height; y++) { - i =3D dst_x * bypp + (dst_y + y) * dst_pitch; + i =3D dst_x * bypp + (dst_y + y) * dst_stride; for (x =3D 0; x < s->regs.dst_width; x++, i +=3D bypp) { stn_he_p(&dst_bits[i], bypp, filler); } --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020917501610.3111889124594; Sun, 8 Mar 2026 18:48:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjL-0005or-4Q; Sun, 08 Mar 2026 21:48:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiw-0005lN-7C for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:01 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiq-0001HO-8A for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:47:55 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id 66D5D5969E8; Mon, 09 Mar 2026 02:47:47 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id RWK0C-Lt52wF; Mon, 9 Mar 2026 02:47:45 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 5AF0E5969EB; Mon, 09 Mar 2026 02:47:45 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <2c7f8fdc527e8c5bad237933a1c8a7a8e5068a3d.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 2/9] ati-vga: Use local variables for register values in ati_2d_blt MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:45 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -1 X-Spam_score: -0.2 X-Spam_bar: / X-Spam_report: (-0.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.819, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.903, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020921916158500 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski ati_2d_blt uses a mixture of locals and direct register access of needed state. This assigns all values derived from register state to local variables. It prepares the function for a larger refactor that removes the dependency on the full device and direct register access entirely. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati_2d.c | 92 +++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index 8a7dcdf6e9..b9cd766130 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -65,10 +65,18 @@ void ati_2d_blt(ATIVGAState *s) { /* FIXME it is probably more complex than this and may need to be */ /* rewritten but for now as a start just to get some output: */ - unsigned dst_x =3D (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? - s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_widt= h); - unsigned dst_y =3D (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? - s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_heig= ht); + uint32_t rop3 =3D s->regs.dp_mix & GMC_ROP3_MASK; + bool left_to_right =3D s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT; + bool top_to_bottom =3D s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM; + uint32_t frgd_clr =3D s->regs.dp_brush_frgd_clr; + uint8_t *palette =3D s->vga.palette; + unsigned dst_offset =3D s->regs.dst_offset; + unsigned dst_width =3D s->regs.dst_width; + unsigned dst_height =3D s->regs.dst_height; + unsigned dst_x =3D (left_to_right ? + s->regs.dst_x : s->regs.dst_x + 1 - dst_width); + unsigned dst_y =3D (top_to_bottom ? + s->regs.dst_y : s->regs.dst_y + 1 - dst_height); int bpp =3D ati_bpp_from_datatype(s); if (!bpp) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); @@ -79,7 +87,7 @@ void ati_2d_blt(ATIVGAState *s) qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n"); return; } - uint8_t *dst_bits =3D s->vga.vram_ptr + s->regs.dst_offset; + uint8_t *dst_bits =3D s->vga.vram_ptr + dst_offset; =20 if (s->dev_id =3D=3D PCI_DEVICE_ID_ATI_RAGE128_PF) { dst_bits +=3D s->regs.crtc_offset & 0x07ffffff; @@ -87,26 +95,25 @@ void ati_2d_blt(ATIVGAState *s) } uint8_t *end =3D s->vga.vram_ptr + s->vga.vram_size; if (dst_x > 0x3fff || dst_y > 0x3fff || dst_bits >=3D end - || dst_bits + dst_x - + (dst_y + s->regs.dst_height) * dst_stride >=3D end) { + || dst_bits + dst_x + (dst_y + dst_height) * dst_stride >=3D end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c\n", - s->regs.src_offset, s->regs.dst_offset, s->regs.default_offset, - s->regs.src_pitch, s->regs.dst_pitch, s->regs.default_pitch, + s->regs.src_offset, dst_offset, s->regs.default_offset, + s->regs.src_pitch, dst_stride, s->regs.default_pitch, s->regs.src_x, s->regs.src_y, dst_x, dst_y, - s->regs.dst_width, s->regs.dst_height, - (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? '>' : '<'), - (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? 'v' : '^')); - switch (s->regs.dp_mix & GMC_ROP3_MASK) { + dst_width, dst_height, + (left_to_right ? '>' : '<'), + (top_to_bottom ? 'v' : '^')); + switch (rop3) { case ROP3_SRCCOPY: { bool fallback =3D false; - unsigned src_x =3D (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? - s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_wid= th); - unsigned src_y =3D (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? - s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_hei= ght); + unsigned src_x =3D (left_to_right ? + s->regs.src_x : s->regs.src_x + 1 - dst_width); + unsigned src_y =3D (top_to_bottom ? + s->regs.src_y : s->regs.src_y + 1 - dst_height); int src_stride =3D s->regs.src_pitch; if (!src_stride) { qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); @@ -120,7 +127,7 @@ void ati_2d_blt(ATIVGAState *s) } if (src_x > 0x3fff || src_y > 0x3fff || src_bits >=3D end || src_bits + src_x - + (src_y + s->regs.dst_height) * src_stride >=3D end) { + + (src_y + dst_height) * src_stride >=3D end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } @@ -128,32 +135,30 @@ void ati_2d_blt(ATIVGAState *s) DPRINTF("pixman_blt(%p, %p, %ld, %ld, %d, %d, %d, %d, %d, %d, %d, = %d)\n", src_bits, dst_bits, src_stride / sizeof(uint32_t), dst_stride / sizeof(uint32_t), bpp, bpp, src_x, src_y, dst= _x, - dst_y, s->regs.dst_width, s->regs.dst_height); + dst_y, dst_width, dst_height); #ifdef CONFIG_PIXMAN int src_stride_words =3D src_stride / sizeof(uint32_t); int dst_stride_words =3D dst_stride / sizeof(uint32_t); - if ((s->use_pixman & BIT(1)) && - s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT && - s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) { + if ((s->use_pixman & BIT(1)) && left_to_right && top_to_bottom) { fallback =3D !pixman_blt((uint32_t *)src_bits, (uint32_t *)dst= _bits, src_stride_words, dst_stride_words, bpp= , bpp, src_x, src_y, dst_x, dst_y, - s->regs.dst_width, s->regs.dst_height); + dst_width, dst_height); } else if (s->use_pixman & BIT(1)) { /* FIXME: We only really need a temporary if src and dst overl= ap */ - int llb =3D s->regs.dst_width * (bpp / 8); + int llb =3D dst_width * (bpp / 8); int tmp_stride_words =3D DIV_ROUND_UP(llb, sizeof(uint32_t)); uint32_t *tmp =3D g_malloc(tmp_stride_words * sizeof(uint32_t)= * - s->regs.dst_height); + dst_height); fallback =3D !pixman_blt((uint32_t *)src_bits, tmp, src_stride_words, tmp_stride_words, bpp= , bpp, src_x, src_y, 0, 0, - s->regs.dst_width, s->regs.dst_height); + dst_width, dst_height); if (!fallback) { fallback =3D !pixman_blt(tmp, (uint32_t *)dst_bits, tmp_stride_words, dst_stride_words, bpp, bpp, 0, 0, dst_x, dst_y, - s->regs.dst_width, s->regs.dst_heig= ht); + dst_width, dst_height); } g_free(tmp); } else @@ -163,17 +168,17 @@ void ati_2d_blt(ATIVGAState *s) } if (fallback) { unsigned int y, i, j, bypp =3D bpp / 8; - for (y =3D 0; y < s->regs.dst_height; y++) { + for (y =3D 0; y < dst_height; y++) { i =3D dst_x * bypp; j =3D src_x * bypp; - if (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM) { + if (top_to_bottom) { i +=3D (dst_y + y) * dst_stride; j +=3D (src_y + y) * src_stride; } else { - i +=3D (dst_y + s->regs.dst_height - 1 - y) * dst_stri= de; - j +=3D (src_y + s->regs.dst_height - 1 - y) * src_stri= de; + i +=3D (dst_y + dst_height - 1 - y) * dst_stride; + j +=3D (src_y + dst_height - 1 - y) * src_stride; } - memmove(&dst_bits[i], &src_bits[j], s->regs.dst_width * by= pp); + memmove(&dst_bits[i], &src_bits[j], dst_width * bypp); } } break; @@ -184,35 +189,34 @@ void ati_2d_blt(ATIVGAState *s) { uint32_t filler =3D 0; =20 - switch (s->regs.dp_mix & GMC_ROP3_MASK) { + switch (rop3) { case ROP3_PATCOPY: - filler =3D s->regs.dp_brush_frgd_clr; + filler =3D frgd_clr; break; case ROP3_BLACKNESS: - filler =3D 0xffUL << 24 | rgb_to_pixel32(s->vga.palette[0], - s->vga.palette[1], s->vga.palette[2]); + filler =3D 0xffUL << 24 | rgb_to_pixel32(palette[0], palette[1= ], + palette[2]); break; case ROP3_WHITENESS: - filler =3D 0xffUL << 24 | rgb_to_pixel32(s->vga.palette[3], - s->vga.palette[4], s->vga.palette[5]); + filler =3D 0xffUL << 24 | rgb_to_pixel32(palette[3], palette[4= ], + palette[5]); break; } =20 DPRINTF("pixman_fill(%p, %ld, %d, %d, %d, %d, %d, %x)\n", dst_bits, dst_stride / sizeof(uint32_t), bpp, dst_x, dst_y, - s->regs.dst_width, s->regs.dst_height, filler); + dst_width, dst_height, filler); #ifdef CONFIG_PIXMAN if (!(s->use_pixman & BIT(0)) || !pixman_fill((uint32_t *)dst_bits, dst_stride / sizeof(uint32_= t), - bpp, dst_x, dst_y, s->regs.dst_width, - s->regs.dst_height, filler)) + bpp, dst_x, dst_y, dst_width, dst_height, filler)) #endif { /* fallback when pixman failed or we don't want to call it */ unsigned int x, y, i, bypp =3D bpp / 8; - for (y =3D 0; y < s->regs.dst_height; y++) { + for (y =3D 0; y < dst_height; y++) { i =3D dst_x * bypp + (dst_y + y) * dst_stride; - for (x =3D 0; x < s->regs.dst_width; x++, i +=3D bypp) { + for (x =3D 0; x < dst_width; x++, i +=3D bypp) { stn_he_p(&dst_bits[i], bypp, filler); } } @@ -221,7 +225,7 @@ void ati_2d_blt(ATIVGAState *s) } default: qemu_log_mask(LOG_UNIMP, "Unimplemented ati_2d blt op %x\n", - (s->regs.dp_mix & GMC_ROP3_MASK) >> 16); + rop3 >> 16); return; } =20 --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020987761609.2937959212436; Sun, 8 Mar 2026 18:49:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjM-0005ov-Fc; Sun, 08 Mar 2026 21:48:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiw-0005lO-7J for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:01 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiq-0001HV-82 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:47:56 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id 7C4E25969EF; Mon, 09 Mar 2026 02:47:48 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id A3IAE80Q8XuP; Mon, 9 Mar 2026 02:47:46 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 657D55969EC; Mon, 09 Mar 2026 02:47:46 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 3/9] ati-vga: Introduce ATI2DCtx struct for 2D blit context MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:46 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020990953154100 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski Previously all state derived from registers was moved to locals. Now we can mechanically replace those locals with fields on the new ATI2DCtx struct. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati_2d.c | 226 +++++++++++++++++++++++++------------------- 1 file changed, 131 insertions(+), 95 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index b9cd766130..9e0115c49d 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -13,6 +13,7 @@ #include "qemu/log.h" #include "ui/pixel_ops.h" #include "ui/console.h" +#include "ui/rect.h" =20 /* * NOTE: @@ -43,21 +44,39 @@ static int ati_bpp_from_datatype(ATIVGAState *s) } } =20 -static void ati_set_dirty(ATIVGAState *s, - const uint8_t *dst_bits, unsigned dst_y) +typedef struct { + int bpp; + uint32_t rop3; + bool left_to_right; + bool top_to_bottom; + uint32_t frgd_clr; + const uint8_t *palette; + const uint8_t *vram_end; + + QemuRect dst; + int dst_stride; + uint8_t *dst_bits; + uint32_t dst_offset; + + QemuRect src; + int src_stride; + const uint8_t *src_bits; +} ATI2DCtx; + +static void ati_set_dirty(VGACommonState *vga, const ATI2DCtx *ctx) { - VGACommonState *vga =3D &s->vga; DisplaySurface *ds =3D qemu_console_surface(vga->con); =20 DPRINTF("%p %u ds: %p %d %d rop: %x\n", vga->vram_ptr, vga->vbe_start_= addr, surface_data(ds), surface_stride(ds), surface_bits_per_pixel(d= s), - (s->regs.dp_mix & GMC_ROP3_MASK) >> 16); - if (dst_bits >=3D vga->vram_ptr + vga->vbe_start_addr && - dst_bits < vga->vram_ptr + vga->vbe_start_addr + + ctx->rop3 >> 16); + if (ctx->dst_bits >=3D vga->vram_ptr + vga->vbe_start_addr && + ctx->dst_bits < vga->vram_ptr + vga->vbe_start_addr + vga->vbe_regs[VBE_DISPI_INDEX_YRES] * vga->vbe_line_offset) { memory_region_set_dirty(&vga->vram, vga->vbe_start_addr + - s->regs.dst_offset + dst_y * surface_strid= e(ds), - s->regs.dst_height * surface_stride(ds)); + ctx->dst_offset + ctx->dst.y + * surface_stride(ds), + ctx->dst.height * surface_stride(ds)); } } =20 @@ -65,100 +84,109 @@ void ati_2d_blt(ATIVGAState *s) { /* FIXME it is probably more complex than this and may need to be */ /* rewritten but for now as a start just to get some output: */ - uint32_t rop3 =3D s->regs.dp_mix & GMC_ROP3_MASK; - bool left_to_right =3D s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT; - bool top_to_bottom =3D s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM; - uint32_t frgd_clr =3D s->regs.dp_brush_frgd_clr; - uint8_t *palette =3D s->vga.palette; - unsigned dst_offset =3D s->regs.dst_offset; - unsigned dst_width =3D s->regs.dst_width; - unsigned dst_height =3D s->regs.dst_height; - unsigned dst_x =3D (left_to_right ? - s->regs.dst_x : s->regs.dst_x + 1 - dst_width); - unsigned dst_y =3D (top_to_bottom ? - s->regs.dst_y : s->regs.dst_y + 1 - dst_height); - int bpp =3D ati_bpp_from_datatype(s); - if (!bpp) { + ATI2DCtx ctx_; + ATI2DCtx *ctx =3D &ctx_; + ctx->rop3 =3D s->regs.dp_mix & GMC_ROP3_MASK; + ctx->left_to_right =3D s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT; + ctx->top_to_bottom =3D s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM; + ctx->frgd_clr =3D s->regs.dp_brush_frgd_clr; + ctx->palette =3D s->vga.palette; + ctx->dst_offset =3D s->regs.dst_offset; + ctx->dst.width =3D s->regs.dst_width; + ctx->dst.height =3D s->regs.dst_height; + ctx->dst.x =3D (ctx->left_to_right ? + s->regs.dst_x : s->regs.dst_x + 1 - ctx->dst.width); + ctx->dst.y =3D (ctx->top_to_bottom ? + s->regs.dst_y : s->regs.dst_y + 1 - ctx->dst.height); + ctx->bpp =3D ati_bpp_from_datatype(s); + if (!ctx->bpp) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); return; } - int dst_stride =3D s->regs.dst_pitch; - if (!dst_stride) { + ctx->dst_stride =3D s->regs.dst_pitch; + if (!ctx->dst_stride) { qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n"); return; } - uint8_t *dst_bits =3D s->vga.vram_ptr + dst_offset; + ctx->dst_bits =3D s->vga.vram_ptr + ctx->dst_offset; =20 if (s->dev_id =3D=3D PCI_DEVICE_ID_ATI_RAGE128_PF) { - dst_bits +=3D s->regs.crtc_offset & 0x07ffffff; - dst_stride *=3D bpp; + ctx->dst_bits +=3D s->regs.crtc_offset & 0x07ffffff; + ctx->dst_stride *=3D ctx->bpp; } - uint8_t *end =3D s->vga.vram_ptr + s->vga.vram_size; - if (dst_x > 0x3fff || dst_y > 0x3fff || dst_bits >=3D end - || dst_bits + dst_x + (dst_y + dst_height) * dst_stride >=3D end) { + ctx->vram_end =3D s->vga.vram_ptr + s->vga.vram_size; + if (ctx->dst.x > 0x3fff || ctx->dst.y > 0x3fff || + ctx->dst_bits >=3D ctx->vram_end || ctx->dst_bits + ctx->dst.x + + (ctx->dst.y + ctx->dst.height) * ctx->dst_stride >=3D ctx->vram_en= d) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c\n", - s->regs.src_offset, dst_offset, s->regs.default_offset, - s->regs.src_pitch, dst_stride, s->regs.default_pitch, - s->regs.src_x, s->regs.src_y, dst_x, dst_y, - dst_width, dst_height, - (left_to_right ? '>' : '<'), - (top_to_bottom ? 'v' : '^')); - switch (rop3) { + s->regs.src_offset, ctx->dst_offset, s->regs.default_offset, + ctx->src_stride, ctx->dst_stride, s->regs.default_pitch, + ctx->src.x, ctx->src.y, ctx->dst.x, ctx->dst.y, + ctx->dst.width, ctx->dst.height, + (ctx->left_to_right ? '>' : '<'), + (ctx->top_to_bottom ? 'v' : '^')); + switch (ctx->rop3) { case ROP3_SRCCOPY: { bool fallback =3D false; - unsigned src_x =3D (left_to_right ? - s->regs.src_x : s->regs.src_x + 1 - dst_width); - unsigned src_y =3D (top_to_bottom ? - s->regs.src_y : s->regs.src_y + 1 - dst_height); - int src_stride =3D s->regs.src_pitch; - if (!src_stride) { + ctx->src.x =3D (ctx->left_to_right ? + s->regs.src_x : s->regs.src_x + 1 - ctx->dst.width); + ctx->src.y =3D (ctx->top_to_bottom ? + s->regs.src_y : s->regs.src_y + 1 - ctx->dst.height); + ctx->src_stride =3D s->regs.src_pitch; + if (!ctx->src_stride) { qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); return; } - uint8_t *src_bits =3D s->vga.vram_ptr + s->regs.src_offset; + ctx->src_bits =3D s->vga.vram_ptr + s->regs.src_offset; =20 if (s->dev_id =3D=3D PCI_DEVICE_ID_ATI_RAGE128_PF) { - src_bits +=3D s->regs.crtc_offset & 0x07ffffff; - src_stride *=3D bpp; + ctx->src_bits +=3D s->regs.crtc_offset & 0x07ffffff; + ctx->src_stride *=3D ctx->bpp; } - if (src_x > 0x3fff || src_y > 0x3fff || src_bits >=3D end - || src_bits + src_x - + (src_y + dst_height) * src_stride >=3D end) { + if (ctx->src.x > 0x3fff || ctx->src.y > 0x3fff || + ctx->src_bits >=3D ctx->vram_end || + ctx->src_bits + ctx->src.x + (ctx->src.y + ctx->dst.height) * + ctx->src_stride >=3D ctx->vram_end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } =20 DPRINTF("pixman_blt(%p, %p, %ld, %ld, %d, %d, %d, %d, %d, %d, %d, = %d)\n", - src_bits, dst_bits, src_stride / sizeof(uint32_t), - dst_stride / sizeof(uint32_t), bpp, bpp, src_x, src_y, dst= _x, - dst_y, dst_width, dst_height); + ctx->src_bits, ctx->dst_bits, + ctx->src_stride / sizeof(uint32_t), + ctx->dst_stride / sizeof(uint32_t), + ctx->bpp, ctx->bpp, ctx->src.x, ctx->src.y, ctx->dst.x, + ctx->dst.y, ctx->dst.width, ctx->dst.height); #ifdef CONFIG_PIXMAN - int src_stride_words =3D src_stride / sizeof(uint32_t); - int dst_stride_words =3D dst_stride / sizeof(uint32_t); - if ((s->use_pixman & BIT(1)) && left_to_right && top_to_bottom) { - fallback =3D !pixman_blt((uint32_t *)src_bits, (uint32_t *)dst= _bits, - src_stride_words, dst_stride_words, bpp= , bpp, - src_x, src_y, dst_x, dst_y, - dst_width, dst_height); + int src_stride_words =3D ctx->src_stride / sizeof(uint32_t); + int dst_stride_words =3D ctx->dst_stride / sizeof(uint32_t); + if ((s->use_pixman & BIT(1)) && + ctx->left_to_right && ctx->top_to_bottom) { + fallback =3D !pixman_blt((uint32_t *)ctx->src_bits, + (uint32_t *)ctx->dst_bits, src_stride_w= ords, + dst_stride_words, ctx->bpp, ctx->bpp, + ctx->src.x, ctx->src.y, ctx->dst.x, + ctx->dst.y, ctx->dst.width, ctx->dst.he= ight); } else if (s->use_pixman & BIT(1)) { /* FIXME: We only really need a temporary if src and dst overl= ap */ - int llb =3D dst_width * (bpp / 8); + int llb =3D ctx->dst.width * (ctx->bpp / 8); int tmp_stride_words =3D DIV_ROUND_UP(llb, sizeof(uint32_t)); uint32_t *tmp =3D g_malloc(tmp_stride_words * sizeof(uint32_t)= * - dst_height); - fallback =3D !pixman_blt((uint32_t *)src_bits, tmp, - src_stride_words, tmp_stride_words, bpp= , bpp, - src_x, src_y, 0, 0, - dst_width, dst_height); + ctx->dst.height); + fallback =3D !pixman_blt((uint32_t *)ctx->src_bits, tmp, + src_stride_words, tmp_stride_words, ctx= ->bpp, + ctx->bpp, ctx->src.x, ctx->src.y, 0, 0, + ctx->dst.width, ctx->dst.height); if (!fallback) { - fallback =3D !pixman_blt(tmp, (uint32_t *)dst_bits, + fallback =3D !pixman_blt(tmp, (uint32_t *)ctx->dst_bits, tmp_stride_words, dst_stride_words, - bpp, bpp, 0, 0, dst_x, dst_y, - dst_width, dst_height); + ctx->bpp, ctx->bpp, 0, 0, + ctx->dst.x, ctx->dst.y, + ctx->dst.width, ctx->dst.height); } g_free(tmp); } else @@ -167,18 +195,21 @@ void ati_2d_blt(ATIVGAState *s) fallback =3D true; } if (fallback) { - unsigned int y, i, j, bypp =3D bpp / 8; - for (y =3D 0; y < dst_height; y++) { - i =3D dst_x * bypp; - j =3D src_x * bypp; - if (top_to_bottom) { - i +=3D (dst_y + y) * dst_stride; - j +=3D (src_y + y) * src_stride; + unsigned int y, i, j, bypp =3D ctx->bpp / 8; + for (y =3D 0; y < ctx->dst.height; y++) { + i =3D ctx->dst.x * bypp; + j =3D ctx->src.x * bypp; + if (ctx->top_to_bottom) { + i +=3D (ctx->dst.y + y) * ctx->dst_stride; + j +=3D (ctx->src.y + y) * ctx->src_stride; } else { - i +=3D (dst_y + dst_height - 1 - y) * dst_stride; - j +=3D (src_y + dst_height - 1 - y) * src_stride; + i +=3D (ctx->dst.y + ctx->dst.height - 1 - y) + * ctx->dst_stride; + j +=3D (ctx->src.y + ctx->dst.height - 1 - y) + * ctx->src_stride; } - memmove(&dst_bits[i], &src_bits[j], dst_width * bypp); + memmove(&ctx->dst_bits[i], &ctx->src_bits[j], + ctx->dst.width * bypp); } } break; @@ -189,35 +220,40 @@ void ati_2d_blt(ATIVGAState *s) { uint32_t filler =3D 0; =20 - switch (rop3) { + switch (ctx->rop3) { case ROP3_PATCOPY: - filler =3D frgd_clr; + filler =3D ctx->frgd_clr; break; case ROP3_BLACKNESS: - filler =3D 0xffUL << 24 | rgb_to_pixel32(palette[0], palette[1= ], - palette[2]); + filler =3D 0xffUL << 24 | rgb_to_pixel32(ctx->palette[0], + ctx->palette[1], + ctx->palette[2]); break; case ROP3_WHITENESS: - filler =3D 0xffUL << 24 | rgb_to_pixel32(palette[3], palette[4= ], - palette[5]); + filler =3D 0xffUL << 24 | rgb_to_pixel32(ctx->palette[3], + ctx->palette[4], + ctx->palette[5]); break; } =20 DPRINTF("pixman_fill(%p, %ld, %d, %d, %d, %d, %d, %x)\n", - dst_bits, dst_stride / sizeof(uint32_t), bpp, dst_x, dst_y, - dst_width, dst_height, filler); + ctx->dst_bits, ctx->dst_stride / sizeof(uint32_t), ctx->bp= p, + ctx->dst.x, ctx->dst.y, ctx->dst.width, ctx->dst.height, + filler); #ifdef CONFIG_PIXMAN if (!(s->use_pixman & BIT(0)) || - !pixman_fill((uint32_t *)dst_bits, dst_stride / sizeof(uint32_= t), - bpp, dst_x, dst_y, dst_width, dst_height, filler)) + !pixman_fill((uint32_t *)ctx->dst_bits, + ctx->dst_stride / sizeof(uint32_t), ctx->bpp, + ctx->dst.x, ctx->dst.y, + ctx->dst.width, ctx->dst.height, filler)) #endif { /* fallback when pixman failed or we don't want to call it */ - unsigned int x, y, i, bypp =3D bpp / 8; - for (y =3D 0; y < dst_height; y++) { - i =3D dst_x * bypp + (dst_y + y) * dst_stride; - for (x =3D 0; x < dst_width; x++, i +=3D bypp) { - stn_he_p(&dst_bits[i], bypp, filler); + unsigned int x, y, i, bypp =3D ctx->bpp / 8; + for (y =3D 0; y < ctx->dst.height; y++) { + i =3D ctx->dst.x * bypp + (ctx->dst.y + y) * ctx->dst_stri= de; + for (x =3D 0; x < ctx->dst.width; x++, i +=3D bypp) { + stn_he_p(&ctx->dst_bits[i], bypp, filler); } } } @@ -225,9 +261,9 @@ void ati_2d_blt(ATIVGAState *s) } default: qemu_log_mask(LOG_UNIMP, "Unimplemented ati_2d blt op %x\n", - rop3 >> 16); + ctx->rop3 >> 16); return; } =20 - ati_set_dirty(s, dst_bits, dst_y); + ati_set_dirty(&s->vga, ctx); } --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020915705773.5247742009888; Sun, 8 Mar 2026 18:48:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjA-0005nE-GQ; Sun, 08 Mar 2026 21:48:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiw-0005lM-78 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:01 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiq-0001Hk-9D for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:47:55 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id 7585D5969E5; Mon, 09 Mar 2026 02:47:49 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id UDS9OQSPixTx; Mon, 9 Mar 2026 02:47:47 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 6FF825969EB; Mon, 09 Mar 2026 02:47:47 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <6e2dccba65d9b369e0db633c0149a77351827222.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 4/9] ati-vga: Extract setup_2d_blt_ctx from ati_2d_blt MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:47 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020921708158500 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski setup_2d_blt_ctx is responsible for knowing how to retrieve the state needed by ati_2d_blt from the registers and assigning it to the ATI2DCtx. This will be useful in a future patch when HOST_DATA needs to make small modifications to the ctx. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati_2d.c | 69 +++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index 9e0115c49d..a83cf14a4a 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -25,7 +25,7 @@ * possible. */ =20 -static int ati_bpp_from_datatype(ATIVGAState *s) +static int ati_bpp_from_datatype(const ATIVGAState *s) { switch (s->regs.dp_datatype & 0xf) { case 2: @@ -80,73 +80,76 @@ static void ati_set_dirty(VGACommonState *vga, const AT= I2DCtx *ctx) } } =20 -void ati_2d_blt(ATIVGAState *s) +static void setup_2d_blt_ctx(const ATIVGAState *s, ATI2DCtx *ctx) { - /* FIXME it is probably more complex than this and may need to be */ - /* rewritten but for now as a start just to get some output: */ - ATI2DCtx ctx_; - ATI2DCtx *ctx =3D &ctx_; + ctx->bpp =3D ati_bpp_from_datatype(s); ctx->rop3 =3D s->regs.dp_mix & GMC_ROP3_MASK; ctx->left_to_right =3D s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT; ctx->top_to_bottom =3D s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM; ctx->frgd_clr =3D s->regs.dp_brush_frgd_clr; ctx->palette =3D s->vga.palette; ctx->dst_offset =3D s->regs.dst_offset; + ctx->vram_end =3D s->vga.vram_ptr + s->vga.vram_size; + ctx->dst.width =3D s->regs.dst_width; ctx->dst.height =3D s->regs.dst_height; ctx->dst.x =3D (ctx->left_to_right ? s->regs.dst_x : s->regs.dst_x + 1 - ctx->dst.width); ctx->dst.y =3D (ctx->top_to_bottom ? s->regs.dst_y : s->regs.dst_y + 1 - ctx->dst.height); - ctx->bpp =3D ati_bpp_from_datatype(s); + ctx->dst_stride =3D s->regs.dst_pitch; + ctx->dst_bits =3D s->vga.vram_ptr + s->regs.dst_offset; + if (s->dev_id =3D=3D PCI_DEVICE_ID_ATI_RAGE128_PF) { + ctx->dst_bits +=3D s->regs.crtc_offset & 0x07ffffff; + ctx->dst_stride *=3D ctx->bpp; + } + + ctx->src.x =3D (ctx->left_to_right ? + s->regs.src_x : s->regs.src_x + 1 - ctx->dst.width); + ctx->src.y =3D (ctx->top_to_bottom ? + s->regs.src_y : s->regs.src_y + 1 - ctx->dst.height); + ctx->src_stride =3D s->regs.src_pitch; + ctx->src_bits =3D s->vga.vram_ptr + s->regs.src_offset; + if (s->dev_id =3D=3D PCI_DEVICE_ID_ATI_RAGE128_PF) { + ctx->src_bits +=3D s->regs.crtc_offset & 0x07ffffff; + ctx->src_stride *=3D ctx->bpp; + } + DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c\n", + s->regs.src_offset, s->regs.dst_offset, s->regs.default_offset, + ctx->src_stride, ctx->dst_stride, s->regs.default_pitch, + ctx->src.x, ctx->src.y, ctx->dst.x, ctx->dst.y, + ctx->dst.width, ctx->dst.height, + (ctx->left_to_right ? '>' : '<'), + (ctx->top_to_bottom ? 'v' : '^')); +} + +void ati_2d_blt(ATIVGAState *s) +{ + ATI2DCtx ctx_; + ATI2DCtx *ctx =3D &ctx_; + setup_2d_blt_ctx(s, ctx); if (!ctx->bpp) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); return; } - ctx->dst_stride =3D s->regs.dst_pitch; if (!ctx->dst_stride) { qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n"); return; } - ctx->dst_bits =3D s->vga.vram_ptr + ctx->dst_offset; - - if (s->dev_id =3D=3D PCI_DEVICE_ID_ATI_RAGE128_PF) { - ctx->dst_bits +=3D s->regs.crtc_offset & 0x07ffffff; - ctx->dst_stride *=3D ctx->bpp; - } - ctx->vram_end =3D s->vga.vram_ptr + s->vga.vram_size; if (ctx->dst.x > 0x3fff || ctx->dst.y > 0x3fff || ctx->dst_bits >=3D ctx->vram_end || ctx->dst_bits + ctx->dst.x + (ctx->dst.y + ctx->dst.height) * ctx->dst_stride >=3D ctx->vram_en= d) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return; } - DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c\n", - s->regs.src_offset, ctx->dst_offset, s->regs.default_offset, - ctx->src_stride, ctx->dst_stride, s->regs.default_pitch, - ctx->src.x, ctx->src.y, ctx->dst.x, ctx->dst.y, - ctx->dst.width, ctx->dst.height, - (ctx->left_to_right ? '>' : '<'), - (ctx->top_to_bottom ? 'v' : '^')); switch (ctx->rop3) { case ROP3_SRCCOPY: { bool fallback =3D false; - ctx->src.x =3D (ctx->left_to_right ? - s->regs.src_x : s->regs.src_x + 1 - ctx->dst.width); - ctx->src.y =3D (ctx->top_to_bottom ? - s->regs.src_y : s->regs.src_y + 1 - ctx->dst.height); - ctx->src_stride =3D s->regs.src_pitch; if (!ctx->src_stride) { qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); return; } - ctx->src_bits =3D s->vga.vram_ptr + s->regs.src_offset; - - if (s->dev_id =3D=3D PCI_DEVICE_ID_ATI_RAGE128_PF) { - ctx->src_bits +=3D s->regs.crtc_offset & 0x07ffffff; - ctx->src_stride *=3D ctx->bpp; - } if (ctx->src.x > 0x3fff || ctx->src.y > 0x3fff || ctx->src_bits >=3D ctx->vram_end || ctx->src_bits + ctx->src.x + (ctx->src.y + ctx->dst.height) * --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020970292528.5993205827839; Sun, 8 Mar 2026 18:49:30 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjO-0005pb-Ef; Sun, 08 Mar 2026 21:48:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiz-0005la-VW for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:03 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiv-0001IB-V0 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:00 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id 7FB6F5969E7; Mon, 09 Mar 2026 02:47:50 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id dvkVew1uYPxV; Mon, 9 Mar 2026 02:47:48 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 78D625969EE; Mon, 09 Mar 2026 02:47:48 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <367949c50ca140a2d18ae66234dafbbc586b553c.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 5/9] ati-vga: Split ati_2d_do_blt from ati_2d_blt MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:48 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020972659154100 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski ati_2d_blt remains the public interface to the blitter but the bulk of the implementation is moved down into ati_2d_do_blt which is passed an ATI2DCtx. ati_2d_do_blt returns a bool that is true when the blit succeeded, which means that a screen region will need to be set dirty. Otherwise false is returned. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati_2d.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index a83cf14a4a..0475fcb585 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -123,24 +123,21 @@ static void setup_2d_blt_ctx(const ATIVGAState *s, AT= I2DCtx *ctx) (ctx->top_to_bottom ? 'v' : '^')); } =20 -void ati_2d_blt(ATIVGAState *s) +static bool ati_2d_do_blt(ATIVGAState *s, ATI2DCtx *ctx) { - ATI2DCtx ctx_; - ATI2DCtx *ctx =3D &ctx_; - setup_2d_blt_ctx(s, ctx); if (!ctx->bpp) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); - return; + return false; } if (!ctx->dst_stride) { qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n"); - return; + return false; } if (ctx->dst.x > 0x3fff || ctx->dst.y > 0x3fff || ctx->dst_bits >=3D ctx->vram_end || ctx->dst_bits + ctx->dst.x + (ctx->dst.y + ctx->dst.height) * ctx->dst_stride >=3D ctx->vram_en= d) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); - return; + return false; } switch (ctx->rop3) { case ROP3_SRCCOPY: @@ -148,14 +145,14 @@ void ati_2d_blt(ATIVGAState *s) bool fallback =3D false; if (!ctx->src_stride) { qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); - return; + return false; } if (ctx->src.x > 0x3fff || ctx->src.y > 0x3fff || ctx->src_bits >=3D ctx->vram_end || ctx->src_bits + ctx->src.x + (ctx->src.y + ctx->dst.height) * ctx->src_stride >=3D ctx->vram_end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); - return; + return false; } =20 DPRINTF("pixman_blt(%p, %p, %ld, %ld, %d, %d, %d, %d, %d, %d, %d, = %d)\n", @@ -265,8 +262,17 @@ void ati_2d_blt(ATIVGAState *s) default: qemu_log_mask(LOG_UNIMP, "Unimplemented ati_2d blt op %x\n", ctx->rop3 >> 16); - return; + return false; } =20 - ati_set_dirty(&s->vga, ctx); + return true; +} + +void ati_2d_blt(ATIVGAState *s) +{ + ATI2DCtx ctx; + setup_2d_blt_ctx(s, &ctx); + if (ati_2d_do_blt(s, &ctx)) { + ati_set_dirty(&s->vga, &ctx); + } } --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020917372608.3175150442808; Sun, 8 Mar 2026 18:48:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjQ-0005qq-En; Sun, 08 Mar 2026 21:48:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPj1-0005lz-26 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:03 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiv-0001ID-Vb for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:02 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id 83BBE5969EC; Mon, 09 Mar 2026 02:47:51 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id OWr6xUq3Kmx9; Mon, 9 Mar 2026 02:47:49 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 845CF5969EB; Mon, 09 Mar 2026 02:47:49 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <6e3545dea9f4522e07e91f9db885a7d74dae781a.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 6/9] ati-vga: Remove ATIVGAState param from ati_2d_do_blt MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:49 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -1 X-Spam_score: -0.2 X-Spam_bar: / X-Spam_report: (-0.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.819, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.903, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020921743158500 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski This completes the decoupling from the ATIVGAState struct. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati_2d.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index 0475fcb585..1dfad730ba 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -123,7 +123,7 @@ static void setup_2d_blt_ctx(const ATIVGAState *s, ATI2= DCtx *ctx) (ctx->top_to_bottom ? 'v' : '^')); } =20 -static bool ati_2d_do_blt(ATIVGAState *s, ATI2DCtx *ctx) +static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman) { if (!ctx->bpp) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); @@ -164,14 +164,14 @@ static bool ati_2d_do_blt(ATIVGAState *s, ATI2DCtx *c= tx) #ifdef CONFIG_PIXMAN int src_stride_words =3D ctx->src_stride / sizeof(uint32_t); int dst_stride_words =3D ctx->dst_stride / sizeof(uint32_t); - if ((s->use_pixman & BIT(1)) && + if ((use_pixman & BIT(1)) && ctx->left_to_right && ctx->top_to_bottom) { fallback =3D !pixman_blt((uint32_t *)ctx->src_bits, (uint32_t *)ctx->dst_bits, src_stride_w= ords, dst_stride_words, ctx->bpp, ctx->bpp, ctx->src.x, ctx->src.y, ctx->dst.x, ctx->dst.y, ctx->dst.width, ctx->dst.he= ight); - } else if (s->use_pixman & BIT(1)) { + } else if (use_pixman & BIT(1)) { /* FIXME: We only really need a temporary if src and dst overl= ap */ int llb =3D ctx->dst.width * (ctx->bpp / 8); int tmp_stride_words =3D DIV_ROUND_UP(llb, sizeof(uint32_t)); @@ -241,7 +241,7 @@ static bool ati_2d_do_blt(ATIVGAState *s, ATI2DCtx *ctx) ctx->dst.x, ctx->dst.y, ctx->dst.width, ctx->dst.height, filler); #ifdef CONFIG_PIXMAN - if (!(s->use_pixman & BIT(0)) || + if (!(use_pixman & BIT(0)) || !pixman_fill((uint32_t *)ctx->dst_bits, ctx->dst_stride / sizeof(uint32_t), ctx->bpp, ctx->dst.x, ctx->dst.y, @@ -272,7 +272,7 @@ void ati_2d_blt(ATIVGAState *s) { ATI2DCtx ctx; setup_2d_blt_ctx(s, &ctx); - if (ati_2d_do_blt(s, &ctx)) { + if (ati_2d_do_blt(&ctx, s->use_pixman)) { ati_set_dirty(&s->vga, &ctx); } } --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020989340622.877288467265; Sun, 8 Mar 2026 18:49:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjN-0005p2-1t; Sun, 08 Mar 2026 21:48:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPj2-0005mh-Ic for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:05 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiz-0001Ii-Nd for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:04 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id 96CF0596A42; Mon, 09 Mar 2026 02:47:52 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id cDBxQwGLZ6hQ; Mon, 9 Mar 2026 02:47:50 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 8E5D35969EE; Mon, 09 Mar 2026 02:47:50 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <4752dfbe240102c2ffa1f2cdab4c9442d4f0dcfb.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 7/9] ati-vga: Implement scissor rectangle clipping for 2D operations MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:50 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -1 X-Spam_score: -0.2 X-Spam_bar: / X-Spam_report: (-0.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.819, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.903, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020991993158500 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski Use scissor registers to clip blit operations. This is required for text rendering in X using the r128 driver. Without it overly-wide glyphs are drawn and create all sorts of chaos. The visible destination rectangle (vis_dst) is the intersection of the scissor rectangle and the destination rectangle (dst). The src also needs to be offset if clipped on the top and/or left sides to ensure that src data is read correctly and appears clipped when drawn rather than shifted. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati_2d.c | 87 ++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index 1dfad730ba..d62ad849f3 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -52,6 +52,7 @@ typedef struct { uint32_t frgd_clr; const uint8_t *palette; const uint8_t *vram_end; + QemuRect scissor; =20 QemuRect dst; int dst_stride; @@ -91,6 +92,11 @@ static void setup_2d_blt_ctx(const ATIVGAState *s, ATI2D= Ctx *ctx) ctx->dst_offset =3D s->regs.dst_offset; ctx->vram_end =3D s->vga.vram_ptr + s->vga.vram_size; =20 + ctx->scissor.width =3D s->regs.sc_right - s->regs.sc_left + 1; + ctx->scissor.height =3D s->regs.sc_bottom - s->regs.sc_top + 1; + ctx->scissor.x =3D s->regs.sc_left; + ctx->scissor.y =3D s->regs.sc_top; + ctx->dst.width =3D s->regs.dst_width; ctx->dst.height =3D s->regs.dst_height; ctx->dst.x =3D (ctx->left_to_right ? @@ -125,6 +131,8 @@ static void setup_2d_blt_ctx(const ATIVGAState *s, ATI2= DCtx *ctx) =20 static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pixman) { + QemuRect vis_src, vis_dst; + if (!ctx->bpp) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); return false; @@ -139,6 +147,29 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_p= ixman) qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return false; } + qemu_rect_intersect(&ctx->dst, &ctx->scissor, &vis_dst); + if (!vis_dst.height || !vis_dst.width) { + /* Nothing is visible, completely clipped */ + return false; + } + /* + * The src must be offset if clipping is applied to the dst. + * This is so that when the source is blit to a dst clipped + * on the top or left the src image is not shifted into the + * clipped region but actually clipped. + */ + vis_src.x =3D ctx->src.x + (vis_dst.x - ctx->dst.x); + vis_src.y =3D ctx->src.y + (vis_dst.y - ctx->dst.y); + vis_src.width =3D vis_dst.width; + vis_src.height =3D vis_dst.height; + + DPRINTF("dst: (%d,%d) %dx%d -> vis_dst: (%d,%d) %dx%d\n", + ctx->dst.x, ctx->dst.y, ctx->dst.width, ctx->dst.height, + vis_dst.x, vis_dst.y, vis_dst.width, vis_dst.height); + DPRINTF("src: (%d,%d) %dx%d -> vis_src: (%d,%d) %dx%d\n", + ctx->src.x, ctx->src.y, ctx->dst.width, ctx->dst.height, + vis_src.x, vis_src.y, vis_src.width, vis_src.height); + switch (ctx->rop3) { case ROP3_SRCCOPY: { @@ -147,10 +178,9 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_p= ixman) qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); return false; } - if (ctx->src.x > 0x3fff || ctx->src.y > 0x3fff || - ctx->src_bits >=3D ctx->vram_end || - ctx->src_bits + ctx->src.x + (ctx->src.y + ctx->dst.height) * - ctx->src_stride >=3D ctx->vram_end) { + if (vis_src.x > 0x3fff || vis_src.y > 0x3fff || + ctx->src_bits >=3D ctx->vram_end || ctx->src_bits + vis_src.x + + (vis_src.y + vis_dst.height) * ctx->src_stride >=3D ctx->vram_= end) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return false; } @@ -159,8 +189,8 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_pi= xman) ctx->src_bits, ctx->dst_bits, ctx->src_stride / sizeof(uint32_t), ctx->dst_stride / sizeof(uint32_t), - ctx->bpp, ctx->bpp, ctx->src.x, ctx->src.y, ctx->dst.x, - ctx->dst.y, ctx->dst.width, ctx->dst.height); + ctx->bpp, ctx->bpp, vis_src.x, vis_src.y, vis_dst.x, vis_d= st.y, + vis_dst.width, vis_dst.height); #ifdef CONFIG_PIXMAN int src_stride_words =3D ctx->src_stride / sizeof(uint32_t); int dst_stride_words =3D ctx->dst_stride / sizeof(uint32_t); @@ -169,24 +199,24 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_= pixman) fallback =3D !pixman_blt((uint32_t *)ctx->src_bits, (uint32_t *)ctx->dst_bits, src_stride_w= ords, dst_stride_words, ctx->bpp, ctx->bpp, - ctx->src.x, ctx->src.y, ctx->dst.x, - ctx->dst.y, ctx->dst.width, ctx->dst.he= ight); + vis_src.x, vis_src.y, vis_dst.x, vis_ds= t.y, + vis_dst.width, vis_dst.height); } else if (use_pixman & BIT(1)) { /* FIXME: We only really need a temporary if src and dst overl= ap */ - int llb =3D ctx->dst.width * (ctx->bpp / 8); + int llb =3D vis_dst.width * (ctx->bpp / 8); int tmp_stride_words =3D DIV_ROUND_UP(llb, sizeof(uint32_t)); uint32_t *tmp =3D g_malloc(tmp_stride_words * sizeof(uint32_t)= * - ctx->dst.height); + vis_dst.height); fallback =3D !pixman_blt((uint32_t *)ctx->src_bits, tmp, src_stride_words, tmp_stride_words, ctx= ->bpp, - ctx->bpp, ctx->src.x, ctx->src.y, 0, 0, - ctx->dst.width, ctx->dst.height); + ctx->bpp, vis_src.x, vis_src.y, 0, 0, + vis_dst.width, vis_dst.height); if (!fallback) { fallback =3D !pixman_blt(tmp, (uint32_t *)ctx->dst_bits, tmp_stride_words, dst_stride_words, ctx->bpp, ctx->bpp, 0, 0, - ctx->dst.x, ctx->dst.y, - ctx->dst.width, ctx->dst.height); + vis_dst.x, vis_dst.y, + vis_dst.width, vis_dst.height); } g_free(tmp); } else @@ -196,20 +226,20 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_= pixman) } if (fallback) { unsigned int y, i, j, bypp =3D ctx->bpp / 8; - for (y =3D 0; y < ctx->dst.height; y++) { - i =3D ctx->dst.x * bypp; - j =3D ctx->src.x * bypp; + for (y =3D 0; y < vis_dst.height; y++) { + i =3D vis_dst.x * bypp; + j =3D vis_src.x * bypp; if (ctx->top_to_bottom) { - i +=3D (ctx->dst.y + y) * ctx->dst_stride; - j +=3D (ctx->src.y + y) * ctx->src_stride; + i +=3D (vis_dst.y + y) * ctx->dst_stride; + j +=3D (vis_src.y + y) * ctx->src_stride; } else { - i +=3D (ctx->dst.y + ctx->dst.height - 1 - y) + i +=3D (vis_dst.y + vis_dst.height - 1 - y) * ctx->dst_stride; - j +=3D (ctx->src.y + ctx->dst.height - 1 - y) + j +=3D (vis_src.y + vis_dst.height - 1 - y) * ctx->src_stride; } memmove(&ctx->dst_bits[i], &ctx->src_bits[j], - ctx->dst.width * bypp); + vis_dst.width * bypp); } } break; @@ -238,21 +268,20 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_= pixman) =20 DPRINTF("pixman_fill(%p, %ld, %d, %d, %d, %d, %d, %x)\n", ctx->dst_bits, ctx->dst_stride / sizeof(uint32_t), ctx->bp= p, - ctx->dst.x, ctx->dst.y, ctx->dst.width, ctx->dst.height, - filler); + vis_dst.x, vis_dst.y, vis_dst.width, vis_dst.height, fille= r); #ifdef CONFIG_PIXMAN if (!(use_pixman & BIT(0)) || !pixman_fill((uint32_t *)ctx->dst_bits, ctx->dst_stride / sizeof(uint32_t), ctx->bpp, - ctx->dst.x, ctx->dst.y, - ctx->dst.width, ctx->dst.height, filler)) + vis_dst.x, vis_dst.y, vis_dst.width, vis_dst.heig= ht, + filler)) #endif { /* fallback when pixman failed or we don't want to call it */ unsigned int x, y, i, bypp =3D ctx->bpp / 8; - for (y =3D 0; y < ctx->dst.height; y++) { - i =3D ctx->dst.x * bypp + (ctx->dst.y + y) * ctx->dst_stri= de; - for (x =3D 0; x < ctx->dst.width; x++, i +=3D bypp) { + for (y =3D 0; y < vis_dst.height; y++) { + i =3D vis_dst.x * bypp + (vis_dst.y + y) * ctx->dst_stride; + for (x =3D 0; x < vis_dst.width; x++, i +=3D bypp) { stn_he_p(&ctx->dst_bits[i], bypp, filler); } } --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020935572243.39665140090028; Sun, 8 Mar 2026 18:48:55 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjP-0005qI-3V; Sun, 08 Mar 2026 21:48:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPj2-0005mg-C2 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:05 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiz-0001Ij-NI for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:04 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id A137B596ADE; Mon, 09 Mar 2026 02:47:53 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id SjV1lnUCMe9v; Mon, 9 Mar 2026 02:47:51 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 99BA8596A41; Mon, 09 Mar 2026 02:47:51 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <235adb69787c818afd023e7f32286166cc70744c.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 8/9] ati-vga: Implement HOST_DATA register writes MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:51 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -1 X-Spam_score: -0.2 X-Spam_bar: / X-Spam_report: (-0.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.819, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.903, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020940779154100 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski Writing to any of the HOST_DATA0-7 registers pushes the written data into a 128-bit accumulator. When the accumulator is full a flush is triggered to copy it to the framebuffer. A final write to HOST_DATA_LAST will also initiate a flush. The flush itself is left for the next patch. Unaligned HOST_DATA* writes result in, from what I can tell, undefined behavior on real hardware. A well-behaved driver shouldn't be doing this anyway. For that reason they are not handled here at all. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan Signed-off-by: BALATON Zoltan --- hw/display/ati.c | 26 ++++++++++++++++++++++++++ hw/display/ati_dbg.c | 9 +++++++++ hw/display/ati_int.h | 9 +++++++++ hw/display/ati_regs.h | 9 +++++++++ 4 files changed, 53 insertions(+) diff --git a/hw/display/ati.c b/hw/display/ati.c index 9a7c5703b0..16dbb743e1 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -1023,6 +1023,27 @@ static void ati_mm_write(void *opaque, hwaddr addr, case SRC_SC_BOTTOM: s->regs.src_sc_bottom =3D data & 0x3fff; break; + case HOST_DATA0: + case HOST_DATA1: + case HOST_DATA2: + case HOST_DATA3: + case HOST_DATA4: + case HOST_DATA5: + case HOST_DATA6: + case HOST_DATA7: + case HOST_DATA_LAST: + if (!s->host_data.active) { + break; + } + s->host_data.acc[s->host_data.next++] =3D data; + if (addr =3D=3D HOST_DATA_LAST) { + qemu_log_mask(LOG_UNIMP, "HOST_DATA finish not yet implemented= \n"); + s->host_data.next =3D 0; + } else if (s->host_data.next >=3D 4) { + qemu_log_mask(LOG_UNIMP, "HOST_DATA flush not yet implemented\= n"); + s->host_data.next =3D 0; + } + break; default: break; } @@ -1128,6 +1149,11 @@ static void ati_vga_reset(DeviceState *dev) /* reset vga */ vga_common_reset(&s->vga); s->mode =3D VGA_MODE; + + s->host_data.active =3D false; + s->host_data.next =3D 0; + s->host_data.row =3D 0; + s->host_data.col =3D 0; } =20 static void ati_vga_exit(PCIDevice *dev) diff --git a/hw/display/ati_dbg.c b/hw/display/ati_dbg.c index 3ffa7f35df..5c799d540a 100644 --- a/hw/display/ati_dbg.c +++ b/hw/display/ati_dbg.c @@ -252,6 +252,15 @@ static struct ati_regdesc ati_reg_names[] =3D { {"MC_SRC1_CNTL", 0x19D8}, {"TEX_CNTL", 0x1800}, {"RAGE128_MPP_TB_CONFIG", 0x01c0}, + {"HOST_DATA0", 0x17c0}, + {"HOST_DATA1", 0x17c4}, + {"HOST_DATA2", 0x17c8}, + {"HOST_DATA3", 0x17cc}, + {"HOST_DATA4", 0x17d0}, + {"HOST_DATA5", 0x17d4}, + {"HOST_DATA6", 0x17d8}, + {"HOST_DATA7", 0x17dc}, + {"HOST_DATA_LAST", 0x17e0}, {NULL, -1} }; =20 diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h index 874c63eb54..063efc7bba 100644 --- a/hw/display/ati_int.h +++ b/hw/display/ati_int.h @@ -96,6 +96,14 @@ typedef struct ATIVGARegs { uint32_t default_tile; } ATIVGARegs; =20 +typedef struct ATIHostDataState { + bool active; + uint32_t row; + uint32_t col; + uint32_t next; + uint32_t acc[4]; +} ATIHostDataState; + struct ATIVGAState { PCIDevice dev; VGACommonState vga; @@ -114,6 +122,7 @@ struct ATIVGAState { MemoryRegion io; MemoryRegion mm; ATIVGARegs regs; + ATIHostDataState host_data; }; =20 const char *ati_reg_name(int num); diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h index 3999edb9b7..48f15e9b1d 100644 --- a/hw/display/ati_regs.h +++ b/hw/display/ati_regs.h @@ -252,6 +252,15 @@ #define DP_T12_CNTL 0x178c #define DST_BRES_T1_LNTH 0x1790 #define DST_BRES_T2_LNTH 0x1794 +#define HOST_DATA0 0x17c0 +#define HOST_DATA1 0x17c4 +#define HOST_DATA2 0x17c8 +#define HOST_DATA3 0x17cc +#define HOST_DATA4 0x17d0 +#define HOST_DATA5 0x17d4 +#define HOST_DATA6 0x17d8 +#define HOST_DATA7 0x17dc +#define HOST_DATA_LAST 0x17e0 #define SCALE_SRC_HEIGHT_WIDTH 0x1994 #define SCALE_OFFSET_0 0x1998 #define SCALE_PITCH 0x199c --=20 2.41.3 From nobody Fri Mar 27 04:58:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773020941123642.8223392431927; Sun, 8 Mar 2026 18:49:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vzPjK-0005oh-QX; Sun, 08 Mar 2026 21:48:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPj1-0005m1-Iq for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:03 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vzPiy-0001If-Vk for qemu-devel@nongnu.org; Sun, 08 Mar 2026 21:48:03 -0400 Received: from localhost (localhost [127.0.0.1]) by zero.eik.bme.hu (Postfix) with ESMTP id B1126596AE1; Mon, 09 Mar 2026 02:47:54 +0100 (CET) Received: from zero.eik.bme.hu ([127.0.0.1]) by localhost (zero.eik.bme.hu [127.0.0.1]) (amavis, port 10028) with ESMTP id 3uikUkAkAPF3; Mon, 9 Mar 2026 02:47:52 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id A2C63596ABF; Mon, 09 Mar 2026 02:47:52 +0100 (CET) X-Virus-Scanned: amavis at eik.bme.hu Message-ID: <8d0d4b52a16f5564e37bbc88496d7ab8d41477ac.1773020351.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH v12 9/9] ati-vga: Implement HOST_DATA flush to VRAM MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , marcandre.lureau@redhat.com, Chad Jablonski , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 09 Mar 2026 02:47:52 +0100 (CET) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1773020944166154100 Content-Type: text/plain; charset="utf-8" From: Chad Jablonski Implement flushing the 128-bit HOST_DATA accumulator to VRAM to enable text rendering in X. Supports all datatypes (monochrome frgd/bkgd, monochrome frgd, and color), however monochrome frgd support is partial and does not properly handle transparency/leave-alone. The flush is broken up into two steps. First, if necessary, expansion of the monochrome bits to the destination color depth. Then the expanded pixels are sent to the ati_2d_do_blt one scanline at a time. ati_2d_do_blt then clips and performs the blit. Signed-off-by: Chad Jablonski Reviewed-by: BALATON Zoltan [balaton: Fix build without pixman] Signed-off-by: BALATON Zoltan --- hw/display/ati.c | 6 +- hw/display/ati_2d.c | 132 +++++++++++++++++++++++++++++++++++++++++- hw/display/ati_int.h | 3 + hw/display/ati_regs.h | 4 ++ 4 files changed, 139 insertions(+), 6 deletions(-) diff --git a/hw/display/ati.c b/hw/display/ati.c index 16dbb743e1..bb9e0bba28 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -1037,11 +1037,9 @@ static void ati_mm_write(void *opaque, hwaddr addr, } s->host_data.acc[s->host_data.next++] =3D data; if (addr =3D=3D HOST_DATA_LAST) { - qemu_log_mask(LOG_UNIMP, "HOST_DATA finish not yet implemented= \n"); - s->host_data.next =3D 0; + ati_host_data_finish(s); } else if (s->host_data.next >=3D 4) { - qemu_log_mask(LOG_UNIMP, "HOST_DATA flush not yet implemented\= n"); - s->host_data.next =3D 0; + ati_host_data_flush(s); } break; default: diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index d62ad849f3..26ae2f1825 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -47,6 +47,7 @@ static int ati_bpp_from_datatype(const ATIVGAState *s) typedef struct { int bpp; uint32_t rop3; + bool host_data_active; bool left_to_right; bool top_to_bottom; uint32_t frgd_clr; @@ -85,6 +86,7 @@ static void setup_2d_blt_ctx(const ATIVGAState *s, ATI2DC= tx *ctx) { ctx->bpp =3D ati_bpp_from_datatype(s); ctx->rop3 =3D s->regs.dp_mix & GMC_ROP3_MASK; + ctx->host_data_active =3D s->host_data.active; ctx->left_to_right =3D s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT; ctx->top_to_bottom =3D s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM; ctx->frgd_clr =3D s->regs.dp_brush_frgd_clr; @@ -178,9 +180,10 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_p= ixman) qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); return false; } - if (vis_src.x > 0x3fff || vis_src.y > 0x3fff || + if (!ctx->host_data_active && + (vis_src.x > 0x3fff || vis_src.y > 0x3fff || ctx->src_bits >=3D ctx->vram_end || ctx->src_bits + vis_src.x + - (vis_src.y + vis_dst.height) * ctx->src_stride >=3D ctx->vram_= end) { + (vis_src.y + vis_dst.height) * ctx->src_stride >=3D ctx->vram_= end)) { qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); return false; } @@ -300,8 +303,133 @@ static bool ati_2d_do_blt(ATI2DCtx *ctx, uint8_t use_= pixman) void ati_2d_blt(ATIVGAState *s) { ATI2DCtx ctx; + uint32_t src_source =3D s->regs.dp_mix & DP_SRC_SOURCE; + + /* Finish any active HOST_DATA blits before starting a new blit */ + ati_host_data_finish(s); + + if (src_source =3D=3D DP_SRC_HOST || src_source =3D=3D DP_SRC_HOST_BYT= EALIGN) { + /* Begin a HOST_DATA blit */ + s->host_data.active =3D true; + s->host_data.next =3D 0; + s->host_data.col =3D 0; + s->host_data.row =3D 0; + return; + } setup_2d_blt_ctx(s, &ctx); if (ati_2d_do_blt(&ctx, s->use_pixman)) { ati_set_dirty(&s->vga, &ctx); } } + +bool ati_host_data_flush(ATIVGAState *s) +{ + ATI2DCtx ctx, chunk; + uint32_t fg =3D s->regs.dp_src_frgd_clr; + uint32_t bg =3D s->regs.dp_src_bkgd_clr; + unsigned bypp, pix_count, row, col, idx; + uint8_t pix_buf[ATI_HOST_DATA_ACC_BITS * sizeof(uint32_t)]; + uint32_t byte_pix_order =3D s->regs.dp_datatype & DP_BYTE_PIX_ORDER; + uint32_t src_source =3D s->regs.dp_mix & DP_SRC_SOURCE; + uint32_t src_datatype =3D s->regs.dp_datatype & DP_SRC_DATATYPE; + + if (!s->host_data.active) { + return false; + } + if (src_source !=3D DP_SRC_HOST) { + qemu_log_mask(LOG_GUEST_ERROR, + "host_data_blt: unsupported src_source %x\n", src_so= urce); + return false; + } + if (src_datatype !=3D SRC_MONO_FRGD_BKGD && src_datatype !=3D SRC_MONO= _FRGD && + src_datatype !=3D SRC_COLOR) { + qemu_log_mask(LOG_GUEST_ERROR, + "host_data_blt: undefined src_datatype %x\n", + src_datatype); + return false; + } + + setup_2d_blt_ctx(s, &ctx); + + if (!ctx.left_to_right || !ctx.top_to_bottom) { + qemu_log_mask(LOG_UNIMP, + "host_data_blt: unsupported blit direction %c%c\n", + ctx.left_to_right ? '>' : '<', + ctx.top_to_bottom ? 'v' : '^'); + return false; + } + + bypp =3D ctx.bpp / 8; + + if (src_datatype =3D=3D SRC_COLOR) { + pix_count =3D ATI_HOST_DATA_ACC_BITS / ctx.bpp; + memcpy(pix_buf, &s->host_data.acc[0], sizeof(s->host_data.acc)); + } else { + pix_count =3D ATI_HOST_DATA_ACC_BITS; + /* Expand monochrome bits to color pixels */ + idx =3D 0; + for (int word =3D 0; word < 4; word++) { + for (int byte =3D 0; byte < 4; byte++) { + uint8_t byte_val =3D s->host_data.acc[word] >> (byte * 8); + for (int i =3D 0; i < 8; i++) { + bool is_fg =3D byte_val & BIT(byte_pix_order ? i : 7 -= i); + uint32_t color =3D is_fg ? fg : bg; + stn_he_p(&pix_buf[idx], bypp, color); + idx +=3D bypp; + } + } + } + } + + /* Copy and then modify blit ctx for use in a chunked blit */ + chunk =3D ctx; + chunk.src_bits =3D pix_buf; + chunk.src.y =3D 0; + chunk.src_stride =3D ATI_HOST_DATA_ACC_BITS * bypp; + + /* Blit one scanline chunk at a time */ + row =3D s->host_data.row; + col =3D s->host_data.col; + idx =3D 0; + DPRINTF("blt %dpx @ row: %d, col: %d\n", pix_count, row, col); + while (idx < pix_count && row < ctx.dst.height) { + unsigned pix_in_scanline =3D MIN(pix_count - idx, + ctx.dst.width - col); + chunk.src.x =3D idx; + /* Build a rect for this scanline chunk */ + chunk.dst.x =3D ctx.dst.x + col; + chunk.dst.y =3D ctx.dst.y + row; + chunk.dst.width =3D pix_in_scanline; + chunk.dst.height =3D 1; + DPRINTF("blt %dpx span @ row: %d, col: %d to dst (%d,%d)\n", + pix_in_scanline, row, col, chunk.dst.x, chunk.dst.y); + if (ati_2d_do_blt(&chunk, s->use_pixman)) { + ati_set_dirty(&s->vga, &chunk); + } + idx +=3D pix_in_scanline; + col +=3D pix_in_scanline; + if (col >=3D ctx.dst.width) { + col =3D 0; + row +=3D 1; + } + } + + /* Track state of the overall blit for use by the next flush */ + s->host_data.next =3D 0; + s->host_data.row =3D row; + s->host_data.col =3D col; + if (s->host_data.row >=3D ctx.dst.height) { + s->host_data.active =3D false; + } + + return s->host_data.active; +} + +void ati_host_data_finish(ATIVGAState *s) +{ + if (ati_host_data_flush(s)) { + qemu_log_mask(LOG_GUEST_ERROR, + "HOST_DATA blit ended before all data was written\n"= ); + } + s->host_data.active =3D false; +} diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h index 063efc7bba..21b74511e0 100644 --- a/hw/display/ati_int.h +++ b/hw/display/ati_int.h @@ -33,6 +33,7 @@ =20 #define ATI_RAGE128_LINEAR_APER_SIZE (64 * MiB) #define ATI_R100_LINEAR_APER_SIZE (128 * MiB) +#define ATI_HOST_DATA_ACC_BITS 128 =20 #define TYPE_ATI_VGA "ati-vga" OBJECT_DECLARE_SIMPLE_TYPE(ATIVGAState, ATI_VGA) @@ -128,5 +129,7 @@ struct ATIVGAState { const char *ati_reg_name(int num); =20 void ati_2d_blt(ATIVGAState *s); +bool ati_host_data_flush(ATIVGAState *s); +void ati_host_data_finish(ATIVGAState *s); =20 #endif /* ATI_INT_H */ diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h index 48f15e9b1d..b813fa119e 100644 --- a/hw/display/ati_regs.h +++ b/hw/display/ati_regs.h @@ -397,7 +397,11 @@ #define DST_32BPP 0x00000006 #define DP_DST_DATATYPE 0x0000000f #define DP_BRUSH_DATATYPE 0x00000f00 +#define SRC_MONO_FRGD_BKGD 0x00000000 +#define SRC_MONO_FRGD 0x00010000 +#define SRC_COLOR 0x00030000 #define DP_SRC_DATATYPE 0x00030000 +#define DP_BYTE_PIX_ORDER 0x40000000 =20 #define BRUSH_SOLIDCOLOR 0x00000d00 =20 --=20 2.41.3