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