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