1 /* 2 * QEMU Cirrus CLGD 54xx VGA Emulator. 3 * 4 * Copyright (c) 2004 Fabrice Bellard 5 * 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 26 #define PUTPIXEL() ROP_OP(&d[0], col) 27 #elif DEPTH == 16 28 #define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) 29 #elif DEPTH == 24 30 #define PUTPIXEL() ROP_OP(&d[0], col); \ 31 ROP_OP(&d[1], (col >> 8)); \ 32 ROP_OP(&d[2], (col >> 16)) 33 #elif DEPTH == 32 34 #define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) 35 #else 36 #error unsupported DEPTH 37 #endif 38 39 static void 40 glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) 41 (CirrusVGAState * s, uint8_t * dst, 42 const uint8_t * src, 43 int dstpitch, int srcpitch, 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; 50 #if DEPTH == 24 51 int skipleft = s->vga.gr[0x2f] & 0x1f; 52 #else 53 int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8); 54 #endif 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; 64 for(y = 0; y < bltheight; y++) { 65 pattern_x = skipleft; 66 d = dst + skipleft; 67 src1 = src + pattern_y * pattern_pitch; 68 for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { 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; 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 } 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 93 /* NOTE: srcpitch is ignored */ 94 static void 95 glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) 96 (CirrusVGAState * s, uint8_t * dst, 97 const uint8_t * src, 98 int dstpitch, int srcpitch, 99 int bltwidth, int bltheight) 100 { 101 uint8_t *d; 102 int x, y; 103 unsigned bits, bits_xor; 104 unsigned int col; 105 unsigned bitmask; 106 unsigned index; 107 #if DEPTH == 24 108 int dstskipleft = s->vga.gr[0x2f] & 0x1f; 109 int srcskipleft = dstskipleft / 3; 110 #else 111 int srcskipleft = s->vga.gr[0x2f] & 0x07; 112 int dstskipleft = srcskipleft * (DEPTH / 8); 113 #endif 114 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 123 for(y = 0; y < bltheight; y++) { 124 bitmask = 0x80 >> srcskipleft; 125 bits = *src++ ^ bits_xor; 126 d = dst + dstskipleft; 127 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { 128 if ((bitmask & 0xff) == 0) { 129 bitmask = 0x80; 130 bits = *src++ ^ bits_xor; 131 } 132 index = (bits & bitmask); 133 if (index) { 134 PUTPIXEL(); 135 } 136 d += (DEPTH / 8); 137 bitmask >>= 1; 138 } 139 dst += dstpitch; 140 } 141 } 142 143 static void 144 glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) 145 (CirrusVGAState * s, uint8_t * dst, 146 const uint8_t * src, 147 int dstpitch, int srcpitch, 148 int bltwidth, int bltheight) 149 { 150 uint32_t colors[2]; 151 uint8_t *d; 152 int x, y; 153 unsigned bits; 154 unsigned int col; 155 unsigned bitmask; 156 int srcskipleft = s->vga.gr[0x2f] & 0x07; 157 int dstskipleft = srcskipleft * (DEPTH / 8); 158 159 colors[0] = s->cirrus_blt_bgcol; 160 colors[1] = s->cirrus_blt_fgcol; 161 for(y = 0; y < bltheight; y++) { 162 bitmask = 0x80 >> srcskipleft; 163 bits = *src++; 164 d = dst + dstskipleft; 165 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { 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 } 175 dst += dstpitch; 176 } 177 } 178 179 static void 180 glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) 181 (CirrusVGAState * s, uint8_t * dst, 182 const uint8_t * src, 183 int dstpitch, int srcpitch, 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; 190 #if DEPTH == 24 191 int dstskipleft = s->vga.gr[0x2f] & 0x1f; 192 int srcskipleft = dstskipleft / 3; 193 #else 194 int srcskipleft = s->vga.gr[0x2f] & 0x07; 195 int dstskipleft = srcskipleft * (DEPTH / 8); 196 #endif 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; 209 bitpos = 7 - srcskipleft; 210 d = dst + dstskipleft; 211 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { 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, 226 const uint8_t * src, 227 int dstpitch, int srcpitch, 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; 235 int srcskipleft = s->vga.gr[0x2f] & 0x07; 236 int dstskipleft = srcskipleft * (DEPTH / 8); 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]; 244 bitpos = 7 - srcskipleft; 245 d = dst + dstskipleft; 246 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { 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 257 static void 258 glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) 259 (CirrusVGAState *s, 260 uint8_t *dst, int dst_pitch, 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 282