On Sun, 2 Nov 2025, Chad Jablonski wrote:
Implement read and write operations on SC_TOP_LEFT, SC_BOTTOM_RIGHT,
and SRC_SC_BOTTOM_RIGHT registers. These registers are also updated
when the src and/or dst clipping fields on DP_GUI_MASTER_CNTL are set
to default clipping.
Scissor clipping is used when rendering text in X.org. The r128 driver
sends host data much wider than is necessary to draw a glyph and cuts it
down to size using clipping before rendering. The actual clipping
implementation follows in a future patch.
Signed-off-by: Chad Jablonski <[email protected]>
---
hw/display/ati.c | 26 ++++++++++++++++++++++++++
hw/display/ati_int.h | 3 +++
hw/display/ati_regs.h | 12 ++++++++++--
3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/hw/display/ati.c b/hw/display/ati.c
index 0b4298d078..eb9b30672f 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -510,6 +510,15 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr,
unsigned int size)
case DEFAULT_SC_BOTTOM_RIGHT:
val = s->regs.default_sc_bottom_right;
break;
+ case SC_TOP_LEFT:
+ val = s->regs.sc_top_left;
+ break;
+ case SC_BOTTOM_RIGHT:
+ val = s->regs.sc_bottom_right;
+ break;
+ case SRC_SC_BOTTOM_RIGHT:
+ val = s->regs.src_sc_bottom_right;
+ break;
default:
break;
}
@@ -862,6 +871,14 @@ static void ati_mm_write(void *opaque, hwaddr addr,
s->regs.dp_datatype = (data & 0x0f00) >> 8 | (data & 0x30f0) << 4 |
(data & 0x4000) << 16;
s->regs.dp_mix = (data & GMC_ROP3_MASK) | (data & 0x7000000) >> 16;
+
+ if ((data & GMC_SRC_CLIPPING_MASK) == GMC_SRC_CLIP_DEFAULT) {
+ s->regs.src_sc_bottom_right = s->regs.default_sc_bottom_right;
+ }
+ if ((data & GMC_DST_CLIPPING_MASK) == GMC_DST_CLIP_DEFAULT) {
+ s->regs.sc_top_left = 0;
+ s->regs.sc_bottom_right = s->regs.default_sc_bottom_right;
+ }
Or is this what you meant by style? Now I get that. I think the bits
should not reset the regs just cause the operation to use the default
values instead but if you can verify what actual hardware does that would
be best.
Regards,
BALATON Zoltan
break;
case DST_WIDTH_X:
s->regs.dst_x = data & 0x3fff;
@@ -937,6 +954,15 @@ static void ati_mm_write(void *opaque, hwaddr addr,
case DEFAULT_SC_BOTTOM_RIGHT:
s->regs.default_sc_bottom_right = data & 0x3fff3fff;
break;
+ case SC_TOP_LEFT:
+ s->regs.sc_top_left = data;
+ break;
+ case SC_BOTTOM_RIGHT:
+ s->regs.sc_bottom_right = data;
+ break;
+ case SRC_SC_BOTTOM_RIGHT:
+ s->regs.src_sc_bottom_right = data;
+ break;
default:
break;
}
diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h
index 708cc1dd3a..aab3cbf81a 100644
--- a/hw/display/ati_int.h
+++ b/hw/display/ati_int.h
@@ -86,6 +86,9 @@ typedef struct ATIVGARegs {
uint32_t default_pitch;
uint32_t default_tile;
uint32_t default_sc_bottom_right;
+ uint32_t sc_top_left;
+ uint32_t sc_bottom_right;
+ uint32_t src_sc_bottom_right;
} ATIVGARegs;
struct ATIVGAState {
diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h
index d7127748ff..2b56b9fb66 100644
--- a/hw/display/ati_regs.h
+++ b/hw/display/ati_regs.h
@@ -392,8 +392,6 @@
/* DP_GUI_MASTER_CNTL bit constants */
#define GMC_SRC_PITCH_OFFSET_CNTL 0x00000001
#define GMC_DST_PITCH_OFFSET_CNTL 0x00000002
-#define GMC_SRC_CLIP_DEFAULT 0x00000000
-#define GMC_DST_CLIP_DEFAULT 0x00000000
#define GMC_BRUSH_SOLIDCOLOR 0x000000d0
#define GMC_SRC_DSTCOLOR 0x00003000
#define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000
@@ -404,6 +402,16 @@
#define GMC_WRITE_MASK_SET 0x40000000
#define GMC_DP_CONVERSION_TEMP_6500 0x00000000
+/* DP_GUI_MASTER_CNTL DP_SRC_CLIPPING named constants */
+#define GMC_SRC_CLIPPING_MASK 0x00000004
+#define GMC_SRC_CLIP_DEFAULT 0x00000000
+#define GMC_SRC_CLIP_LEAVE_ALONE 0x00000004
+
+/* DP_GUI_MASTER_CNTL DP_DST_CLIPPING named constants */
+#define GMC_DST_CLIPPING_MASK 0x00000008
+#define GMC_DST_CLIP_DEFAULT 0x00000000
+#define GMC_DST_CLIP_LEAVE_ALONE 0x00000008
+
/* DP_GUI_MASTER_CNTL ROP3 named constants */
#define GMC_ROP3_MASK 0x00ff0000
#define ROP3_BLACKNESS 0x00000000