]>
Commit | Line | Data |
---|---|---|
a5082316 FB |
1 | /* |
2 | * QEMU Cirrus CLGD 54xx VGA Emulator. | |
5fafdf24 | 3 | * |
a5082316 | 4 | * Copyright (c) 2004 Fabrice Bellard |
5fafdf24 | 5 | * |
a5082316 FB |
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 | |
026aeffc | 26 | #define PUTPIXEL(s, a, c) ROP_OP(s, a, c) |
a5082316 | 27 | #elif DEPTH == 16 |
026aeffc | 28 | #define PUTPIXEL(s, a, c) ROP_OP_16(s, a, c) |
a5082316 | 29 | #elif DEPTH == 24 |
026aeffc GH |
30 | #define PUTPIXEL(s, a, c) do { \ |
31 | ROP_OP(s, a, c); \ | |
32 | ROP_OP(s, a + 1, (col >> 8)); \ | |
33 | ROP_OP(s, a + 2, (col >> 16)); \ | |
34 | } while (0) | |
a5082316 | 35 | #elif DEPTH == 32 |
026aeffc | 36 | #define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c) |
a5082316 FB |
37 | #else |
38 | #error unsupported DEPTH | |
3b46e624 | 39 | #endif |
a5082316 | 40 | |
e69390ce FB |
41 | static void |
42 | glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) | |
026aeffc GH |
43 | (CirrusVGAState *s, uint32_t dstaddr, |
44 | const uint8_t *src, | |
5fafdf24 | 45 | int dstpitch, int srcpitch, |
e69390ce FB |
46 | int bltwidth, int bltheight) |
47 | { | |
026aeffc | 48 | uint32_t addr; |
e69390ce FB |
49 | int x, y, pattern_y, pattern_pitch, pattern_x; |
50 | unsigned int col; | |
51 | const uint8_t *src1; | |
ad81218e | 52 | #if DEPTH == 24 |
4e12cd94 | 53 | int skipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e | 54 | #else |
4e12cd94 | 55 | int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8); |
ad81218e | 56 | #endif |
e69390ce FB |
57 | |
58 | #if DEPTH == 8 | |
59 | pattern_pitch = 8; | |
60 | #elif DEPTH == 16 | |
61 | pattern_pitch = 16; | |
62 | #else | |
63 | pattern_pitch = 32; | |
64 | #endif | |
65 | pattern_y = s->cirrus_blt_srcaddr & 7; | |
e69390ce | 66 | for(y = 0; y < bltheight; y++) { |
2f636b45 | 67 | pattern_x = skipleft; |
026aeffc | 68 | addr = dstaddr + skipleft; |
e69390ce | 69 | src1 = src + pattern_y * pattern_pitch; |
e3a4e4b6 | 70 | for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { |
e69390ce FB |
71 | #if DEPTH == 8 |
72 | col = src1[pattern_x]; | |
73 | pattern_x = (pattern_x + 1) & 7; | |
74 | #elif DEPTH == 16 | |
75 | col = ((uint16_t *)(src1 + pattern_x))[0]; | |
76 | pattern_x = (pattern_x + 2) & 15; | |
b30d4608 FB |
77 | #elif DEPTH == 24 |
78 | { | |
79 | const uint8_t *src2 = src1 + pattern_x * 3; | |
80 | col = src2[0] | (src2[1] << 8) | (src2[2] << 16); | |
81 | pattern_x = (pattern_x + 1) & 7; | |
82 | } | |
e69390ce FB |
83 | #else |
84 | col = ((uint32_t *)(src1 + pattern_x))[0]; | |
85 | pattern_x = (pattern_x + 4) & 31; | |
86 | #endif | |
026aeffc GH |
87 | PUTPIXEL(s, addr, col); |
88 | addr += (DEPTH / 8); | |
e69390ce FB |
89 | } |
90 | pattern_y = (pattern_y + 1) & 7; | |
026aeffc | 91 | dstaddr += dstpitch; |
e69390ce FB |
92 | } |
93 | } | |
94 | ||
4c8732d7 | 95 | /* NOTE: srcpitch is ignored */ |
a5082316 FB |
96 | static void |
97 | glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) | |
026aeffc GH |
98 | (CirrusVGAState *s, uint32_t dstaddr, |
99 | const uint8_t *src, | |
5fafdf24 | 100 | int dstpitch, int srcpitch, |
a5082316 FB |
101 | int bltwidth, int bltheight) |
102 | { | |
026aeffc | 103 | uint32_t addr; |
a5082316 | 104 | int x, y; |
b30d4608 | 105 | unsigned bits, bits_xor; |
a5082316 FB |
106 | unsigned int col; |
107 | unsigned bitmask; | |
108 | unsigned index; | |
ad81218e | 109 | #if DEPTH == 24 |
4e12cd94 | 110 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e FB |
111 | int srcskipleft = dstskipleft / 3; |
112 | #else | |
4e12cd94 | 113 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 114 | int dstskipleft = srcskipleft * (DEPTH / 8); |
ad81218e | 115 | #endif |
a5082316 | 116 | |
b30d4608 FB |
117 | if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { |
118 | bits_xor = 0xff; | |
119 | col = s->cirrus_blt_bgcol; | |
120 | } else { | |
121 | bits_xor = 0x00; | |
122 | col = s->cirrus_blt_fgcol; | |
123 | } | |
124 | ||
a5082316 | 125 | for(y = 0; y < bltheight; y++) { |
a5082316 | 126 | bitmask = 0x80 >> srcskipleft; |
b30d4608 | 127 | bits = *src++ ^ bits_xor; |
026aeffc | 128 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 129 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
a5082316 FB |
130 | if ((bitmask & 0xff) == 0) { |
131 | bitmask = 0x80; | |
b30d4608 | 132 | bits = *src++ ^ bits_xor; |
a5082316 FB |
133 | } |
134 | index = (bits & bitmask); | |
135 | if (index) { | |
026aeffc | 136 | PUTPIXEL(s, addr, col); |
a5082316 | 137 | } |
026aeffc | 138 | addr += (DEPTH / 8); |
a5082316 FB |
139 | bitmask >>= 1; |
140 | } | |
026aeffc | 141 | dstaddr += dstpitch; |
4c8732d7 FB |
142 | } |
143 | } | |
144 | ||
4c8732d7 | 145 | static void |
b30d4608 | 146 | glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) |
026aeffc GH |
147 | (CirrusVGAState *s, uint32_t dstaddr, |
148 | const uint8_t *src, | |
5fafdf24 | 149 | int dstpitch, int srcpitch, |
4c8732d7 FB |
150 | int bltwidth, int bltheight) |
151 | { | |
b30d4608 | 152 | uint32_t colors[2]; |
026aeffc | 153 | uint32_t addr; |
4c8732d7 FB |
154 | int x, y; |
155 | unsigned bits; | |
156 | unsigned int col; | |
157 | unsigned bitmask; | |
4e12cd94 | 158 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 159 | int dstskipleft = srcskipleft * (DEPTH / 8); |
4c8732d7 | 160 | |
b30d4608 FB |
161 | colors[0] = s->cirrus_blt_bgcol; |
162 | colors[1] = s->cirrus_blt_fgcol; | |
4c8732d7 FB |
163 | for(y = 0; y < bltheight; y++) { |
164 | bitmask = 0x80 >> srcskipleft; | |
165 | bits = *src++; | |
026aeffc | 166 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 167 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
4c8732d7 FB |
168 | if ((bitmask & 0xff) == 0) { |
169 | bitmask = 0x80; | |
170 | bits = *src++; | |
171 | } | |
b30d4608 | 172 | col = colors[!!(bits & bitmask)]; |
026aeffc GH |
173 | PUTPIXEL(s, addr, col); |
174 | addr += (DEPTH / 8); | |
b30d4608 FB |
175 | bitmask >>= 1; |
176 | } | |
026aeffc | 177 | dstaddr += dstpitch; |
b30d4608 FB |
178 | } |
179 | } | |
180 | ||
181 | static void | |
182 | glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) | |
026aeffc GH |
183 | (CirrusVGAState *s, uint32_t dstaddr, |
184 | const uint8_t *src, | |
5fafdf24 | 185 | int dstpitch, int srcpitch, |
b30d4608 FB |
186 | int bltwidth, int bltheight) |
187 | { | |
026aeffc | 188 | uint32_t addr; |
b30d4608 FB |
189 | int x, y, bitpos, pattern_y; |
190 | unsigned int bits, bits_xor; | |
191 | unsigned int col; | |
ad81218e | 192 | #if DEPTH == 24 |
4e12cd94 | 193 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e FB |
194 | int srcskipleft = dstskipleft / 3; |
195 | #else | |
4e12cd94 | 196 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 197 | int dstskipleft = srcskipleft * (DEPTH / 8); |
ad81218e | 198 | #endif |
b30d4608 FB |
199 | |
200 | if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { | |
201 | bits_xor = 0xff; | |
202 | col = s->cirrus_blt_bgcol; | |
203 | } else { | |
204 | bits_xor = 0x00; | |
205 | col = s->cirrus_blt_fgcol; | |
206 | } | |
207 | pattern_y = s->cirrus_blt_srcaddr & 7; | |
208 | ||
209 | for(y = 0; y < bltheight; y++) { | |
210 | bits = src[pattern_y] ^ bits_xor; | |
e3a4e4b6 | 211 | bitpos = 7 - srcskipleft; |
026aeffc | 212 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 213 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
b30d4608 | 214 | if ((bits >> bitpos) & 1) { |
026aeffc | 215 | PUTPIXEL(s, addr, col); |
4c8732d7 | 216 | } |
026aeffc | 217 | addr += (DEPTH / 8); |
b30d4608 | 218 | bitpos = (bitpos - 1) & 7; |
4c8732d7 | 219 | } |
b30d4608 | 220 | pattern_y = (pattern_y + 1) & 7; |
026aeffc | 221 | dstaddr += dstpitch; |
a5082316 FB |
222 | } |
223 | } | |
224 | ||
225 | static void | |
b30d4608 | 226 | glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) |
026aeffc GH |
227 | (CirrusVGAState *s, uint32_t dstaddr, |
228 | const uint8_t *src, | |
5fafdf24 | 229 | int dstpitch, int srcpitch, |
a5082316 FB |
230 | int bltwidth, int bltheight) |
231 | { | |
a5082316 | 232 | uint32_t colors[2]; |
026aeffc | 233 | uint32_t addr; |
b30d4608 FB |
234 | int x, y, bitpos, pattern_y; |
235 | unsigned int bits; | |
a5082316 | 236 | unsigned int col; |
4e12cd94 | 237 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 238 | int dstskipleft = srcskipleft * (DEPTH / 8); |
a5082316 FB |
239 | |
240 | colors[0] = s->cirrus_blt_bgcol; | |
241 | colors[1] = s->cirrus_blt_fgcol; | |
b30d4608 FB |
242 | pattern_y = s->cirrus_blt_srcaddr & 7; |
243 | ||
a5082316 | 244 | for(y = 0; y < bltheight; y++) { |
b30d4608 | 245 | bits = src[pattern_y]; |
e3a4e4b6 | 246 | bitpos = 7 - srcskipleft; |
026aeffc | 247 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 248 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
b30d4608 | 249 | col = colors[(bits >> bitpos) & 1]; |
026aeffc GH |
250 | PUTPIXEL(s, addr, col); |
251 | addr += (DEPTH / 8); | |
b30d4608 | 252 | bitpos = (bitpos - 1) & 7; |
a5082316 | 253 | } |
b30d4608 | 254 | pattern_y = (pattern_y + 1) & 7; |
026aeffc | 255 | dstaddr += dstpitch; |
a5082316 FB |
256 | } |
257 | } | |
258 | ||
5fafdf24 | 259 | static void |
a5082316 FB |
260 | glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) |
261 | (CirrusVGAState *s, | |
026aeffc | 262 | uint32_t dstaddr, int dst_pitch, |
a5082316 FB |
263 | int width, int height) |
264 | { | |
026aeffc | 265 | uint32_t addr; |
a5082316 FB |
266 | uint32_t col; |
267 | int x, y; | |
268 | ||
269 | col = s->cirrus_blt_fgcol; | |
270 | ||
a5082316 | 271 | for(y = 0; y < height; y++) { |
026aeffc | 272 | addr = dstaddr; |
a5082316 | 273 | for(x = 0; x < width; x += (DEPTH / 8)) { |
026aeffc GH |
274 | PUTPIXEL(s, addr, col); |
275 | addr += (DEPTH / 8); | |
a5082316 | 276 | } |
026aeffc | 277 | dstaddr += dst_pitch; |
a5082316 FB |
278 | } |
279 | } | |
280 | ||
281 | #undef DEPTH | |
282 | #undef PUTPIXEL |