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. This also includes a very minor refactor of the combined default_sc_bottom_right field in the registers struct to default_sc_bottom and default_sc_right. This was done to stay consistent with the other scissor registers and prevent repeated masking and extraction. Signed-off-by: Chad Jablonski <[email protected]> Reviewed-by: BALATON Zoltan <[email protected]> --- v5: Removed unused default_sc_bottom_right field --- hw/display/ati.c | 70 +++++++++++++++++++++++++++++++++++++++++-- hw/display/ati_int.h | 9 +++++- hw/display/ati_regs.h | 2 ++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/hw/display/ati.c b/hw/display/ati.c index 968ee4efca..21339d7e26 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -521,7 +521,32 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size) val |= s->regs.default_tile << 16; break; case DEFAULT_SC_BOTTOM_RIGHT: - val = s->regs.default_sc_bottom_right; + val = (s->regs.default_sc_bottom << 16) | + s->regs.default_sc_right; + break; + case SC_TOP: + val = s->regs.sc_top; + break; + case SC_LEFT: + val = s->regs.sc_left; + break; + case SC_BOTTOM: + val = s->regs.sc_bottom; + break; + case SC_RIGHT: + val = s->regs.sc_right; + break; + case SRC_SC_BOTTOM: + val = s->regs.src_sc_bottom; + break; + case SRC_SC_RIGHT: + val = s->regs.src_sc_right; + break; + case SC_TOP_LEFT: + case SC_BOTTOM_RIGHT: + case SRC_SC_BOTTOM_RIGHT: + qemu_log_mask(LOG_GUEST_ERROR, + "Read from write-only register 0x%x\n", (unsigned)addr); break; default: break; @@ -884,6 +909,16 @@ static void ati_mm_write(void *opaque, hwaddr addr, 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: s->regs.dst_x = data & 0x3fff; @@ -963,7 +998,38 @@ static void ati_mm_write(void *opaque, hwaddr addr, } break; case DEFAULT_SC_BOTTOM_RIGHT: - s->regs.default_sc_bottom_right = data & 0x3fff3fff; + s->regs.default_sc_right = data & 0x3fff; + s->regs.default_sc_bottom = (data >> 16) & 0x3fff; + break; + case SC_TOP_LEFT: + s->regs.sc_left = data & 0x3fff; + s->regs.sc_top = (data >> 16) & 0x3fff; + break; + case SC_LEFT: + s->regs.sc_left = data & 0x3fff; + break; + case SC_TOP: + s->regs.sc_top = data & 0x3fff; + break; + case SC_BOTTOM_RIGHT: + s->regs.sc_right = data & 0x3fff; + s->regs.sc_bottom = (data >> 16) & 0x3fff; + break; + case SC_RIGHT: + s->regs.sc_right = data & 0x3fff; + break; + case SC_BOTTOM: + s->regs.sc_bottom = data & 0x3fff; + break; + case SRC_SC_BOTTOM_RIGHT: + s->regs.src_sc_right = data & 0x3fff; + s->regs.src_sc_bottom = (data >> 16) & 0x3fff; + break; + case SRC_SC_RIGHT: + s->regs.src_sc_right = data & 0x3fff; + break; + case SRC_SC_BOTTOM: + s->regs.src_sc_bottom = data & 0x3fff; break; default: break; diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h index f5a47b82b0..7cf0933fa1 100644 --- a/hw/display/ati_int.h +++ b/hw/display/ati_int.h @@ -81,7 +81,14 @@ typedef struct ATIVGARegs { uint32_t default_offset; uint32_t default_pitch; uint32_t default_tile; - uint32_t default_sc_bottom_right; + uint16_t default_sc_bottom; + uint16_t default_sc_right; + uint16_t sc_top; + uint16_t sc_left; + uint16_t sc_bottom; + uint16_t sc_right; + uint16_t src_sc_bottom; + uint16_t src_sc_right; } ATIVGARegs; struct ATIVGAState { diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h index 0a0825db04..3999edb9b7 100644 --- a/hw/display/ati_regs.h +++ b/hw/display/ati_regs.h @@ -397,6 +397,8 @@ #define GMC_DST_PITCH_OFFSET_CNTL 0x00000002 #define GMC_SRC_CLIP_DEFAULT 0x00000000 #define GMC_DST_CLIP_DEFAULT 0x00000000 +#define GMC_SRC_CLIPPING 0x00000004 +#define GMC_DST_CLIPPING 0x00000008 #define GMC_BRUSH_SOLIDCOLOR 0x000000d0 #define GMC_SRC_DSTCOLOR 0x00003000 #define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000 -- 2.51.2
