xref: /qemu/hw/display/cirrus_vga_rop2.h (revision 6402cbbb)
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 #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
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
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
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
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