Browse Source

support texture wrap modes

David Rose 17 years ago
parent
commit
8d96071d4b

+ 6 - 0
panda/src/tinydisplay/config_tinydisplay.cxx

@@ -84,6 +84,12 @@ ConfigVariableBool td_ignore_mipmaps
    PRC_DESC("Configure this true to disable use of mipmaps on the "
             "tinydisplay software renderer."));
 
+ConfigVariableBool td_ignore_clamp
+  ("td-ignore-clamp", false,
+   PRC_DESC("Configure this true to disable texture clamp mode and other "
+            "wrap modes other than repeat (all textures will repeat, which "
+            "is a little cheaper)."));
+
 ConfigVariableBool td_perspective_textures
   ("td-perspective-textures", true,
    PRC_DESC("Configure this false to disable use of perspective-correct "

+ 1 - 0
panda/src/tinydisplay/config_tinydisplay.h

@@ -36,6 +36,7 @@ extern ConfigVariableInt osx_mouse_wheel_scale;
 
 extern ConfigVariableInt td_texture_ram;
 extern ConfigVariableBool td_ignore_mipmaps;
+extern ConfigVariableBool td_ignore_clamp;
 extern ConfigVariableBool td_perspective_textures;
 
 #endif

+ 173 - 50
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -1371,6 +1371,10 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
   if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), 1)) {
     return false;
   }
+  gltex->border_color.v[0] = 0.0f;
+  gltex->border_color.v[1] = 0.0f;
+  gltex->border_color.v[2] = 0.0f;
+  gltex->border_color.v[3] = 0.0f;
 
   PIXEL *ip = gltex->levels[0].pixmap + gltex->xsize * gltex->ysize;
   PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
@@ -1683,7 +1687,22 @@ update_texture(TextureContext *tc, bool force, int stage_index) {
   GLTexture *gltex = &gtc->_gltex;
 
   _c->current_textures[stage_index] = gltex;
-  _c->zb->current_textures[stage_index] = gltex->levels;
+
+  ZTextureDef *texture_def = &_c->zb->current_textures[stage_index];
+  texture_def->levels = gltex->levels;
+  texture_def->s_max = gltex->s_max;
+  texture_def->t_max = gltex->t_max;
+
+  const V4 &bc = gltex->border_color;
+  int r = (int)(bc.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) 
+                + ZB_POINT_RED_MIN);
+  int g = (int)(bc.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) 
+                + ZB_POINT_GREEN_MIN);
+  int b = (int)(bc.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) 
+                + ZB_POINT_BLUE_MIN);
+  int a = (int)(bc.v[3] * (ZB_POINT_ALPHA_MAX - ZB_POINT_ALPHA_MIN) 
+                + ZB_POINT_ALPHA_MIN);
+  texture_def->border_color = RGBA_TO_PIXEL(r, g, b, a);
 
   return true;
 }
@@ -2159,11 +2178,12 @@ do_issue_texture() {
   }
   nassertv(num_stages <= MAX_TEXTURE_STAGES);
 
-  Texture::QualityLevel quality_level = _texture_quality_override;
-  Texture::FilterType minfilter = Texture::FT_nearest;
-  Texture::FilterType magfilter = Texture::FT_nearest;
-  bool all_use_mipmaps = true;
   bool all_replace = true;
+  bool all_nearest = true;
+  bool all_mipmap_nearest = true;
+  bool any_mipmap = false;
+  bool needs_general = false;
+  Texture::QualityLevel best_quality_level = Texture::QL_default;
 
   for (int si = 0; si < num_stages; ++si) {
     TextureStage *stage = _target_texture->get_on_ff_stage(si);
@@ -2187,17 +2207,100 @@ do_issue_texture() {
       all_replace = false;
     }
 
-    if (quality_level < texture->get_quality_level()) {
+    Texture::QualityLevel quality_level = _texture_quality_override;
+    if (quality_level == Texture::QL_default) {
       quality_level = texture->get_quality_level();
     }
-    if (minfilter < texture->get_minfilter()) {
-      minfilter = texture->get_minfilter();
+    if (quality_level == Texture::QL_default) {
+      quality_level = texture_quality_level;
     }
-    if (magfilter < texture->get_magfilter()) {
-      magfilter = texture->get_magfilter();
+
+    best_quality_level = max(best_quality_level, quality_level);
+
+    ZTextureDef *texture_def = &_c->zb->current_textures[si];
+    
+    // Fill in the filter func pointers.  These may not actually get
+    // called, if we decide below we can inline the filters.
+    Texture::FilterType minfilter = texture->get_minfilter();
+    Texture::FilterType magfilter = texture->get_magfilter();
+
+    if (td_ignore_mipmaps && Texture::is_mipmap(minfilter)) {
+      // Downgrade mipmaps.
+      if (minfilter == Texture::FT_nearest_mipmap_nearest) {
+        minfilter = Texture::FT_nearest;
+      } else {
+        minfilter = Texture::FT_linear;
+      }
     }
-    if (!texture->uses_mipmaps()) {
-      all_use_mipmaps = false;
+
+    // Depending on this particular texture's quality level, we may
+    // downgrade the requested filters.
+    if (quality_level == Texture::QL_fastest) {
+      minfilter = Texture::FT_nearest;
+      magfilter = Texture::FT_nearest;
+
+    } else if (quality_level == Texture::QL_normal) {
+      if (Texture::is_mipmap(minfilter)) {
+        minfilter = Texture::FT_nearest_mipmap_nearest;
+      } else {
+        minfilter = Texture::FT_nearest;
+      }
+      magfilter = Texture::FT_nearest;
+    }
+
+    texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
+    texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
+    
+    Texture::WrapMode wrap_u = texture->get_wrap_u();
+    Texture::WrapMode wrap_v = texture->get_wrap_v();
+    if (td_ignore_clamp) {
+      wrap_u = Texture::WM_repeat;
+      wrap_v = Texture::WM_repeat;
+    }
+
+    if (wrap_u != Texture::WM_repeat || wrap_v != Texture::WM_repeat) {
+      // We have some nonstandard wrap mode.  This will force the use
+      // of the general texfilter mode.
+      needs_general = true;
+
+      // We need another level of indirection to implement the
+      // different texcoord wrap modes.  This means we will be using
+      // the _impl function pointers, which are called by the toplevel
+      // function.
+
+      texture_def->tex_minfilter_func_impl = texture_def->tex_minfilter_func;
+      texture_def->tex_magfilter_func_impl = texture_def->tex_magfilter_func;
+
+      // Now assign the toplevel function pointer to do the
+      // appropriate texture coordinate wrapping/clamping.
+      texture_def->tex_minfilter_func = apply_wrap_general_minfilter;
+      texture_def->tex_magfilter_func = apply_wrap_general_magfilter;
+
+      texture_def->tex_wrap_u_func = get_tex_wrap_func(wrap_u);
+      texture_def->tex_wrap_v_func = get_tex_wrap_func(wrap_v);
+
+      // The following special cases are handled inline, rather than
+      // relying on the above wrap function pointers.
+      if (wrap_u && Texture::WM_border_color && wrap_v == Texture::WM_border_color) {
+        texture_def->tex_minfilter_func = apply_wrap_border_color_minfilter;
+        texture_def->tex_magfilter_func = apply_wrap_border_color_magfilter;
+      } else if (wrap_u && Texture::WM_clamp && wrap_v == Texture::WM_clamp) {
+        texture_def->tex_minfilter_func = apply_wrap_clamp_minfilter;
+        texture_def->tex_magfilter_func = apply_wrap_clamp_magfilter;
+      }
+    }
+
+    if (minfilter != Texture::FT_nearest || magfilter != Texture::FT_nearest) {
+      all_nearest = false;
+    }
+
+    if (minfilter != Texture::FT_nearest_mipmap_nearest ||
+        magfilter != Texture::FT_nearest) {
+      all_mipmap_nearest = false;
+    }
+
+    if (Texture::is_mipmap(minfilter)) {
+      any_mipmap = true;
     }
   }
 
@@ -2214,33 +2317,21 @@ do_issue_texture() {
     _texturing_state = 1;    // textured (not perspective correct)
   }
 
-  if (quality_level == Texture::QL_default) {
-    quality_level = texture_quality_level;
-  }
-
-  if (quality_level == Texture::QL_best) {
+  if (best_quality_level == Texture::QL_best) {
     // This is the most generic texture filter.  Slow, but pretty.
     _texfilter_state = 2;  // tgeneral
 
-    if (!all_use_mipmaps && Texture::is_mipmap(minfilter)) {
-      // We can't enable mipmaps unless all the textures in the stack
-      // enable mipmaps.
-      minfilter = Texture::FT_linear;
-    }
-
-    _c->zb->tex_minfilter_func = get_tex_filter_func(minfilter);
-    _c->zb->tex_magfilter_func = get_tex_filter_func(magfilter);
-
-    if (minfilter == Texture::FT_nearest && magfilter == Texture::FT_nearest) {
-      // This case is inlined.
-      _texfilter_state = 0;    // tnearest
-    } else if (minfilter == Texture::FT_nearest_mipmap_nearest &&
-               magfilter == Texture::FT_nearest) {
-      // So is this case.
-      _texfilter_state = 1;  // tmipmap
+    if (!needs_general) {
+      if (all_nearest) {
+        // This case is inlined.
+        _texfilter_state = 0;    // tnearest
+      } else if (all_mipmap_nearest) {
+        // So is this case.
+        _texfilter_state = 1;  // tmipmap
+      }
     }
 
-  } else if (quality_level == Texture::QL_fastest) {
+  } else if (best_quality_level == Texture::QL_fastest) {
     // This is the cheapest texture filter.  We disallow mipmaps and
     // perspective correctness.
     _texfilter_state = 0;    // tnearest
@@ -2251,9 +2342,15 @@ do_issue_texture() {
     // there are no mipmaps, and mipmap_nearest if there are any
     // mipmaps--these are the two inlined filters.
     _texfilter_state = 0;    // tnearest
-    if (all_use_mipmaps && !td_ignore_mipmaps) {
+    if (any_mipmap) {
       _texfilter_state = 1;  // tmipmap
     }
+
+    if (needs_general) {
+      // To support nonstandard texcoord wrapping etc, we need to
+      // force the general texfilter mode.
+      _texfilter_state = 2;  // tgeneral
+    }
   }
 }
 
@@ -2365,6 +2462,11 @@ upload_texture(TinyTextureContext *gtc, bool force) {
   if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), num_levels)) {
     return false;
   }
+  Colorf border_color = tex->get_border_color();
+  gltex->border_color.v[0] = border_color[0];
+  gltex->border_color.v[1] = border_color[1];
+  gltex->border_color.v[2] = border_color[2];
+  gltex->border_color.v[3] = border_color[3];
 
   int bytecount = 0;
   int xsize = gltex->xsize;
@@ -2470,6 +2572,11 @@ upload_simple_texture(TinyTextureContext *gtc) {
   if (!setup_gltex(gltex, width, height, 1)) {
     return false;
   }
+  Colorf border_color = tex->get_border_color();
+  gltex->border_color.v[0] = border_color[0];
+  gltex->border_color.v[1] = border_color[1];
+  gltex->border_color.v[2] = border_color[2];
+  gltex->border_color.v[3] = border_color[3];
 
   ZTextureLevel *dest = &gltex->levels[0];
   memcpy(dest->pixmap, image_ptr, image_size);
@@ -2546,9 +2653,10 @@ setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
     next_buffer += bytecount;
     nassertr(next_buffer <= end_of_buffer, false);
 
-    dest->s_mask = (1 << (s_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS);
-    dest->t_mask = (1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS);
-    dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits);
+    dest->s_mask = ((1 << (s_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
+    dest->t_mask = ((1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
+    dest->s_shift = (ZB_POINT_ST_FRAC_BITS + level);
+    dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits + level);
     
     x_size = max((x_size >> 1), 1);
     y_size = max((y_size >> 1), 1);
@@ -2982,33 +3090,48 @@ get_tex_filter_func(Texture::FilterType filter) {
     return &lookup_texture_bilinear;
 
   case Texture::FT_nearest_mipmap_nearest:
-    if (td_ignore_mipmaps) {
-      return &lookup_texture_nearest;
-    }
     return &lookup_texture_mipmap_nearest;
 
   case Texture::FT_nearest_mipmap_linear:
-    if (td_ignore_mipmaps) {
-      return &lookup_texture_nearest;
-    }
     return &lookup_texture_mipmap_linear;
       
   case Texture::FT_linear_mipmap_nearest:
-    if (td_ignore_mipmaps) {
-      return &lookup_texture_bilinear;
-    }
     return &lookup_texture_mipmap_bilinear;
 
   case Texture::FT_linear_mipmap_linear:
-    if (td_ignore_mipmaps) {
-      return &lookup_texture_bilinear;
-    }
     return &lookup_texture_mipmap_trilinear;
 
   default:
     return &lookup_texture_nearest;
   }
 }
+ 
+////////////////////////////////////////////////////////////////////
+//     Function: TinyGraphicsStateGuardian::get_tex_wrap_func
+//       Access: Private, Static
+//  Description: Returns the pointer to the appropriate wrap
+//               function according to the texture's wrap mode.
+////////////////////////////////////////////////////////////////////
+ZB_texWrapFunc TinyGraphicsStateGuardian::
+get_tex_wrap_func(Texture::WrapMode wrap_mode) {
+  switch (wrap_mode) {
+  case Texture::WM_clamp:
+  case Texture::WM_border_color:  // border_color is handled later.
+    return &texcoord_clamp;
+
+  case Texture::WM_repeat:
+  case Texture::WM_invalid:
+    return &texcoord_repeat;
+
+  case Texture::WM_mirror:
+    return &texcoord_mirror;
+
+  case Texture::WM_mirror_once:
+    return &texcoord_mirror_once;
+  }
+
+  return &texcoord_repeat;
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: TinyGraphicsStateGuardian::texgen_null

+ 1 - 0
panda/src/tinydisplay/tinyGraphicsStateGuardian.h

@@ -125,6 +125,7 @@ private:
   static void load_matrix(M4 *matrix, const TransformState *transform);
   static int get_color_blend_op(ColorBlendAttrib::Operand operand);
   static ZB_lookupTextureFunc get_tex_filter_func(Texture::FilterType filter);
+  static ZB_texWrapFunc get_tex_wrap_func(Texture::WrapMode wrap_mode);
 
   INLINE void clear_light_state();
 

+ 98 - 48
panda/src/tinydisplay/zbuffer.cxx

@@ -36,6 +36,7 @@ ZBuffer *ZB_open(int xsize, int ysize, int mode,
     zb = (ZBuffer *)gl_malloc(sizeof(ZBuffer));
     if (zb == NULL)
 	return NULL;
+    memset(zb, 0, sizeof(ZBuffer));
 
     /* xsize must be a multiple of 4 */
     xsize = (xsize + 3) & ~3;
@@ -82,9 +83,6 @@ ZBuffer *ZB_open(int xsize, int ysize, int mode,
 	zb->pbuf = (PIXEL *)frame_buffer;
     }
 
-    zb->current_textures[0] = NULL;
-    zb->current_textures[1] = NULL;
-
     return zb;
   error:
     gl_free(zb);
@@ -375,25 +373,24 @@ void ZB_clear_viewport(ZBuffer * zb, int clear_z, ZPOINT z,
 
 // Grab the nearest texel from the base level.  This is also
 // implemented inline as ZB_LOOKUP_TEXTURE_NEAREST.
-PIXEL lookup_texture_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
+PIXEL lookup_texture_nearest(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx)
 {
-  return ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t);
+  return ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t);
 }
 
 // Bilinear filter four texels in the base level.
-PIXEL lookup_texture_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
+PIXEL lookup_texture_bilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx)
 {
-  ZTextureLevel *base_level = texture_levels;
   PIXEL p1, p2, p3, p4;
   int sf, tf;
   int r, g, b, a;
 
-  p1 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH);
-  p2 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t - ZB_ST_FRAC_HIGH);
+  p1 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH);
+  p2 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH);
   sf = s & ZB_ST_FRAC_MASK;
 
-  p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s - ZB_ST_FRAC_HIGH, t);
-  p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t);
+  p3 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t);
+  p4 = ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t);
   tf = t & ZB_ST_FRAC_MASK;
 
   r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
@@ -406,19 +403,19 @@ PIXEL lookup_texture_bilinear(ZTextureLevel *texture_levels, int s, int t, unsig
 
 // Grab the nearest texel from the nearest mipmap level.  This is also
 // implemented inline as ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST.
-PIXEL lookup_texture_mipmap_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
+PIXEL lookup_texture_mipmap_nearest(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx)
 {
-  return ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level);
+  return ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level);
 }
 
 // Linear filter the two texels from the two nearest mipmap levels.
-PIXEL lookup_texture_mipmap_linear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
+PIXEL lookup_texture_mipmap_linear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx)
 {
   PIXEL p1, p2;
   int r, g, b, a;
 
-  p1 = ZB_LOOKUP_TEXTURE_NEAREST(texture_levels + level - 1, s >> (level - 1), t >> (level - 1));
-  p2 = ZB_LOOKUP_TEXTURE_NEAREST(texture_levels + level, s >> level, t >> level);
+  p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level - 1);
+  p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level);
 
   unsigned int bitsize = (level - 1) + ZB_POINT_ST_FRAC_BITS;
   r = LINEAR_FILTER_BITSIZE(PIXEL_R(p1), PIXEL_R(p2), level_dx, bitsize);
@@ -430,23 +427,19 @@ PIXEL lookup_texture_mipmap_linear(ZTextureLevel *texture_levels, int s, int t,
 }
 
 // Bilinear filter four texels in the nearest mipmap level.
-PIXEL lookup_texture_mipmap_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
+PIXEL lookup_texture_mipmap_bilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx)
 {
-  ZTextureLevel *base_level = texture_levels + level;
-  s >>= level;
-  t >>= level;
-
   PIXEL p1, p2, p3, p4;
   int sf, tf;
   int r, g, b, a;
 
-  p1 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH);
-  p2 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t - ZB_ST_FRAC_HIGH);
-  sf = s & ZB_ST_FRAC_MASK;
+  p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH, level);
+  p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH, level);
+  sf = (s >> level) & ZB_ST_FRAC_MASK;
 
-  p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s - ZB_ST_FRAC_HIGH, t);
-  p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t);
-  tf = t & ZB_ST_FRAC_MASK;
+  p3 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t, level);
+  p4 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level);
+  tf = (t >> level) & ZB_ST_FRAC_MASK;
 
   r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
   g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf);
@@ -458,26 +451,22 @@ PIXEL lookup_texture_mipmap_bilinear(ZTextureLevel *texture_levels, int s, int t
 
 // Bilinear filter four texels in each of the nearest two mipmap
 // levels, then linear filter them together.
-PIXEL lookup_texture_mipmap_trilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
+PIXEL lookup_texture_mipmap_trilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx)
 {
   PIXEL p1a, p2a;
 
   {
-    ZTextureLevel *base_level = texture_levels + level - 1;
-    int sl = s >> (level - 1);
-    int tl = t >> (level - 1);
-    
     PIXEL p1, p2, p3, p4;
     int sf, tf;
     int r, g, b, a;
 
-    p1 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl - ZB_ST_FRAC_HIGH, tl - ZB_ST_FRAC_HIGH);
-    p2 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl - ZB_ST_FRAC_HIGH);
-    sf = sl & ZB_ST_FRAC_MASK;
+    p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH, level - 1);
+    p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH, level - 1);
+    sf = (s >> (level - 1)) & ZB_ST_FRAC_MASK;
     
-    p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl - ZB_ST_FRAC_HIGH, tl);
-    p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl);
-    tf = tl & ZB_ST_FRAC_MASK;
+    p3 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t, level - 1);
+    p4 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level - 1);
+    tf = (t >> (level - 1)) & ZB_ST_FRAC_MASK;
     
     r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
     g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf);
@@ -487,21 +476,17 @@ PIXEL lookup_texture_mipmap_trilinear(ZTextureLevel *texture_levels, int s, int
   }
 
   {
-    ZTextureLevel *base_level = texture_levels + level;
-    int sl = s >> level;
-    int tl = t >> level;
-    
     PIXEL p1, p2, p3, p4;
     int sf, tf;
     int r, g, b, a;
 
-    p1 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl - ZB_ST_FRAC_HIGH, tl - ZB_ST_FRAC_HIGH);
-    p2 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl - ZB_ST_FRAC_HIGH);
-    sf = sl & ZB_ST_FRAC_MASK;
+    p1 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t - ZB_ST_FRAC_HIGH, level);
+    p2 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t - ZB_ST_FRAC_HIGH, level);
+    sf = (s >> level) & ZB_ST_FRAC_MASK;
     
-    p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl - ZB_ST_FRAC_HIGH, tl);
-    p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl);
-    tf = tl & ZB_ST_FRAC_MASK;
+    p3 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s - ZB_ST_FRAC_HIGH, t, level);
+    p4 = ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level);
+    tf = (t >> level) & ZB_ST_FRAC_MASK;
     
     r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
     g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf);
@@ -519,3 +504,68 @@ PIXEL lookup_texture_mipmap_trilinear(ZTextureLevel *texture_levels, int s, int
 
   return RGBA_TO_PIXEL(r, g, b, a);
 }
+
+
+// Apply the wrap mode to s and t coordinates by calling the generic
+// wrap mode function.
+PIXEL apply_wrap_general_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) {
+  s = (*texture_def->tex_wrap_u_func)(s, texture_def->s_max);
+  t = (*texture_def->tex_wrap_v_func)(t, texture_def->t_max);
+  return (*texture_def->tex_minfilter_func_impl)(texture_def, s, t, level, level_dx);
+}
+PIXEL apply_wrap_general_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) {
+  s = (*texture_def->tex_wrap_u_func)(s, texture_def->s_max);
+  t = (*texture_def->tex_wrap_v_func)(t, texture_def->t_max);
+  return (*texture_def->tex_magfilter_func_impl)(texture_def, s, t, level, level_dx);
+}
+
+// Outside the legal range of s and t, return just the texture's
+// border color.
+PIXEL apply_wrap_border_color_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) {
+  if (s < 0 || t < 0 || s > texture_def->s_max || t > texture_def->t_max) {
+    return texture_def->border_color;
+  }
+  return (*texture_def->tex_minfilter_func_impl)(texture_def, s, t, level, level_dx);
+}
+PIXEL apply_wrap_border_color_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) {
+  if (s < 0 || t < 0 || s > texture_def->s_max || t > texture_def->t_max) {
+    return texture_def->border_color;
+  }
+  return (*texture_def->tex_magfilter_func_impl)(texture_def, s, t, level, level_dx);
+}
+
+// Outside the legal range of s and t, clamp s and t to the edge.
+// This is also duplicated by texcoord_clamp(), but using these
+// functions instead saves two additional function calls per pixel.
+PIXEL apply_wrap_clamp_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) {
+  s = min(max(s, 0), texture_def->s_max);
+  t = min(max(t, 0), texture_def->t_max);
+  return (*texture_def->tex_minfilter_func_impl)(texture_def, s, t, level, level_dx);
+}
+PIXEL apply_wrap_clamp_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx) {
+  s = min(max(s, 0), texture_def->s_max);
+  t = min(max(t, 0), texture_def->t_max);
+  return (*texture_def->tex_magfilter_func_impl)(texture_def, s, t, level, level_dx);
+}
+
+int texcoord_clamp(int coord, int max_coord) {
+  return min(max(coord, 0), max_coord);
+}
+
+int texcoord_repeat(int coord, int max_coord) {
+  return coord;
+}
+
+int texcoord_mirror(int coord, int max_coord) {
+  if ((coord & ((max_coord << 1) - 1)) > max_coord) {
+    coord = (max_coord << 1) - coord;
+  }
+  return coord;
+}
+
+int texcoord_mirror_once(int coord, int max_coord) {
+  if (coord > max_coord) {
+    coord = (max_coord << 1) - coord;
+  }
+  return max(coord, 0);
+}

+ 45 - 18
panda/src/tinydisplay/zbuffer.h

@@ -26,15 +26,15 @@ typedef unsigned int ZPOINT;
 #define MAX_MIPMAP_LEVELS (32 - ZB_POINT_ST_FRAC_BITS + 1)
 
 /* Returns the index within a texture level for the given (s, t) texel. */
-#define ZB_TEXEL(level, s, t)                                         \
-  ((((t) & (level)->t_mask) >> (level)->t_shift) |                  \
-   (((s) & (level)->s_mask) >> ZB_POINT_ST_FRAC_BITS))
+#define ZB_TEXEL(texture_level, s, t)                                   \
+  ((((t) & (texture_level).t_mask) >> (texture_level).t_shift) |      \
+   (((s) & (texture_level).s_mask) >> (texture_level).s_shift))
 
-#define ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t) \
-  (texture_levels)->pixmap[ZB_TEXEL(texture_levels, s, t)]
+#define ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t) \
+  (texture_def)->levels[0].pixmap[ZB_TEXEL((texture_def)->levels[0], s, t)]
 
-#define ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level) \
-  ZB_LOOKUP_TEXTURE_NEAREST((texture_levels) + (level), (s) >> (level), (t) >> (level))
+#define ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level) \
+  (texture_def)->levels[(level)].pixmap[ZB_TEXEL((texture_def)->levels[(level)], s, t)]
 
 /* A special abs() function which doesn't require any branching
    instructions.  Might not work on some exotic hardware. */
@@ -105,18 +105,33 @@ typedef unsigned int PIXEL;
 
 typedef struct {
   PIXEL *pixmap;
-  unsigned int s_mask, t_mask, t_shift;
+  unsigned int s_mask, s_shift, t_mask, t_shift;
 } ZTextureLevel;
 
 typedef struct ZBuffer ZBuffer;
 typedef struct ZBufferPoint ZBufferPoint;
+typedef struct ZTextureDef ZTextureDef;
 
 typedef void (*ZB_fillTriangleFunc)(ZBuffer  *,
                                     ZBufferPoint *,ZBufferPoint *,ZBufferPoint *);
 
 typedef void (*ZB_storePixelFunc)(ZBuffer *zb, PIXEL &result, int r, int g, int b, int a);
 
-typedef PIXEL (*ZB_lookupTextureFunc)(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
+typedef PIXEL (*ZB_lookupTextureFunc)(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+
+typedef int (*ZB_texWrapFunc)(int coord, int max_coord); 
+
+struct ZTextureDef {
+  ZTextureLevel *levels;
+  ZB_lookupTextureFunc tex_minfilter_func;
+  ZB_lookupTextureFunc tex_magfilter_func;
+  ZB_lookupTextureFunc tex_minfilter_func_impl;
+  ZB_lookupTextureFunc tex_magfilter_func_impl;
+  ZB_texWrapFunc tex_wrap_u_func;
+  ZB_texWrapFunc tex_wrap_v_func;
+  int s_max, t_max;
+  PIXEL border_color;
+};
 
 struct ZBuffer {
   int xsize,ysize;
@@ -130,12 +145,10 @@ struct ZBuffer {
   int nb_colors;
   unsigned char *dctable;
   int *ctable;
-  ZTextureLevel *current_textures[MAX_TEXTURE_STAGES];  // This is actually an array of texture levels for each stage.
+  ZTextureDef current_textures[MAX_TEXTURE_STAGES];
   int reference_alpha;
   int blend_r, blend_g, blend_b, blend_a;
   ZB_storePixelFunc store_pix_func;
-  ZB_lookupTextureFunc tex_minfilter_func;
-  ZB_lookupTextureFunc tex_magfilter_func;
 };
 
 struct ZBufferPoint {
@@ -192,12 +205,26 @@ void ZB_clear_viewport(ZBuffer * zb, int clear_z, ZPOINT z,
                        int clear_color, unsigned int r, unsigned int g, unsigned int b, unsigned int a,
                        int xmin, int ymin, int xsize, int ysize);
 
-PIXEL lookup_texture_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
-PIXEL lookup_texture_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
-PIXEL lookup_texture_mipmap_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
-PIXEL lookup_texture_mipmap_linear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
-PIXEL lookup_texture_mipmap_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
-PIXEL lookup_texture_mipmap_trilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL lookup_texture_nearest(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL lookup_texture_bilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL lookup_texture_mipmap_nearest(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL lookup_texture_mipmap_linear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL lookup_texture_mipmap_bilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL lookup_texture_mipmap_trilinear(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+
+PIXEL apply_wrap_general_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL apply_wrap_general_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+
+PIXEL apply_wrap_border_color_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL apply_wrap_border_color_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+
+PIXEL apply_wrap_clamp_minfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+PIXEL apply_wrap_clamp_magfilter(ZTextureDef *texture_def, int s, int t, unsigned int level, unsigned int level_dx);
+
+int texcoord_clamp(int coord, int max_coord);
+int texcoord_repeat(int coord, int max_coord);
+int texcoord_mirror(int coord, int max_coord);
+int texcoord_mirror_once(int coord, int max_coord);
 
 /* linesize is in BYTES */
 void ZB_copyFrameBuffer(ZBuffer *zb,void *buf,int linesize);

+ 1 - 0
panda/src/tinydisplay/zgl.h

@@ -123,6 +123,7 @@ typedef struct GLTexture {
   int num_levels;
   int xsize, ysize;
   int s_max, t_max;
+  V4 border_color;
 
   void *allocated_buffer;
   int total_bytecount;

+ 3 - 3
panda/src/tinydisplay/ztriangle.py

@@ -60,9 +60,9 @@ CodeTable = {
     'zless' : '#define ZCMP(zpix, z) ((ZPOINT)(zpix) < (ZPOINT)(z))',
 
     # texture filters
-    'tnearest' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t)',
-    'tmipmap' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level)',
-    'tgeneral' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ((level == 0) ? zb->tex_magfilter_func(texture_levels, s, t, level, level_dx) : zb->tex_minfilter_func(texture_levels, s, t, level, level_dx))',
+    'tnearest' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define ZB_LOOKUP_TEXTURE(texture_def, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t)',
+    'tmipmap' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_def, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level)',
+    'tgeneral' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_def, s, t, level, level_dx) ((level == 0) ? (texture_def)->tex_magfilter_func(texture_def, s, t, level, level_dx) : (texture_def)->tex_minfilter_func(texture_def, s, t, level, level_dx))',
 }
 
 ops = [0] * len(Options)

File diff suppressed because it is too large
+ 112 - 112
panda/src/tinydisplay/ztriangle_code.h


+ 23 - 23
panda/src/tinydisplay/ztriangle_two.h

@@ -117,7 +117,7 @@ static void FNAME(smooth_untextured) (ZBuffer *zb,
 static void FNAME(white_textured) (ZBuffer *zb,
                                    ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2)
 {
-  ZTextureLevel *texture_levels;
+  ZTextureDef *texture_def;
 
 #define INTERP_Z
 #define INTERP_ST
@@ -128,14 +128,14 @@ static void FNAME(white_textured) (ZBuffer *zb,
 
 #define DRAW_INIT()				\
   {						\
-    texture_levels = zb->current_textures[0];       \
+    texture_def = &zb->current_textures[0];       \
   }
 
 #define PUT_PIXEL(_a)                                                   \
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx);      \
+      tmp = ZB_LOOKUP_TEXTURE(texture_def, s, t, mipmap_level, mipmap_dx);      \
       if (ACMP(zb, PIXEL_A(tmp))) {                                     \
         STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \
         STORE_Z(pz[_a], zz);                                            \
@@ -154,7 +154,7 @@ static void FNAME(white_textured) (ZBuffer *zb,
 static void FNAME(flat_textured) (ZBuffer *zb,
                                   ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2)
 {
-  ZTextureLevel *texture_levels;
+  ZTextureDef *texture_def;
   int or0, og0, ob0, oa0;
 
 #define INTERP_Z
@@ -170,7 +170,7 @@ static void FNAME(flat_textured) (ZBuffer *zb,
       /* This alpha is zero, and we'll never get other than 0. */       \
       return;                                   \
     }                                           \
-    texture_levels = zb->current_textures[0];       \
+    texture_def = &zb->current_textures[0];       \
     or0 = p2->r;                                \
     og0 = p2->g;                                \
     ob0 = p2->b;                                \
@@ -181,7 +181,7 @@ static void FNAME(flat_textured) (ZBuffer *zb,
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx);      \
+      tmp = ZB_LOOKUP_TEXTURE(texture_def, s, t, mipmap_level, mipmap_dx);      \
       int a = PALPHA_MULT(oa0, PIXEL_A(tmp));                           \
       if (ACMP(zb, a)) {                                                \
         STORE_PIX(pp[_a],                                               \
@@ -209,7 +209,7 @@ static void FNAME(flat_textured) (ZBuffer *zb,
 static void FNAME(smooth_textured) (ZBuffer *zb,
                                     ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2)
 {
-  ZTextureLevel *texture_levels;
+  ZTextureDef *texture_def;
 
 #define INTERP_Z
 #define INTERP_ST
@@ -235,14 +235,14 @@ static void FNAME(smooth_textured) (ZBuffer *zb,
 
 #define DRAW_INIT()                             \
   {                                             \
-    texture_levels = zb->current_textures[0];       \
+    texture_def = &zb->current_textures[0];       \
   }
 
 #define PUT_PIXEL(_a)                                                   \
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx);      \
+      tmp = ZB_LOOKUP_TEXTURE(texture_def, s, t, mipmap_level, mipmap_dx);      \
       int a = PALPHA_MULT(oa1, PIXEL_A(tmp));                           \
       if (ACMP(zb, a)) {                                                \
         STORE_PIX(pp[_a],                                               \
@@ -279,7 +279,7 @@ static void FNAME(smooth_textured) (ZBuffer *zb,
 static void FNAME(white_perspective) (ZBuffer *zb,
                                       ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2)
 {
-  ZTextureLevel *texture_levels;
+  ZTextureDef *texture_def;
   float fdzdx,fndzdx,ndszdx,ndtzdx;
 
 #define INTERP_Z
@@ -293,7 +293,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
 
 #define DRAW_INIT()				\
   {						\
-    texture_levels = zb->current_textures[0];       \
+    texture_def = &zb->current_textures[0];       \
     fdzdx=(float)dzdx;                          \
     fndzdx=NB_INTERP * fdzdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
@@ -305,7 +305,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx);      \
+      tmp = ZB_LOOKUP_TEXTURE(texture_def, s, t, mipmap_level, mipmap_dx);      \
       if (ACMP(zb, PIXEL_A(tmp))) {                                     \
         STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \
         STORE_Z(pz[_a], zz);                                            \
@@ -388,7 +388,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
 static void FNAME(flat_perspective) (ZBuffer *zb,
                                      ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2)
 {
-  ZTextureLevel *texture_levels;
+  ZTextureDef *texture_def;
   float fdzdx,fndzdx,ndszdx,ndtzdx;
   int or0, og0, ob0, oa0;
 
@@ -406,7 +406,7 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
       /* This alpha is zero, and we'll never get other than 0. */       \
       return;                                   \
     }                                           \
-    texture_levels = zb->current_textures[0];       \
+    texture_def = &zb->current_textures[0];       \
     fdzdx=(float)dzdx;                          \
     fndzdx=NB_INTERP * fdzdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
@@ -421,7 +421,7 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx);      \
+      tmp = ZB_LOOKUP_TEXTURE(texture_def, s, t, mipmap_level, mipmap_dx);      \
       int a = PALPHA_MULT(oa0, PIXEL_A(tmp));                           \
       if (ACMP(zb, a)) {                                                \
         STORE_PIX(pp[_a],                                               \
@@ -518,7 +518,7 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
 static void FNAME(smooth_perspective) (ZBuffer *zb,
                                        ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2)
 {
-  ZTextureLevel *texture_levels;
+  ZTextureDef *texture_def;
   float fdzdx,fndzdx,ndszdx,ndtzdx;
 
 #define INTERP_Z
@@ -545,7 +545,7 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
 
 #define DRAW_INIT() 				\
   {						\
-    texture_levels = zb->current_textures[0];       \
+    texture_def = &zb->current_textures[0];       \
     fdzdx=(float)dzdx;                          \
     fndzdx=NB_INTERP * fdzdx;                   \
     ndszdx=NB_INTERP * dszdx;                   \
@@ -556,7 +556,7 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
+      tmp = ZB_LOOKUP_TEXTURE(texture_def, s, t, mipmap_level, mipmap_dx); \
       int a = PALPHA_MULT(oa1, PIXEL_A(tmp));                           \
       if (ACMP(zb, a)) {                                                \
         STORE_PIX(pp[_a],                                               \
@@ -683,10 +683,10 @@ static void FNAME(smooth_multitex2) (ZBuffer *zb,
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(zb->current_textures[0], s, t, mipmap_level, mipmap_dx); \
+      tmp = ZB_LOOKUP_TEXTURE(&zb->current_textures[0], s, t, mipmap_level, mipmap_dx); \
       int a = PALPHA_MULT(oa1, PIXEL_A(tmp));                           \
       if (ACMP(zb, a)) {                                                \
-        int tmpa = ZB_LOOKUP_TEXTURE(zb->current_textures[1], sa, ta, mipmap_levela, mipmap_dxa); \
+        int tmpa = ZB_LOOKUP_TEXTURE(&zb->current_textures[1], sa, ta, mipmap_levela, mipmap_dxa); \
         STORE_PIX(pp[_a],                                               \
                   RGBA_TO_PIXEL(PCOMPONENT_MULT3(or1, PIXEL_R(tmp), PIXEL_R(tmpa)),     \
                                 PCOMPONENT_MULT3(og1, PIXEL_G(tmp), PIXEL_G(tmpa)),     \
@@ -840,11 +840,11 @@ static void FNAME(smooth_multitex3) (ZBuffer *zb,
   {                                                                     \
     zz=z >> ZB_POINT_Z_FRAC_BITS;                                       \
     if (ZCMP(pz[_a], zz)) {                                             \
-      tmp = ZB_LOOKUP_TEXTURE(zb->current_textures[0], s, t, mipmap_level, mipmap_dx); \
+      tmp = ZB_LOOKUP_TEXTURE(&zb->current_textures[0], s, t, mipmap_level, mipmap_dx); \
       int a = PALPHA_MULT(oa1, PIXEL_A(tmp));                           \
       if (ACMP(zb, a)) {                                                \
-        int tmpa = ZB_LOOKUP_TEXTURE(zb->current_textures[1], sa, ta, mipmap_levela, mipmap_dxa); \
-        int tmpb = ZB_LOOKUP_TEXTURE(zb->current_textures[2], sb, tb, mipmap_levelb, mipmap_dxb); \
+        int tmpa = ZB_LOOKUP_TEXTURE(&zb->current_textures[1], sa, ta, mipmap_levela, mipmap_dxa); \
+        int tmpb = ZB_LOOKUP_TEXTURE(&zb->current_textures[2], sb, tb, mipmap_levelb, mipmap_dxb); \
         STORE_PIX(pp[_a],                                               \
                   RGBA_TO_PIXEL(PCOMPONENT_MULT4(or1, PIXEL_R(tmp), PIXEL_R(tmpa), PIXEL_R(tmpb)),     \
                                 PCOMPONENT_MULT4(og1, PIXEL_G(tmp), PIXEL_G(tmpa), PIXEL_G(tmpb)),     \

Some files were not shown because too many files changed in this diff