Merge branch 'master' of ssh://repo.or.cz/srv/git/tgl
[tgl.git] / src / zbuffer.c
blobee38ea6eb753496599b52036fe58777cd5f9b9d8
1 /*
3 * Z buffer: 16 bits Z / 16 bits color
4 *
5 */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <assert.h>
9 #include <string.h>
10 #include "zbuffer.h"
12 ZBuffer *ZB_open(int xsize, int ysize, int mode,
13 int nb_colors,
14 unsigned char *color_indexes,
15 int *color_table,
16 void *frame_buffer)
18 ZBuffer *zb;
19 int size;
21 zb = gl_malloc(sizeof(ZBuffer));
22 if (zb == NULL)
23 return NULL;
25 zb->xsize = xsize;
26 zb->ysize = ysize;
27 zb->mode = mode;
28 zb->linesize = (xsize * PSZB + 3) & ~3;
30 switch (mode) {
31 #ifdef TGL_FEATURE_8_BITS
32 case ZB_MODE_INDEX:
33 ZB_initDither(zb, nb_colors, color_indexes, color_table);
34 break;
35 #endif
36 #ifdef TGL_FEATURE_32_BITS
37 case ZB_MODE_RGBA:
38 #endif
39 #ifdef TGL_FEATURE_24_BITS
40 case ZB_MODE_RGB24:
41 #endif
42 case ZB_MODE_5R6G5B:
43 zb->nb_colors = 0;
44 break;
45 default:
46 goto error;
49 size = zb->xsize * zb->ysize * sizeof(unsigned short);
51 zb->zbuf = gl_malloc(size);
52 if (zb->zbuf == NULL)
53 goto error;
55 if (frame_buffer == NULL) {
56 zb->pbuf = gl_malloc(zb->ysize * zb->linesize);
57 if (zb->pbuf == NULL) {
58 gl_free(zb->zbuf);
59 goto error;
61 zb->frame_buffer_allocated = 1;
62 } else {
63 zb->frame_buffer_allocated = 0;
64 zb->pbuf = frame_buffer;
67 zb->current_texture = NULL;
69 return zb;
70 error:
71 gl_free(zb);
72 return NULL;
75 void ZB_close(ZBuffer * zb)
77 #ifdef TGL_FEATURE_8_BITS
78 if (zb->mode == ZB_MODE_INDEX)
79 ZB_closeDither(zb);
80 #endif
82 if (zb->frame_buffer_allocated)
83 gl_free(zb->pbuf);
85 gl_free(zb->zbuf);
86 gl_free(zb);
89 void ZB_resize(ZBuffer * zb, void *frame_buffer, int xsize, int ysize)
91 int size;
93 /* xsize must be a multiple of 4 */
94 xsize = xsize & ~3;
96 zb->xsize = xsize;
97 zb->ysize = ysize;
98 zb->linesize = (xsize * PSZB + 3) & ~3;
100 size = zb->xsize * zb->ysize * sizeof(unsigned short);
102 gl_free(zb->zbuf);
103 zb->zbuf = gl_malloc(size);
105 if (zb->frame_buffer_allocated)
106 gl_free(zb->pbuf);
108 if (frame_buffer == NULL) {
109 zb->pbuf = gl_malloc(zb->ysize * zb->linesize);
110 zb->frame_buffer_allocated = 1;
111 } else {
112 zb->pbuf = frame_buffer;
113 zb->frame_buffer_allocated = 0;
117 static void ZB_copyBuffer(ZBuffer * zb,
118 void *buf,
119 int linesize)
121 unsigned char *p1;
122 PIXEL *q;
123 int y, n;
125 q = zb->pbuf;
126 p1 = buf;
127 n = zb->xsize * PSZB;
128 for (y = 0; y < zb->ysize; y++) {
129 memcpy(p1, q, n);
130 p1 += linesize;
131 q = (PIXEL *) ((char *) q + zb->linesize);
135 #if TGL_FEATURE_RENDER_BITS == 16
137 /* 32 bpp copy */
139 #ifdef TGL_FEATURE_32_BITS
141 #define RGB16_TO_RGB32(p0,p1,v)\
143 unsigned int g,b,gb;\
144 g = (v & 0x07E007E0) << 5;\
145 b = (v & 0x001F001F) << 3;\
146 gb = g | b;\
147 p0 = (gb & 0x0000FFFF) | ((v & 0x0000F800) << 8);\
148 p1 = (gb >> 16) | ((v & 0xF8000000) >> 8);\
151 static void ZB_copyFrameBufferRGB32(ZBuffer * zb,
152 void *buf,
153 int linesize)
155 unsigned short *q;
156 unsigned int *p, *p1, v, w0, w1;
157 int y, n;
159 q = zb->pbuf;
160 p1 = (unsigned int *) buf;
162 for (y = 0; y < zb->ysize; y++) {
163 p = p1;
164 n = zb->xsize >> 2;
165 do {
166 v = *(unsigned int *) q;
167 #if BYTE_ORDER == BIG_ENDIAN
168 RGB16_TO_RGB32(w1, w0, v);
169 #else
170 RGB16_TO_RGB32(w0, w1, v);
171 #endif
172 p[0] = w0;
173 p[1] = w1;
175 v = *(unsigned int *) (q + 2);
176 #if BYTE_ORDER == BIG_ENDIAN
177 RGB16_TO_RGB32(w1, w0, v);
178 #else
179 RGB16_TO_RGB32(w0, w1, v);
180 #endif
181 p[2] = w0;
182 p[3] = w1;
184 q += 4;
185 p += 4;
186 } while (--n > 0);
188 p1 += linesize;
192 #endif
194 /* 24 bit packed pixel handling */
196 #ifdef TGL_FEATURE_24_BITS
198 /* order: RGBR GBRG BRGB */
200 /* XXX: packed pixel 24 bit support not tested */
201 /* XXX: big endian case not optimised */
203 #if BYTE_ORDER == BIG_ENDIAN
205 #define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\
207 unsigned int r1,g1,b1,gb1,g2,b2,gb2;\
208 v1 = (v1 << 16) | (v1 >> 16);\
209 v2 = (v2 << 16) | (v2 >> 16);\
210 r1 = (v1 & 0xF800F800);\
211 g1 = (v1 & 0x07E007E0) << 5;\
212 b1 = (v1 & 0x001F001F) << 3;\
213 gb1 = g1 | b1;\
214 p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\
215 g2 = (v2 & 0x07E007E0) << 5;\
216 b2 = (v2 & 0x001F001F) << 3;\
217 gb2 = g2 | b2;\
218 p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\
219 p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\
222 #else
224 #define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\
226 unsigned int r1,g1,b1,gb1,g2,b2,gb2;\
227 r1 = (v1 & 0xF800F800);\
228 g1 = (v1 & 0x07E007E0) << 5;\
229 b1 = (v1 & 0x001F001F) << 3;\
230 gb1 = g1 | b1;\
231 p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\
232 g2 = (v2 & 0x07E007E0) << 5;\
233 b2 = (v2 & 0x001F001F) << 3;\
234 gb2 = g2 | b2;\
235 p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\
236 p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\
239 #endif
241 static void ZB_copyFrameBufferRGB24(ZBuffer * zb,
242 void *buf,
243 int linesize)
245 unsigned short *q;
246 unsigned int *p, *p1, w0, w1, w2, v0, v1;
247 int y, n;
249 q = zb->pbuf;
250 p1 = (unsigned int *) buf;
251 linesize = linesize * 3;
253 for (y = 0; y < zb->ysize; y++) {
254 p = p1;
255 n = zb->xsize >> 2;
256 do {
257 v0 = *(unsigned int *) q;
258 v1 = *(unsigned int *) (q + 2);
259 RGB16_TO_RGB24(w0, w1, w2, v0, v1);
260 p[0] = w0;
261 p[1] = w1;
262 p[2] = w2;
264 q += 4;
265 p += 3;
266 } while (--n > 0);
268 p1 = (char *)p1 + linesize;
272 #endif
274 void ZB_copyFrameBuffer(ZBuffer * zb, void *buf,
275 int linesize)
277 switch (zb->mode) {
278 #ifdef TGL_FEATURE_8_BITS
279 case ZB_MODE_INDEX:
280 ZB_ditherFrameBuffer(zb, buf, linesize >> 1);
281 break;
282 #endif
283 #ifdef TGL_FEATURE_16_BITS
284 case ZB_MODE_5R6G5B:
285 ZB_copyBuffer(zb, buf, linesize);
286 break;
287 #endif
288 #ifdef TGL_FEATURE_32_BITS
289 case ZB_MODE_RGBA:
290 ZB_copyFrameBufferRGB32(zb, buf, linesize >> 1);
291 break;
292 #endif
293 #ifdef TGL_FEATURE_24_BITS
294 case ZB_MODE_RGB24:
295 ZB_copyFrameBufferRGB24(zb, buf, linesize >> 1);
296 break;
297 #endif
298 default:
299 assert(0);
303 #endif /* TGL_FEATURE_RENDER_BITS == 16 */
305 #if TGL_FEATURE_RENDER_BITS == 24
307 #define RGB24_TO_RGB16(r, g, b) \
308 ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
310 /* XXX: not optimized */
311 static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb,
312 void *buf, int linesize)
314 PIXEL *q;
315 unsigned short *p, *p1;
316 int y, n;
318 q = zb->pbuf;
319 p1 = (unsigned short *) buf;
321 for (y = 0; y < zb->ysize; y++) {
322 p = p1;
323 n = zb->xsize >> 2;
324 do {
325 p[0] = RGB24_TO_RGB16(q[0], q[1], q[2]);
326 p[1] = RGB24_TO_RGB16(q[3], q[4], q[5]);
327 p[2] = RGB24_TO_RGB16(q[6], q[7], q[8]);
328 p[3] = RGB24_TO_RGB16(q[9], q[10], q[11]);
329 q = (PIXEL *)((char *)q + 4 * PSZB);
330 p += 4;
331 } while (--n > 0);
332 p1 = (unsigned short *)((char *)p1 + linesize);
336 void ZB_copyFrameBuffer(ZBuffer * zb, void *buf,
337 int linesize)
339 switch (zb->mode) {
340 #ifdef TGL_FEATURE_16_BITS
341 case ZB_MODE_5R6G5B:
342 ZB_copyFrameBuffer5R6G5B(zb, buf, linesize);
343 break;
344 #endif
345 #ifdef TGL_FEATURE_24_BITS
346 case ZB_MODE_RGB24:
347 ZB_copyBuffer(zb, buf, linesize);
348 break;
349 #endif
350 default:
351 assert(0);
355 #endif /* TGL_FEATURE_RENDER_BITS == 24 */
357 #if TGL_FEATURE_RENDER_BITS == 32
359 #define RGB32_TO_RGB16(v) \
360 (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3))
362 /* XXX: not optimized */
363 static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb,
364 void *buf, int linesize)
366 PIXEL *q;
367 unsigned short *p, *p1;
368 int y, n;
370 q = zb->pbuf;
371 p1 = (unsigned short *) buf;
373 for (y = 0; y < zb->ysize; y++) {
374 p = p1;
375 n = zb->xsize >> 2;
376 do {
377 p[0] = RGB32_TO_RGB16(q[0]);
378 p[1] = RGB32_TO_RGB16(q[1]);
379 p[2] = RGB32_TO_RGB16(q[2]);
380 p[3] = RGB32_TO_RGB16(q[3]);
381 q += 4;
382 p += 4;
383 } while (--n > 0);
384 p1 = (unsigned short *)((char *)p1 + linesize);
388 void ZB_copyFrameBuffer(ZBuffer * zb, void *buf,
389 int linesize)
391 switch (zb->mode) {
392 #ifdef TGL_FEATURE_16_BITS
393 case ZB_MODE_5R6G5B:
394 ZB_copyFrameBuffer5R6G5B(zb, buf, linesize);
395 break;
396 #endif
397 #ifdef TGL_FEATURE_32_BITS
398 case ZB_MODE_RGBA:
399 ZB_copyBuffer(zb, buf, linesize);
400 break;
401 #endif
402 default:
403 assert(0);
407 #endif /* TGL_FEATURE_RENDER_BITS == 32 */
411 * adr must be aligned on an 'int'
413 void memset_s(void *adr, int val, int count)
415 int i, n, v;
416 unsigned int *p;
417 unsigned short *q;
419 p = adr;
420 v = val | (val << 16);
422 n = count >> 3;
423 for (i = 0; i < n; i++) {
424 p[0] = v;
425 p[1] = v;
426 p[2] = v;
427 p[3] = v;
428 p += 4;
431 q = (unsigned short *) p;
432 n = count & 7;
433 for (i = 0; i < n; i++)
434 *q++ = val;
437 void memset_l(void *adr, int val, int count)
439 int i, n, v;
440 unsigned int *p;
442 p = adr;
443 v = val;
444 n = count >> 2;
445 for (i = 0; i < n; i++) {
446 p[0] = v;
447 p[1] = v;
448 p[2] = v;
449 p[3] = v;
450 p += 4;
453 n = count & 3;
454 for (i = 0; i < n; i++)
455 *p++ = val;
458 /* count must be a multiple of 4 and >= 4 */
459 void memset_RGB24(void *adr,int r, int v, int b,long count)
461 long i, n;
462 register long v1,v2,v3,*pt=(long *)(adr);
463 unsigned char *p,R=(unsigned char)r,V=(unsigned char)v,B=(unsigned char)b;
465 p=(unsigned char *)adr;
466 *p++=R;
467 *p++=V;
468 *p++=B;
469 *p++=R;
470 *p++=V;
471 *p++=B;
472 *p++=R;
473 *p++=V;
474 *p++=B;
475 *p++=R;
476 *p++=V;
477 *p++=B;
478 v1=*pt++;
479 v2=*pt++;
480 v3=*pt++;
481 n = count >> 2;
482 for(i=1;i<n;i++) {
483 *pt++=v1;
484 *pt++=v2;
485 *pt++=v3;
489 void ZB_clear(ZBuffer * zb, int clear_z, int z,
490 int clear_color, int r, int g, int b)
492 #if TGL_FEATURE_RENDER_BITS != 24
493 int color;
494 #endif
495 int y;
496 PIXEL *pp;
498 if (clear_z) {
499 memset_s(zb->zbuf, z, zb->xsize * zb->ysize);
501 if (clear_color) {
502 pp = zb->pbuf;
503 for (y = 0; y < zb->ysize; y++) {
504 #if TGL_FEATURE_RENDER_BITS == 15 || TGL_FEATURE_RENDER_BITS == 16
505 color = RGB_TO_PIXEL(r, g, b);
506 memset_s(pp, color, zb->xsize);
507 #elif TGL_FEATURE_RENDER_BITS == 32
508 color = RGB_TO_PIXEL(r, g, b);
509 memset_l(pp, color, zb->xsize);
510 #elif TGL_FEATURE_RENDER_BITS == 24
511 memset_RGB24(pp,r>>8,g>>8,b>>8,zb->xsize);
512 #else
513 #error TODO
514 #endif
515 pp = (PIXEL *) ((char *) pp + zb->linesize);