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

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

unix.superglobalmegacorp.com

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