1a5082316Sbellard /*
2a5082316Sbellard * QEMU Cirrus CLGD 54xx VGA Emulator.
3a5082316Sbellard *
4a5082316Sbellard * Copyright (c) 2004 Fabrice Bellard
5a5082316Sbellard *
6a5082316Sbellard * Permission is hereby granted, free of charge, to any person obtaining a copy
7a5082316Sbellard * of this software and associated documentation files (the "Software"), to deal
8a5082316Sbellard * in the Software without restriction, including without limitation the rights
9a5082316Sbellard * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10a5082316Sbellard * copies of the Software, and to permit persons to whom the Software is
11a5082316Sbellard * furnished to do so, subject to the following conditions:
12a5082316Sbellard *
13a5082316Sbellard * The above copyright notice and this permission notice shall be included in
14a5082316Sbellard * all copies or substantial portions of the Software.
15a5082316Sbellard *
16a5082316Sbellard * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17a5082316Sbellard * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18a5082316Sbellard * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19a5082316Sbellard * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20a5082316Sbellard * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21a5082316Sbellard * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22a5082316Sbellard * THE SOFTWARE.
23a5082316Sbellard */
24a5082316Sbellard
25a5082316Sbellard #if DEPTH == 8
26026aeffcSGerd Hoffmann #define PUTPIXEL(s, a, c) ROP_OP(s, a, c)
27a5082316Sbellard #elif DEPTH == 16
28026aeffcSGerd Hoffmann #define PUTPIXEL(s, a, c) ROP_OP_16(s, a, c)
29a5082316Sbellard #elif DEPTH == 24
30026aeffcSGerd Hoffmann #define PUTPIXEL(s, a, c) do { \
31026aeffcSGerd Hoffmann ROP_OP(s, a, c); \
32*db6cd4c8SGerd Hoffmann ROP_OP(s, a + 1, (c >> 8)); \
33*db6cd4c8SGerd Hoffmann ROP_OP(s, a + 2, (c >> 16)); \
34026aeffcSGerd Hoffmann } while (0)
35a5082316Sbellard #elif DEPTH == 32
36026aeffcSGerd Hoffmann #define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c)
37a5082316Sbellard #else
38a5082316Sbellard #error unsupported DEPTH
39a5082316Sbellard #endif
40a5082316Sbellard
41e69390ceSbellard static void
glue(glue (glue (cirrus_patternfill_,ROP_NAME),_),DEPTH)42e69390ceSbellard glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
43026aeffcSGerd Hoffmann (CirrusVGAState *s, uint32_t dstaddr,
44ffaf8577SGerd Hoffmann uint32_t srcaddr,
45e69390ceSbellard int dstpitch, int srcpitch,
46e69390ceSbellard int bltwidth, int bltheight)
47e69390ceSbellard {
48026aeffcSGerd Hoffmann uint32_t addr;
49e69390ceSbellard int x, y, pattern_y, pattern_pitch, pattern_x;
50e69390ceSbellard unsigned int col;
51ffaf8577SGerd Hoffmann uint32_t src1addr;
52ad81218eSbellard #if DEPTH == 24
534e12cd94SAvi Kivity int skipleft = s->vga.gr[0x2f] & 0x1f;
54ad81218eSbellard #else
554e12cd94SAvi Kivity int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8);
56ad81218eSbellard #endif
57e69390ceSbellard
58e69390ceSbellard #if DEPTH == 8
59e69390ceSbellard pattern_pitch = 8;
60e69390ceSbellard #elif DEPTH == 16
61e69390ceSbellard pattern_pitch = 16;
62e69390ceSbellard #else
63e69390ceSbellard pattern_pitch = 32;
64e69390ceSbellard #endif
65e69390ceSbellard pattern_y = s->cirrus_blt_srcaddr & 7;
66e69390ceSbellard for(y = 0; y < bltheight; y++) {
672f636b45Sbellard pattern_x = skipleft;
68026aeffcSGerd Hoffmann addr = dstaddr + skipleft;
69ffaf8577SGerd Hoffmann src1addr = srcaddr + pattern_y * pattern_pitch;
70e3a4e4b6Sbellard for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
71e69390ceSbellard #if DEPTH == 8
72ffaf8577SGerd Hoffmann col = cirrus_src(s, src1addr + pattern_x);
73e69390ceSbellard pattern_x = (pattern_x + 1) & 7;
74e69390ceSbellard #elif DEPTH == 16
75ffaf8577SGerd Hoffmann col = cirrus_src16(s, src1addr + pattern_x);
76e69390ceSbellard pattern_x = (pattern_x + 2) & 15;
77b30d4608Sbellard #elif DEPTH == 24
78b30d4608Sbellard {
79ffaf8577SGerd Hoffmann uint32_t src2addr = src1addr + pattern_x * 3;
80ffaf8577SGerd Hoffmann col = cirrus_src(s, src2addr) |
81ffaf8577SGerd Hoffmann (cirrus_src(s, src2addr + 1) << 8) |
82ffaf8577SGerd Hoffmann (cirrus_src(s, src2addr + 2) << 16);
83b30d4608Sbellard pattern_x = (pattern_x + 1) & 7;
84b30d4608Sbellard }
85e69390ceSbellard #else
86ffaf8577SGerd Hoffmann col = cirrus_src32(s, src1addr + pattern_x);
87e69390ceSbellard pattern_x = (pattern_x + 4) & 31;
88e69390ceSbellard #endif
89026aeffcSGerd Hoffmann PUTPIXEL(s, addr, col);
90026aeffcSGerd Hoffmann addr += (DEPTH / 8);
91e69390ceSbellard }
92e69390ceSbellard pattern_y = (pattern_y + 1) & 7;
93026aeffcSGerd Hoffmann dstaddr += dstpitch;
94e69390ceSbellard }
95e69390ceSbellard }
96e69390ceSbellard
974c8732d7Sbellard /* NOTE: srcpitch is ignored */
98a5082316Sbellard static void
glue(glue (glue (cirrus_colorexpand_transp_,ROP_NAME),_),DEPTH)99a5082316Sbellard glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
100026aeffcSGerd Hoffmann (CirrusVGAState *s, uint32_t dstaddr,
101ffaf8577SGerd Hoffmann uint32_t srcaddr,
102a5082316Sbellard int dstpitch, int srcpitch,
103a5082316Sbellard int bltwidth, int bltheight)
104a5082316Sbellard {
105026aeffcSGerd Hoffmann uint32_t addr;
106a5082316Sbellard int x, y;
107b30d4608Sbellard unsigned bits, bits_xor;
108a5082316Sbellard unsigned int col;
109a5082316Sbellard unsigned bitmask;
110a5082316Sbellard unsigned index;
111ad81218eSbellard #if DEPTH == 24
1124e12cd94SAvi Kivity int dstskipleft = s->vga.gr[0x2f] & 0x1f;
113ad81218eSbellard int srcskipleft = dstskipleft / 3;
114ad81218eSbellard #else
1154e12cd94SAvi Kivity int srcskipleft = s->vga.gr[0x2f] & 0x07;
116e3a4e4b6Sbellard int dstskipleft = srcskipleft * (DEPTH / 8);
117ad81218eSbellard #endif
118a5082316Sbellard
119b30d4608Sbellard if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
120b30d4608Sbellard bits_xor = 0xff;
121b30d4608Sbellard col = s->cirrus_blt_bgcol;
122b30d4608Sbellard } else {
123b30d4608Sbellard bits_xor = 0x00;
124a5082316Sbellard col = s->cirrus_blt_fgcol;
125b30d4608Sbellard }
126b30d4608Sbellard
127a5082316Sbellard for(y = 0; y < bltheight; y++) {
128a5082316Sbellard bitmask = 0x80 >> srcskipleft;
129ffaf8577SGerd Hoffmann bits = cirrus_src(s, srcaddr++) ^ bits_xor;
130026aeffcSGerd Hoffmann addr = dstaddr + dstskipleft;
131e3a4e4b6Sbellard for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
132a5082316Sbellard if ((bitmask & 0xff) == 0) {
133a5082316Sbellard bitmask = 0x80;
134ffaf8577SGerd Hoffmann bits = cirrus_src(s, srcaddr++) ^ bits_xor;
135a5082316Sbellard }
136a5082316Sbellard index = (bits & bitmask);
137a5082316Sbellard if (index) {
138026aeffcSGerd Hoffmann PUTPIXEL(s, addr, col);
139a5082316Sbellard }
140026aeffcSGerd Hoffmann addr += (DEPTH / 8);
141a5082316Sbellard bitmask >>= 1;
142a5082316Sbellard }
143026aeffcSGerd Hoffmann dstaddr += dstpitch;
1444c8732d7Sbellard }
1454c8732d7Sbellard }
1464c8732d7Sbellard
147a5082316Sbellard static void
glue(glue (glue (cirrus_colorexpand_,ROP_NAME),_),DEPTH)148a5082316Sbellard glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
149026aeffcSGerd Hoffmann (CirrusVGAState *s, uint32_t dstaddr,
150ffaf8577SGerd Hoffmann uint32_t srcaddr,
151a5082316Sbellard int dstpitch, int srcpitch,
152a5082316Sbellard int bltwidth, int bltheight)
153a5082316Sbellard {
154a5082316Sbellard uint32_t colors[2];
155026aeffcSGerd Hoffmann uint32_t addr;
156a5082316Sbellard int x, y;
157a5082316Sbellard unsigned bits;
158a5082316Sbellard unsigned int col;
159a5082316Sbellard unsigned bitmask;
1604e12cd94SAvi Kivity int srcskipleft = s->vga.gr[0x2f] & 0x07;
161e3a4e4b6Sbellard int dstskipleft = srcskipleft * (DEPTH / 8);
162a5082316Sbellard
163a5082316Sbellard colors[0] = s->cirrus_blt_bgcol;
164a5082316Sbellard colors[1] = s->cirrus_blt_fgcol;
165a5082316Sbellard for(y = 0; y < bltheight; y++) {
166a5082316Sbellard bitmask = 0x80 >> srcskipleft;
167ffaf8577SGerd Hoffmann bits = cirrus_src(s, srcaddr++);
168026aeffcSGerd Hoffmann addr = dstaddr + dstskipleft;
169e3a4e4b6Sbellard for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
170a5082316Sbellard if ((bitmask & 0xff) == 0) {
171a5082316Sbellard bitmask = 0x80;
172ffaf8577SGerd Hoffmann bits = cirrus_src(s, srcaddr++);
173a5082316Sbellard }
174a5082316Sbellard col = colors[!!(bits & bitmask)];
175026aeffcSGerd Hoffmann PUTPIXEL(s, addr, col);
176026aeffcSGerd Hoffmann addr += (DEPTH / 8);
177a5082316Sbellard bitmask >>= 1;
178a5082316Sbellard }
179026aeffcSGerd Hoffmann dstaddr += dstpitch;
180a5082316Sbellard }
181a5082316Sbellard }
182a5082316Sbellard
183a5082316Sbellard static void
glue(glue (glue (cirrus_colorexpand_pattern_transp_,ROP_NAME),_),DEPTH)184b30d4608Sbellard glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
185026aeffcSGerd Hoffmann (CirrusVGAState *s, uint32_t dstaddr,
186ffaf8577SGerd Hoffmann uint32_t srcaddr,
187b30d4608Sbellard int dstpitch, int srcpitch,
188b30d4608Sbellard int bltwidth, int bltheight)
189b30d4608Sbellard {
190026aeffcSGerd Hoffmann uint32_t addr;
191b30d4608Sbellard int x, y, bitpos, pattern_y;
192b30d4608Sbellard unsigned int bits, bits_xor;
193b30d4608Sbellard unsigned int col;
194ad81218eSbellard #if DEPTH == 24
1954e12cd94SAvi Kivity int dstskipleft = s->vga.gr[0x2f] & 0x1f;
196ad81218eSbellard int srcskipleft = dstskipleft / 3;
197ad81218eSbellard #else
1984e12cd94SAvi Kivity int srcskipleft = s->vga.gr[0x2f] & 0x07;
199e3a4e4b6Sbellard int dstskipleft = srcskipleft * (DEPTH / 8);
200ad81218eSbellard #endif
201b30d4608Sbellard
202b30d4608Sbellard if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
203b30d4608Sbellard bits_xor = 0xff;
204b30d4608Sbellard col = s->cirrus_blt_bgcol;
205b30d4608Sbellard } else {
206b30d4608Sbellard bits_xor = 0x00;
207b30d4608Sbellard col = s->cirrus_blt_fgcol;
208b30d4608Sbellard }
209b30d4608Sbellard pattern_y = s->cirrus_blt_srcaddr & 7;
210b30d4608Sbellard
211b30d4608Sbellard for(y = 0; y < bltheight; y++) {
212ffaf8577SGerd Hoffmann bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor;
213e3a4e4b6Sbellard bitpos = 7 - srcskipleft;
214026aeffcSGerd Hoffmann addr = dstaddr + dstskipleft;
215e3a4e4b6Sbellard for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
216b30d4608Sbellard if ((bits >> bitpos) & 1) {
217026aeffcSGerd Hoffmann PUTPIXEL(s, addr, col);
218b30d4608Sbellard }
219026aeffcSGerd Hoffmann addr += (DEPTH / 8);
220b30d4608Sbellard bitpos = (bitpos - 1) & 7;
221b30d4608Sbellard }
222b30d4608Sbellard pattern_y = (pattern_y + 1) & 7;
223026aeffcSGerd Hoffmann dstaddr += dstpitch;
224b30d4608Sbellard }
225b30d4608Sbellard }
226b30d4608Sbellard
227b30d4608Sbellard static void
glue(glue (glue (cirrus_colorexpand_pattern_,ROP_NAME),_),DEPTH)228b30d4608Sbellard glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
229026aeffcSGerd Hoffmann (CirrusVGAState *s, uint32_t dstaddr,
230ffaf8577SGerd Hoffmann uint32_t srcaddr,
231b30d4608Sbellard int dstpitch, int srcpitch,
232b30d4608Sbellard int bltwidth, int bltheight)
233b30d4608Sbellard {
234b30d4608Sbellard uint32_t colors[2];
235026aeffcSGerd Hoffmann uint32_t addr;
236b30d4608Sbellard int x, y, bitpos, pattern_y;
237b30d4608Sbellard unsigned int bits;
238b30d4608Sbellard unsigned int col;
2394e12cd94SAvi Kivity int srcskipleft = s->vga.gr[0x2f] & 0x07;
240e3a4e4b6Sbellard int dstskipleft = srcskipleft * (DEPTH / 8);
241b30d4608Sbellard
242b30d4608Sbellard colors[0] = s->cirrus_blt_bgcol;
243b30d4608Sbellard colors[1] = s->cirrus_blt_fgcol;
244b30d4608Sbellard pattern_y = s->cirrus_blt_srcaddr & 7;
245b30d4608Sbellard
246b30d4608Sbellard for(y = 0; y < bltheight; y++) {
247ffaf8577SGerd Hoffmann bits = cirrus_src(s, srcaddr + pattern_y);
248e3a4e4b6Sbellard bitpos = 7 - srcskipleft;
249026aeffcSGerd Hoffmann addr = dstaddr + dstskipleft;
250e3a4e4b6Sbellard for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
251b30d4608Sbellard col = colors[(bits >> bitpos) & 1];
252026aeffcSGerd Hoffmann PUTPIXEL(s, addr, col);
253026aeffcSGerd Hoffmann addr += (DEPTH / 8);
254b30d4608Sbellard bitpos = (bitpos - 1) & 7;
255b30d4608Sbellard }
256b30d4608Sbellard pattern_y = (pattern_y + 1) & 7;
257026aeffcSGerd Hoffmann dstaddr += dstpitch;
258b30d4608Sbellard }
259b30d4608Sbellard }
260b30d4608Sbellard
261b30d4608Sbellard static void
glue(glue (glue (cirrus_fill_,ROP_NAME),_),DEPTH)262a5082316Sbellard glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
263a5082316Sbellard (CirrusVGAState *s,
264026aeffcSGerd Hoffmann uint32_t dstaddr, int dst_pitch,
265a5082316Sbellard int width, int height)
266a5082316Sbellard {
267026aeffcSGerd Hoffmann uint32_t addr;
268a5082316Sbellard uint32_t col;
269a5082316Sbellard int x, y;
270a5082316Sbellard
271a5082316Sbellard col = s->cirrus_blt_fgcol;
272a5082316Sbellard
273a5082316Sbellard for(y = 0; y < height; y++) {
274026aeffcSGerd Hoffmann addr = dstaddr;
275a5082316Sbellard for(x = 0; x < width; x += (DEPTH / 8)) {
276026aeffcSGerd Hoffmann PUTPIXEL(s, addr, col);
277026aeffcSGerd Hoffmann addr += (DEPTH / 8);
278a5082316Sbellard }
279026aeffcSGerd Hoffmann dstaddr += dst_pitch;
280a5082316Sbellard }
281a5082316Sbellard }
282a5082316Sbellard
283a5082316Sbellard #undef DEPTH
284a5082316Sbellard #undef PUTPIXEL
285