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