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

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

unix.superglobalmegacorp.com

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