diff options
| author | ShengYi Hung <aokblast@FreeBSD.org> | 2026-06-24 14:31:03 +0000 |
|---|---|---|
| committer | ShengYi Hung <aokblast@FreeBSD.org> | 2026-06-30 19:52:55 +0000 |
| commit | 76aa776b5f47ecd0d45336e22795fef98af57d2f (patch) | |
| tree | a52f2a6815cee5117e6ca948c8d0ccf24adb4685 | |
| parent | eca26803d880060555393ab89b44b967cd467a0e (diff) | |
stand: Fix shadow buffer offset handling
The shadow buffer is addressed relative to `tg_origin`, which includes
the padding offset, whereas `gfxfb_blt` operates on coordinates without
that offset. To make `gfx_fb_copy_area` emulate the behavior of
`gfxfb_blt`, the source coordinates must include the padding offset,
while the destination coordinates must not. The original implementation
omitted the offset from the source coordinates; this change corrects
that.
Additionally, `gfx_fb_cons_display` already applies the padding offset,
so the redundant adjustment is removed.
PR: 296246
Reported by: 2khramtsov@gmail.com
Reviewed by: imp
Tested by: 2khramtsov@gmail.com, junchoon@dec.sakura.ne.jp,
naito.yuichiro_@gmail.com
Fixes: 32da2f23ae4d
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D57821
| -rw-r--r-- | stand/common/gfx_fb.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/stand/common/gfx_fb.c b/stand/common/gfx_fb.c index 7ed0cf6bdb39..8185afccf944 100644 --- a/stand/common/gfx_fb.c +++ b/stand/common/gfx_fb.c @@ -1400,26 +1400,32 @@ gfx_fb_copy_area(teken_gfx_t *state, const teken_rect_t *s, pitch = state->tg_fb.fb_width; bytes = width * sizeof (*state->tg_shadow_fb); - uint32_t dst_x = dx + state->tg_origin.tp_col; - uint32_t dst_y = dy + state->tg_origin.tp_row; + uint32_t ssx = sx + state->tg_origin.tp_col; + uint32_t ssy = sy + state->tg_origin.tp_row; + uint32_t dsx = dx + state->tg_origin.tp_col; + uint32_t dsy = dy + state->tg_origin.tp_row; + uint32_t dst_x = dsx; + uint32_t dst_y = dsy; uint32_t dst_h = height; /* * To handle overlapping areas, set up reverse copy here. + * The origin offset cancels out in the comparison so the + * terminal-relative form is equivalent. */ if (dy * pitch + dx > sy * pitch + sx) { - sy += height; - dy += height; + ssy += height; + dsy += height; step = -step; } while (height-- > 0) { - uint32_t *source = &state->tg_shadow_fb[sy * pitch + sx]; - uint32_t *destination = &state->tg_shadow_fb[dy * pitch + dx]; + uint32_t *source = &state->tg_shadow_fb[ssy * pitch + ssx]; + uint32_t *destination = &state->tg_shadow_fb[dsy * pitch + dsx]; bcopy(source, destination, bytes); - sy += step; - dy += step; + ssy += step; + dsy += step; } gfx_shadow_mark_dirty(dst_x, dst_y, width, dst_h); @@ -1618,13 +1624,11 @@ gfx_fb_cons_display(uint32_t x, uint32_t y, uint32_t width, uint32_t height, */ if (gfx_state.tg_shadow_fb != NULL) { uint32_t pitch = gfx_state.tg_fb.fb_width; - uint32_t sy = y - gfx_state.tg_origin.tp_row; - uint32_t sx = x - gfx_state.tg_origin.tp_col; p = data; for (uint32_t row = 0; row < height; row++) { buf = (void *)(gfx_state.tg_shadow_fb + - (sy + row) * pitch + sx); + (y + row) * pitch + x); bitmap_cpy(buf, &p[row * width], width); } gfx_shadow_mark_dirty(x, y, width, height); |
