]>
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 | |
8c78881f | 26 | #define PUTPIXEL() ROP_OP(&d[0], col) |
a5082316 | 27 | #elif DEPTH == 16 |
8c78881f | 28 | #define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) |
a5082316 | 29 | #elif DEPTH == 24 |
8c78881f BS |
30 | #define PUTPIXEL() ROP_OP(&d[0], col); \ |
31 | ROP_OP(&d[1], (col >> 8)); \ | |
32 | ROP_OP(&d[2], (col >> 16)) | |
a5082316 | 33 | #elif DEPTH == 32 |
8c78881f | 34 | #define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) |
a5082316 FB |
35 | #else |
36 | #error unsupported DEPTH | |
3b46e624 | 37 | #endif |
a5082316 | 38 | |
e69390ce FB |
39 | static void |
40 | glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) | |
41 | (CirrusVGAState * s, uint8_t * dst, | |
5fafdf24 TS |
42 | const uint8_t * src, |
43 | int dstpitch, int srcpitch, | |
e69390ce FB |
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; | |
ad81218e | 50 | #if DEPTH == 24 |
4e12cd94 | 51 | int skipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e | 52 | #else |
4e12cd94 | 53 | int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8); |
ad81218e | 54 | #endif |
e69390ce FB |
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; | |
e69390ce | 64 | for(y = 0; y < bltheight; y++) { |
2f636b45 | 65 | pattern_x = skipleft; |
e3a4e4b6 | 66 | d = dst + skipleft; |
e69390ce | 67 | src1 = src + pattern_y * pattern_pitch; |
e3a4e4b6 | 68 | for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { |
e69390ce FB |
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; | |
b30d4608 FB |
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 | } | |
e69390ce FB |
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 | ||
4c8732d7 | 93 | /* NOTE: srcpitch is ignored */ |
a5082316 FB |
94 | static void |
95 | glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) | |
96 | (CirrusVGAState * s, uint8_t * dst, | |
5fafdf24 TS |
97 | const uint8_t * src, |
98 | int dstpitch, int srcpitch, | |
a5082316 FB |
99 | int bltwidth, int bltheight) |
100 | { | |
a5082316 FB |
101 | uint8_t *d; |
102 | int x, y; | |
b30d4608 | 103 | unsigned bits, bits_xor; |
a5082316 FB |
104 | unsigned int col; |
105 | unsigned bitmask; | |
106 | unsigned index; | |
ad81218e | 107 | #if DEPTH == 24 |
4e12cd94 | 108 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e FB |
109 | int srcskipleft = dstskipleft / 3; |
110 | #else | |
4e12cd94 | 111 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 112 | int dstskipleft = srcskipleft * (DEPTH / 8); |
ad81218e | 113 | #endif |
a5082316 | 114 | |
b30d4608 FB |
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 | ||
a5082316 | 123 | for(y = 0; y < bltheight; y++) { |
a5082316 | 124 | bitmask = 0x80 >> srcskipleft; |
b30d4608 | 125 | bits = *src++ ^ bits_xor; |
e3a4e4b6 FB |
126 | d = dst + dstskipleft; |
127 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { | |
a5082316 FB |
128 | if ((bitmask & 0xff) == 0) { |
129 | bitmask = 0x80; | |
b30d4608 | 130 | bits = *src++ ^ bits_xor; |
a5082316 FB |
131 | } |
132 | index = (bits & bitmask); | |
133 | if (index) { | |
134 | PUTPIXEL(); | |
135 | } | |
136 | d += (DEPTH / 8); | |
137 | bitmask >>= 1; | |
138 | } | |
4c8732d7 FB |
139 | dst += dstpitch; |
140 | } | |
141 | } | |
142 | ||
4c8732d7 | 143 | static void |
b30d4608 | 144 | glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) |
4c8732d7 | 145 | (CirrusVGAState * s, uint8_t * dst, |
5fafdf24 TS |
146 | const uint8_t * src, |
147 | int dstpitch, int srcpitch, | |
4c8732d7 FB |
148 | int bltwidth, int bltheight) |
149 | { | |
b30d4608 | 150 | uint32_t colors[2]; |
4c8732d7 FB |
151 | uint8_t *d; |
152 | int x, y; | |
153 | unsigned bits; | |
154 | unsigned int col; | |
155 | unsigned bitmask; | |
4e12cd94 | 156 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 157 | int dstskipleft = srcskipleft * (DEPTH / 8); |
4c8732d7 | 158 | |
b30d4608 FB |
159 | colors[0] = s->cirrus_blt_bgcol; |
160 | colors[1] = s->cirrus_blt_fgcol; | |
4c8732d7 FB |
161 | for(y = 0; y < bltheight; y++) { |
162 | bitmask = 0x80 >> srcskipleft; | |
163 | bits = *src++; | |
e3a4e4b6 FB |
164 | d = dst + dstskipleft; |
165 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { | |
4c8732d7 FB |
166 | if ((bitmask & 0xff) == 0) { |
167 | bitmask = 0x80; | |
168 | bits = *src++; | |
169 | } | |
b30d4608 FB |
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, | |
5fafdf24 TS |
182 | const uint8_t * src, |
183 | int dstpitch, int srcpitch, | |
b30d4608 FB |
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; | |
ad81218e | 190 | #if DEPTH == 24 |
4e12cd94 | 191 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e FB |
192 | int srcskipleft = dstskipleft / 3; |
193 | #else | |
4e12cd94 | 194 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 195 | int dstskipleft = srcskipleft * (DEPTH / 8); |
ad81218e | 196 | #endif |
b30d4608 FB |
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; | |
e3a4e4b6 FB |
209 | bitpos = 7 - srcskipleft; |
210 | d = dst + dstskipleft; | |
211 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { | |
b30d4608 | 212 | if ((bits >> bitpos) & 1) { |
4c8732d7 FB |
213 | PUTPIXEL(); |
214 | } | |
215 | d += (DEPTH / 8); | |
b30d4608 | 216 | bitpos = (bitpos - 1) & 7; |
4c8732d7 | 217 | } |
b30d4608 | 218 | pattern_y = (pattern_y + 1) & 7; |
a5082316 FB |
219 | dst += dstpitch; |
220 | } | |
221 | } | |
222 | ||
223 | static void | |
b30d4608 | 224 | glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) |
a5082316 | 225 | (CirrusVGAState * s, uint8_t * dst, |
5fafdf24 TS |
226 | const uint8_t * src, |
227 | int dstpitch, int srcpitch, | |
a5082316 FB |
228 | int bltwidth, int bltheight) |
229 | { | |
a5082316 FB |
230 | uint32_t colors[2]; |
231 | uint8_t *d; | |
b30d4608 FB |
232 | int x, y, bitpos, pattern_y; |
233 | unsigned int bits; | |
a5082316 | 234 | unsigned int col; |
4e12cd94 | 235 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 236 | int dstskipleft = srcskipleft * (DEPTH / 8); |
a5082316 FB |
237 | |
238 | colors[0] = s->cirrus_blt_bgcol; | |
239 | colors[1] = s->cirrus_blt_fgcol; | |
b30d4608 FB |
240 | pattern_y = s->cirrus_blt_srcaddr & 7; |
241 | ||
a5082316 | 242 | for(y = 0; y < bltheight; y++) { |
b30d4608 | 243 | bits = src[pattern_y]; |
e3a4e4b6 FB |
244 | bitpos = 7 - srcskipleft; |
245 | d = dst + dstskipleft; | |
246 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { | |
b30d4608 | 247 | col = colors[(bits >> bitpos) & 1]; |
a5082316 FB |
248 | PUTPIXEL(); |
249 | d += (DEPTH / 8); | |
b30d4608 | 250 | bitpos = (bitpos - 1) & 7; |
a5082316 | 251 | } |
b30d4608 | 252 | pattern_y = (pattern_y + 1) & 7; |
a5082316 FB |
253 | dst += dstpitch; |
254 | } | |
255 | } | |
256 | ||
5fafdf24 | 257 | static void |
a5082316 FB |
258 | glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) |
259 | (CirrusVGAState *s, | |
5fafdf24 | 260 | uint8_t *dst, int dst_pitch, |
a5082316 FB |
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 |