|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * Common code needed by all the various graphics systems. ! 5: * ! 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" ! 14: #include "memory.h" ! 15: #include "custom.h" ! 16: #include "newcpu.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: */ ! 28: static UBYTE dither[4][4] = ! 29: { ! 30: {0,8,2,10}, ! 31: {12,4,14,6}, ! 32: {3,11,1,9}, ! 33: {14 /* 15 */,7,13,5} ! 34: }; ! 35: ! 36: unsigned long doMask(int p, int bits, int shift) ! 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: ! 48: void alloc_colors64k(int rw, int gw, int bw, int rs, int gs, int bs) ! 49: { ! 50: int i; ! 51: for(i=0; i<4096; i++) { ! 52: int r = i >> 8; ! 53: int g = (i >> 4) & 0xF; ! 54: int b = i & 0xF; ! 55: xcolors[i] = doMask(r, rw, rs) | doMask(g, gw, gs) | doMask(b, bw, bs); ! 56: } ! 57: } ! 58: ! 59: static int allocated[4096]; ! 60: ! 61: void alloc_colors256(allocfunc_type allocfunc) ! 62: { ! 63: int nb_cols[3]; /* r,g,b */ ! 64: int maxcol = 256; ! 65: int i,j,k,l,t; ! 66: int diff[4096]; ! 67: ! 68: xcolnr *map; ! 69: ! 70: map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol); ! 71: ! 72: /* ! 73: * compute #cols per components ! 74: */ ! 75: for(i = 1; i*i*i <= maxcol; ++i) ! 76: ; ! 77: --i; ! 78: ! 79: nb_cols[RED] = i; ! 80: nb_cols[GRN] = i; ! 81: nb_cols[BLU] = i; ! 82: ! 83: /* ! 84: * set the colormap ! 85: */ ! 86: l=0; ! 87: for(i = 0; i < nb_cols[RED]; ++i) { ! 88: int r = (i * 15 + (nb_cols[RED] - 1)/2) / (nb_cols[RED] - 1); ! 89: for(j = 0; j < nb_cols[GRN]; ++j) { ! 90: int g = (j * 15 + (nb_cols[GRN] - 1)/2) / (nb_cols[GRN] - 1); ! 91: for(k = 0; k < nb_cols[BLU]; ++k) { ! 92: int b = (k * 15 + (nb_cols[BLU] - 1)/2) / (nb_cols[BLU] - 1); ! 93: int result; ! 94: result = allocfunc(r, g, b, map + l); ! 95: l++; ! 96: } ! 97: } ! 98: } ! 99: /* printf("%d color(s) lost\n",maxcol - l);*/ ! 100: ! 101: /* ! 102: * for each component compute the mapping ! 103: */ ! 104: { ! 105: int diffr, diffg, diffb, maxdiff = 0, won = 0, lost; ! 106: int r, d = 8; ! 107: for(r=0; r<16; ++r) { ! 108: int cr, g, q; ! 109: ! 110: k = nb_cols[RED]-1; ! 111: cr = (r * k) / 15; ! 112: q = (r * k) % 15; ! 113: if(q > d && cr < k) ++cr; ! 114: diffr = abs(cr*k-r); ! 115: for(g=0; g<16; ++g) { ! 116: int cg, b; ! 117: ! 118: k = nb_cols[GRN]-1; ! 119: cg = (g * k) / 15; ! 120: q = (g * k) % 15; ! 121: if(q > d && cg < k) ++cg; ! 122: diffg = abs(cg*k-g); ! 123: for(b=0; b<16; ++b) { ! 124: int cb, rgb = (r<<8) | (g<<4) | b; ! 125: ! 126: k = nb_cols[BLU]-1; ! 127: cb = (b * k) / 15; ! 128: q = (b * k) % 15; ! 129: if(q > d && cb < k) ++cb; ! 130: diffb = abs(cb*k-b); ! 131: xcolors[rgb] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb]; ! 132: diff[rgb] = diffr+diffg+diffb; ! 133: if (diff[rgb] > maxdiff) ! 134: maxdiff = diff[rgb]; ! 135: } ! 136: } ! 137: } ! 138: while (maxdiff > 0 && l < maxcol) { ! 139: int newmaxdiff = 0; ! 140: lost = 0; won++; ! 141: for(r = 15; r >= 0; r--) { ! 142: int cr, g, q; ! 143: ! 144: for(g = 15; g >= 0; g--) { ! 145: int cg, b; ! 146: ! 147: for(b = 15; b >= 0; b--) { ! 148: int cb, rgb = (r<<8) | (g<<4) | b; ! 149: ! 150: if (diff[rgb] == maxdiff) { ! 151: int result; ! 152: ! 153: if (l >= maxcol) ! 154: lost++; ! 155: else { ! 156: result = allocfunc(r, g, b, xcolors + rgb); ! 157: l++; ! 158: } ! 159: diff[rgb] = 0; ! 160: } else if (diff[rgb] > newmaxdiff) ! 161: newmaxdiff = diff[rgb]; ! 162: ! 163: } ! 164: } ! 165: } ! 166: maxdiff = newmaxdiff; ! 167: } ! 168: /* printf("%d color(s) lost, %d stages won\n",lost, won);*/ ! 169: } ! 170: free (map); ! 171: } ! 172: ! 173: /* ! 174: * This dithering process works by letting UAE run internaly in 12bit ! 175: * mode and doing the dithering on the fly when rendering to the display. ! 176: * The dithering algorithm is quite fast but uses lot of memory (4*8*2^12 = ! 177: * 128Kb). I don't think that is a trouble right now, but when UAE will ! 178: * emulate AGA and work internaly in 24bit mode, that dithering algorithm ! 179: * will need 4*8*2^24 = 512Mb. Obviously that fast algorithm will not be ! 180: * tractable. However, we could then use an other algorithm, slower, but ! 181: * far more reasonable (I am thinking about the one that is used in DJPEG). ! 182: */ ! 183: ! 184: UBYTE cidx[4][8*4096]; /* fast, but memory hungry =:-( */ ! 185: ! 186: /* ! 187: * Compute dithering structures ! 188: */ ! 189: void setup_greydither(int bits, allocfunc_type allocfunc) ! 190: { ! 191: int i,j,k,l,t; ! 192: int maxcol = 1 << bits; ! 193: xcolnr *map; ! 194: ! 195: for (i = 0; i < 4096; i++) ! 196: xcolors[i] = i; ! 197: ! 198: map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol); ! 199: ! 200: /* ! 201: * set the colormap ! 202: */ ! 203: for(i = 0; i < maxcol; ++i) { ! 204: int c, result; ! 205: c = (15 * i + (maxcol-1)/2) / (maxcol - 1); ! 206: result = allocfunc(c, c, c, map + i); ! 207: /* @@@ check for errors */ ! 208: } ! 209: ! 210: /* ! 211: * for each componant compute the mapping ! 212: */ ! 213: for(i=0;i<4;++i) { ! 214: for(j=0;j<4;++j) { ! 215: int r, d = dither[i][j]*17; ! 216: for(r=0; r<16; ++r) { ! 217: int g; ! 218: for(g=0; g<16; ++g) { ! 219: int b; ! 220: for(b=0; b<16; ++b) { ! 221: int rgb = (r<<8) | (g<<4) | b; ! 222: int c,p,q; ! 223: ! 224: c = (77 * r + ! 225: 151 * g + ! 226: 28 * b) / 15; /* c in 0..256 */ ! 227: ! 228: k = maxcol-1; ! 229: p = (c * k) / 256; ! 230: q = (c * k) % 256; ! 231: if(q / k > d / k && p < k) ++p; ! 232: cidx[i][rgb + (j+4)*4096] = ! 233: cidx[i][rgb + j*4096] = map[p]; ! 234: } ! 235: } ! 236: } ! 237: } ! 238: } ! 239: free (map); ! 240: } ! 241: ! 242: void setup_dither(int bits, allocfunc_type allocfunc) ! 243: { ! 244: int nb_cols[3]; /* r,g,b */ ! 245: int maxcol = 1 << bits; ! 246: int i,j,k,l,t; ! 247: ! 248: xcolnr *map; ! 249: int *redvals, *grnvals, *bluvals; ! 250: ! 251: map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol); ! 252: ! 253: for (i = 0; i < 4096; i++) ! 254: xcolors[i] = i; ! 255: ! 256: /* ! 257: * compute #cols per components ! 258: */ ! 259: for(i = 1; i*i*i <= maxcol; ++i) ! 260: ; ! 261: --i; ! 262: ! 263: nb_cols[RED] = i; ! 264: nb_cols[GRN] = i; ! 265: nb_cols[BLU] = i; ! 266: ! 267: if(nb_cols[RED]*(++i)*nb_cols[BLU] <= maxcol) { ! 268: nb_cols[GRN] = i; ! 269: if((i)*nb_cols[GRN]*nb_cols[BLU] <= maxcol) nb_cols[RED] = i; ! 270: } ! 271: ! 272: redvals = (int *)malloc(sizeof(int) * maxcol); ! 273: grnvals = redvals + nb_cols[RED]; ! 274: bluvals = grnvals + nb_cols[BLU]; ! 275: /* ! 276: * set the colormap ! 277: */ ! 278: l=0; ! 279: for(i = 0; i < nb_cols[RED]; ++i) { ! 280: int r = (i * 15 + (nb_cols[RED] - 1)/2) / (nb_cols[RED] - 1); ! 281: redvals[i] = r; ! 282: for(j = 0; j < nb_cols[GRN]; ++j) { ! 283: int g = (j * 15 + (nb_cols[GRN] - 1)/2) / (nb_cols[GRN] - 1); ! 284: grnvals[j] = g; ! 285: for(k = 0; k < nb_cols[BLU]; ++k) { ! 286: int b = (k * 15 + (nb_cols[BLU] - 1)/2) / (nb_cols[BLU] - 1); ! 287: int result; ! 288: bluvals[k] = b; ! 289: result = allocfunc(r, g, b, map + l); ! 290: l++; ! 291: } ! 292: } ! 293: } ! 294: fprintf(stderr, "%d color(s) lost\n",maxcol - l); ! 295: ! 296: /* ! 297: * for each component compute the mapping ! 298: */ ! 299: { ! 300: int r; ! 301: for(r=0; r<16; ++r) { ! 302: int g; ! 303: for(g=0; g<16; ++g) { ! 304: int b; ! 305: for(b=0; b<16; ++b) { ! 306: int rederr = 0, grnerr = 0, bluerr = 0; ! 307: int rgb = (r<<8) | (g<<4) | b; ! 308: ! 309: for(i=0;i<4;++i) for(j=0;j<4;++j) { ! 310: int d = dither[i][j]; ! 311: int cr, cg, cb, k, q; ! 312: #if 0 /* Slightly different algorithm. Needs some tuning. */ ! 313: k = nb_cols[RED]-1; ! 314: cr = r * k / 15; ! 315: q = r * k - 15*cr; ! 316: if (cr < 0) cr = 0; ! 317: else ! 318: if(q / k > d / k && rederr <= 0) ++cr; ! 319: if (cr > k) cr = k; ! 320: rederr += redvals[cr]-r; ! 321: ! 322: k = nb_cols[GRN]-1; ! 323: cg = g * k / 15; ! 324: q = g * k - 15*cg; ! 325: if (cg < 0) cg = 0; ! 326: else ! 327: if (q / k > d / k && grnerr <= 0) ++cg; ! 328: if (cg > k) cg = k; ! 329: grnerr += grnvals[cg]-g; ! 330: ! 331: k = nb_cols[BLU]-1; ! 332: cb = b * k / 15; ! 333: q = b * k - 15*cb; ! 334: if (cb < 0) cb = 0; ! 335: else ! 336: if (q / k > d / k && bluerr <= 0) ++cb; ! 337: if (cb > k) cb = k; ! 338: bluerr += bluvals[cb]-b; ! 339: #else ! 340: k = nb_cols[RED]-1; ! 341: cr = r * k / 15; ! 342: q = r * k - 15*cr; ! 343: if (cr < 0) cr = 0; ! 344: else ! 345: if(q / k > d / k) ++cr; ! 346: if (cr > k) cr = k; ! 347: ! 348: k = nb_cols[GRN]-1; ! 349: cg = g * k / 15; ! 350: q = g * k - 15*cg; ! 351: if (cg < 0) cg = 0; ! 352: else ! 353: if (q / k > d / k) ++cg; ! 354: if (cg > k) cg = k; ! 355: ! 356: k = nb_cols[BLU]-1; ! 357: cb = b * k / 15; ! 358: q = b * k - 15*cb; ! 359: if (cb < 0) cb = 0; ! 360: else ! 361: if (q / k > d / k) ++cb; ! 362: if (cb > k) cb = k; ! 363: #endif ! 364: cidx[i][rgb + (j+4)*4096] = cidx[i][rgb + j*4096] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb]; ! 365: } ! 366: } ! 367: } ! 368: } ! 369: } ! 370: free (map); ! 371: } ! 372: ! 373: #ifndef X86_ASSEMBLY ! 374: /* ! 375: * Dither the line. ! 376: * Make sure you call this only with (len & 3) == 0, or you'll just make ! 377: * yourself unhappy. ! 378: */ ! 379: ! 380: void DitherLine(UBYTE *l, UWORD *r4g4b4, int x, int y, UWORD len, int bits) ! 381: { ! 382: UBYTE *dith = cidx[y&3]+(x&3)*4096; ! 383: UBYTE d = 0; ! 384: int bitsleft = 8; ! 385: ! 386: while(len) { ! 387: int v; ! 388: v = dith[0*4096 + *r4g4b4++]; ! 389: bitsleft -= bits; ! 390: d |= (v << bitsleft); ! 391: if (!bitsleft) ! 392: *l++ = d, bitsleft = 8, d = 0; ! 393: ! 394: v = dith[1*4096 + *r4g4b4++]; ! 395: bitsleft -= bits; ! 396: d |= (v << bitsleft); ! 397: if (!bitsleft) ! 398: *l++ = d, bitsleft = 8, d = 0; ! 399: ! 400: v = dith[2*4096 + *r4g4b4++]; ! 401: bitsleft -= bits; ! 402: d |= (v << bitsleft); ! 403: if (!bitsleft) ! 404: *l++ = d, bitsleft = 8, d = 0; ! 405: ! 406: v = dith[3*4096 + *r4g4b4++]; ! 407: bitsleft -= bits; ! 408: d |= (v << bitsleft); ! 409: if (!bitsleft) ! 410: *l++ = d, bitsleft = 8, d = 0; ! 411: len -= 4; ! 412: } ! 413: } ! 414: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.