New mipmap lambda calculation. Previously, trilinear filtering could
authorBrian Paul <brian.paul@tungstengraphics.com>
Sat, 16 Mar 2002 18:02:07 +0000 (18:02 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sat, 16 Mar 2002 18:02:07 +0000 (18:02 +0000)
result in _very_ blurry textures.  Still need to do some optimization
of the new code in s_span.c

src/mesa/swrast/s_aatriangle.c
src/mesa/swrast/s_aatritemp.h
src/mesa/swrast/s_pointtemp.h
src/mesa/swrast/s_span.c
src/mesa/swrast/s_texture.c
src/mesa/swrast/s_triangle.c
src/mesa/swrast/s_tritemp.h

index 0162319a668359cfe6e3da4ca9f747d912926fa7..ea939a5369fad94030e37748cb84f4b71c52d1db 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: s_aatriangle.c,v 1.22 2002/01/27 18:32:03 brianp Exp $ */
+/* $Id: s_aatriangle.c,v 1.23 2002/03/16 18:02:07 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  4.0.1
+ * Version:  4.1
  *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -124,7 +124,6 @@ solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
 }
 
 
-
 /*
  * Solve plane and return clamped GLchan value.
  */
@@ -352,23 +351,36 @@ index_aa_tri(GLcontext *ctx,
 
 /*
  * Compute mipmap level of detail.
+ * XXX we should really include the R coordinate in this computation
+ * in order to do 3-D texture mipmapping.
  */
 static INLINE GLfloat
 compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
-               GLfloat invQ, GLfloat width, GLfloat height)
+               const GLfloat qPlane[4], GLfloat cx, GLfloat cy,
+               GLfloat invQ, GLfloat texWidth, GLfloat texHeight)
 {
-   GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width;
-   GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width;
-   GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height;
-   GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height;
-   GLfloat r1 = dudx * dudx + dudy * dudy;
-   GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
-   GLfloat rho2 = r1 + r2;
-   /* return log base 2 of rho */
-   if (rho2 == 0.0F)
-      return 0.0;
-   else
-      return (GLfloat) (log(rho2) * 1.442695 * 0.5); /* 1.442695 = 1/log(2) */
+   const GLfloat s = solve_plane(cx, cy, sPlane);
+   const GLfloat t = solve_plane(cx, cy, tPlane);
+   const GLfloat invQ_x1 = solve_plane_recip(cx+1.0, cy, qPlane);
+   const GLfloat invQ_y1 = solve_plane_recip(cx, cy+1.0, qPlane);
+   const GLfloat s_x1 = s - sPlane[0] / sPlane[2];
+   const GLfloat s_y1 = s - sPlane[1] / sPlane[2];
+   const GLfloat t_x1 = t - tPlane[0] / tPlane[2];
+   const GLfloat t_y1 = t - tPlane[1] / tPlane[2];
+   GLfloat dsdx = s_x1 * invQ_x1 - s * invQ;
+   GLfloat dsdy = s_y1 * invQ_y1 - s * invQ;
+   GLfloat dtdx = t_x1 * invQ_x1 - t * invQ;
+   GLfloat dtdy = t_y1 * invQ_y1 - t * invQ;
+   GLfloat maxU, maxV, rho, lambda;
+   dsdx = FABSF(dsdx);
+   dsdy = FABSF(dsdy);
+   dtdx = FABSF(dtdx);
+   dtdy = FABSF(dtdy);
+   maxU = MAX2(dsdx, dsdy) * texWidth;
+   maxV = MAX2(dtdx, dtdy) * texHeight;
+   rho = MAX2(maxU, maxV);
+   lambda = LOG2(rho);
+   return lambda;
 }
 
 
index 90b8fe74e315a250e9dbcc64037da51aac423c6a..2fd59b232339bd4494ce7f7ccfcd60fb2b93bfe5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_aatritemp.h,v 1.26 2002/01/28 03:42:28 brianp Exp $ */
+/* $Id: s_aatritemp.h,v 1.27 2002/03/16 18:02:07 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
    GLfloat sPlane[4], tPlane[4], uPlane[4], vPlane[4];
    GLfloat texWidth, texHeight;
 #elif defined(DO_MULTITEX)
-   GLfloat sPlane[MAX_TEXTURE_UNITS][4];
-   GLfloat tPlane[MAX_TEXTURE_UNITS][4];
-   GLfloat uPlane[MAX_TEXTURE_UNITS][4];
-   GLfloat vPlane[MAX_TEXTURE_UNITS][4];
+   GLfloat sPlane[MAX_TEXTURE_UNITS][4];  /* texture S */
+   GLfloat tPlane[MAX_TEXTURE_UNITS][4];  /* texture T */
+   GLfloat uPlane[MAX_TEXTURE_UNITS][4];  /* texture R */
+   GLfloat vPlane[MAX_TEXTURE_UNITS][4];  /* texture Q */
    GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS];
 #endif
    GLfloat bf = SWRAST_CONTEXT(ctx)->_backface_sign;
                span.texcoords[0][count][0] = solve_plane(cx, cy, sPlane) * invQ;
                span.texcoords[0][count][1] = solve_plane(cx, cy, tPlane) * invQ;
                span.texcoords[0][count][2] = solve_plane(cx, cy, uPlane) * invQ;
-               span.lambda[0][count] = compute_lambda(sPlane, tPlane, invQ,
+               span.lambda[0][count] = compute_lambda(sPlane, tPlane, vPlane,
+                                                      cx, cy, invQ,
                                                       texWidth, texHeight);
             }
 #elif defined(DO_MULTITEX)
                      span.texcoords[unit][count][1] = solve_plane(cx, cy, tPlane[unit]) * invQ;
                      span.texcoords[unit][count][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
                      span.lambda[unit][count] = compute_lambda(sPlane[unit],
-                                                               tPlane[unit], invQ, texWidth[unit], texHeight[unit]);
+                                      tPlane[unit], vPlane[unit], cx, cy, invQ,
+                                      texWidth[unit], texHeight[unit]);
                   }
                }
             }
                span.texcoords[0][ix][0] = solve_plane(cx, cy, sPlane) * invQ;
                span.texcoords[0][ix][1] = solve_plane(cx, cy, tPlane) * invQ;
                span.texcoords[0][ix][2] = solve_plane(cx, cy, uPlane) * invQ;
-               span.lambda[0][ix] = compute_lambda(sPlane, tPlane, invQ,
-                                              texWidth, texHeight);
+               span.lambda[0][ix] = compute_lambda(sPlane, tPlane, vPlane,
+                                          cx, cy, invQ, texWidth, texHeight);
             }
 #elif defined(DO_MULTITEX)
             {
                      span.texcoords[unit][ix][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
                      span.lambda[unit][ix] = compute_lambda(sPlane[unit],
                                                             tPlane[unit],
-                                                            invQ,
+                                                            vPlane[unit],
+                                                            cx, cy, invQ,
                                                             texWidth[unit],
                                                             texHeight[unit]);
                   }
index 02dc9fee2cdeb007acd9cc41ec0ec83c6728ed3a..8fa608f8242eea69610a0d98a61c5d58365f23ba 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_pointtemp.h,v 1.12 2002/02/02 17:24:11 brianp Exp $ */
+/* $Id: s_pointtemp.h,v 1.13 2002/03/16 18:02:08 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -120,7 +120,6 @@ NAME ( GLcontext *ctx, const SWvertex *vert )
 #endif
 #if FLAGS & TEXTURE
    span.interpMask |= SPAN_TEXTURE;
-   span.arrayMask |= SPAN_LAMBDA;
    for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
       if (ctx->Texture.Unit[u]._ReallyEnabled) {
          const GLfloat q = vert->texcoord[u][3];
@@ -129,11 +128,10 @@ NAME ( GLcontext *ctx, const SWvertex *vert )
          span.tex[u][1] = vert->texcoord[u][1] * invQ;
          span.tex[u][2] = vert->texcoord[u][2] * invQ;
          span.tex[u][3] = q;
-         span.texStep[u][0] = 0.0;
-         span.texStep[u][1] = 0.0;
-         span.texStep[u][2] = 0.0;
-         span.texStep[u][3] = 0.0;
-         span.rho[u] = 0.0;
+         span.texStepX[u][0] = span.texStepY[u][0] = 0.0;
+         span.texStepX[u][1] = span.texStepY[u][1] = 0.0;
+         span.texStepX[u][2] = span.texStepY[u][2] = 0.0;
+         span.texStepX[u][3] = span.texStepY[u][3] = 0.0;
       }
    }
 #endif
index 90de11b86a30cbb2491e02ef67874548d6ac7667..2ce8b76cf57f8cb350784886907541c665eec398 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_span.c,v 1.36 2002/02/17 17:30:57 brianp Exp $ */
+/* $Id: s_span.c,v 1.37 2002/03/16 18:02:08 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -36,6 +36,7 @@
 #include "colormac.h"
 #include "context.h"
 #include "macros.h"
+#include "mmath.h"
 #include "mem.h"
 
 #include "s_alpha.h"
@@ -263,52 +264,51 @@ _mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
 
 
 /*
- * Return log_base_2(x) / 2.
- * We divide by two here since we didn't square rho in the triangle function.
+ * This the ideal solution, as given in the OpenGL spec.
  */
-#ifdef USE_IEEE
-
 #if 0
-/* This is pretty fast, but not accurate enough (only 2 fractional bits).
- * Based on code from http://www.stereopsis.com/log2.html
- */
-static INLINE GLfloat HALF_LOG2(GLfloat x)
+static GLfloat
+compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
+               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
+               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
 {
-   const GLfloat y = x * x * x * x;
-   const GLuint ix = *((GLuint *) &y);
-   const GLuint exp = (ix >> 23) & 0xFF;
-   const GLint log2 = ((GLint) exp) - 127;
-   return (GLfloat) log2 * (0.5 / 4.0);  /* 4, because of x^4 above */
+   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
+   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
+   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
+   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
+   GLfloat x = sqrt(dudx * dudx + dvdx * dvdx);
+   GLfloat y = sqrt(dudy * dudy + dvdy * dvdy);
+   GLfloat rho = MAX2(x, y);
+   GLfloat lambda = LOG2(rho);
+   return lambda;
 }
 #endif
 
-/* Pretty fast, and accurate.
- * Based on code from http://www.flipcode.com/totd/
+
+/*
+ * This is a faster approximation
  */
-static INLINE GLfloat HALF_LOG2(GLfloat val)
+static GLfloat
+compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
+               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
+               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
 {
-   GLint *exp_ptr = (GLint *) &val;
-   GLint x = *exp_ptr;
-   const GLint log_2 = ((x >> 23) & 255) - 128;
-   x &= ~(255 << 23);
-   x += 127 << 23;
-   *exp_ptr = x;
-   val = ((-1.0f/3) * val + 2) * val - 2.0f/3;
-   return 0.5F * (val + log_2);
+   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
+   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
+   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
+   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
+   GLfloat maxU, maxV, rho, lambda;
+   dsdx2 = FABSF(dsdx2);
+   dsdy2 = FABSF(dsdy2);
+   dtdx2 = FABSF(dtdx2);
+   dtdy2 = FABSF(dtdy2);
+   maxU = MAX2(dsdx2, dsdy2) * texW;
+   maxV = MAX2(dtdx2, dtdy2) * texH;
+   rho = MAX2(maxU, maxV);
+   lambda = LOG2(rho);
+   return lambda;
 }
 
-#else /* USE_IEEE */
-
-/* Slow, portable solution.
- * NOTE: log_base_2(x) = log(x) / log(2)
- * NOTE: 1.442695 = 1/log(2).
- */
-#define HALF_LOG2(x)  ((GLfloat) (log(x) * (1.442695F * 0.5F)))
-
-#endif /* USE_IEEE */
-
-
-
 /*
  * Fill in the span.texcoords array from the interpolation values.
  * XXX We could optimize here for the case when dq = 0.  That would
@@ -320,76 +320,64 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
    ASSERT(span->interpMask & SPAN_TEXTURE);
 
    if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
-      if (span->interpMask & SPAN_LAMBDA) {
-         /* multitexture, lambda */
-         GLuint u;
-         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-            if (ctx->Texture.Unit[u]._ReallyEnabled) {
-               const GLfloat rho = span->rho[u];
-               const GLfloat ds = span->texStep[u][0];
-               const GLfloat dt = span->texStep[u][1];
-               const GLfloat dr = span->texStep[u][2];
-               const GLfloat dq = span->texStep[u][3];
+      /* multitexture */
+      GLuint u;
+      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+         if (ctx->Texture.Unit[u]._ReallyEnabled) {
+            const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
+            const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
+            GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
+            if (needLambda) {
+               const GLfloat texW = (GLfloat) img->Width;
+               const GLfloat texH = (GLfloat) img->Height;
+               const GLfloat dsdx = span->texStepX[u][0];
+               const GLfloat dsdy = span->texStepY[u][0];
+               const GLfloat dtdx = span->texStepX[u][1];
+               const GLfloat dtdy = span->texStepY[u][1];
+               const GLfloat drdx = span->texStepX[u][2];
+               const GLfloat dqdx = span->texStepX[u][3];
+               const GLfloat dqdy = span->texStepY[u][3];
                GLfloat s = span->tex[u][0];
                GLfloat t = span->tex[u][1];
                GLfloat r = span->tex[u][2];
                GLfloat q = span->tex[u][3];
                GLuint i;
-               if (dq == 0.0) {
-                  /* Ortho projection or polygon's parallel to window X axis */
+               for (i = 0; i < span->end; i++) {
                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
-                  const GLfloat lambda = HALF_LOG2(rho * invQ * invQ);
-                  for (i = 0; i < span->end; i++) {
-                     span->texcoords[u][i][0] = s * invQ;
-                     span->texcoords[u][i][1] = t * invQ;
-                     span->texcoords[u][i][2] = r * invQ;
-                     span->lambda[u][i] = lambda;
-                     s += ds;
-                     t += dt;
-                     r += dr;
-                  }
-               }
-               else {
-                  for (i = 0; i < span->end; i++) {
-                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
-                     span->texcoords[u][i][0] = s * invQ;
-                     span->texcoords[u][i][1] = t * invQ;
-                     span->texcoords[u][i][2] = r * invQ;
-                     span->lambda[u][i] = HALF_LOG2(rho * invQ * invQ);
-                     s += ds;
-                     t += dt;
-                     r += dr;
-                     q += dq;
-                  }
+                  span->texcoords[u][i][0] = s * invQ;
+                  span->texcoords[u][i][1] = t * invQ;
+                  span->texcoords[u][i][2] = r * invQ;
+                  span->lambda[u][i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
+                                                      dqdx, dqdy, texW, texH,
+                                                      s, t, q, invQ);
+                  s += dsdx;
+                  t += dtdx;
+                  r += drdx;
+                  q += dqdx;
                }
+               span->arrayMask |= SPAN_LAMBDA;
             }
-         }
-         span->arrayMask |= SPAN_LAMBDA;
-      }
-      else {
-         /* multitexture, no lambda */
-         GLuint u;
-         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-            if (ctx->Texture.Unit[u]._ReallyEnabled) {
-               const GLfloat ds = span->texStep[u][0];
-               const GLfloat dt = span->texStep[u][1];
-               const GLfloat dr = span->texStep[u][2];
-               const GLfloat dq = span->texStep[u][3];
+            else {
+               const GLfloat dsdx = span->texStepX[u][0];
+               const GLfloat dtdx = span->texStepX[u][1];
+               const GLfloat drdx = span->texStepX[u][2];
+               const GLfloat dqdx = span->texStepX[u][3];
                GLfloat s = span->tex[u][0];
                GLfloat t = span->tex[u][1];
                GLfloat r = span->tex[u][2];
                GLfloat q = span->tex[u][3];
                GLuint i;
-               if (dq == 0.0) {
+               if (dqdx == 0.0) {
                   /* Ortho projection or polygon's parallel to window X axis */
                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
                   for (i = 0; i < span->end; i++) {
                      span->texcoords[u][i][0] = s * invQ;
                      span->texcoords[u][i][1] = t * invQ;
                      span->texcoords[u][i][2] = r * invQ;
-                     s += ds;
-                     t += dt;
-                     r += dr;
+                     span->lambda[u][i] = 0.0;
+                     s += dsdx;
+                     t += dtdx;
+                     r += drdx;
                   }
                }
                else {
@@ -398,79 +386,74 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
                      span->texcoords[u][i][0] = s * invQ;
                      span->texcoords[u][i][1] = t * invQ;
                      span->texcoords[u][i][2] = r * invQ;
-                     s += ds;
-                     t += dt;
-                     r += dr;
-                     q += dq;
+                     span->lambda[u][i] = 0.0;
+                     s += dsdx;
+                     t += dtdx;
+                     r += drdx;
+                     q += dqdx;
                   }
                }
-            }
-         }
-      }
+            } /* lambda */
+         } /* if */
+      } /* for */
    }
    else {
-      if (span->interpMask & SPAN_LAMBDA) {
+      /* single texture */
+      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
+      const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
+      GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
+      if (needLambda) {
          /* just texture unit 0, with lambda */
-         const GLfloat rho = span->rho[0];
-         const GLfloat ds = span->texStep[0][0];
-         const GLfloat dt = span->texStep[0][1];
-         const GLfloat dr = span->texStep[0][2];
-         const GLfloat dq = span->texStep[0][3];
+         const GLfloat texW = (GLfloat) img->Width;
+         const GLfloat texH = (GLfloat) img->Height;
+         const GLfloat dsdx = span->texStepX[0][0];
+         const GLfloat dsdy = span->texStepY[0][0];
+         const GLfloat dtdx = span->texStepX[0][1];
+         const GLfloat dtdy = span->texStepY[0][1];
+         const GLfloat drdx = span->texStepX[0][2];
+         const GLfloat dqdx = span->texStepX[0][3];
+         const GLfloat dqdy = span->texStepY[0][3];
          GLfloat s = span->tex[0][0];
          GLfloat t = span->tex[0][1];
          GLfloat r = span->tex[0][2];
          GLfloat q = span->tex[0][3];
          GLuint i;
-         if (dq == 0.0) {
-            /* Ortho projection or polygon's parallel to window X axis */
+         for (i = 0; i < span->end; i++) {
             const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
-            const GLfloat lambda = HALF_LOG2(rho * invQ * invQ);
-            for (i = 0; i < span->end; i++) {
-               span->texcoords[0][i][0] = s * invQ;
-               span->texcoords[0][i][1] = t * invQ;
-               span->texcoords[0][i][2] = r * invQ;
-               span->lambda[0][i] = lambda;
-               s += ds;
-               t += dt;
-               r += dr;
-            }
-         }
-         else {
-            for (i = 0; i < span->end; i++) {
-               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
-               span->texcoords[0][i][0] = s * invQ;
-               span->texcoords[0][i][1] = t * invQ;
-               span->texcoords[0][i][2] = r * invQ;
-               span->lambda[0][i] = HALF_LOG2(rho * invQ * invQ);
-               s += ds;
-               t += dt;
-               r += dr;
-               q += dq;
-            }
+            span->lambda[0][i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
+                                                dqdx, dqdy, texW, texH,
+                                                s, t, q, invQ);
+            span->texcoords[0][i][0] = s * invQ;
+            span->texcoords[0][i][1] = t * invQ;
+            span->texcoords[0][i][2] = r * invQ;
+            s += dsdx;
+            t += dtdx;
+            r += drdx;
+            q += dqdx;
          }
          span->arrayMask |= SPAN_LAMBDA;
       }
       else {
          /* just texture 0, without lambda */
-         const GLfloat ds = span->texStep[0][0];
-         const GLfloat dt = span->texStep[0][1];
-         const GLfloat dr = span->texStep[0][2];
-         const GLfloat dq = span->texStep[0][3];
+         const GLfloat dsdx = span->texStepX[0][0];
+         const GLfloat dtdx = span->texStepX[0][1];
+         const GLfloat drdx = span->texStepX[0][2];
+         const GLfloat dqdx = span->texStepX[0][3];
          GLfloat s = span->tex[0][0];
          GLfloat t = span->tex[0][1];
          GLfloat r = span->tex[0][2];
          GLfloat q = span->tex[0][3];
          GLuint i;
-         if (dq == 0.0) {
+         if (dqdx == 0.0) {
             /* Ortho projection or polygon's parallel to window X axis */
             const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
             for (i = 0; i < span->end; i++) {
                span->texcoords[0][i][0] = s * invQ;
                span->texcoords[0][i][1] = t * invQ;
                span->texcoords[0][i][2] = r * invQ;
-               s += ds;
-               t += dt;
-               r += dr;
+               s += dsdx;
+               t += dtdx;
+               r += drdx;
             }
          }
          else {
@@ -479,10 +462,10 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
                span->texcoords[0][i][0] = s * invQ;
                span->texcoords[0][i][1] = t * invQ;
                span->texcoords[0][i][2] = r * invQ;
-               s += ds;
-               t += dt;
-               r += dr;
-               q += dq;
+               s += dsdx;
+               t += dtdx;
+               r += drdx;
+               q += dqdx;
             }
          }
       }
index 43604291304e6090110ad5b4220f9415a0787f71..a487bd8970dd59d40e492e1abee61b7c14f23fcc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_texture.c,v 1.55 2002/03/08 00:09:18 brianp Exp $ */
+/* $Id: s_texture.c,v 1.56 2002/03/16 18:02:08 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -310,18 +310,22 @@ compute_min_mag_ranges( GLfloat minMagThresh, GLuint n, const GLfloat lambda[],
                         GLuint *magStart, GLuint *magEnd )
 {
    ASSERT(lambda != NULL);
-#ifdef DEBUG
-   /* verify that lambda[] is monotonous */
+#if 0
+   /* Verify that lambda[] is monotonous.
+    * We can't really use this because the inaccuracy in the LOG2 function
+    * causes this test to fail, yet the resulting texturing is correct.
+    */
    if (n > 1) {
       GLuint i;
+      printf("lambda delta = %g\n", lambda[0] - lambda[n-1]);
       if (lambda[0] >= lambda[n-1]) { /* decreasing */
          for (i = 0; i < n - 1; i++) {
-            ASSERT((GLint) (lambda[i] * 100) >= (GLint) (lambda[i+1] * 100));
+            ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10));
          }
       }
       else { /* increasing */
          for (i = 0; i < n - 1; i++) {
-            ASSERT((GLint) (lambda[i] * 100) <= (GLint) (lambda[i+1] * 100));
+            ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
          }
       }
    }
@@ -367,8 +371,10 @@ compute_min_mag_ranges( GLfloat minMagThresh, GLuint n, const GLfloat lambda[],
       }
    }
 
-#ifdef DEBUG
-   /* Verify the min/mag Start/End values */
+#if 0
+   /* Verify the min/mag Start/End values
+    * We don't use this either (see above)
+    */
    {
       GLint i;
       for (i = 0; i < n; i++) {
@@ -3280,6 +3286,18 @@ _swrast_texture_fragments( GLcontext *ctx, GLuint texUnit, GLuint n,
          GLchan texel[MAX_WIDTH][4];
          
          if (lambda) {
+#if 0
+            float min, max;
+            int i;
+            min = max = lambda[0];
+            for (i = 1; i < n; i++) {
+               if (lambda[i] > max)
+                  max = lambda[i];
+               if (lambda[i] < min)
+                  min = lambda[i];
+            }
+            printf("min/max %g / %g\n", min, max);
+#endif
             if (textureUnit->LodBias != 0.0F) {
                /* apply LOD bias, but don't clamp yet */
                GLuint i;
index 9bdc2035242d7727db103db1b3006e72b38c519d..17775526174430d0dae3125dc2b236cba7ff5148 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_triangle.c,v 1.54 2002/02/02 17:24:11 brianp Exp $ */
+/* $Id: s_triangle.c,v 1.55 2002/03/16 18:02:08 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -722,13 +722,13 @@ fast_persp_span(GLcontext *ctx, struct sw_span *span,
    GLfloat tex_coord[3], tex_step[3];
    GLchan *dest = span->color.rgba[0];
 
-   tex_coord[0] = span->tex[0][0]  * (info->smask + 1),
-     tex_step[0] = span->texStep[0][0] * (info->smask + 1);
-   tex_coord[1] = span->tex[0][1] * (info->tmask + 1),
-     tex_step[1] = span->texStep[0][1] * (info->tmask + 1);
+   tex_coord[0] = span->tex[0][0]  * (info->smask + 1);
+   tex_step[0] = span->texStepX[0][0] * (info->smask + 1);
+   tex_coord[1] = span->tex[0][1] * (info->tmask + 1);
+   tex_step[1] = span->texStepX[0][1] * (info->tmask + 1);
    /* span->tex[0][2] only if 3D-texturing, here only 2D */
-   tex_coord[2] = span->tex[0][3],
-     tex_step[2] = span->texStep[0][3];
+   tex_coord[2] = span->tex[0][3];
+   tex_step[2] = span->texStepX[0][3];
 
    switch (info->filter) {
    case GL_NEAREST:
@@ -934,44 +934,16 @@ static void general_textured_triangle( GLcontext *ctx,
 
 
 
-/*
- * Render a smooth-shaded, textured, RGBA triangle.
- * Interpolate S,T,R with perspective correction and compute lambda for
- * each fragment.  Lambda is used to determine whether to use the
- * minification or magnification filter.  If minification and using
- * mipmaps, lambda is also used to select the texture level of detail.
- */
-static void lambda_textured_triangle( GLcontext *ctx,
-                                     const SWvertex *v0,
-                                     const SWvertex *v1,
-                                     const SWvertex *v2 )
-{
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
-#define INTERP_RGB 1
-#define INTERP_SPEC 1
-#define INTERP_ALPHA 1
-#define INTERP_TEX 1
-#define INTERP_LAMBDA 1
-
-#define RENDER_SPAN( span )   _mesa_write_texture_span(ctx, &span, GL_POLYGON);
-
-#include "s_tritemp.h"
-}
-
-
 /*
  * This is the big one!
- * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates
- * with lambda (LOD).
+ * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates.
  * Yup, it's slow.
  */
 static void
-lambda_multitextured_triangle( GLcontext *ctx,
-                               const SWvertex *v0,
-                               const SWvertex *v1,
-                               const SWvertex *v2 )
+multitextured_triangle( GLcontext *ctx,
+                        const SWvertex *v0,
+                        const SWvertex *v1,
+                        const SWvertex *v2 )
 {
 
 #define INTERP_Z 1
@@ -981,7 +953,6 @@ lambda_multitextured_triangle( GLcontext *ctx,
 #define INTERP_ALPHA 1
 #define INTERP_SPEC 1
 #define INTERP_MULTITEX 1
-#define INTERP_LAMBDA 1
 
 #define RENDER_SPAN( span )   _mesa_write_texture_span(ctx, &span, GL_POLYGON);
 
@@ -1201,24 +1172,12 @@ _swrast_choose_triangle( GLcontext *ctx )
            }
         }
          else {
-            /* More complicated textures (mipmap, multi-tex, sep specular) */
-            GLboolean needLambda;
-            /* if mag filter != min filter we need to compute lambda */
-            const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
-            if (obj && obj->MinFilter != obj->MagFilter)
-               needLambda = GL_TRUE;
-            else
-               needLambda = GL_FALSE;
+            /* general case textured triangles */
             if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) {
-               USE(lambda_multitextured_triangle);
+               USE(multitextured_triangle);
             }
             else {
-               if (needLambda) {
-                 USE(lambda_textured_triangle);
-              }
-               else {
-                  USE(general_textured_triangle);
-              }
+               USE(general_textured_triangle);
             }
          }
       }
index 4a602186d783598ba0b9bbbf062eaca201a91387..0c04db939331858f08e41c8f8fd03b152b3482d8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_tritemp.h,v 1.34 2002/03/01 04:28:32 brianp Exp $ */
+/* $Id: s_tritemp.h,v 1.35 2002/03/16 18:02:08 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -43,8 +43,6 @@
  *    INTERP_TEX      - if defined, interpolate set 0 float STRQ texcoords
  *                         NOTE:  OpenGL STRQ = Mesa STUV (R was taken for red)
  *    INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords
- *    INTERP_LAMBDA   - if defined, compute lambda value (for mipmapping)
- *                         a lambda value for every texture unit
  *    INTERP_FLOAT_RGBA - if defined, interpolate RGBA with floating point
  *    INTERP_FLOAT_SPEC - if defined, interpolate specular with floating point
  *
       GLfloat dtdx, dtdy;
 #endif
 #ifdef INTERP_TEX
-      GLfloat dsdy;
-      GLfloat dtdy;
-      GLfloat dudy;
-      GLfloat dvdy;
+      GLfloat dsdx, dsdy;
+      GLfloat dtdx, dtdy;
+      GLfloat dudx, dudy;
+      GLfloat dvdx, dvdy;
 #endif
 #ifdef INTERP_MULTITEX
-      GLfloat dsdy[MAX_TEXTURE_UNITS];
-      GLfloat dtdy[MAX_TEXTURE_UNITS];
-      GLfloat dudy[MAX_TEXTURE_UNITS];
-      GLfloat dvdy[MAX_TEXTURE_UNITS];
-#endif
-
-#if defined(INTERP_LAMBDA) && !defined(INTERP_TEX) && !defined(INTERP_MULTITEX)
-#error "Mipmapping without texturing doesn't make sense."
+      GLfloat dsdx[MAX_TEXTURE_UNITS], dsdy[MAX_TEXTURE_UNITS];
+      GLfloat dtdx[MAX_TEXTURE_UNITS], dtdy[MAX_TEXTURE_UNITS];
+      GLfloat dudx[MAX_TEXTURE_UNITS], dudy[MAX_TEXTURE_UNITS];
+      GLfloat dvdx[MAX_TEXTURE_UNITS], dvdy[MAX_TEXTURE_UNITS];
 #endif
 
       /*
 
          eMaj_ds = vMax->texcoord[0][0] * wMax - vMin->texcoord[0][0] * wMin;
          eBot_ds = vMid->texcoord[0][0] * wMid - vMin->texcoord[0][0] * wMin;
-         span.texStep[0][0] = oneOverArea * (eMaj_ds * eBot.dy
-                                             - eMaj.dy * eBot_ds);
+         dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
          dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
+         span.texStepX[0][0] = dsdx;
+         span.texStepY[0][0] = dsdy;
 
          eMaj_dt = vMax->texcoord[0][1] * wMax - vMin->texcoord[0][1] * wMin;
          eBot_dt = vMid->texcoord[0][1] * wMid - vMin->texcoord[0][1] * wMin;
-         span.texStep[0][1] = oneOverArea * (eMaj_dt * eBot.dy
-                                             - eMaj.dy * eBot_dt);
+         dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
          dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
+         span.texStepX[0][1] = dtdx;
+         span.texStepY[0][1] = dtdy;
 
          eMaj_du = vMax->texcoord[0][2] * wMax - vMin->texcoord[0][2] * wMin;
          eBot_du = vMid->texcoord[0][2] * wMid - vMin->texcoord[0][2] * wMin;
-         span.texStep[0][2] = oneOverArea * (eMaj_du * eBot.dy
-                                             - eMaj.dy * eBot_du);
+         dudx = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
          dudy = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
+         span.texStepX[0][2] = dudx;
+         span.texStepY[0][2] = dudy;
 
          eMaj_dv = vMax->texcoord[0][3] * wMax - vMin->texcoord[0][3] * wMin;
          eBot_dv = vMid->texcoord[0][3] * wMid - vMin->texcoord[0][3] * wMin;
-         span.texStep[0][3] = oneOverArea * (eMaj_dv * eBot.dy
-                                             - eMaj.dy * eBot_dv);
+         dvdx = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
          dvdy = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
+         span.texStepX[0][3] = dvdx;
+         span.texStepY[0][3] = dvdy;
       }
-#  ifdef INTERP_LAMBDA
-      {
-         const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
-         const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
-         const GLfloat texWidth = (GLfloat) texImage->Width;
-         const GLfloat texHeight = (GLfloat) texImage->Height;
-         GLfloat dudx = span.texStep[0][0] * texWidth;
-         GLfloat dudy = dsdy * texWidth;
-         GLfloat dvdx = span.texStep[0][1] * texHeight;
-         GLfloat dvdy = dtdy * texHeight;
-         GLfloat r1 = dudx * dudx + dudy * dudy;
-         GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
-         span.rho[0] = r1 + r2; /* was rho2 = MAX2(r1,r2) */
-         span.interpMask |= SPAN_LAMBDA;
-      }
-#  endif
 #endif
 #ifdef INTERP_MULTITEX
       span.interpMask |= SPAN_TEXTURE;
-#  ifdef INTERP_LAMBDA
-      span.interpMask |= SPAN_LAMBDA;
-#  endif
       {
          GLfloat wMax = vMax->win[3];
          GLfloat wMin = vMin->win[3];
                        - vMin->texcoord[u][0] * wMin;
                eBot_ds = vMid->texcoord[u][0] * wMid
                        - vMin->texcoord[u][0] * wMin;
-               span.texStep[u][0] = oneOverArea * (eMaj_ds * eBot.dy
-                                                   - eMaj.dy * eBot_ds);
+               dsdx[u] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
                dsdy[u] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
+               span.texStepX[u][0] = dsdx[u];
+               span.texStepY[u][0] = dsdy[u];
 
                eMaj_dt = vMax->texcoord[u][1] * wMax
                        - vMin->texcoord[u][1] * wMin;
                eBot_dt = vMid->texcoord[u][1] * wMid
                        - vMin->texcoord[u][1] * wMin;
-               span.texStep[u][1] = oneOverArea * (eMaj_dt * eBot.dy
-                                                   - eMaj.dy * eBot_dt);
+               dtdx[u] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
                dtdy[u] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
+               span.texStepX[u][1] = dtdx[u];
+               span.texStepY[u][1] = dtdy[u];
 
                eMaj_du = vMax->texcoord[u][2] * wMax
                        - vMin->texcoord[u][2] * wMin;
                eBot_du = vMid->texcoord[u][2] * wMid
                        - vMin->texcoord[u][2] * wMin;
-               span.texStep[u][2] = oneOverArea * (eMaj_du * eBot.dy
-                                                   - eMaj.dy * eBot_du);
+               dudx[u] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
                dudy[u] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
+               span.texStepX[u][2] = dudx[u];
+               span.texStepY[u][2] = dudy[u];
 
                eMaj_dv = vMax->texcoord[u][3] * wMax
                        - vMin->texcoord[u][3] * wMin;
                eBot_dv = vMid->texcoord[u][3] * wMid
                        - vMin->texcoord[u][3] * wMin;
-               span.texStep[u][3] = oneOverArea * (eMaj_dv * eBot.dy
-                                                   - eMaj.dy * eBot_dv);
+               dvdx[u] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
                dvdy[u] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
-#  ifdef INTERP_LAMBDA
-               {
-                  const struct gl_texture_object *obj
-                     = ctx->Texture.Unit[u]._Current;
-                  const struct gl_texture_image *texImage
-                     = obj->Image[obj->BaseLevel];
-                  const GLfloat texWidth = (GLfloat) texImage->Width;
-                  const GLfloat texHeight = (GLfloat) texImage->Height;
-                  GLfloat dudx = span.texStep[u][0] * texWidth;
-                  GLfloat dudy = dsdy[u] * texWidth;
-                  GLfloat dvdx = span.texStep[u][1] * texHeight;
-                  GLfloat dvdy = dtdy[u] * texHeight;
-                  GLfloat r1 = dudx * dudx + dudy * dudy;
-                  GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
-                  span.rho[u] = r1 + r2; /* was rho2 = MAX2(r1,r2) */
-               }
-#  endif
+               span.texStepX[u][3] = dvdx[u];
+               span.texStepY[u][3] = dvdy[u];
             }
          }
       }
                   GLfloat invW = vLower->win[3];
                   GLfloat s0, t0, u0, v0;
                   s0 = vLower->texcoord[0][0] * invW;
-                  sLeft = s0 + (span.texStep[0][0] * adjx + dsdy * adjy)
+                  sLeft = s0 + (span.texStepX[0][0] * adjx + dsdy * adjy)
                      * (1.0F/FIXED_SCALE);
-                  dsOuter = dsdy + dxOuter * span.texStep[0][0];
+                  dsOuter = dsdy + dxOuter * span.texStepX[0][0];
                   t0 = vLower->texcoord[0][1] * invW;
-                  tLeft = t0 + (span.texStep[0][1] * adjx + dtdy * adjy)
+                  tLeft = t0 + (span.texStepX[0][1] * adjx + dtdy * adjy)
                      * (1.0F/FIXED_SCALE);
-                  dtOuter = dtdy + dxOuter * span.texStep[0][1];
+                  dtOuter = dtdy + dxOuter * span.texStepX[0][1];
                   u0 = vLower->texcoord[0][2] * invW;
-                  uLeft = u0 + (span.texStep[0][2] * adjx + dudy * adjy)
+                  uLeft = u0 + (span.texStepX[0][2] * adjx + dudy * adjy)
                      * (1.0F/FIXED_SCALE);
-                  duOuter = dudy + dxOuter * span.texStep[0][2];
+                  duOuter = dudy + dxOuter * span.texStepX[0][2];
                   v0 = vLower->texcoord[0][3] * invW;
-                  vLeft = v0 + (span.texStep[0][3] * adjx + dvdy * adjy)
+                  vLeft = v0 + (span.texStepX[0][3] * adjx + dvdy * adjy)
                      * (1.0F/FIXED_SCALE);
-                  dvOuter = dvdy + dxOuter * span.texStep[0][3];
+                  dvOuter = dvdy + dxOuter * span.texStepX[0][3];
                }
 #endif
 #ifdef INTERP_MULTITEX
                         GLfloat invW = vLower->win[3];
                         GLfloat s0, t0, u0, v0;
                         s0 = vLower->texcoord[u][0] * invW;
-                        sLeft[u] = s0 + (span.texStep[u][0] * adjx + dsdy[u]
+                        sLeft[u] = s0 + (span.texStepX[u][0] * adjx + dsdy[u]
                                          * adjy) * (1.0F/FIXED_SCALE);
-                        dsOuter[u] = dsdy[u] + dxOuter * span.texStep[u][0];
+                        dsOuter[u] = dsdy[u] + dxOuter * span.texStepX[u][0];
                         t0 = vLower->texcoord[u][1] * invW;
-                        tLeft[u] = t0 + (span.texStep[u][1] * adjx + dtdy[u]
+                        tLeft[u] = t0 + (span.texStepX[u][1] * adjx + dtdy[u]
                                          * adjy) * (1.0F/FIXED_SCALE);
-                        dtOuter[u] = dtdy[u] + dxOuter * span.texStep[u][1];
+                        dtOuter[u] = dtdy[u] + dxOuter * span.texStepX[u][1];
                         u0 = vLower->texcoord[u][2] * invW;
-                        uLeft[u] = u0 + (span.texStep[u][2] * adjx + dudy[u]
+                        uLeft[u] = u0 + (span.texStepX[u][2] * adjx + dudy[u]
                                          * adjy) * (1.0F/FIXED_SCALE);
-                        duOuter[u] = dudy[u] + dxOuter * span.texStep[u][2];
+                        duOuter[u] = dudy[u] + dxOuter * span.texStepX[u][2];
                         v0 = vLower->texcoord[u][3] * invW;
-                        vLeft[u] = v0 + (span.texStep[u][3] * adjx + dvdy[u]
+                        vLeft[u] = v0 + (span.texStepX[u][3] * adjx + dvdy[u]
                                          * adjy) * (1.0F/FIXED_SCALE);
-                        dvOuter[u] = dvdy[u] + dxOuter * span.texStep[u][3];
+                        dvOuter[u] = dvdy[u] + dxOuter * span.texStepX[u][3];
                      }
                   }
                }
             fdtInner = fdtOuter + span.intTexStep[1];
 #endif
 #ifdef INTERP_TEX
-            dsInner = dsOuter + span.texStep[0][0];
-            dtInner = dtOuter + span.texStep[0][1];
-            duInner = duOuter + span.texStep[0][2];
-            dvInner = dvOuter + span.texStep[0][3];
+            dsInner = dsOuter + span.texStepX[0][0];
+            dtInner = dtOuter + span.texStepX[0][1];
+            duInner = duOuter + span.texStepX[0][2];
+            dvInner = dvOuter + span.texStepX[0][3];
 #endif
 #ifdef INTERP_MULTITEX
             {
                GLuint u;
                for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
                   if (ctx->Texture.Unit[u]._ReallyEnabled) {
-                     dsInner[u] = dsOuter[u] + span.texStep[u][0];
-                     dtInner[u] = dtOuter[u] + span.texStep[u][1];
-                     duInner[u] = duOuter[u] + span.texStep[u][2];
-                     dvInner[u] = dvOuter[u] + span.texStep[u][3];
+                     dsInner[u] = dsOuter[u] + span.texStepX[u][0];
+                     dtInner[u] = dtOuter[u] + span.texStepX[u][1];
+                     duInner[u] = duOuter[u] + span.texStepX[u][2];
+                     dvInner[u] = dvOuter[u] + span.texStepX[u][3];
                   }
                }
             }
 #undef INTERP_INT_TEX
 #undef INTERP_TEX
 #undef INTERP_MULTITEX
-#undef INTERP_LAMBDA
 #undef INTERP_FLOAT_RGBA
 #undef INTERP_FLOAT_SPEC