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