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
