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

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

unix.superglobalmegacorp.com

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