xref: /openbmc/qemu/hw/display/cirrus_vga_rop2.h (revision a001631cb8eef07654e0ca508dd24f448e0fd936)
147b43a1fSPaolo Bonzini /*
247b43a1fSPaolo Bonzini  * QEMU Cirrus CLGD 54xx VGA Emulator.
347b43a1fSPaolo Bonzini  *
447b43a1fSPaolo Bonzini  * Copyright (c) 2004 Fabrice Bellard
547b43a1fSPaolo Bonzini  *
647b43a1fSPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
747b43a1fSPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
847b43a1fSPaolo Bonzini  * in the Software without restriction, including without limitation the rights
947b43a1fSPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1047b43a1fSPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
1147b43a1fSPaolo Bonzini  * furnished to do so, subject to the following conditions:
1247b43a1fSPaolo Bonzini  *
1347b43a1fSPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
1447b43a1fSPaolo Bonzini  * all copies or substantial portions of the Software.
1547b43a1fSPaolo Bonzini  *
1647b43a1fSPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1747b43a1fSPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1847b43a1fSPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1947b43a1fSPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2047b43a1fSPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2147b43a1fSPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2247b43a1fSPaolo Bonzini  * THE SOFTWARE.
2347b43a1fSPaolo Bonzini  */
2447b43a1fSPaolo Bonzini 
2547b43a1fSPaolo Bonzini #if DEPTH == 8
26026aeffcSGerd Hoffmann #define PUTPIXEL(s, a, c)    ROP_OP(s, a, c)
2747b43a1fSPaolo Bonzini #elif DEPTH == 16
28026aeffcSGerd Hoffmann #define PUTPIXEL(s, a, c)    ROP_OP_16(s, a, c)
2947b43a1fSPaolo Bonzini #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)
3547b43a1fSPaolo Bonzini #elif DEPTH == 32
36026aeffcSGerd Hoffmann #define PUTPIXEL(s, a, c)    ROP_OP_32(s, a, c)
3747b43a1fSPaolo Bonzini #else
3847b43a1fSPaolo Bonzini #error unsupported DEPTH
3947b43a1fSPaolo Bonzini #endif
4047b43a1fSPaolo Bonzini 
4147b43a1fSPaolo Bonzini static void
glue(glue (glue (cirrus_patternfill_,ROP_NAME),_),DEPTH)4247b43a1fSPaolo Bonzini glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
43026aeffcSGerd Hoffmann      (CirrusVGAState *s, uint32_t dstaddr,
44ffaf8577SGerd Hoffmann       uint32_t srcaddr,
4547b43a1fSPaolo Bonzini       int dstpitch, int srcpitch,
4647b43a1fSPaolo Bonzini       int bltwidth, int bltheight)
4747b43a1fSPaolo Bonzini {
48026aeffcSGerd Hoffmann     uint32_t addr;
4947b43a1fSPaolo Bonzini     int x, y, pattern_y, pattern_pitch, pattern_x;
5047b43a1fSPaolo Bonzini     unsigned int col;
51ffaf8577SGerd Hoffmann     uint32_t src1addr;
5247b43a1fSPaolo Bonzini #if DEPTH == 24
5347b43a1fSPaolo Bonzini     int skipleft = s->vga.gr[0x2f] & 0x1f;
5447b43a1fSPaolo Bonzini #else
5547b43a1fSPaolo Bonzini     int skipleft = (s->vga.gr[0x2f] & 0x07) * (DEPTH / 8);
5647b43a1fSPaolo Bonzini #endif
5747b43a1fSPaolo Bonzini 
5847b43a1fSPaolo Bonzini #if DEPTH == 8
5947b43a1fSPaolo Bonzini     pattern_pitch = 8;
6047b43a1fSPaolo Bonzini #elif DEPTH == 16
6147b43a1fSPaolo Bonzini     pattern_pitch = 16;
6247b43a1fSPaolo Bonzini #else
6347b43a1fSPaolo Bonzini     pattern_pitch = 32;
6447b43a1fSPaolo Bonzini #endif
6547b43a1fSPaolo Bonzini     pattern_y = s->cirrus_blt_srcaddr & 7;
6647b43a1fSPaolo Bonzini     for(y = 0; y < bltheight; y++) {
6747b43a1fSPaolo Bonzini         pattern_x = skipleft;
68026aeffcSGerd Hoffmann         addr = dstaddr + skipleft;
69ffaf8577SGerd Hoffmann         src1addr = srcaddr + pattern_y * pattern_pitch;
7047b43a1fSPaolo Bonzini         for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
7147b43a1fSPaolo Bonzini #if DEPTH == 8
72ffaf8577SGerd Hoffmann             col = cirrus_src(s, src1addr + pattern_x);
7347b43a1fSPaolo Bonzini             pattern_x = (pattern_x + 1) & 7;
7447b43a1fSPaolo Bonzini #elif DEPTH == 16
75ffaf8577SGerd Hoffmann             col = cirrus_src16(s, src1addr + pattern_x);
7647b43a1fSPaolo Bonzini             pattern_x = (pattern_x + 2) & 15;
7747b43a1fSPaolo Bonzini #elif DEPTH == 24
7847b43a1fSPaolo Bonzini             {
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);
8347b43a1fSPaolo Bonzini                 pattern_x = (pattern_x + 1) & 7;
8447b43a1fSPaolo Bonzini             }
8547b43a1fSPaolo Bonzini #else
86ffaf8577SGerd Hoffmann             col = cirrus_src32(s, src1addr + pattern_x);
8747b43a1fSPaolo Bonzini             pattern_x = (pattern_x + 4) & 31;
8847b43a1fSPaolo Bonzini #endif
89026aeffcSGerd Hoffmann             PUTPIXEL(s, addr, col);
90026aeffcSGerd Hoffmann             addr += (DEPTH / 8);
9147b43a1fSPaolo Bonzini         }
9247b43a1fSPaolo Bonzini         pattern_y = (pattern_y + 1) & 7;
93026aeffcSGerd Hoffmann         dstaddr += dstpitch;
9447b43a1fSPaolo Bonzini     }
9547b43a1fSPaolo Bonzini }
9647b43a1fSPaolo Bonzini 
9747b43a1fSPaolo Bonzini /* NOTE: srcpitch is ignored */
9847b43a1fSPaolo Bonzini static void
glue(glue (glue (cirrus_colorexpand_transp_,ROP_NAME),_),DEPTH)9947b43a1fSPaolo Bonzini glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
100026aeffcSGerd Hoffmann      (CirrusVGAState *s, uint32_t dstaddr,
101ffaf8577SGerd Hoffmann       uint32_t srcaddr,
10247b43a1fSPaolo Bonzini       int dstpitch, int srcpitch,
10347b43a1fSPaolo Bonzini       int bltwidth, int bltheight)
10447b43a1fSPaolo Bonzini {
105026aeffcSGerd Hoffmann     uint32_t addr;
10647b43a1fSPaolo Bonzini     int x, y;
10747b43a1fSPaolo Bonzini     unsigned bits, bits_xor;
10847b43a1fSPaolo Bonzini     unsigned int col;
10947b43a1fSPaolo Bonzini     unsigned bitmask;
11047b43a1fSPaolo Bonzini     unsigned index;
11147b43a1fSPaolo Bonzini #if DEPTH == 24
11247b43a1fSPaolo Bonzini     int dstskipleft = s->vga.gr[0x2f] & 0x1f;
11347b43a1fSPaolo Bonzini     int srcskipleft = dstskipleft / 3;
11447b43a1fSPaolo Bonzini #else
11547b43a1fSPaolo Bonzini     int srcskipleft = s->vga.gr[0x2f] & 0x07;
11647b43a1fSPaolo Bonzini     int dstskipleft = srcskipleft * (DEPTH / 8);
11747b43a1fSPaolo Bonzini #endif
11847b43a1fSPaolo Bonzini 
11947b43a1fSPaolo Bonzini     if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
12047b43a1fSPaolo Bonzini         bits_xor = 0xff;
12147b43a1fSPaolo Bonzini         col = s->cirrus_blt_bgcol;
12247b43a1fSPaolo Bonzini     } else {
12347b43a1fSPaolo Bonzini         bits_xor = 0x00;
12447b43a1fSPaolo Bonzini         col = s->cirrus_blt_fgcol;
12547b43a1fSPaolo Bonzini     }
12647b43a1fSPaolo Bonzini 
12747b43a1fSPaolo Bonzini     for(y = 0; y < bltheight; y++) {
12847b43a1fSPaolo Bonzini         bitmask = 0x80 >> srcskipleft;
129ffaf8577SGerd Hoffmann         bits = cirrus_src(s, srcaddr++) ^ bits_xor;
130026aeffcSGerd Hoffmann         addr = dstaddr + dstskipleft;
13147b43a1fSPaolo Bonzini         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
13247b43a1fSPaolo Bonzini             if ((bitmask & 0xff) == 0) {
13347b43a1fSPaolo Bonzini                 bitmask = 0x80;
134ffaf8577SGerd Hoffmann                 bits = cirrus_src(s, srcaddr++) ^ bits_xor;
13547b43a1fSPaolo Bonzini             }
13647b43a1fSPaolo Bonzini             index = (bits & bitmask);
13747b43a1fSPaolo Bonzini             if (index) {
138026aeffcSGerd Hoffmann                 PUTPIXEL(s, addr, col);
13947b43a1fSPaolo Bonzini             }
140026aeffcSGerd Hoffmann             addr += (DEPTH / 8);
14147b43a1fSPaolo Bonzini             bitmask >>= 1;
14247b43a1fSPaolo Bonzini         }
143026aeffcSGerd Hoffmann         dstaddr += dstpitch;
14447b43a1fSPaolo Bonzini     }
14547b43a1fSPaolo Bonzini }
14647b43a1fSPaolo Bonzini 
14747b43a1fSPaolo Bonzini static void
glue(glue (glue (cirrus_colorexpand_,ROP_NAME),_),DEPTH)14847b43a1fSPaolo Bonzini glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
149026aeffcSGerd Hoffmann      (CirrusVGAState *s, uint32_t dstaddr,
150ffaf8577SGerd Hoffmann       uint32_t srcaddr,
15147b43a1fSPaolo Bonzini       int dstpitch, int srcpitch,
15247b43a1fSPaolo Bonzini       int bltwidth, int bltheight)
15347b43a1fSPaolo Bonzini {
15447b43a1fSPaolo Bonzini     uint32_t colors[2];
155026aeffcSGerd Hoffmann     uint32_t addr;
15647b43a1fSPaolo Bonzini     int x, y;
15747b43a1fSPaolo Bonzini     unsigned bits;
15847b43a1fSPaolo Bonzini     unsigned int col;
15947b43a1fSPaolo Bonzini     unsigned bitmask;
16047b43a1fSPaolo Bonzini     int srcskipleft = s->vga.gr[0x2f] & 0x07;
16147b43a1fSPaolo Bonzini     int dstskipleft = srcskipleft * (DEPTH / 8);
16247b43a1fSPaolo Bonzini 
16347b43a1fSPaolo Bonzini     colors[0] = s->cirrus_blt_bgcol;
16447b43a1fSPaolo Bonzini     colors[1] = s->cirrus_blt_fgcol;
16547b43a1fSPaolo Bonzini     for(y = 0; y < bltheight; y++) {
16647b43a1fSPaolo Bonzini         bitmask = 0x80 >> srcskipleft;
167ffaf8577SGerd Hoffmann         bits = cirrus_src(s, srcaddr++);
168026aeffcSGerd Hoffmann         addr = dstaddr + dstskipleft;
16947b43a1fSPaolo Bonzini         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
17047b43a1fSPaolo Bonzini             if ((bitmask & 0xff) == 0) {
17147b43a1fSPaolo Bonzini                 bitmask = 0x80;
172ffaf8577SGerd Hoffmann                 bits = cirrus_src(s, srcaddr++);
17347b43a1fSPaolo Bonzini             }
17447b43a1fSPaolo Bonzini             col = colors[!!(bits & bitmask)];
175026aeffcSGerd Hoffmann             PUTPIXEL(s, addr, col);
176026aeffcSGerd Hoffmann             addr += (DEPTH / 8);
17747b43a1fSPaolo Bonzini             bitmask >>= 1;
17847b43a1fSPaolo Bonzini         }
179026aeffcSGerd Hoffmann         dstaddr += dstpitch;
18047b43a1fSPaolo Bonzini     }
18147b43a1fSPaolo Bonzini }
18247b43a1fSPaolo Bonzini 
18347b43a1fSPaolo Bonzini static void
glue(glue (glue (cirrus_colorexpand_pattern_transp_,ROP_NAME),_),DEPTH)18447b43a1fSPaolo Bonzini glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
185026aeffcSGerd Hoffmann      (CirrusVGAState *s, uint32_t dstaddr,
186ffaf8577SGerd Hoffmann       uint32_t srcaddr,
18747b43a1fSPaolo Bonzini       int dstpitch, int srcpitch,
18847b43a1fSPaolo Bonzini       int bltwidth, int bltheight)
18947b43a1fSPaolo Bonzini {
190026aeffcSGerd Hoffmann     uint32_t addr;
19147b43a1fSPaolo Bonzini     int x, y, bitpos, pattern_y;
19247b43a1fSPaolo Bonzini     unsigned int bits, bits_xor;
19347b43a1fSPaolo Bonzini     unsigned int col;
19447b43a1fSPaolo Bonzini #if DEPTH == 24
19547b43a1fSPaolo Bonzini     int dstskipleft = s->vga.gr[0x2f] & 0x1f;
19647b43a1fSPaolo Bonzini     int srcskipleft = dstskipleft / 3;
19747b43a1fSPaolo Bonzini #else
19847b43a1fSPaolo Bonzini     int srcskipleft = s->vga.gr[0x2f] & 0x07;
19947b43a1fSPaolo Bonzini     int dstskipleft = srcskipleft * (DEPTH / 8);
20047b43a1fSPaolo Bonzini #endif
20147b43a1fSPaolo Bonzini 
20247b43a1fSPaolo Bonzini     if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
20347b43a1fSPaolo Bonzini         bits_xor = 0xff;
20447b43a1fSPaolo Bonzini         col = s->cirrus_blt_bgcol;
20547b43a1fSPaolo Bonzini     } else {
20647b43a1fSPaolo Bonzini         bits_xor = 0x00;
20747b43a1fSPaolo Bonzini         col = s->cirrus_blt_fgcol;
20847b43a1fSPaolo Bonzini     }
20947b43a1fSPaolo Bonzini     pattern_y = s->cirrus_blt_srcaddr & 7;
21047b43a1fSPaolo Bonzini 
21147b43a1fSPaolo Bonzini     for(y = 0; y < bltheight; y++) {
212ffaf8577SGerd Hoffmann         bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor;
21347b43a1fSPaolo Bonzini         bitpos = 7 - srcskipleft;
214026aeffcSGerd Hoffmann         addr = dstaddr + dstskipleft;
21547b43a1fSPaolo Bonzini         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
21647b43a1fSPaolo Bonzini             if ((bits >> bitpos) & 1) {
217026aeffcSGerd Hoffmann                 PUTPIXEL(s, addr, col);
21847b43a1fSPaolo Bonzini             }
219026aeffcSGerd Hoffmann             addr += (DEPTH / 8);
22047b43a1fSPaolo Bonzini             bitpos = (bitpos - 1) & 7;
22147b43a1fSPaolo Bonzini         }
22247b43a1fSPaolo Bonzini         pattern_y = (pattern_y + 1) & 7;
223026aeffcSGerd Hoffmann         dstaddr += dstpitch;
22447b43a1fSPaolo Bonzini     }
22547b43a1fSPaolo Bonzini }
22647b43a1fSPaolo Bonzini 
22747b43a1fSPaolo Bonzini static void
glue(glue (glue (cirrus_colorexpand_pattern_,ROP_NAME),_),DEPTH)22847b43a1fSPaolo Bonzini glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
229026aeffcSGerd Hoffmann      (CirrusVGAState *s, uint32_t dstaddr,
230ffaf8577SGerd Hoffmann       uint32_t srcaddr,
23147b43a1fSPaolo Bonzini       int dstpitch, int srcpitch,
23247b43a1fSPaolo Bonzini       int bltwidth, int bltheight)
23347b43a1fSPaolo Bonzini {
23447b43a1fSPaolo Bonzini     uint32_t colors[2];
235026aeffcSGerd Hoffmann     uint32_t addr;
23647b43a1fSPaolo Bonzini     int x, y, bitpos, pattern_y;
23747b43a1fSPaolo Bonzini     unsigned int bits;
23847b43a1fSPaolo Bonzini     unsigned int col;
23947b43a1fSPaolo Bonzini     int srcskipleft = s->vga.gr[0x2f] & 0x07;
24047b43a1fSPaolo Bonzini     int dstskipleft = srcskipleft * (DEPTH / 8);
24147b43a1fSPaolo Bonzini 
24247b43a1fSPaolo Bonzini     colors[0] = s->cirrus_blt_bgcol;
24347b43a1fSPaolo Bonzini     colors[1] = s->cirrus_blt_fgcol;
24447b43a1fSPaolo Bonzini     pattern_y = s->cirrus_blt_srcaddr & 7;
24547b43a1fSPaolo Bonzini 
24647b43a1fSPaolo Bonzini     for(y = 0; y < bltheight; y++) {
247ffaf8577SGerd Hoffmann         bits = cirrus_src(s, srcaddr + pattern_y);
24847b43a1fSPaolo Bonzini         bitpos = 7 - srcskipleft;
249026aeffcSGerd Hoffmann         addr = dstaddr + dstskipleft;
25047b43a1fSPaolo Bonzini         for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
25147b43a1fSPaolo Bonzini             col = colors[(bits >> bitpos) & 1];
252026aeffcSGerd Hoffmann             PUTPIXEL(s, addr, col);
253026aeffcSGerd Hoffmann             addr += (DEPTH / 8);
25447b43a1fSPaolo Bonzini             bitpos = (bitpos - 1) & 7;
25547b43a1fSPaolo Bonzini         }
25647b43a1fSPaolo Bonzini         pattern_y = (pattern_y + 1) & 7;
257026aeffcSGerd Hoffmann         dstaddr += dstpitch;
25847b43a1fSPaolo Bonzini     }
25947b43a1fSPaolo Bonzini }
26047b43a1fSPaolo Bonzini 
26147b43a1fSPaolo Bonzini static void
glue(glue (glue (cirrus_fill_,ROP_NAME),_),DEPTH)26247b43a1fSPaolo Bonzini glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
26347b43a1fSPaolo Bonzini      (CirrusVGAState *s,
264026aeffcSGerd Hoffmann       uint32_t dstaddr, int dst_pitch,
26547b43a1fSPaolo Bonzini       int width, int height)
26647b43a1fSPaolo Bonzini {
267026aeffcSGerd Hoffmann     uint32_t addr;
26847b43a1fSPaolo Bonzini     uint32_t col;
26947b43a1fSPaolo Bonzini     int x, y;
27047b43a1fSPaolo Bonzini 
27147b43a1fSPaolo Bonzini     col = s->cirrus_blt_fgcol;
27247b43a1fSPaolo Bonzini 
27347b43a1fSPaolo Bonzini     for(y = 0; y < height; y++) {
274026aeffcSGerd Hoffmann         addr = dstaddr;
27547b43a1fSPaolo Bonzini         for(x = 0; x < width; x += (DEPTH / 8)) {
276026aeffcSGerd Hoffmann             PUTPIXEL(s, addr, col);
277026aeffcSGerd Hoffmann             addr += (DEPTH / 8);
27847b43a1fSPaolo Bonzini         }
279026aeffcSGerd Hoffmann         dstaddr += dst_pitch;
28047b43a1fSPaolo Bonzini     }
28147b43a1fSPaolo Bonzini }
28247b43a1fSPaolo Bonzini 
28347b43a1fSPaolo Bonzini #undef DEPTH
28447b43a1fSPaolo Bonzini #undef PUTPIXEL
285