bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 1 | /* |
| 2 | * QEMU Cirrus CLGD 54xx VGA Emulator. |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 4 | * Copyright (c) 2004 Fabrice Bellard |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 5 | * |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | * of this software and associated documentation files (the "Software"), to deal |
| 8 | * in the Software without restriction, including without limitation the rights |
| 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 10 | * copies of the Software, and to permit persons to whom the Software is |
| 11 | * furnished to do so, subject to the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice shall be included in |
| 14 | * all copies or substantial portions of the Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 22 | * THE SOFTWARE. |
| 23 | */ |
| 24 | |
| 25 | #if DEPTH == 8 |
Blue Swirl | 8c78881 | 2010-10-13 18:38:07 +0000 | [diff] [blame] | 26 | #define PUTPIXEL() ROP_OP(&d[0], col) |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 27 | #elif DEPTH == 16 |
Blue Swirl | 8c78881 | 2010-10-13 18:38:07 +0000 | [diff] [blame] | 28 | #define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 29 | #elif DEPTH == 24 |
Blue Swirl | 8c78881 | 2010-10-13 18:38:07 +0000 | [diff] [blame] | 30 | #define PUTPIXEL() ROP_OP(&d[0], col); \ |
| 31 | ROP_OP(&d[1], (col >> 8)); \ |
| 32 | ROP_OP(&d[2], (col >> 16)) |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 33 | #elif DEPTH == 32 |
Blue Swirl | 8c78881 | 2010-10-13 18:38:07 +0000 | [diff] [blame] | 34 | #define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 35 | #else |
| 36 | #error unsupported DEPTH |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 37 | #endif |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 38 | |
bellard | e69390c | 2004-06-09 23:12:09 +0000 | [diff] [blame] | 39 | static void |
| 40 | glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) |
| 41 | (CirrusVGAState * s, uint8_t * dst, |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 42 | const uint8_t * src, |
| 43 | int dstpitch, int srcpitch, |
bellard | e69390c | 2004-06-09 23:12:09 +0000 | [diff] [blame] | 44 | int bltwidth, int bltheight) |
| 45 | { |
| 46 | uint8_t *d; |
| 47 | int x, y, pattern_y, pattern_pitch, pattern_x; |
| 48 | unsigned int col; |
| 49 | const uint8_t *src1; |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 50 | #if DEPTH == 24 |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 51 | int skipleft = s->vga.gr[0x2f] & 0x1f; |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 52 | #else |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 53 | int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8); |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 54 | #endif |
bellard | e69390c | 2004-06-09 23:12:09 +0000 | [diff] [blame] | 55 | |
| 56 | #if DEPTH == 8 |
| 57 | pattern_pitch = 8; |
| 58 | #elif DEPTH == 16 |
| 59 | pattern_pitch = 16; |
| 60 | #else |
| 61 | pattern_pitch = 32; |
| 62 | #endif |
| 63 | pattern_y = s->cirrus_blt_srcaddr & 7; |
bellard | e69390c | 2004-06-09 23:12:09 +0000 | [diff] [blame] | 64 | for(y = 0; y < bltheight; y++) { |
bellard | 2f636b4 | 2005-07-02 20:12:37 +0000 | [diff] [blame] | 65 | pattern_x = skipleft; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 66 | d = dst + skipleft; |
bellard | e69390c | 2004-06-09 23:12:09 +0000 | [diff] [blame] | 67 | src1 = src + pattern_y * pattern_pitch; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 68 | for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { |
bellard | e69390c | 2004-06-09 23:12:09 +0000 | [diff] [blame] | 69 | #if DEPTH == 8 |
| 70 | col = src1[pattern_x]; |
| 71 | pattern_x = (pattern_x + 1) & 7; |
| 72 | #elif DEPTH == 16 |
| 73 | col = ((uint16_t *)(src1 + pattern_x))[0]; |
| 74 | pattern_x = (pattern_x + 2) & 15; |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 75 | #elif DEPTH == 24 |
| 76 | { |
| 77 | const uint8_t *src2 = src1 + pattern_x * 3; |
| 78 | col = src2[0] | (src2[1] << 8) | (src2[2] << 16); |
| 79 | pattern_x = (pattern_x + 1) & 7; |
| 80 | } |
bellard | e69390c | 2004-06-09 23:12:09 +0000 | [diff] [blame] | 81 | #else |
| 82 | col = ((uint32_t *)(src1 + pattern_x))[0]; |
| 83 | pattern_x = (pattern_x + 4) & 31; |
| 84 | #endif |
| 85 | PUTPIXEL(); |
| 86 | d += (DEPTH / 8); |
| 87 | } |
| 88 | pattern_y = (pattern_y + 1) & 7; |
| 89 | dst += dstpitch; |
| 90 | } |
| 91 | } |
| 92 | |
bellard | 4c8732d | 2004-06-07 19:46:45 +0000 | [diff] [blame] | 93 | /* NOTE: srcpitch is ignored */ |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 94 | static void |
| 95 | glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) |
| 96 | (CirrusVGAState * s, uint8_t * dst, |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 97 | const uint8_t * src, |
| 98 | int dstpitch, int srcpitch, |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 99 | int bltwidth, int bltheight) |
| 100 | { |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 101 | uint8_t *d; |
| 102 | int x, y; |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 103 | unsigned bits, bits_xor; |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 104 | unsigned int col; |
| 105 | unsigned bitmask; |
| 106 | unsigned index; |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 107 | #if DEPTH == 24 |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 108 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 109 | int srcskipleft = dstskipleft / 3; |
| 110 | #else |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 111 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 112 | int dstskipleft = srcskipleft * (DEPTH / 8); |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 113 | #endif |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 114 | |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 115 | if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { |
| 116 | bits_xor = 0xff; |
| 117 | col = s->cirrus_blt_bgcol; |
| 118 | } else { |
| 119 | bits_xor = 0x00; |
| 120 | col = s->cirrus_blt_fgcol; |
| 121 | } |
| 122 | |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 123 | for(y = 0; y < bltheight; y++) { |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 124 | bitmask = 0x80 >> srcskipleft; |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 125 | bits = *src++ ^ bits_xor; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 126 | d = dst + dstskipleft; |
| 127 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 128 | if ((bitmask & 0xff) == 0) { |
| 129 | bitmask = 0x80; |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 130 | bits = *src++ ^ bits_xor; |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 131 | } |
| 132 | index = (bits & bitmask); |
| 133 | if (index) { |
| 134 | PUTPIXEL(); |
| 135 | } |
| 136 | d += (DEPTH / 8); |
| 137 | bitmask >>= 1; |
| 138 | } |
bellard | 4c8732d | 2004-06-07 19:46:45 +0000 | [diff] [blame] | 139 | dst += dstpitch; |
| 140 | } |
| 141 | } |
| 142 | |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 143 | static void |
| 144 | glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) |
| 145 | (CirrusVGAState * s, uint8_t * dst, |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 146 | const uint8_t * src, |
| 147 | int dstpitch, int srcpitch, |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 148 | int bltwidth, int bltheight) |
| 149 | { |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 150 | uint32_t colors[2]; |
| 151 | uint8_t *d; |
| 152 | int x, y; |
| 153 | unsigned bits; |
| 154 | unsigned int col; |
| 155 | unsigned bitmask; |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 156 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 157 | int dstskipleft = srcskipleft * (DEPTH / 8); |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 158 | |
| 159 | colors[0] = s->cirrus_blt_bgcol; |
| 160 | colors[1] = s->cirrus_blt_fgcol; |
| 161 | for(y = 0; y < bltheight; y++) { |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 162 | bitmask = 0x80 >> srcskipleft; |
| 163 | bits = *src++; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 164 | d = dst + dstskipleft; |
| 165 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 166 | if ((bitmask & 0xff) == 0) { |
| 167 | bitmask = 0x80; |
| 168 | bits = *src++; |
| 169 | } |
| 170 | col = colors[!!(bits & bitmask)]; |
| 171 | PUTPIXEL(); |
| 172 | d += (DEPTH / 8); |
| 173 | bitmask >>= 1; |
| 174 | } |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 175 | dst += dstpitch; |
| 176 | } |
| 177 | } |
| 178 | |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 179 | static void |
| 180 | glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) |
| 181 | (CirrusVGAState * s, uint8_t * dst, |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 182 | const uint8_t * src, |
| 183 | int dstpitch, int srcpitch, |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 184 | int bltwidth, int bltheight) |
| 185 | { |
| 186 | uint8_t *d; |
| 187 | int x, y, bitpos, pattern_y; |
| 188 | unsigned int bits, bits_xor; |
| 189 | unsigned int col; |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 190 | #if DEPTH == 24 |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 191 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 192 | int srcskipleft = dstskipleft / 3; |
| 193 | #else |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 194 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 195 | int dstskipleft = srcskipleft * (DEPTH / 8); |
bellard | ad81218 | 2005-04-26 20:49:17 +0000 | [diff] [blame] | 196 | #endif |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 197 | |
| 198 | if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { |
| 199 | bits_xor = 0xff; |
| 200 | col = s->cirrus_blt_bgcol; |
| 201 | } else { |
| 202 | bits_xor = 0x00; |
| 203 | col = s->cirrus_blt_fgcol; |
| 204 | } |
| 205 | pattern_y = s->cirrus_blt_srcaddr & 7; |
| 206 | |
| 207 | for(y = 0; y < bltheight; y++) { |
| 208 | bits = src[pattern_y] ^ bits_xor; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 209 | bitpos = 7 - srcskipleft; |
| 210 | d = dst + dstskipleft; |
| 211 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 212 | if ((bits >> bitpos) & 1) { |
| 213 | PUTPIXEL(); |
| 214 | } |
| 215 | d += (DEPTH / 8); |
| 216 | bitpos = (bitpos - 1) & 7; |
| 217 | } |
| 218 | pattern_y = (pattern_y + 1) & 7; |
| 219 | dst += dstpitch; |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | static void |
| 224 | glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) |
| 225 | (CirrusVGAState * s, uint8_t * dst, |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 226 | const uint8_t * src, |
| 227 | int dstpitch, int srcpitch, |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 228 | int bltwidth, int bltheight) |
| 229 | { |
| 230 | uint32_t colors[2]; |
| 231 | uint8_t *d; |
| 232 | int x, y, bitpos, pattern_y; |
| 233 | unsigned int bits; |
| 234 | unsigned int col; |
Avi Kivity | 4e12cd9 | 2009-05-03 22:25:16 +0300 | [diff] [blame] | 235 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 236 | int dstskipleft = srcskipleft * (DEPTH / 8); |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 237 | |
| 238 | colors[0] = s->cirrus_blt_bgcol; |
| 239 | colors[1] = s->cirrus_blt_fgcol; |
| 240 | pattern_y = s->cirrus_blt_srcaddr & 7; |
| 241 | |
| 242 | for(y = 0; y < bltheight; y++) { |
| 243 | bits = src[pattern_y]; |
bellard | e3a4e4b | 2005-04-17 17:56:18 +0000 | [diff] [blame] | 244 | bitpos = 7 - srcskipleft; |
| 245 | d = dst + dstskipleft; |
| 246 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
bellard | b30d460 | 2004-07-06 01:50:49 +0000 | [diff] [blame] | 247 | col = colors[(bits >> bitpos) & 1]; |
| 248 | PUTPIXEL(); |
| 249 | d += (DEPTH / 8); |
| 250 | bitpos = (bitpos - 1) & 7; |
| 251 | } |
| 252 | pattern_y = (pattern_y + 1) & 7; |
| 253 | dst += dstpitch; |
| 254 | } |
| 255 | } |
| 256 | |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 257 | static void |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 258 | glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) |
| 259 | (CirrusVGAState *s, |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 260 | uint8_t *dst, int dst_pitch, |
bellard | a508231 | 2004-06-06 15:16:19 +0000 | [diff] [blame] | 261 | int width, int height) |
| 262 | { |
| 263 | uint8_t *d, *d1; |
| 264 | uint32_t col; |
| 265 | int x, y; |
| 266 | |
| 267 | col = s->cirrus_blt_fgcol; |
| 268 | |
| 269 | d1 = dst; |
| 270 | for(y = 0; y < height; y++) { |
| 271 | d = d1; |
| 272 | for(x = 0; x < width; x += (DEPTH / 8)) { |
| 273 | PUTPIXEL(); |
| 274 | d += (DEPTH / 8); |
| 275 | } |
| 276 | d1 += dst_pitch; |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | #undef DEPTH |
| 281 | #undef PUTPIXEL |