Skip to content

Commit 9982c60

Browse files
zbalatonkraxel
authored andcommitted
sm501: Fix and optimize overlap check
When doing reverse blit we need to check if source and dest overlap but it is not trivial due to possible different base and pitch of source and dest. Do rectangle overlap if base and pitch match, otherwise just check if memory area containing the rects overlaps so rects could possibly overlap. Signed-off-by: BALATON Zoltan <[email protected]> Message-Id: <[email protected]> Reviewed-by: Peter Maydell <[email protected]> Signed-off-by: Gerd Hoffmann <[email protected]>
1 parent d8327a6 commit 9982c60

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

hw/display/sm501.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,7 @@ static void sm501_2d_operation(SM501State *s)
690690
unsigned int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF;
691691
int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0;
692692
int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt);
693+
bool overlap = false;
693694

694695
if ((s->twoD_stretch >> 16) & 0xF) {
695696
qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n");
@@ -784,16 +785,21 @@ static void sm501_2d_operation(SM501State *s)
784785
ldn_he_p(&s->local_mem[src_base + si], bypp));
785786
break;
786787
}
787-
/* Check for overlaps, this could be made more exact */
788-
uint32_t sb, se, db, de;
789-
sb = src_base + src_x + src_y * (width + src_pitch);
790-
se = sb + width + height * (width + src_pitch);
791-
db = dst_base + dst_x + dst_y * (width + dst_pitch);
792-
de = db + width + height * (width + dst_pitch);
793-
if (rtl && ((db >= sb && db <= se) || (de >= sb && de <= se))) {
794-
/* regions may overlap: copy via temporary */
795-
int llb = width * bypp;
796-
int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t));
788+
/* If reverse blit do simple check for overlaps */
789+
if (rtl && src_base == dst_base && src_pitch == dst_pitch) {
790+
overlap = (src_x < dst_x + width && src_x + width > dst_x &&
791+
src_y < dst_y + height && src_y + height > dst_y);
792+
} else if (rtl) {
793+
unsigned int sb, se, db, de;
794+
sb = src_base + (src_x + src_y * src_pitch) * bypp;
795+
se = sb + (width + (height - 1) * src_pitch) * bypp;
796+
db = dst_base + (dst_x + dst_y * dst_pitch) * bypp;
797+
de = db + (width + (height - 1) * dst_pitch) * bypp;
798+
overlap = (db < se && sb < de);
799+
}
800+
if (overlap) {
801+
/* pixman can't do reverse blit: copy via temporary */
802+
int tmp_stride = DIV_ROUND_UP(width * bypp, sizeof(uint32_t));
797803
uint32_t *tmp = tmp_buf;
798804

799805
if (tmp_stride * sizeof(uint32_t) * height > sizeof(tmp_buf)) {

0 commit comments

Comments
 (0)