|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.