xref: /openbmc/qemu/hw/display/cirrus_vga_rop2.h (revision 6683d7bc)
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()    ROP_OP(&d[0], col)
27 #elif DEPTH == 16
28 #define PUTPIXEL()    ROP_OP_16((uint16_t *)&d[0], col)
29 #elif DEPTH == 24
30 #define PUTPIXEL()    ROP_OP(&d[0], col);        \
31                       ROP_OP(&d[1], (col >> 8)); \
32                       ROP_OP(&d[2], (col >> 16))
33 #elif DEPTH == 32
34 #define PUTPIXEL()    ROP_OP_32(((uint32_t *)&d[0]), col)
35 #else
36 #error unsupported DEPTH
37 #endif
38 
39 static void
40 glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
41      (CirrusVGAState * s, uint8_t * dst,
42       const uint8_t * src,
43       int dstpitch, int srcpitch,
44       int bltwidth, int bltheight)
45 {
46     uint8_t *d;
47     int x, y, pattern_y, pattern_pitch, pattern_x;
48     unsigned int col;
49     const uint8_t *src1;
50 #if DEPTH == 24
51     int skipleft = s->vga.gr[0x2f] & 0x1f;
52 #else
53     int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8);
54 #endif
55 
56 #if DEPTH == 8
57     pattern_pitch = 8;
58 #elif DEPTH == 16
59     pattern_pitch = 16;
60 #else
61     pattern_pitch = 32;
62 #endif
63     pattern_y = s->cirrus_blt_srcaddr & 7;
64     for(y = 0; y < bltheight; y++) {
65         pattern_x = skipleft;
66         d = dst + skipleft;
67         src1 = src + pattern_y * pattern_pitch;
68         for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
69 #if DEPTH == 8
70             col = src1[pattern_x];
71             pattern_x = (pattern_x + 1) & 7;
72 #elif DEPTH == 16
73             col = ((uint16_t *)(src1 + pattern_x))[0];
74             pattern_x = (pattern_x + 2) & 15;
75 #elif DEPTH == 24
76             {
77                 const uint8_t *src2 = src1 + pattern_x * 3;
78                 col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
79                 pattern_x = (pattern_x + 1) & 7;
80             }
81 #else
82             col = ((uint32_t *)(src1 + pattern_x))[0];
83             pattern_x = (pattern_x + 4) & 31;
84 #endif
85             PUTPIXEL();
86             d += (DEPTH / 8);
87         }
88         pattern_y = (pattern_y + 1) & 7;
89         dst += dstpitch;
90     }
91 }
92 
93 /* NOTE: srcpitch is ignored */
94 static void
95 glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
96      (CirrusVGAState * s, uint8_t * dst,
97       const uint8_t * src,
98       int dstpitch, int srcpitch,
99       int bltwidth, int bltheight)
100 {
101     uint8_t *d;
102     int x, y;
103     unsigned bits, bits_xor;
104     unsigned int col;
105     unsigned bitmask;
106     unsigned index;
107 #if DEPTH == 24
108     int dstskipleft = s->vga.gr[0x2f] & 0x1f;
109     int srcskipleft = dstskipleft / 3;
110 #else
111     int srcskipleft = s->vga.gr[0x2f] & 0x07;
112     int dstskipleft = srcskipleft * (DEPTH / 8);
113 #endif
114 
115     if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
116         bits_xor = 0xff;
117         col = s->cirrus_blt_bgcol;
118     } else {
119         bits_xor = 0x00;
120         col = s->cirrus_blt_fgcol;
121     }
122 
123     for(y = 0; y < bltheight; y++) {
124         bitmask = 0x80 >> srcskipleft;
125         bits = *src++ ^ bits_xor;
126         d = dst + dstskipleft;
127         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
128             if ((bitmask & 0xff) == 0) {
129                 bitmask = 0x80;
130                 bits = *src++ ^ bits_xor;
131             }
132             index = (bits & bitmask);
133             if (index) {
134                 PUTPIXEL();
135             }
136             d += (DEPTH / 8);
137             bitmask >>= 1;
138         }
139         dst += dstpitch;
140     }
141 }
142 
143 static void
144 glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
145      (CirrusVGAState * s, uint8_t * dst,
146       const uint8_t * src,
147       int dstpitch, int srcpitch,
148       int bltwidth, int bltheight)
149 {
150     uint32_t colors[2];
151     uint8_t *d;
152     int x, y;
153     unsigned bits;
154     unsigned int col;
155     unsigned bitmask;
156     int srcskipleft = s->vga.gr[0x2f] & 0x07;
157     int dstskipleft = srcskipleft * (DEPTH / 8);
158 
159     colors[0] = s->cirrus_blt_bgcol;
160     colors[1] = s->cirrus_blt_fgcol;
161     for(y = 0; y < bltheight; y++) {
162         bitmask = 0x80 >> srcskipleft;
163         bits = *src++;
164         d = dst + dstskipleft;
165         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
166             if ((bitmask & 0xff) == 0) {
167                 bitmask = 0x80;
168                 bits = *src++;
169             }
170             col = colors[!!(bits & bitmask)];
171             PUTPIXEL();
172             d += (DEPTH / 8);
173             bitmask >>= 1;
174         }
175         dst += dstpitch;
176     }
177 }
178 
179 static void
180 glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
181      (CirrusVGAState * s, uint8_t * dst,
182       const uint8_t * src,
183       int dstpitch, int srcpitch,
184       int bltwidth, int bltheight)
185 {
186     uint8_t *d;
187     int x, y, bitpos, pattern_y;
188     unsigned int bits, bits_xor;
189     unsigned int col;
190 #if DEPTH == 24
191     int dstskipleft = s->vga.gr[0x2f] & 0x1f;
192     int srcskipleft = dstskipleft / 3;
193 #else
194     int srcskipleft = s->vga.gr[0x2f] & 0x07;
195     int dstskipleft = srcskipleft * (DEPTH / 8);
196 #endif
197 
198     if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
199         bits_xor = 0xff;
200         col = s->cirrus_blt_bgcol;
201     } else {
202         bits_xor = 0x00;
203         col = s->cirrus_blt_fgcol;
204     }
205     pattern_y = s->cirrus_blt_srcaddr & 7;
206 
207     for(y = 0; y < bltheight; y++) {
208         bits = src[pattern_y] ^ bits_xor;
209         bitpos = 7 - srcskipleft;
210         d = dst + dstskipleft;
211         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
212             if ((bits >> bitpos) & 1) {
213                 PUTPIXEL();
214             }
215             d += (DEPTH / 8);
216             bitpos = (bitpos - 1) & 7;
217         }
218         pattern_y = (pattern_y + 1) & 7;
219         dst += dstpitch;
220     }
221 }
222 
223 static void
224 glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
225      (CirrusVGAState * s, uint8_t * dst,
226       const uint8_t * src,
227       int dstpitch, int srcpitch,
228       int bltwidth, int bltheight)
229 {
230     uint32_t colors[2];
231     uint8_t *d;
232     int x, y, bitpos, pattern_y;
233     unsigned int bits;
234     unsigned int col;
235     int srcskipleft = s->vga.gr[0x2f] & 0x07;
236     int dstskipleft = srcskipleft * (DEPTH / 8);
237 
238     colors[0] = s->cirrus_blt_bgcol;
239     colors[1] = s->cirrus_blt_fgcol;
240     pattern_y = s->cirrus_blt_srcaddr & 7;
241 
242     for(y = 0; y < bltheight; y++) {
243         bits = src[pattern_y];
244         bitpos = 7 - srcskipleft;
245         d = dst + dstskipleft;
246         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
247             col = colors[(bits >> bitpos) & 1];
248             PUTPIXEL();
249             d += (DEPTH / 8);
250             bitpos = (bitpos - 1) & 7;
251         }
252         pattern_y = (pattern_y + 1) & 7;
253         dst += dstpitch;
254     }
255 }
256 
257 static void
258 glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
259      (CirrusVGAState *s,
260       uint8_t *dst, int dst_pitch,
261       int width, int height)
262 {
263     uint8_t *d, *d1;
264     uint32_t col;
265     int x, y;
266 
267     col = s->cirrus_blt_fgcol;
268 
269     d1 = dst;
270     for(y = 0; y < height; y++) {
271         d = d1;
272         for(x = 0; x < width; x += (DEPTH / 8)) {
273             PUTPIXEL();
274             d += (DEPTH / 8);
275         }
276         d1 += dst_pitch;
277     }
278 }
279 
280 #undef DEPTH
281 #undef PUTPIXEL
282