]>
Commit | Line | Data |
---|---|---|
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 |