The r128 latches the default values of src/dst clipping, pitch, and
offset when the default flags are set on DP_GUI_MASTER_CNTL. The r100
does not do this and instead uses the default values at blit time without
updating the registers.

Tested and validated against a Rage 128 Pro Ultra (PCI 1002:5446) and
Radeon QY (RV100) (PCI 1002:5159).

Signed-off-by: Chad Jablonski <[email protected]>
---
 hw/display/ati.c    | 36 +++++++++++++++++++-----------------
 hw/display/ati_2d.c | 41 ++++++++++++++++++++++++++++++-----------
 2 files changed, 49 insertions(+), 28 deletions(-)

diff --git a/hw/display/ati.c b/hw/display/ati.c
index db7e08a462..76070d76a7 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -895,23 +895,25 @@ static void ati_mm_write(void *opaque, hwaddr addr,
                               (data & 0x4000) << 16;
         s->regs.dp_mix = (data & GMC_ROP3_MASK) | (data & 0x7000000) >> 16;
 
-        if (!(data & GMC_SRC_PITCH_OFFSET_CNTL)) {
-            s->regs.src_offset = s->regs.default_offset;
-            s->regs.src_pitch = s->regs.default_pitch;
-        }
-        if (!(data & GMC_DST_PITCH_OFFSET_CNTL)) {
-            s->regs.dst_offset = s->regs.default_offset;
-            s->regs.dst_pitch = s->regs.default_pitch;
-        }
-        if (!(data & GMC_SRC_CLIPPING)) {
-            s->regs.src_sc_right = s->regs.default_sc_right;
-            s->regs.src_sc_bottom = s->regs.default_sc_bottom;
-        }
-        if (!(data & GMC_DST_CLIPPING)) {
-            s->regs.sc_top = 0;
-            s->regs.sc_left = 0;
-            s->regs.sc_right = s->regs.default_sc_right;
-            s->regs.sc_bottom = s->regs.default_sc_bottom;
+        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
+            if (!(data & GMC_SRC_PITCH_OFFSET_CNTL)) {
+                s->regs.src_offset = s->regs.default_offset;
+                s->regs.src_pitch = s->regs.default_pitch;
+            }
+            if (!(data & GMC_DST_PITCH_OFFSET_CNTL)) {
+                s->regs.dst_offset = s->regs.default_offset;
+                s->regs.dst_pitch = s->regs.default_pitch;
+            }
+            if (!(data & GMC_SRC_CLIPPING)) {
+                s->regs.src_sc_right = s->regs.default_sc_right;
+                s->regs.src_sc_bottom = s->regs.default_sc_bottom;
+            }
+            if (!(data & GMC_DST_CLIPPING)) {
+                s->regs.sc_top = 0;
+                s->regs.sc_left = 0;
+                s->regs.sc_right = s->regs.default_sc_right;
+                s->regs.sc_bottom = s->regs.default_sc_bottom;
+            }
         }
         break;
     case DST_WIDTH_X:
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index 3b27917bf4..f51ecb747a 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -104,18 +104,26 @@ static void setup_2d_blt_ctx(ATIVGAState *s, ATI2DCtx 
*ctx)
     ctx->top_to_bottom = s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM;
     ctx->need_swap = (HOST_BIG_ENDIAN != s->vga.big_endian_fb);
     ctx->frgd_clr = s->regs.dp_brush_frgd_clr;
-    ctx->dst_offset = s->regs.dst_offset;
 
     if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
         /* r128 scissor values are inclusive */
         ctx->scissor.width = s->regs.sc_right - s->regs.sc_left + 1;
         ctx->scissor.height = s->regs.sc_bottom - s->regs.sc_top + 1;
+        ctx->scissor.x = s->regs.sc_left;
+        ctx->scissor.y = s->regs.sc_top;
     } else {
-        ctx->scissor.width = s->regs.sc_right - s->regs.sc_left;
-        ctx->scissor.height = s->regs.sc_bottom - s->regs.sc_top;
+        if (s->regs.dp_gui_master_cntl & GMC_DST_CLIPPING) {
+            ctx->scissor.x = s->regs.sc_left;
+            ctx->scissor.y = s->regs.sc_top;
+            ctx->scissor.width = s->regs.sc_right - s->regs.sc_left;
+            ctx->scissor.height = s->regs.sc_bottom - s->regs.sc_top;
+        } else {
+            ctx->scissor.x = 0;
+            ctx->scissor.y = 0;
+            ctx->scissor.width = s->regs.default_sc_right;
+            ctx->scissor.height = s->regs.default_sc_bottom;
+        }
     }
-    ctx->scissor.x = s->regs.sc_left;
-    ctx->scissor.y = s->regs.sc_top;
 
     ctx->dst.width = s->regs.dst_width;
     ctx->dst.height = s->regs.dst_height;
@@ -123,20 +131,30 @@ static void setup_2d_blt_ctx(ATIVGAState *s, ATI2DCtx 
*ctx)
                  s->regs.dst_x : s->regs.dst_x + 1 - ctx->dst.width);
     ctx->dst.y = (ctx->top_to_bottom ?
                  s->regs.dst_y : s->regs.dst_y + 1 - ctx->dst.height);
-    ctx->dst_stride = s->regs.dst_pitch;
-    ctx->dst_bits = s->vga.vram_ptr + s->regs.dst_offset;
     if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
-        ctx->dst_stride *= ctx->bpp;
+        ctx->dst_stride = s->regs.dst_pitch * ctx->bpp;
+        ctx->dst_offset = s->regs.dst_offset;
+    } else {
+        ctx->dst_stride = s->regs.dp_gui_master_cntl & 
GMC_DST_PITCH_OFFSET_CNTL
+                          ? s->regs.dst_pitch : s->regs.default_pitch;
+        ctx->dst_offset = s->regs.dp_gui_master_cntl & 
GMC_DST_PITCH_OFFSET_CNTL
+                          ? s->regs.dst_offset : s->regs.default_offset;
     }
+    ctx->dst_bits = s->vga.vram_ptr + ctx->dst_offset;
 
     ctx->src.x = (ctx->left_to_right ?
                  s->regs.src_x : s->regs.src_x + 1 - ctx->dst.width);
     ctx->src.y = (ctx->top_to_bottom ?
                  s->regs.src_y : s->regs.src_y + 1 - ctx->dst.height);
-    ctx->src_stride = s->regs.src_pitch;
-    ctx->src_bits = s->vga.vram_ptr + s->regs.src_offset;
     if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
-        ctx->src_stride *= ctx->bpp;
+        ctx->src_stride = s->regs.src_pitch * ctx->bpp;
+        ctx->src_bits = s->vga.vram_ptr + s->regs.src_offset;
+    } else {
+        ctx->src_stride = s->regs.dp_gui_master_cntl & 
GMC_SRC_PITCH_OFFSET_CNTL
+                          ? s->regs.src_pitch : s->regs.default_pitch;
+        ctx->src_bits = s->vga.vram_ptr +
+                        (s->regs.dp_gui_master_cntl & GMC_SRC_PITCH_OFFSET_CNTL
+                        ? s->regs.src_offset : s->regs.default_offset);
     }
     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,
@@ -181,6 +199,7 @@ static bool ati_2d_do_blt(const ATI2DCtx *ctx, uint8_t 
use_pixman)
     qemu_rect_intersect(&ctx->dst, &ctx->scissor, &vis_dst);
     if (!vis_dst.height || !vis_dst.width) {
         /* Nothing is visible, completely clipped */
+        DPRINTF("entire blt clipped, nothing drawn\n");
         return false;
     }
     /*
-- 
2.54.0


Reply via email to