]>
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); \ | |
db6cd4c8 GH |
32 | ROP_OP(s, a + 1, (c >> 8)); \ |
33 | ROP_OP(s, a + 2, (c >> 16)); \ | |
026aeffc | 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 | 43 | (CirrusVGAState *s, uint32_t dstaddr, |
ffaf8577 | 44 | uint32_t srcaddr, |
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; | |
ffaf8577 | 51 | uint32_t src1addr; |
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; |
ffaf8577 | 69 | src1addr = srcaddr + pattern_y * pattern_pitch; |
e3a4e4b6 | 70 | for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { |
e69390ce | 71 | #if DEPTH == 8 |
ffaf8577 | 72 | col = cirrus_src(s, src1addr + pattern_x); |
e69390ce FB |
73 | pattern_x = (pattern_x + 1) & 7; |
74 | #elif DEPTH == 16 | |
ffaf8577 | 75 | col = cirrus_src16(s, src1addr + pattern_x); |
e69390ce | 76 | pattern_x = (pattern_x + 2) & 15; |
b30d4608 FB |
77 | #elif DEPTH == 24 |
78 | { | |
ffaf8577 GH |
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); | |
b30d4608 FB |
83 | pattern_x = (pattern_x + 1) & 7; |
84 | } | |
e69390ce | 85 | #else |
ffaf8577 | 86 | col = cirrus_src32(s, src1addr + pattern_x); |
e69390ce FB |
87 | pattern_x = (pattern_x + 4) & 31; |
88 | #endif | |
026aeffc GH |
89 | PUTPIXEL(s, addr, col); |
90 | addr += (DEPTH / 8); | |
e69390ce FB |
91 | } |
92 | pattern_y = (pattern_y + 1) & 7; | |
026aeffc | 93 | dstaddr += dstpitch; |
e69390ce FB |
94 | } |
95 | } | |
96 | ||
4c8732d7 | 97 | /* NOTE: srcpitch is ignored */ |
a5082316 FB |
98 | static void |
99 | glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) | |
026aeffc | 100 | (CirrusVGAState *s, uint32_t dstaddr, |
ffaf8577 | 101 | uint32_t srcaddr, |
5fafdf24 | 102 | int dstpitch, int srcpitch, |
a5082316 FB |
103 | int bltwidth, int bltheight) |
104 | { | |
026aeffc | 105 | uint32_t addr; |
a5082316 | 106 | int x, y; |
b30d4608 | 107 | unsigned bits, bits_xor; |
a5082316 FB |
108 | unsigned int col; |
109 | unsigned bitmask; | |
110 | unsigned index; | |
ad81218e | 111 | #if DEPTH == 24 |
4e12cd94 | 112 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e FB |
113 | int srcskipleft = dstskipleft / 3; |
114 | #else | |
4e12cd94 | 115 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 116 | int dstskipleft = srcskipleft * (DEPTH / 8); |
ad81218e | 117 | #endif |
a5082316 | 118 | |
b30d4608 FB |
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 | ||
a5082316 | 127 | for(y = 0; y < bltheight; y++) { |
a5082316 | 128 | bitmask = 0x80 >> srcskipleft; |
ffaf8577 | 129 | bits = cirrus_src(s, srcaddr++) ^ bits_xor; |
026aeffc | 130 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 131 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
a5082316 FB |
132 | if ((bitmask & 0xff) == 0) { |
133 | bitmask = 0x80; | |
ffaf8577 | 134 | bits = cirrus_src(s, srcaddr++) ^ bits_xor; |
a5082316 FB |
135 | } |
136 | index = (bits & bitmask); | |
137 | if (index) { | |
026aeffc | 138 | PUTPIXEL(s, addr, col); |
a5082316 | 139 | } |
026aeffc | 140 | addr += (DEPTH / 8); |
a5082316 FB |
141 | bitmask >>= 1; |
142 | } | |
026aeffc | 143 | dstaddr += dstpitch; |
4c8732d7 FB |
144 | } |
145 | } | |
146 | ||
4c8732d7 | 147 | static void |
b30d4608 | 148 | glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) |
026aeffc | 149 | (CirrusVGAState *s, uint32_t dstaddr, |
ffaf8577 | 150 | uint32_t srcaddr, |
5fafdf24 | 151 | int dstpitch, int srcpitch, |
4c8732d7 FB |
152 | int bltwidth, int bltheight) |
153 | { | |
b30d4608 | 154 | uint32_t colors[2]; |
026aeffc | 155 | uint32_t addr; |
4c8732d7 FB |
156 | int x, y; |
157 | unsigned bits; | |
158 | unsigned int col; | |
159 | unsigned bitmask; | |
4e12cd94 | 160 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 161 | int dstskipleft = srcskipleft * (DEPTH / 8); |
4c8732d7 | 162 | |
b30d4608 FB |
163 | colors[0] = s->cirrus_blt_bgcol; |
164 | colors[1] = s->cirrus_blt_fgcol; | |
4c8732d7 FB |
165 | for(y = 0; y < bltheight; y++) { |
166 | bitmask = 0x80 >> srcskipleft; | |
ffaf8577 | 167 | bits = cirrus_src(s, srcaddr++); |
026aeffc | 168 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 169 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
4c8732d7 FB |
170 | if ((bitmask & 0xff) == 0) { |
171 | bitmask = 0x80; | |
ffaf8577 | 172 | bits = cirrus_src(s, srcaddr++); |
4c8732d7 | 173 | } |
b30d4608 | 174 | col = colors[!!(bits & bitmask)]; |
026aeffc GH |
175 | PUTPIXEL(s, addr, col); |
176 | addr += (DEPTH / 8); | |
b30d4608 FB |
177 | bitmask >>= 1; |
178 | } | |
026aeffc | 179 | dstaddr += dstpitch; |
b30d4608 FB |
180 | } |
181 | } | |
182 | ||
183 | static void | |
184 | glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) | |
026aeffc | 185 | (CirrusVGAState *s, uint32_t dstaddr, |
ffaf8577 | 186 | uint32_t srcaddr, |
5fafdf24 | 187 | int dstpitch, int srcpitch, |
b30d4608 FB |
188 | int bltwidth, int bltheight) |
189 | { | |
026aeffc | 190 | uint32_t addr; |
b30d4608 FB |
191 | int x, y, bitpos, pattern_y; |
192 | unsigned int bits, bits_xor; | |
193 | unsigned int col; | |
ad81218e | 194 | #if DEPTH == 24 |
4e12cd94 | 195 | int dstskipleft = s->vga.gr[0x2f] & 0x1f; |
ad81218e FB |
196 | int srcskipleft = dstskipleft / 3; |
197 | #else | |
4e12cd94 | 198 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 199 | int dstskipleft = srcskipleft * (DEPTH / 8); |
ad81218e | 200 | #endif |
b30d4608 FB |
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++) { | |
ffaf8577 | 212 | bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor; |
e3a4e4b6 | 213 | bitpos = 7 - srcskipleft; |
026aeffc | 214 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 215 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
b30d4608 | 216 | if ((bits >> bitpos) & 1) { |
026aeffc | 217 | PUTPIXEL(s, addr, col); |
4c8732d7 | 218 | } |
026aeffc | 219 | addr += (DEPTH / 8); |
b30d4608 | 220 | bitpos = (bitpos - 1) & 7; |
4c8732d7 | 221 | } |
b30d4608 | 222 | pattern_y = (pattern_y + 1) & 7; |
026aeffc | 223 | dstaddr += dstpitch; |
a5082316 FB |
224 | } |
225 | } | |
226 | ||
227 | static void | |
b30d4608 | 228 | glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) |
026aeffc | 229 | (CirrusVGAState *s, uint32_t dstaddr, |
ffaf8577 | 230 | uint32_t srcaddr, |
5fafdf24 | 231 | int dstpitch, int srcpitch, |
a5082316 FB |
232 | int bltwidth, int bltheight) |
233 | { | |
a5082316 | 234 | uint32_t colors[2]; |
026aeffc | 235 | uint32_t addr; |
b30d4608 FB |
236 | int x, y, bitpos, pattern_y; |
237 | unsigned int bits; | |
a5082316 | 238 | unsigned int col; |
4e12cd94 | 239 | int srcskipleft = s->vga.gr[0x2f] & 0x07; |
e3a4e4b6 | 240 | int dstskipleft = srcskipleft * (DEPTH / 8); |
a5082316 FB |
241 | |
242 | colors[0] = s->cirrus_blt_bgcol; | |
243 | colors[1] = s->cirrus_blt_fgcol; | |
b30d4608 FB |
244 | pattern_y = s->cirrus_blt_srcaddr & 7; |
245 | ||
a5082316 | 246 | for(y = 0; y < bltheight; y++) { |
ffaf8577 | 247 | bits = cirrus_src(s, srcaddr + pattern_y); |
e3a4e4b6 | 248 | bitpos = 7 - srcskipleft; |
026aeffc | 249 | addr = dstaddr + dstskipleft; |
e3a4e4b6 | 250 | for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { |
b30d4608 | 251 | col = colors[(bits >> bitpos) & 1]; |
026aeffc GH |
252 | PUTPIXEL(s, addr, col); |
253 | addr += (DEPTH / 8); | |
b30d4608 | 254 | bitpos = (bitpos - 1) & 7; |
a5082316 | 255 | } |
b30d4608 | 256 | pattern_y = (pattern_y + 1) & 7; |
026aeffc | 257 | dstaddr += dstpitch; |
a5082316 FB |
258 | } |
259 | } | |
260 | ||
5fafdf24 | 261 | static void |
a5082316 FB |
262 | glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) |
263 | (CirrusVGAState *s, | |
026aeffc | 264 | uint32_t dstaddr, int dst_pitch, |
a5082316 FB |
265 | int width, int height) |
266 | { | |
026aeffc | 267 | uint32_t addr; |
a5082316 FB |
268 | uint32_t col; |
269 | int x, y; | |
270 | ||
271 | col = s->cirrus_blt_fgcol; | |
272 | ||
a5082316 | 273 | for(y = 0; y < height; y++) { |
026aeffc | 274 | addr = dstaddr; |
a5082316 | 275 | for(x = 0; x < width; x += (DEPTH / 8)) { |
026aeffc GH |
276 | PUTPIXEL(s, addr, col); |
277 | addr += (DEPTH / 8); | |
a5082316 | 278 | } |
026aeffc | 279 | dstaddr += dst_pitch; |
a5082316 FB |
280 | } |
281 | } | |
282 | ||
283 | #undef DEPTH | |
284 | #undef PUTPIXEL |