dfb8478
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
dfb8478
Date: Tue, 24 Jan 2017 16:35:38 +0100
dfb8478
Subject: [PATCH] cirrus: allow zero source pitch in pattern fill rops
dfb8478
dfb8478
The rops used by cirrus_bitblt_common_patterncopy only use
dfb8478
the destination pitch, so the source pitch shoul allowed to
dfb8478
be zero and the blit with used for the range check around the
dfb8478
source address.
dfb8478
dfb8478
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
dfb8478
Message-id: 1485272138-23249-1-git-send-email-w.bumiller@proxmox.com
dfb8478
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
dfb8478
(cherry picked from commit 5858dd1801883309bdd208d72ddb81c4e9fee30c)
dfb8478
---
dfb8478
 hw/display/cirrus_vga.c | 27 +++++++++++++++++++--------
dfb8478
 1 file changed, 19 insertions(+), 8 deletions(-)
dfb8478
dfb8478
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
dfb8478
index 0f05e45..98f089e 100644
dfb8478
--- a/hw/display/cirrus_vga.c
dfb8478
+++ b/hw/display/cirrus_vga.c
dfb8478
@@ -272,9 +272,6 @@ static void cirrus_update_memory_access(CirrusVGAState *s);
dfb8478
 static bool blit_region_is_unsafe(struct CirrusVGAState *s,
dfb8478
                                   int32_t pitch, int32_t addr)
dfb8478
 {
dfb8478
-    if (!pitch) {
dfb8478
-        return true;
dfb8478
-    }
dfb8478
     if (pitch < 0) {
dfb8478
         int64_t min = addr
dfb8478
             + ((int64_t)s->cirrus_blt_height-1) * pitch;
dfb8478
@@ -294,8 +291,11 @@ static bool blit_region_is_unsafe(struct CirrusVGAState *s,
dfb8478
     return false;
dfb8478
 }
dfb8478
 
dfb8478
-static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
dfb8478
+static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only,
dfb8478
+                           bool zero_src_pitch_ok)
dfb8478
 {
dfb8478
+    int32_t check_pitch;
dfb8478
+
dfb8478
     /* should be the case, see cirrus_bitblt_start */
dfb8478
     assert(s->cirrus_blt_width > 0);
dfb8478
     assert(s->cirrus_blt_height > 0);
dfb8478
@@ -304,6 +304,10 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
dfb8478
         return true;
dfb8478
     }
dfb8478
 
dfb8478
+    if (!s->cirrus_blt_dstpitch) {
dfb8478
+        return true;
dfb8478
+    }
dfb8478
+
dfb8478
     if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
dfb8478
                               s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {
dfb8478
         return true;
dfb8478
@@ -311,7 +315,13 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
dfb8478
     if (dst_only) {
dfb8478
         return false;
dfb8478
     }
dfb8478
-    if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
dfb8478
+
dfb8478
+    check_pitch = s->cirrus_blt_srcpitch;
dfb8478
+    if (!zero_src_pitch_ok && !check_pitch) {
dfb8478
+        check_pitch = s->cirrus_blt_width;
dfb8478
+    }
dfb8478
+
dfb8478
+    if (blit_region_is_unsafe(s, check_pitch,
dfb8478
                               s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {
dfb8478
         return true;
dfb8478
     }
dfb8478
@@ -681,8 +691,9 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
dfb8478
 
dfb8478
     dst = s->vga.vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
dfb8478
 
dfb8478
-    if (blit_is_unsafe(s, false))
dfb8478
+    if (blit_is_unsafe(s, false, true)) {
dfb8478
         return 0;
dfb8478
+    }
dfb8478
 
dfb8478
     (*s->cirrus_rop) (s, dst, src,
dfb8478
                       s->cirrus_blt_dstpitch, 0,
dfb8478
@@ -699,7 +710,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
dfb8478
 {
dfb8478
     cirrus_fill_t rop_func;
dfb8478
 
dfb8478
-    if (blit_is_unsafe(s, true)) {
dfb8478
+    if (blit_is_unsafe(s, true, true)) {
dfb8478
         return 0;
dfb8478
     }
dfb8478
     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
dfb8478
@@ -803,7 +814,7 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
dfb8478
 
dfb8478
 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
dfb8478
 {
dfb8478
-    if (blit_is_unsafe(s, false))
dfb8478
+    if (blit_is_unsafe(s, false, false))
dfb8478
         return 0;
dfb8478
 
dfb8478
     return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,