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