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