cirrus_invalidate_region() calls memory_region_set_dirty() on a per-line basis, always ranging from off_begin to off_begin+bytesperline. With a negative pitch off_begin marks the top most used address and thus we need to do an initial shift backwards by bytesperline for negative pitches of backward blits, otherwise the first iteration covers the line going from the start offset forwards instead of backwards.
Signed-off-by: Wolfgang Bumiller <w.bumil...@proxmox.com> --- I bumped the patch context to 4 lines to get it to include the memory_region_set_dirty() call which takes an unsigned length (`hwaddr size`) because I'm also not too happy about the masking going on there since it means off_cur_end may be less than off_cur, but if the range checks are finnaly correct I don't think this case could happen anymore? (A check shouldn't hurt though, or maybe an assert()?) hw/display/cirrus_vga.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index b1a0773..af61981 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -669,8 +669,12 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, int y; int off_cur; int off_cur_end; + if (off_pitch < 0) { + off_begin -= bytesperline; + } + for (y = 0; y < lines; y++) { off_cur = off_begin; off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask; memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur); -- 2.1.4