Annotation of uae/src/gfxutil.c, revision 1.1.1.9

1.1.1.3   root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.3   root        3:   *
1.1       root        4:   * Common code needed by all the various graphics systems.
1.1.1.3   root        5:   *
1.1       root        6:   * (c) 1996 Bernd Schmidt, Ed Hanway, Samuel Devulder
                      7:   */
                      8: 
                      9: #include "sysconfig.h"
                     10: #include "sysdeps.h"
                     11: 
                     12: #include "config.h"
                     13: #include "options.h"
1.1.1.6   root       14: #include "threaddep/thread.h"
1.1       root       15: #include "memory.h"
                     16: #include "custom.h"
                     17: #include "keyboard.h"
                     18: #include "xwin.h"
                     19: 
                     20: #define        RED     0
                     21: #define        GRN     1
                     22: #define        BLU     2
                     23: 
                     24: /*
                     25:  * dither matrix
                     26:  */
1.1.1.3   root       27: static uae_u8 dither[4][4] =
1.1       root       28: {
1.1.1.4   root       29:   { 0, 8, 2, 10 },
                     30:   { 12, 4, 14, 6 },
                     31:   { 3, 11, 1, 9 },
                     32:   { 14 /* 15 */, 7, 13, 5 }
1.1       root       33: };
                     34: 
1.1.1.4   root       35: unsigned long doMask (int p, int bits, int shift)
1.1       root       36: {
                     37:     /* p is a value from 0 to 15 (Amiga color value)
                     38:      * scale to 0..255, shift to align msb with mask, and apply mask */
                     39: 
                     40:     unsigned long val = p * 0x11111111UL;
                     41:     val >>= (32 - bits);
                     42:     val <<= shift;
                     43: 
                     44:     return val;
                     45: }
                     46: 
1.1.1.4   root       47: int bits_in_mask (unsigned long mask)
                     48: {
                     49:     int n = 0;
                     50:     while (mask) {
                     51:        n += mask & 1;
                     52:        mask >>= 1;
                     53:     }
                     54:     return n;
                     55: }
                     56: 
                     57: int mask_shift (unsigned long mask)
                     58: {
                     59:     int n = 0;
                     60:     while (!(mask & 1)) {
                     61:        n++;
                     62:        mask >>= 1;
                     63:     }
                     64:     return n;
                     65: }
                     66: 
                     67: unsigned long doMask256 (int p, int bits, int shift)
                     68: {
                     69:     /* p is a value from 0 to 255 (Amiga color value)
                     70:      * shift to align msb with mask, and apply mask */
                     71: 
                     72:     unsigned long val = p * 0x01010101UL;
                     73:     val >>= (32 - bits);
                     74:     val <<= shift;
                     75: 
                     76:     return val;
                     77: }
                     78: 
1.1.1.8   root       79: static unsigned int doColor (int i, int bits, int shift)
1.1.1.5   root       80: {
                     81:     int shift2;
                     82:     if(bits >= 8) shift2 = 0; else shift2 = 8 - bits;
                     83:     return (i >> shift2) << shift;
                     84: }
                     85: 
1.1.1.4   root       86: void alloc_colors64k (int rw, int gw, int bw, int rs, int gs, int bs)
1.1       root       87: {
                     88:     int i;
1.1.1.4   root       89:     for (i = 0; i < 4096; i++) {
1.1       root       90:        int r = i >> 8;
                     91:        int g = (i >> 4) & 0xF;
                     92:        int b = i & 0xF;
                     93:        xcolors[i] = doMask(r, rw, rs) | doMask(g, gw, gs) | doMask(b, bw, bs);
                     94:     }
1.1.1.5   root       95:     /* create AGA color tables */
1.1.1.8   root       96:     for(i = 0; i < 256; i++) {
1.1.1.5   root       97:        xredcolors[i] = doColor(i, rw, rs);
                     98:        xgreencolors[i] = doColor(i, gw, gs);
                     99:        xbluecolors[i] = doColor(i, bw, bs);
                    100:     }
1.1       root      101: }
                    102: 
                    103: static int allocated[4096];
1.1.1.2   root      104: static int color_diff[4096];
                    105: static int newmaxcol = 0;
                    106: 
1.1.1.4   root      107: void setup_maxcol (int max)
1.1.1.2   root      108: {
                    109:     newmaxcol = max;
                    110: }
1.1       root      111: 
1.1.1.4   root      112: void alloc_colors256 (allocfunc_type allocfunc)
1.1       root      113: {
                    114:     int nb_cols[3]; /* r,g,b */
1.1.1.2   root      115:     int maxcol = newmaxcol == 0 ? 256 : newmaxcol;
1.1.1.8   root      116:     int i,j,k,l;
1.1       root      117: 
                    118:     xcolnr *map;
1.1.1.3   root      119: 
1.1.1.4   root      120:     map = (xcolnr *)malloc (sizeof(xcolnr) * maxcol);
                    121:     if (!map) {
                    122:        write_log ("Not enough mem for colormap!\n");
                    123:        abort ();
1.1.1.3   root      124:     }
                    125: 
1.1       root      126:     /*
                    127:      * compute #cols per components
                    128:      */
1.1.1.4   root      129:     for (i = 1; i*i*i <= maxcol; ++i)
1.1       root      130:        ;
                    131:     --i;
                    132: 
                    133:     nb_cols[RED] = i;
                    134:     nb_cols[GRN] = i;
                    135:     nb_cols[BLU] = i;
                    136: 
                    137:     /*
                    138:      * set the colormap
                    139:      */
1.1.1.4   root      140:     l = 0;
                    141:     for (i = 0; i < nb_cols[RED]; ++i) {
1.1.1.3   root      142:        int r = (i * 15) / (nb_cols[RED] - 1);
1.1.1.4   root      143:        for (j = 0; j < nb_cols[GRN]; ++j) {
1.1.1.3   root      144:            int g = (j * 15) / (nb_cols[GRN] - 1);
1.1.1.4   root      145:            for (k = 0; k < nb_cols[BLU]; ++k) {
1.1.1.3   root      146:                int b = (k * 15) / (nb_cols[BLU] - 1);
1.1       root      147:                int result;
1.1.1.4   root      148:                result = allocfunc (r, g, b, map + l);
1.1       root      149:                l++;
                    150:            }
                    151:        }
                    152:     }
                    153: /*    printf("%d color(s) lost\n",maxcol - l);*/
                    154: 
                    155:     /*
                    156:      * for each component compute the mapping
                    157:      */
                    158:     {
                    159:        int diffr, diffg, diffb, maxdiff = 0, won = 0, lost;
                    160:        int r, d = 8;
1.1.1.4   root      161:        for (r = 0; r < 16; ++r) {
1.1       root      162:            int cr, g, q;
1.1.1.3   root      163: 
1.1.1.4   root      164:            k = nb_cols[RED]-1;
1.1       root      165:            cr = (r * k) / 15;
1.1.1.4   root      166:            q = (r * k) % 15;
                    167:            if (q > d && cr < k) ++cr;
                    168:            diffr = abs (cr*k - r);
                    169:            for (g = 0; g < 16; ++g) {
1.1       root      170:                int cg, b;
1.1.1.3   root      171: 
1.1.1.4   root      172:                k = nb_cols[GRN]-1;
1.1       root      173:                cg = (g * k) / 15;
                    174:                q  = (g * k) % 15;
1.1.1.4   root      175:                if (q > d && cg < k) ++cg;
                    176:                diffg = abs (cg*k - g);
                    177:                for (b = 0; b < 16; ++b) {
                    178:                    int cb, rgb = (r << 8) | (g << 4) | b;
1.1       root      179: 
1.1.1.4   root      180:                    k = nb_cols[BLU]-1;
1.1       root      181:                    cb = (b * k) / 15;
1.1.1.4   root      182:                    q = (b * k) % 15;
                    183:                    if (q > d && cb < k) ++cb;
                    184:                    diffb = abs (cb*k - b);
                    185:                    xcolors[rgb] = map[(cr * nb_cols[GRN] + cg) * nb_cols[BLU] + cb];
                    186:                    color_diff[rgb] = diffr + diffg + diffb;
1.1.1.2   root      187:                    if (color_diff[rgb] > maxdiff)
                    188:                        maxdiff = color_diff[rgb];
1.1       root      189:                }
                    190:            }
                    191:        }
                    192:        while (maxdiff > 0 && l < maxcol) {
                    193:            int newmaxdiff = 0;
                    194:            lost = 0; won++;
1.1.1.4   root      195:            for (r = 15; r >= 0; r--) {
                    196:                int g;
1.1.1.3   root      197: 
1.1.1.4   root      198:                for (g = 15; g >= 0; g--) {
                    199:                    int b;
1.1.1.3   root      200: 
1.1.1.4   root      201:                    for (b = 15; b >= 0; b--) {
                    202:                        int rgb = (r << 8) | (g << 4) | b;
1.1       root      203: 
1.1.1.2   root      204:                        if (color_diff[rgb] == maxdiff) {
1.1       root      205:                            int result;
1.1.1.3   root      206: 
1.1       root      207:                            if (l >= maxcol)
                    208:                                lost++;
                    209:                            else {
1.1.1.4   root      210:                                result = allocfunc (r, g, b, xcolors + rgb);
1.1       root      211:                                l++;
                    212:                            }
1.1.1.2   root      213:                            color_diff[rgb] = 0;
                    214:                        } else if (color_diff[rgb] > newmaxdiff)
                    215:                                newmaxdiff = color_diff[rgb];
1.1.1.3   root      216: 
1.1       root      217:                    }
                    218:                }
                    219:            }
                    220:            maxdiff = newmaxdiff;
                    221:        }
                    222: /*     printf("%d color(s) lost, %d stages won\n",lost, won);*/
                    223:     }
                    224:     free (map);
                    225: }
                    226: 
                    227: /*
                    228:  * This dithering process works by letting UAE run internaly in 12bit
                    229:  * mode and doing the dithering on the fly when rendering to the display.
                    230:  * The dithering algorithm is quite fast but uses lot of memory (4*8*2^12 =
1.1.1.3   root      231:  * 128Kb). I don't think that is a trouble right now, but when UAE will
1.1       root      232:  * emulate AGA and work internaly in 24bit mode, that dithering algorithm
                    233:  * will need 4*8*2^24 = 512Mb. Obviously that fast algorithm will not be
1.1.1.3   root      234:  * tractable. However, we could then use an other algorithm, slower, but
1.1       root      235:  * far more reasonable (I am thinking about the one that is used in DJPEG).
                    236:  */
                    237: 
1.1.1.3   root      238: uae_u8 cidx[4][8*4096]; /* fast, but memory hungry =:-( */
1.1       root      239: 
                    240: /*
                    241:  * Compute dithering structures
                    242:  */
1.1.1.4   root      243: void setup_greydither_maxcol (int maxcol, allocfunc_type allocfunc)
1.1       root      244: {
1.1.1.4   root      245:     int i,j,k;
1.1       root      246:     xcolnr *map;
1.1.1.3   root      247: 
1.1       root      248:     for (i = 0; i < 4096; i++)
                    249:        xcolors[i] = i;
1.1.1.3   root      250: 
1.1.1.4   root      251:     map = (xcolnr *)malloc (sizeof(xcolnr) * maxcol);
                    252:     if (!map) {
                    253:        write_log ("Not enough mem for colormap!\n");
1.1.1.3   root      254:        abort();
                    255:     }
1.1       root      256: 
                    257:     /*
                    258:      * set the colormap
                    259:      */
1.1.1.4   root      260:     for (i = 0; i < maxcol; ++i) {
1.1       root      261:        int c, result;
                    262:        c = (15 * i + (maxcol-1)/2) / (maxcol - 1);
1.1.1.3   root      263:        result = allocfunc(c, c, c, map + i);
1.1       root      264:        /* @@@ check for errors */
                    265:     }
                    266: 
                    267:     /*
                    268:      * for each componant compute the mapping
                    269:      */
1.1.1.4   root      270:     for (i = 0; i < 4; ++i) {
                    271:        for (j = 0; j < 4; ++j) {
1.1       root      272:            int r, d = dither[i][j]*17;
1.1.1.4   root      273:            for (r = 0; r<16; ++r) {
1.1       root      274:                int g;
1.1.1.4   root      275:                for (g = 0; g < 16; ++g) {
1.1       root      276:                    int  b;
1.1.1.4   root      277:                    for (b = 0; b < 16; ++b) {
                    278:                        int rgb = (r << 8) | (g << 4) | b;
1.1       root      279:                        int c,p,q;
1.1.1.3   root      280: 
                    281:                        c = (77  * r +
                    282:                             151 * g +
1.1       root      283:                             28  * b) / 15; /* c in 0..256 */
1.1.1.3   root      284: 
                    285:                        k = maxcol-1;
1.1       root      286:                        p = (c * k) / 256;
                    287:                        q = (c * k) % 256;
1.1.1.4   root      288:                        if (q /*/ k*/> d /*/ k*/ && p < k) ++p;
1.1.1.2   root      289: /* sam:                      ^^^^^^^ */
                    290: /*  It seems that produces better output */
1.1.1.3   root      291:                        cidx[i][rgb + (j+4)*4096] =
1.1       root      292:                            cidx[i][rgb + j*4096] = map[p];
                    293:                    }
                    294:                }
                    295:            }
                    296:        }
                    297:     }
                    298:     free (map);
                    299: }
                    300: 
1.1.1.4   root      301: void setup_greydither (int bits, allocfunc_type allocfunc)
1.1.1.2   root      302: {
                    303:     setup_greydither_maxcol(1 << bits, allocfunc);
                    304: }
                    305: 
1.1.1.4   root      306: void setup_dither (int bits, allocfunc_type allocfunc)
1.1       root      307: {
                    308:     int nb_cols[3]; /* r,g,b */
                    309:     int maxcol = 1 << bits;
1.1.1.4   root      310:     int i,j,k,l;
1.1       root      311: 
                    312:     xcolnr *map;
                    313:     int *redvals, *grnvals, *bluvals;
1.1.1.3   root      314: 
1.1.1.4   root      315:     map = (xcolnr *)malloc (sizeof(xcolnr) * maxcol);
                    316:     if (!map) {
                    317:        write_log ("Not enough mem for colormap!\n");
1.1.1.3   root      318:        abort();
                    319:     }
1.1       root      320: 
                    321:     for (i = 0; i < 4096; i++)
                    322:        xcolors[i] = i;
1.1.1.3   root      323: 
1.1       root      324:     /*
                    325:      * compute #cols per components
                    326:      */
1.1.1.4   root      327:     for (i = 1; i*i*i <= maxcol; ++i)
1.1       root      328:        ;
                    329:     --i;
                    330: 
                    331:     nb_cols[RED] = i;
                    332:     nb_cols[GRN] = i;
                    333:     nb_cols[BLU] = i;
                    334: 
1.1.1.4   root      335:     if (nb_cols[RED]*(++i)*nb_cols[BLU] <= maxcol) {
1.1       root      336:        nb_cols[GRN] = i;
1.1.1.4   root      337:        if ((i)*nb_cols[GRN]*nb_cols[BLU] <= maxcol)
                    338:            nb_cols[RED] = i;
1.1       root      339:     }
                    340: 
1.1.1.4   root      341:     redvals = (int *)malloc (sizeof(int) * maxcol);
1.1       root      342:     grnvals = redvals + nb_cols[RED];
1.1.1.3   root      343:     bluvals = grnvals + nb_cols[GRN];
1.1       root      344:     /*
                    345:      * set the colormap
                    346:      */
1.1.1.4   root      347:     l = 0;
                    348:     for (i = 0; i < nb_cols[RED]; ++i) {
1.1.1.3   root      349:        int r = (i * 15) / (nb_cols[RED] - 1);
1.1       root      350:        redvals[i] = r;
1.1.1.4   root      351:        for (j = 0; j < nb_cols[GRN]; ++j) {
1.1.1.3   root      352:            int g = (j * 15) / (nb_cols[GRN] - 1);
1.1       root      353:            grnvals[j] = g;
1.1.1.4   root      354:            for (k = 0; k < nb_cols[BLU]; ++k) {
1.1.1.3   root      355:                int b = (k * 15) / (nb_cols[BLU] - 1);
1.1       root      356:                int result;
                    357:                bluvals[k] = b;
                    358:                result = allocfunc(r, g, b, map + l);
                    359:                l++;
                    360:            }
                    361:        }
                    362:     }
1.1.1.7   root      363: /*    write_log ("%d color(s) lost\n",maxcol - l);*/
1.1       root      364: 
                    365:     /*
                    366:      * for each component compute the mapping
                    367:      */
                    368:     {
                    369:        int r;
1.1.1.4   root      370:        for (r = 0; r < 16; ++r) {
1.1       root      371:            int g;
1.1.1.4   root      372:            for (g = 0; g < 16; ++g) {
1.1       root      373:                int b;
1.1.1.4   root      374:                for (b = 0; b < 16; ++b) {
                    375:                    int rgb = (r << 8) | (g << 4) | b;
1.1       root      376: 
1.1.1.4   root      377:                    for (i = 0; i < 4; ++i) for (j = 0; j < 4; ++j) {
1.1       root      378:                        int d = dither[i][j];
                    379:                        int cr, cg, cb, k, q;
                    380: #if 0 /* Slightly different algorithm. Needs some tuning. */
1.1.1.4   root      381:                        int rederr = 0, grnerr = 0, bluerr = 0;
                    382: 
1.1       root      383:                        k  = nb_cols[RED]-1;
                    384:                        cr = r * k / 15;
                    385:                        q  = r * k - 15*cr;
1.1.1.4   root      386:                        if (cr < 0)
                    387:                            cr = 0;
                    388:                        else if (q / k > d / k && rederr <= 0)
                    389:                            ++cr;
1.1       root      390:                        if (cr > k) cr = k;
                    391:                        rederr += redvals[cr]-r;
1.1.1.3   root      392: 
1.1       root      393:                        k  = nb_cols[GRN]-1;
                    394:                        cg = g * k / 15;
                    395:                        q  = g * k - 15*cg;
1.1.1.4   root      396:                        if (cg < 0)
                    397:                            cg = 0;
                    398:                        else if (q / k > d / k && grnerr <= 0)
                    399:                            ++cg;
1.1       root      400:                        if (cg > k) cg = k;
                    401:                        grnerr += grnvals[cg]-g;
                    402: 
                    403:                        k  = nb_cols[BLU]-1;
                    404:                        cb = b * k / 15;
                    405:                        q  = b * k - 15*cb;
1.1.1.4   root      406:                        if (cb < 0)
                    407:                            cb = 0;
                    408:                        else if (q / k > d / k && bluerr <= 0)
                    409:                            ++cb;
1.1       root      410:                        if (cb > k) cb = k;
                    411:                        bluerr += bluvals[cb]-b;
                    412: #else
                    413:                        k  = nb_cols[RED]-1;
                    414:                        cr = r * k / 15;
                    415:                        q  = r * k - 15*cr;
1.1.1.4   root      416:                        if (cr < 0)
                    417:                            cr = 0;
                    418:                        else if (q /*/ k*/ > d /*/ k*/)
                    419:                            ++cr;
1.1       root      420:                        if (cr > k) cr = k;
1.1.1.3   root      421: 
1.1       root      422:                        k  = nb_cols[GRN]-1;
                    423:                        cg = g * k / 15;
                    424:                        q  = g * k - 15*cg;
1.1.1.4   root      425:                        if (cg < 0)
                    426:                            cg = 0;
                    427:                        else if (q /*/ k*/ > d /*/ k*/)
                    428:                            ++cg;
1.1       root      429:                        if (cg > k) cg = k;
                    430: 
                    431:                        k  = nb_cols[BLU]-1;
                    432:                        cb = b * k / 15;
                    433:                        q  = b * k - 15*cb;
1.1.1.4   root      434:                        if (cb < 0)
                    435:                            cb = 0;
                    436:                        else if (q /*/ k*/ > d /*/ k*/)
                    437:                            ++cb;
1.1       root      438:                        if (cb > k) cb = k;
                    439: #endif
                    440:                        cidx[i][rgb + (j+4)*4096] = cidx[i][rgb + j*4096] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb];
                    441:                    }
                    442:                }
                    443:            }
                    444:        }
                    445:     }
1.1.1.4   root      446:     free (redvals);
1.1       root      447:     free (map);
                    448: }
                    449: 
1.1.1.3   root      450: #if !defined X86_ASSEMBLY
1.1       root      451: /*
                    452:  * Dither the line.
                    453:  * Make sure you call this only with (len & 3) == 0, or you'll just make
                    454:  * yourself unhappy.
                    455:  */
                    456: 
1.1.1.4   root      457: void DitherLine (uae_u8 *l, uae_u16 *r4g4b4, int x, int y, uae_s16 len, int bits)
1.1       root      458: {
1.1.1.3   root      459:     uae_u8 *dith = cidx[y&3]+(x&3)*4096;
                    460:     uae_u8 d = 0;
1.1       root      461:     int bitsleft = 8;
1.1.1.3   root      462: 
1.1.1.4   root      463:     if (bits == 8) {
                    464:        while (len > 0) {
1.1.1.2   root      465:            *l++ = dith[0*4096 + *r4g4b4++];
                    466:            *l++ = dith[1*4096 + *r4g4b4++];
                    467:            *l++ = dith[2*4096 + *r4g4b4++];
                    468:            *l++ = dith[3*4096 + *r4g4b4++];
                    469:            len -= 4;
                    470:        }
                    471:        return;
                    472:     }
                    473: 
1.1.1.4   root      474:     while (len) {
1.1       root      475:        int v;
                    476:        v = dith[0*4096 + *r4g4b4++];
                    477:        bitsleft -= bits;
                    478:        d |= (v << bitsleft);
                    479:        if (!bitsleft)
                    480:            *l++ = d, bitsleft = 8, d = 0;
1.1.1.3   root      481: 
1.1       root      482:        v = dith[1*4096 + *r4g4b4++];
                    483:        bitsleft -= bits;
                    484:        d |= (v << bitsleft);
                    485:        if (!bitsleft)
                    486:            *l++ = d, bitsleft = 8, d = 0;
1.1.1.3   root      487: 
1.1       root      488:        v = dith[2*4096 + *r4g4b4++];
                    489:        bitsleft -= bits;
                    490:        d |= (v << bitsleft);
                    491:        if (!bitsleft)
                    492:            *l++ = d, bitsleft = 8, d = 0;
1.1.1.3   root      493: 
1.1       root      494:        v = dith[3*4096 + *r4g4b4++];
                    495:        bitsleft -= bits;
                    496:        d |= (v << bitsleft);
                    497:        if (!bitsleft)
                    498:            *l++ = d, bitsleft = 8, d = 0;
                    499:        len -= 4;
                    500:     }
                    501: }
                    502: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.