Panda3D

zbuffer.cxx

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 }
 All Classes Functions Variables Enumerations