master
h 326 lines 9.95 KB
Raw
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(s, a, c) ROP_OP(s, a, c)
27 #elif DEPTH == 16
28 #define PUTPIXEL(s, a, c) ROP_OP_16(s, a, c)
29 #elif DEPTH == 24
30 #define PUTPIXEL(s, a, c) do { \
31 ROP_OP(s, a, c); \
32 ROP_OP(s, a + 1, (c >> 8)); \
33 ROP_OP(s, a + 2, (c >> 16)); \
34 } while (0)
35 #elif DEPTH == 32
36 #define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c)
37 #else
38 #error unsupported DEPTH
39 #endif
40
41 static void
42 glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
43 (CirrusVGAState *s, uint32_t dstaddr,
44 uint32_t srcaddr,
45 int dstpitch, int srcpitch,
46 int bltwidth, int bltheight)
47 {
48 uint32_t addr;
49 int x, y, pattern_y, pattern_pitch, pattern_x;
50 unsigned int col;
51 uint32_t src1addr;
52 #if DEPTH == 24
53 int skipleft = s->vga.gr[0x2f] & 0x1f;
54 #else
55 int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8);
56 #endif
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;
66 for(y = 0; y < bltheight; y++) {
67 pattern_x = skipleft;
68 addr = dstaddr + skipleft;
69 src1addr = srcaddr + pattern_y * pattern_pitch;
70 for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
71 #if DEPTH == 8
72 col = cirrus_src(s, src1addr + pattern_x);
73 pattern_x = (pattern_x + 1) & 7;
74 #elif DEPTH == 16
75 col = cirrus_src16(s, src1addr + pattern_x);
76 pattern_x = (pattern_x + 2) & 15;
77 #elif DEPTH == 24
78 {
79 uint32_t src2addr = src1addr + pattern_x * 3;
80 col = cirrus_src(s, src2addr) |
81 (cirrus_src(s, src2addr + 1) << 8) |
82 (cirrus_src(s, src2addr + 2) << 16);
83 pattern_x = (pattern_x + 1) & 7;
84 }
85 #else
86 col = cirrus_src32(s, src1addr + pattern_x);
87 pattern_x = (pattern_x + 4) & 31;
88 #endif
89 PUTPIXEL(s, addr, col);
90 addr += (DEPTH / 8);
91 }
92 pattern_y = (pattern_y + 1) & 7;
93 dstaddr += dstpitch;
94 }
95 }
96
97 /* NOTE: srcpitch is ignored */
98 static void
99 glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
100 (CirrusVGAState *s, uint32_t dstaddr,
101 uint32_t srcaddr,
102 int dstpitch, int srcpitch,
103 int bltwidth, int bltheight)
104 {
105 uint32_t addr;
106 int x, y;
107 unsigned bits, bits_xor;
108 unsigned int col;
109 unsigned bitmask;
110 unsigned index;
111
112 /*
113 * Raster ops where the source is a monochrome bitmap with
114 * color expansion to 8/16/24/32bpp destination.
115 */
116
117 #if DEPTH == 24
118 /*
119 * For packed-24 modes, GR2F bits [4:0] are a count of destination
120 * bytes to be suppressed for each scanline, which we keep in
121 * dstskipleft. We want to track the number of whole bytes
122 * to skip in the source (always either 0 or 1) and the number
123 * of bits within the byte to skip.
124 */
125 int dstskipleft = s->vga.gr[0x2f] & 0x1f;
126 int srcskipleftbits = (dstskipleft / 3) & 0x7;
127 int srcskipleftbytes = (dstskipleft / 3) >> 3;
128 #else
129 /*
130 * In all other modes, GR2F bits [2:0] are a count of how many
131 * destination pixels to suppress for each scanline, which is our
132 * srcskipleftbits. We get dstskipleft, the number of bytes to
133 * skip, by multiplying this by the bytes-per-pixel. In these
134 * modes we never need to skip an entire source byte.
135 */
136 int srcskipleftbits = s->vga.gr[0x2f] & 0x07;
137 int srcskipleftbytes = 0;
138 int dstskipleft = srcskipleftbits * (DEPTH / 8);
139 #endif
140
141 if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
142 bits_xor = 0xff;
143 col = s->cirrus_blt_bgcol;
144 } else {
145 bits_xor = 0x00;
146 col = s->cirrus_blt_fgcol;
147 }
148
149 for(y = 0; y < bltheight; y++) {
150 bitmask = 0x80 >> srcskipleftbits;
151 srcaddr += srcskipleftbytes;
152 bits = cirrus_src(s, srcaddr++) ^ bits_xor;
153 addr = dstaddr + dstskipleft;
154 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
155 if ((bitmask & 0xff) == 0) {
156 bitmask = 0x80;
157 bits = cirrus_src(s, srcaddr++) ^ bits_xor;
158 }
159 index = (bits & bitmask);
160 if (index) {
161 PUTPIXEL(s, addr, col);
162 }
163 addr += (DEPTH / 8);
164 bitmask >>= 1;
165 }
166 dstaddr += dstpitch;
167 }
168 }
169
170 static void
171 glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
172 (CirrusVGAState *s, uint32_t dstaddr,
173 uint32_t srcaddr,
174 int dstpitch, int srcpitch,
175 int bltwidth, int bltheight)
176 {
177 uint32_t colors[2];
178 uint32_t addr;
179 int x, y;
180 unsigned bits;
181 unsigned int col;
182 unsigned bitmask;
183 int srcskipleft = s->vga.gr[0x2f] & 0x07;
184 int dstskipleft = srcskipleft * (DEPTH / 8);
185
186 colors[0] = s->cirrus_blt_bgcol;
187 colors[1] = s->cirrus_blt_fgcol;
188 for(y = 0; y < bltheight; y++) {
189 bitmask = 0x80 >> srcskipleft;
190 bits = cirrus_src(s, srcaddr++);
191 addr = dstaddr + dstskipleft;
192 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
193 if ((bitmask & 0xff) == 0) {
194 bitmask = 0x80;
195 bits = cirrus_src(s, srcaddr++);
196 }
197 col = colors[!!(bits & bitmask)];
198 PUTPIXEL(s, addr, col);
199 addr += (DEPTH / 8);
200 bitmask >>= 1;
201 }
202 dstaddr += dstpitch;
203 }
204 }
205
206 static void
207 glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
208 (CirrusVGAState *s, uint32_t dstaddr,
209 uint32_t srcaddr,
210 int dstpitch, int srcpitch,
211 int bltwidth, int bltheight)
212 {
213 uint32_t addr;
214 int x, y, bitpos, pattern_y;
215 unsigned int bits, bits_xor;
216 unsigned int col;
217
218 /*
219 * Copy from an 8x8 monochrome pattern with color expansion.
220 */
221
222 #if DEPTH == 24
223 /*
224 * For packed-24 modes, GR2F bits [4:0] are a count of destination
225 * bytes to be suppressed for each scanline, which we keep in
226 * dstskipleft. Our srcskipleft is the number of pixels to skip
227 * within the 8x8 source pattern to match up with that number
228 * of suppressed bytes. As the pattern repeats every 8 bits we
229 * take the number of pixels mod 8.
230 */
231 int dstskipleft = s->vga.gr[0x2f] & 0x1f;
232 int srcskipleft = (dstskipleft / 3) & 0x7;
233 #else
234 /*
235 * In all other modes, GR2F bits [2:0] are a count of how many
236 * destination pixels to suppress for each scanline, which is our
237 * srcskipleft. We get dstskipleft, the number of bytes to skip,
238 * by multiplying this by the bytes-per-pixel.
239 */
240 int srcskipleft = s->vga.gr[0x2f] & 0x07;
241 int dstskipleft = srcskipleft * (DEPTH / 8);
242 #endif
243
244 if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
245 bits_xor = 0xff;
246 col = s->cirrus_blt_bgcol;
247 } else {
248 bits_xor = 0x00;
249 col = s->cirrus_blt_fgcol;
250 }
251 pattern_y = s->cirrus_blt_srcaddr & 7;
252
253 for(y = 0; y < bltheight; y++) {
254 bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor;
255 bitpos = 7 - srcskipleft;
256 addr = dstaddr + dstskipleft;
257 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
258 if ((bits >> bitpos) & 1) {
259 PUTPIXEL(s, addr, col);
260 }
261 addr += (DEPTH / 8);
262 bitpos = (bitpos - 1) & 7;
263 }
264 pattern_y = (pattern_y + 1) & 7;
265 dstaddr += dstpitch;
266 }
267 }
268
269 static void
270 glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
271 (CirrusVGAState *s, uint32_t dstaddr,
272 uint32_t srcaddr,
273 int dstpitch, int srcpitch,
274 int bltwidth, int bltheight)
275 {
276 uint32_t colors[2];
277 uint32_t addr;
278 int x, y, bitpos, pattern_y;
279 unsigned int bits;
280 unsigned int col;
281 int srcskipleft = s->vga.gr[0x2f] & 0x07;
282 int dstskipleft = srcskipleft * (DEPTH / 8);
283
284 colors[0] = s->cirrus_blt_bgcol;
285 colors[1] = s->cirrus_blt_fgcol;
286 pattern_y = s->cirrus_blt_srcaddr & 7;
287
288 for(y = 0; y < bltheight; y++) {
289 bits = cirrus_src(s, srcaddr + pattern_y);
290 bitpos = 7 - srcskipleft;
291 addr = dstaddr + dstskipleft;
292 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
293 col = colors[(bits >> bitpos) & 1];
294 PUTPIXEL(s, addr, col);
295 addr += (DEPTH / 8);
296 bitpos = (bitpos - 1) & 7;
297 }
298 pattern_y = (pattern_y + 1) & 7;
299 dstaddr += dstpitch;
300 }
301 }
302
303 static void
304 glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
305 (CirrusVGAState *s,
306 uint32_t dstaddr, int dst_pitch,
307 int width, int height)
308 {
309 uint32_t addr;
310 uint32_t col;
311 int x, y;
312
313 col = s->cirrus_blt_fgcol;
314
315 for(y = 0; y < height; y++) {
316 addr = dstaddr;
317 for(x = 0; x < width; x += (DEPTH / 8)) {
318 PUTPIXEL(s, addr, col);
319 addr += (DEPTH / 8);
320 }
321 dstaddr += dst_pitch;
322 }
323 }
324
325 #undef DEPTH
326 #undef PUTPIXEL