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