cirrus blitter fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@907 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index f0b22e7..55a866a 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -136,6 +136,7 @@
 
 // control 0x33
 #define CIRRUS_BLTMODEEXT_SOLIDFILL        0x04
+#define CIRRUS_BLTMODEEXT_COLOREXPINV      0x02
 #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
 
 // memory-mapped IO
@@ -325,7 +326,7 @@
 #include "cirrus_vga_rop.h"
 
 #define ROP_NAME 1
-#define ROP_OP(d, s) d = 0xff
+#define ROP_OP(d, s) d = ~0
 #include "cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_and_dst
@@ -435,6 +436,25 @@
     ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
 };
 
+static const cirrus_bitblt_rop_t cirrus_colorexpand_transp_inv[16][4] = {
+    ROP2(cirrus_colorexpand_transp_inv_0),
+    ROP2(cirrus_colorexpand_transp_inv_src_and_dst),
+    ROP_NOP2(cirrus_bitblt_rop_nop),
+    ROP2(cirrus_colorexpand_transp_inv_src_and_notdst),
+    ROP2(cirrus_colorexpand_transp_inv_notdst),
+    ROP2(cirrus_colorexpand_transp_inv_src),
+    ROP2(cirrus_colorexpand_transp_inv_1),
+    ROP2(cirrus_colorexpand_transp_inv_notsrc_and_dst),
+    ROP2(cirrus_colorexpand_transp_inv_src_xor_dst),
+    ROP2(cirrus_colorexpand_transp_inv_src_or_dst),
+    ROP2(cirrus_colorexpand_transp_inv_notsrc_or_notdst),
+    ROP2(cirrus_colorexpand_transp_inv_src_notxor_dst),
+    ROP2(cirrus_colorexpand_transp_inv_src_or_notdst),
+    ROP2(cirrus_colorexpand_transp_inv_notsrc),
+    ROP2(cirrus_colorexpand_transp_inv_notsrc_or_dst),
+    ROP2(cirrus_colorexpand_transp_inv_notsrc_and_notdst),
+};
+
 static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
     ROP2(cirrus_colorexpand_0),
     ROP2(cirrus_colorexpand_src_and_dst),
@@ -820,8 +840,13 @@
             CIRRUS_BLTMODE_COLOREXPAND) {
 
             if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
-                cirrus_bitblt_fgcol(s);
-                s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+                if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
+                    cirrus_bitblt_bgcol(s);
+                    s->cirrus_rop = cirrus_colorexpand_transp_inv[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+                } else {
+                    cirrus_bitblt_fgcol(s);
+                    s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+                }
             } else {
                 cirrus_bitblt_fgcol(s);
                 cirrus_bitblt_bgcol(s);
diff --git a/hw/cirrus_vga_rop2.h b/hw/cirrus_vga_rop2.h
index 6826627..c7514d3 100644
--- a/hw/cirrus_vga_rop2.h
+++ b/hw/cirrus_vga_rop2.h
@@ -36,14 +36,14 @@
 #error unsupported DEPTH
 #endif                
 
+/* NOTE: srcpitch is ignored */
 static void
 glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
      (CirrusVGAState * s, uint8_t * dst,
-      const uint8_t * src1, 
+      const uint8_t * src, 
       int dstpitch, int srcpitch, 
       int bltwidth, int bltheight)
 {
-    const uint8_t *src;
     uint8_t *d;
     int x, y;
     unsigned bits;
@@ -54,7 +54,6 @@
 
     col = s->cirrus_blt_fgcol;
     for(y = 0; y < bltheight; y++) {
-        src = src1;
         bitmask = 0x80 >> srcskipleft;
         bits = *src++;
         d = dst;
@@ -70,7 +69,43 @@
             d += (DEPTH / 8);
             bitmask >>= 1;
         }
-        src1 += srcpitch;
+        dst += dstpitch;
+    }
+}
+
+/* NOTE: srcpitch is ignored */
+static void
+glue(glue(glue(cirrus_colorexpand_transp_inv_, ROP_NAME), _),DEPTH)
+     (CirrusVGAState * s, uint8_t * dst,
+      const uint8_t * src, 
+      int dstpitch, int srcpitch, 
+      int bltwidth, int bltheight)
+{
+    uint8_t *d;
+    int x, y;
+    unsigned bits;
+    unsigned int col;
+    unsigned bitmask;
+    unsigned index;
+    int srcskipleft = 0;
+
+    col = s->cirrus_blt_bgcol;
+    for(y = 0; y < bltheight; y++) {
+        bitmask = 0x80 >> srcskipleft;
+        bits = *src++;
+        d = dst;
+        for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
+            if ((bitmask & 0xff) == 0) {
+                bitmask = 0x80;
+                bits = *src++;
+            }
+            index = (bits & bitmask);
+            if (!index) {
+                PUTPIXEL();
+            }
+            d += (DEPTH / 8);
+            bitmask >>= 1;
+        }
         dst += dstpitch;
     }
 }
@@ -78,11 +113,10 @@
 static void
 glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
      (CirrusVGAState * s, uint8_t * dst,
-      const uint8_t * src1, 
+      const uint8_t * src, 
       int dstpitch, int srcpitch, 
       int bltwidth, int bltheight)
 {
-    const uint8_t *src;
     uint32_t colors[2];
     uint8_t *d;
     int x, y;
@@ -94,7 +128,6 @@
     colors[0] = s->cirrus_blt_bgcol;
     colors[1] = s->cirrus_blt_fgcol;
     for(y = 0; y < bltheight; y++) {
-        src = src1;
         bitmask = 0x80 >> srcskipleft;
         bits = *src++;
         d = dst;
@@ -108,7 +141,6 @@
             d += (DEPTH / 8);
             bitmask >>= 1;
         }
-        src1 += srcpitch;
         dst += dstpitch;
     }
 }