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
glue(glue (glue (cirrus_patternfill_,ROP_NAME),_),DEPTH)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
glue(glue (glue (cirrus_colorexpand_transp_,ROP_NAME),_),DEPTH)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 #if DEPTH == 24
112 int dstskipleft = s->vga.gr[0x2f] & 0x1f;
113 int srcskipleft = dstskipleft / 3;
114 #else
115 int srcskipleft = s->vga.gr[0x2f] & 0x07;
116 int dstskipleft = srcskipleft * (DEPTH / 8);
117 #endif
118
119 if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
120 bits_xor = 0xff;
121 col = s->cirrus_blt_bgcol;
122 } else {
123 bits_xor = 0x00;
124 col = s->cirrus_blt_fgcol;
125 }
126
127 for(y = 0; y < bltheight; y++) {
128 bitmask = 0x80 >> srcskipleft;
129 bits = cirrus_src(s, srcaddr++) ^ bits_xor;
130 addr = dstaddr + dstskipleft;
131 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
132 if ((bitmask & 0xff) == 0) {
133 bitmask = 0x80;
134 bits = cirrus_src(s, srcaddr++) ^ bits_xor;
135 }
136 index = (bits & bitmask);
137 if (index) {
138 PUTPIXEL(s, addr, col);
139 }
140 addr += (DEPTH / 8);
141 bitmask >>= 1;
142 }
143 dstaddr += dstpitch;
144 }
145 }
146
147 static void
glue(glue (glue (cirrus_colorexpand_,ROP_NAME),_),DEPTH)148 glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
149 (CirrusVGAState *s, uint32_t dstaddr,
150 uint32_t srcaddr,
151 int dstpitch, int srcpitch,
152 int bltwidth, int bltheight)
153 {
154 uint32_t colors[2];
155 uint32_t addr;
156 int x, y;
157 unsigned bits;
158 unsigned int col;
159 unsigned bitmask;
160 int srcskipleft = s->vga.gr[0x2f] & 0x07;
161 int dstskipleft = srcskipleft * (DEPTH / 8);
162
163 colors[0] = s->cirrus_blt_bgcol;
164 colors[1] = s->cirrus_blt_fgcol;
165 for(y = 0; y < bltheight; y++) {
166 bitmask = 0x80 >> srcskipleft;
167 bits = cirrus_src(s, srcaddr++);
168 addr = dstaddr + dstskipleft;
169 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
170 if ((bitmask & 0xff) == 0) {
171 bitmask = 0x80;
172 bits = cirrus_src(s, srcaddr++);
173 }
174 col = colors[!!(bits & bitmask)];
175 PUTPIXEL(s, addr, col);
176 addr += (DEPTH / 8);
177 bitmask >>= 1;
178 }
179 dstaddr += dstpitch;
180 }
181 }
182
183 static void
glue(glue (glue (cirrus_colorexpand_pattern_transp_,ROP_NAME),_),DEPTH)184 glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
185 (CirrusVGAState *s, uint32_t dstaddr,
186 uint32_t srcaddr,
187 int dstpitch, int srcpitch,
188 int bltwidth, int bltheight)
189 {
190 uint32_t addr;
191 int x, y, bitpos, pattern_y;
192 unsigned int bits, bits_xor;
193 unsigned int col;
194 #if DEPTH == 24
195 int dstskipleft = s->vga.gr[0x2f] & 0x1f;
196 int srcskipleft = dstskipleft / 3;
197 #else
198 int srcskipleft = s->vga.gr[0x2f] & 0x07;
199 int dstskipleft = srcskipleft * (DEPTH / 8);
200 #endif
201
202 if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
203 bits_xor = 0xff;
204 col = s->cirrus_blt_bgcol;
205 } else {
206 bits_xor = 0x00;
207 col = s->cirrus_blt_fgcol;
208 }
209 pattern_y = s->cirrus_blt_srcaddr & 7;
210
211 for(y = 0; y < bltheight; y++) {
212 bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor;
213 bitpos = 7 - srcskipleft;
214 addr = dstaddr + dstskipleft;
215 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
216 if ((bits >> bitpos) & 1) {
217 PUTPIXEL(s, addr, col);
218 }
219 addr += (DEPTH / 8);
220 bitpos = (bitpos - 1) & 7;
221 }
222 pattern_y = (pattern_y + 1) & 7;
223 dstaddr += dstpitch;
224 }
225 }
226
227 static void
glue(glue (glue (cirrus_colorexpand_pattern_,ROP_NAME),_),DEPTH)228 glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
229 (CirrusVGAState *s, uint32_t dstaddr,
230 uint32_t srcaddr,
231 int dstpitch, int srcpitch,
232 int bltwidth, int bltheight)
233 {
234 uint32_t colors[2];
235 uint32_t addr;
236 int x, y, bitpos, pattern_y;
237 unsigned int bits;
238 unsigned int col;
239 int srcskipleft = s->vga.gr[0x2f] & 0x07;
240 int dstskipleft = srcskipleft * (DEPTH / 8);
241
242 colors[0] = s->cirrus_blt_bgcol;
243 colors[1] = s->cirrus_blt_fgcol;
244 pattern_y = s->cirrus_blt_srcaddr & 7;
245
246 for(y = 0; y < bltheight; y++) {
247 bits = cirrus_src(s, srcaddr + pattern_y);
248 bitpos = 7 - srcskipleft;
249 addr = dstaddr + dstskipleft;
250 for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
251 col = colors[(bits >> bitpos) & 1];
252 PUTPIXEL(s, addr, col);
253 addr += (DEPTH / 8);
254 bitpos = (bitpos - 1) & 7;
255 }
256 pattern_y = (pattern_y + 1) & 7;
257 dstaddr += dstpitch;
258 }
259 }
260
261 static void
glue(glue (glue (cirrus_fill_,ROP_NAME),_),DEPTH)262 glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
263 (CirrusVGAState *s,
264 uint32_t dstaddr, int dst_pitch,
265 int width, int height)
266 {
267 uint32_t addr;
268 uint32_t col;
269 int x, y;
270
271 col = s->cirrus_blt_fgcol;
272
273 for(y = 0; y < height; y++) {
274 addr = dstaddr;
275 for(x = 0; x < width; x += (DEPTH / 8)) {
276 PUTPIXEL(s, addr, col);
277 addr += (DEPTH / 8);
278 }
279 dstaddr += dst_pitch;
280 }
281 }
282
283 #undef DEPTH
284 #undef PUTPIXEL
285