Panda3D
|
00001 /* 00002 00003 * Z buffer: 16 bits Z / 32 bits color 00004 * 00005 */ 00006 #include <stdlib.h> 00007 #include <stdio.h> 00008 #include <assert.h> 00009 #include <string.h> 00010 #include "zbuffer.h" 00011 #include "pnotify.h" 00012 00013 #ifdef DO_PSTATS 00014 int pixel_count_white_untextured; 00015 int pixel_count_flat_untextured; 00016 int pixel_count_smooth_untextured; 00017 int pixel_count_white_textured; 00018 int pixel_count_flat_textured; 00019 int pixel_count_smooth_textured; 00020 int pixel_count_white_perspective; 00021 int pixel_count_flat_perspective; 00022 int pixel_count_smooth_perspective; 00023 int pixel_count_smooth_multitex2; 00024 int pixel_count_smooth_multitex3; 00025 #endif // DO_PSTATS 00026 00027 ZBuffer * 00028 ZB_open(int xsize, int ysize, int mode, 00029 int nb_colors, 00030 unsigned char *color_indexes, 00031 unsigned int *color_table, 00032 void *frame_buffer) { 00033 ZBuffer *zb; 00034 int size; 00035 00036 zb = (ZBuffer *)gl_malloc(sizeof(ZBuffer)); 00037 if (zb == NULL) 00038 return NULL; 00039 memset(zb, 0, sizeof(ZBuffer)); 00040 00041 /* xsize must be a multiple of 4 */ 00042 xsize = (xsize + 3) & ~3; 00043 00044 zb->xsize = xsize; 00045 zb->ysize = ysize; 00046 zb->mode = mode; 00047 zb->linesize = (xsize * PSZB + 3) & ~3; 00048 00049 switch (mode) { 00050 #ifdef TGL_FEATURE_8_BITS 00051 case ZB_MODE_INDEX: 00052 ZB_initDither(zb, nb_colors, color_indexes, color_table); 00053 break; 00054 #endif 00055 #ifdef TGL_FEATURE_32_BITS 00056 case ZB_MODE_RGBA: 00057 #endif 00058 #ifdef TGL_FEATURE_24_BITS 00059 case ZB_MODE_RGB24: 00060 #endif 00061 case ZB_MODE_5R6G5B: 00062 zb->nb_colors = 0; 00063 break; 00064 default: 00065 goto error; 00066 } 00067 00068 size = zb->xsize * zb->ysize * sizeof(ZPOINT); 00069 00070 zb->zbuf = (ZPOINT *)gl_malloc(size); 00071 if (zb->zbuf == NULL) 00072 goto error; 00073 00074 if (frame_buffer == NULL) { 00075 zb->pbuf = (PIXEL *)gl_malloc(zb->ysize * zb->linesize); 00076 if (zb->pbuf == NULL) { 00077 gl_free(zb->zbuf); 00078 goto error; 00079 } 00080 zb->frame_buffer_allocated = 1; 00081 } else { 00082 zb->frame_buffer_allocated = 0; 00083 zb->pbuf = (PIXEL *)frame_buffer; 00084 } 00085 00086 return zb; 00087 error: 00088 gl_free(zb); 00089 return NULL; 00090 } 00091 00092 void 00093 ZB_close(ZBuffer * zb) { 00094 #ifdef TGL_FEATURE_8_BITS 00095 if (zb->mode == ZB_MODE_INDEX) 00096 ZB_closeDither(zb); 00097 #endif 00098 00099 if (zb->frame_buffer_allocated) 00100 gl_free(zb->pbuf); 00101 00102 gl_free(zb->zbuf); 00103 gl_free(zb); 00104 } 00105 00106 void 00107 ZB_resize(ZBuffer * zb, void *frame_buffer, int xsize, int ysize) { 00108 int size; 00109 00110 /* xsize must be a multiple of 4 */ 00111 xsize = (xsize + 3) & ~3; 00112 00113 zb->xsize = xsize; 00114 zb->ysize = ysize; 00115 zb->linesize = (xsize * PSZB + 3) & ~3; 00116 00117 size = zb->xsize * zb->ysize * sizeof(ZPOINT); 00118 gl_free(zb->zbuf); 00119 zb->zbuf = (ZPOINT *)gl_malloc(size); 00120 00121 if (zb->frame_buffer_allocated) 00122 gl_free(zb->pbuf); 00123 00124 if (frame_buffer == NULL) { 00125 zb->pbuf = (PIXEL *)gl_malloc(zb->ysize * zb->linesize); 00126 zb->frame_buffer_allocated = 1; 00127 } else { 00128 zb->pbuf = (PIXEL *)frame_buffer; 00129 zb->frame_buffer_allocated = 0; 00130 } 00131 } 00132 00133 static void 00134 ZB_copyBuffer(const ZBuffer * zb, 00135 void *buf, 00136 int linesize) { 00137 unsigned char *p1; 00138 PIXEL *q; 00139 int y, n; 00140 00141 q = zb->pbuf; 00142 p1 = (unsigned char *)buf; 00143 n = zb->xsize * PSZB; 00144 for (y = 0; y < zb->ysize; y++) { 00145 memcpy(p1, q, n); 00146 p1 += linesize; 00147 q = (PIXEL *) ((char *) q + zb->linesize); 00148 } 00149 } 00150 00151 static void 00152 ZB_copyBufferNoAlpha(const ZBuffer * zb, void *buf, int linesize) { 00153 const PIXEL *q = zb->pbuf; 00154 PIXEL *p = (PIXEL *)buf; 00155 int xsize = zb->xsize; 00156 for (int y = 0; y < zb->ysize; ++y) { 00157 const PIXEL *q1 = q; 00158 PIXEL *p1 = p; 00159 PIXEL *p2 = p1 + xsize; 00160 while (p1 < p2) { 00161 // Make sure the alpha bits are set to 0xff. 00162 #ifdef WORDS_BIGENDIAN 00163 *p1 = *q1 | 0x000000ff; 00164 #else 00165 *p1 = *q1 | 0xff000000; 00166 #endif 00167 ++p1; 00168 ++q1; 00169 } 00170 p = (PIXEL *) ((char *) p + linesize); 00171 q = (const PIXEL *) ((const char *) q + zb->linesize); 00172 } 00173 } 00174 00175 #define RGB32_TO_RGB16(v) \ 00176 (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3)) 00177 00178 /* XXX: not optimized */ 00179 static void ZB_copyFrameBuffer5R6G5B(const ZBuffer * zb, 00180 void *buf, int linesize) 00181 { 00182 PIXEL *q; 00183 unsigned short *p, *p1; 00184 int y, n; 00185 00186 q = zb->pbuf; 00187 p1 = (unsigned short *) buf; 00188 00189 for (y = 0; y < zb->ysize; y++) { 00190 p = p1; 00191 n = zb->xsize >> 2; 00192 do { 00193 p[0] = RGB32_TO_RGB16(q[0]); 00194 p[1] = RGB32_TO_RGB16(q[1]); 00195 p[2] = RGB32_TO_RGB16(q[2]); 00196 p[3] = RGB32_TO_RGB16(q[3]); 00197 q += 4; 00198 p += 4; 00199 } while (--n > 0); 00200 p1 = (unsigned short *)((char *)p1 + linesize); 00201 } 00202 } 00203 00204 /* XXX: not optimized */ 00205 static void ZB_copyFrameBufferRGB24(const ZBuffer * zb, 00206 void *buf, int linesize) 00207 { 00208 PIXEL *q; 00209 unsigned char *p, *p1; 00210 int y, n; 00211 00212 fprintf(stderr, "copyFrameBufferRGB24\n"); 00213 00214 q = zb->pbuf; 00215 p1 = (unsigned char *) buf; 00216 00217 for (y = 0; y < zb->ysize; y++) { 00218 p = p1; 00219 n = zb->xsize; 00220 do { 00221 p[0] = q[0]; 00222 p[1] = q[1]; 00223 p[2] = q[2]; 00224 q += 4; 00225 p += 3; 00226 } while (--n > 0); 00227 p1 += linesize; 00228 } 00229 } 00230 00231 void 00232 ZB_copyFrameBuffer(const ZBuffer * zb, void *buf, 00233 int linesize) { 00234 switch (zb->mode) { 00235 #ifdef TGL_FEATURE_16_BITS 00236 case ZB_MODE_5R6G5B: 00237 ZB_copyFrameBuffer5R6G5B(zb, buf, linesize); 00238 break; 00239 #endif 00240 #ifdef TGL_FEATURE_24_BITS 00241 case ZB_MODE_RGB24: 00242 ZB_copyFrameBufferRGB24(zb, buf, linesize); 00243 break; 00244 #endif 00245 #ifdef TGL_FEATURE_32_BITS 00246 case ZB_MODE_RGBA: 00247 ZB_copyBuffer(zb, buf, linesize); 00248 break; 00249 #endif 00250 default: 00251 assert(0); 00252 } 00253 } 00254 00255 void 00256 ZB_copyFrameBufferNoAlpha(const ZBuffer * zb, void *buf, 00257 int linesize) { 00258 switch (zb->mode) { 00259 #ifdef TGL_FEATURE_16_BITS 00260 case ZB_MODE_5R6G5B: 00261 ZB_copyFrameBuffer5R6G5B(zb, buf, linesize); 00262 break; 00263 #endif 00264 #ifdef TGL_FEATURE_24_BITS 00265 case ZB_MODE_RGB24: 00266 ZB_copyFrameBufferRGB24(zb, buf, linesize); 00267 break; 00268 #endif 00269 #ifdef TGL_FEATURE_32_BITS 00270 case ZB_MODE_RGBA: 00271 ZB_copyBufferNoAlpha(zb, buf, linesize); 00272 break; 00273 #endif 00274 default: 00275 assert(0); 00276 } 00277 } 00278 00279 // Copy from (source_xmin,source_ymin)+(source_xsize,source_ysize) to 00280 // (dest_xmin,dest_ymin)+(dest_xsize,dest_ysize). 00281 void ZB_zoomFrameBuffer(ZBuffer *dest, int dest_xmin, int dest_ymin, int dest_xsize, int dest_ysize, 00282 const ZBuffer *source, int source_xmin, int source_ymin, int source_xsize, int source_ysize) { 00283 int tyinc = dest->linesize / PSZB; 00284 int fyinc = source->linesize / PSZB; 00285 00286 int fyt = 0; 00287 for (int ty = 0; ty < dest_ysize; ++ty) { 00288 int fy = fyt / dest_ysize; 00289 fyt += source_ysize; 00290 00291 PIXEL *tp = dest->pbuf + dest_xmin + (dest_ymin + ty) * tyinc; 00292 PIXEL *fp = source->pbuf + source_xmin + (source_ymin + fy) * fyinc; 00293 ZPOINT *tz = dest->zbuf + dest_xmin + (dest_ymin + ty) * dest->xsize; 00294 ZPOINT *fz = source->zbuf + source_xmin + (source_ymin + fy) * source->xsize; 00295 int fxt = 0; 00296 for (int tx = 0; tx < dest_xsize; ++tx) { 00297 int fx = fxt / dest_xsize; 00298 fxt += source_xsize; 00299 00300 tp[tx] = fp[fx]; 00301 tz[tx] = fz[fx]; 00302 } 00303 } 00304 } 00305 00306 00307 /* 00308 * adr must be aligned on an 'int' 00309 */ 00310 void 00311 memset_s(void *adr, int val, int count) { 00312 int i, n, v; 00313 unsigned int *p; 00314 unsigned short *q; 00315 00316 p = (unsigned int *)adr; 00317 v = val | (val << 16); 00318 00319 n = count >> 3; 00320 for (i = 0; i < n; i++) { 00321 p[0] = v; 00322 p[1] = v; 00323 p[2] = v; 00324 p[3] = v; 00325 p += 4; 00326 } 00327 00328 q = (unsigned short *) p; 00329 n = count & 7; 00330 for (i = 0; i < n; i++) 00331 *q++ = val; 00332 } 00333 00334 void 00335 memset_l(void *adr, int val, int count) { 00336 int i, n, v; 00337 unsigned int *p; 00338 00339 p = (unsigned int *)adr; 00340 v = val; 00341 n = count >> 2; 00342 for (i = 0; i < n; i++) { 00343 p[0] = v; 00344 p[1] = v; 00345 p[2] = v; 00346 p[3] = v; 00347 p += 4; 00348 } 00349 00350 n = count & 3; 00351 for (i = 0; i < n; i++) 00352 *p++ = val; 00353 } 00354 00355 /* count must be a multiple of 4 and >= 4 */ 00356 void 00357 memset_RGB24(void *adr,int r, int v, int b,long count) { 00358 long i, n; 00359 register long v1,v2,v3,*pt=(long *)(adr); 00360 unsigned char *p,R=(unsigned char)r,V=(unsigned char)v,B=(unsigned char)b; 00361 00362 p=(unsigned char *)adr; 00363 *p++=R; 00364 *p++=V; 00365 *p++=B; 00366 *p++=R; 00367 *p++=V; 00368 *p++=B; 00369 *p++=R; 00370 *p++=V; 00371 *p++=B; 00372 *p++=R; 00373 *p++=V; 00374 *p++=B; 00375 v1=*pt++; 00376 v2=*pt++; 00377 v3=*pt++; 00378 n = count >> 2; 00379 for(i=1;i<n;i++) { 00380 *pt++=v1; 00381 *pt++=v2; 00382 *pt++=v3; 00383 } 00384 } 00385 00386 void 00387 ZB_clear(ZBuffer * zb, int clear_z, ZPOINT z, 00388 int clear_color, unsigned int r, unsigned int g, unsigned int b, unsigned int a) { 00389 unsigned int color; 00390 int y; 00391 PIXEL *pp; 00392 00393 if (clear_z) { 00394 memset(zb->zbuf, 0, zb->xsize * zb->ysize * sizeof(ZPOINT)); 00395 } 00396 if (clear_color) { 00397 color = RGBA_TO_PIXEL(r, g, b, a); 00398 pp = zb->pbuf; 00399 for (y = 0; y < zb->ysize; y++) { 00400 memset_l(pp, color, zb->xsize); 00401 pp = (PIXEL *) ((char *) pp + zb->linesize); 00402 } 00403 } 00404 } 00405 00406 void 00407 ZB_clear_viewport(ZBuffer * zb, int clear_z, ZPOINT z, 00408 int clear_color, unsigned int r, unsigned int g, unsigned int b, unsigned int a, 00409 int xmin, int ymin, int xsize, int ysize) { 00410 unsigned int color; 00411 int y; 00412 PIXEL *pp; 00413 ZPOINT *zz; 00414 00415 nassertv(xmin >= 0 && xmin < zb->xsize && 00416 ymin >= 0 && ymin < zb->ysize && 00417 xmin + xsize >= 0 && xmin + xsize <= zb->xsize && 00418 ymin + ysize >= 0 && ymin + ysize <= zb->ysize); 00419 00420 if (clear_z) { 00421 zz = zb->zbuf + xmin + ymin * zb->xsize; 00422 for (y = 0; y < ysize; ++y) { 00423 memset(zz, 0, xsize * sizeof(ZPOINT)); 00424 zz += zb->xsize; 00425 } 00426 } 00427 if (clear_color) { 00428 color = RGBA_TO_PIXEL(r, g, b, a); 00429 pp = zb->pbuf + xmin + ymin * (zb->linesize / PSZB); 00430 for (y = 0; y < ysize; ++y) { 00431 memset_l(pp, color, xsize); 00432 pp += zb->xsize; 00433 } 00434 } 00435 } 00436 00437 #define ZB_ST_FRAC_HIGH (1 << ZB_POINT_ST_FRAC_BITS) 00438 #define ZB_ST_FRAC_MASK (ZB_ST_FRAC_HIGH - 1) 00439 00440 #define LINEAR_FILTER_BITSIZE(c1, c2, f, bitsize) \ 00441 ((((c2) * (f)) >> bitsize) + (((c1) * ((1 << bitsize) - (f))) >> bitsize)) 00442 00443 #define LINEAR_FILTER(c1, c2, f) \ 00444 LINEAR_FILTER_BITSIZE(c1, c2, f, ZB_POINT_ST_FRAC_BITS) 00445 00446 #define BILINEAR_FILTER(c1, c2, c3, c4, sf, tf) \ 00447 (LINEAR_FILTER(LINEAR_FILTER(c1, c2, sf), LINEAR_FILTER(c3, c4, sf), tf)) 00448 00449 // Grab the nearest texel from the base level. This is also 00450 // implemented inline as ZB_LOOKUP_TEXTURE_NEAREST. 00451 PIXEL 00452 lookup_texture_nearest(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00453 return ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t); 00454 } 00455 00456 // Bilinear filter four texels in the base level. 00457 PIXEL 00458 lookup_texture_bilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00459 PIXEL p1, p2, p3, p4; 00460 int sf, tf; 00461 int r, g, b, a; 00462 00463 p1 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH); 00464 p2 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH); 00465 sf = s & ZB_ST_FRAC_MASK; 00466 00467 p3 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t); 00468 p4 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t); 00469 tf = t & ZB_ST_FRAC_MASK; 00470 00471 r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf); 00472 g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf); 00473 b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf); 00474 a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf); 00475 00476 return RGBA_TO_PIXEL(r, g, b, a); 00477 } 00478 00479 // Grab the nearest texel from the nearest mipmap level. This is also 00480 // implemented inline as ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST. 00481 PIXEL 00482 lookup_texture_mipmap_nearest(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00483 return ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level); 00484 } 00485 00486 // Linear filter the two texels from the two nearest mipmap levels. 00487 PIXEL 00488 lookup_texture_mipmap_linear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00489 PIXEL p1, p2; 00490 int r, g, b, a; 00491 00492 p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level - 1); 00493 p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level); 00494 00495 unsigned int bitsize = (level - 1) + ZB_POINT_ST_FRAC_BITS; 00496 r = LINEAR_FILTER_BITSIZE(PIXEL_R(p1), PIXEL_R(p2), level_dx, bitsize); 00497 g = LINEAR_FILTER_BITSIZE(PIXEL_G(p1), PIXEL_G(p2), level_dx, bitsize); 00498 b = LINEAR_FILTER_BITSIZE(PIXEL_B(p1), PIXEL_B(p2), level_dx, bitsize); 00499 a = LINEAR_FILTER_BITSIZE(PIXEL_A(p1), PIXEL_A(p2), level_dx, bitsize); 00500 00501 return RGBA_TO_PIXEL(r, g, b, a); 00502 } 00503 00504 // Bilinear filter four texels in the nearest mipmap level. 00505 PIXEL 00506 lookup_texture_mipmap_bilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00507 PIXEL p1, p2, p3, p4; 00508 int sf, tf; 00509 int r, g, b, a; 00510 00511 p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH, level); 00512 p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH, level); 00513 sf = (s >> level) & ZB_ST_FRAC_MASK; 00514 00515 p3 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t, level); 00516 p4 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level); 00517 tf = (t >> level) & ZB_ST_FRAC_MASK; 00518 00519 r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf); 00520 g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf); 00521 b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf); 00522 a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf); 00523 00524 return RGBA_TO_PIXEL(r, g, b, a); 00525 } 00526 00527 // Bilinear filter four texels in each of the nearest two mipmap 00528 // levels, then linear filter them together. 00529 PIXEL 00530 lookup_texture_mipmap_trilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00531 PIXEL p1a, p2a; 00532 00533 { 00534 PIXEL p1, p2, p3, p4; 00535 int sf, tf; 00536 int r, g, b, a; 00537 00538 p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH, level - 1); 00539 p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH, level - 1); 00540 sf = (s >> (level - 1)) & ZB_ST_FRAC_MASK; 00541 00542 p3 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t, level - 1); 00543 p4 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level - 1); 00544 tf = (t >> (level - 1)) & ZB_ST_FRAC_MASK; 00545 00546 r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf); 00547 g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf); 00548 b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf); 00549 a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf); 00550 p1a = RGBA_TO_PIXEL(r, g, b, a); 00551 } 00552 00553 { 00554 PIXEL p1, p2, p3, p4; 00555 int sf, tf; 00556 int r, g, b, a; 00557 00558 p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH, level); 00559 p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH, level); 00560 sf = (s >> level) & ZB_ST_FRAC_MASK; 00561 00562 p3 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t, level); 00563 p4 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level); 00564 tf = (t >> level) & ZB_ST_FRAC_MASK; 00565 00566 r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf); 00567 g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf); 00568 b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf); 00569 a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf); 00570 p2a = RGBA_TO_PIXEL(r, g, b, a); 00571 } 00572 00573 int r, g, b, a; 00574 unsigned int bitsize = (level - 1) + ZB_POINT_ST_FRAC_BITS; 00575 r = LINEAR_FILTER_BITSIZE(PIXEL_R(p1a), PIXEL_R(p2a), level_dx, bitsize); 00576 g = LINEAR_FILTER_BITSIZE(PIXEL_G(p1a), PIXEL_G(p2a), level_dx, bitsize); 00577 b = LINEAR_FILTER_BITSIZE(PIXEL_B(p1a), PIXEL_B(p2a), level_dx, bitsize); 00578 a = LINEAR_FILTER_BITSIZE(PIXEL_A(p1a), PIXEL_A(p2a), level_dx, bitsize); 00579 00580 return RGBA_TO_PIXEL(r, g, b, a); 00581 } 00582 00583 00584 // Apply the wrap mode to s and t coordinates by calling the generic 00585 // wrap mode function. 00586 PIXEL 00587 apply_wrap_general_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00588 s = (*texture_def->tex_wrap_u_func)(s, texture_def->s_max); 00589 t = (*texture_def->tex_wrap_v_func)(t, texture_def->t_max); 00590 return (*texture_def->tex_minfilter_func_impl)(texture_def, s, t, level, level_dx); 00591 } 00592 00593 PIXEL 00594 apply_wrap_general_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00595 s = (*texture_def->tex_wrap_u_func)(s, texture_def->s_max); 00596 t = (*texture_def->tex_wrap_v_func)(t, texture_def->t_max); 00597 return (*texture_def->tex_magfilter_func_impl)(texture_def, s, t, level, level_dx); 00598 } 00599 00600 // Outside the legal range of s and t, return just the texture's 00601 // border color. 00602 PIXEL 00603 apply_wrap_border_color_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00604 if (s < 0 || t < 0 || s > texture_def->s_max || t > texture_def->t_max) { 00605 return texture_def->border_color; 00606 } 00607 return (*texture_def->tex_minfilter_func_impl)(texture_def, s, t, level, level_dx); 00608 } 00609 00610 PIXEL 00611 apply_wrap_border_color_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00612 if (s < 0 || t < 0 || s > texture_def->s_max || t > texture_def->t_max) { 00613 return texture_def->border_color; 00614 } 00615 return (*texture_def->tex_magfilter_func_impl)(texture_def, s, t, level, level_dx); 00616 } 00617 00618 // Outside the legal range of s and t, clamp s and t to the edge. 00619 // This is also duplicated by texcoord_clamp(), but using these 00620 // functions instead saves two additional function calls per pixel. 00621 PIXEL 00622 apply_wrap_clamp_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00623 s = min(max(s, 0), texture_def->s_max); 00624 t = min(max(t, 0), texture_def->t_max); 00625 return (*texture_def->tex_minfilter_func_impl)(texture_def, s, t, level, level_dx); 00626 } 00627 00628 PIXEL 00629 apply_wrap_clamp_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) { 00630 s = min(max(s, 0), texture_def->s_max); 00631 t = min(max(t, 0), texture_def->t_max); 00632 return (*texture_def->tex_magfilter_func_impl)(texture_def, s, t, level, level_dx); 00633 } 00634 00635 int 00636 texcoord_clamp(int coord, int max_coord) { 00637 return min(max(coord, 0), max_coord); 00638 } 00639 00640 int 00641 texcoord_repeat(int coord, int max_coord) { 00642 return coord; 00643 } 00644 00645 int 00646 texcoord_mirror(int coord, int max_coord) { 00647 if ((coord & ((max_coord << 1) - 1)) > max_coord) { 00648 coord = (max_coord << 1) - coord; 00649 } 00650 return coord; 00651 } 00652 00653 int 00654 texcoord_mirror_once(int coord, int max_coord) { 00655 if (coord > max_coord) { 00656 coord = (max_coord << 1) - coord; 00657 } 00658 return max(coord, 0); 00659 }