Fix typo
[mesa.git] / src / mesa / swrast / s_tritemp.h
index 6674bc74f9e9860e20f2c2a964ac396211309a4a..254907dea5b99993a28c6a8a95deff0fcfd36383 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: s_tritemp.h,v 1.5 2000/11/21 23:17:36 brianp Exp $ */
+/* $Id: s_tritemp.h,v 1.11 2001/03/03 00:37:27 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
  * Version:  3.5
  * 
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2001  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"),
  *    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, the lambda value is computed at every
+ *                         pixel, to apply MIPMAPPING, and min/maxification
+ *    INTERP_MULTILAMBDA - like above but for multitexturing, i.e.
+ *                         a lambda value for every texture unit
  *
  * When one can directly address pixels in the color buffer the following
  * macros can be defined and used to compute pixel addresses during
    } EdgeT;
 
 #ifdef INTERP_Z
-   const GLint depthBits = ctx->Visual.DepthBits;
+   const GLint depthBits = ctx->Visual.depthBits;
    const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
-   const GLfloat maxDepth = ctx->Visual.DepthMaxF;
+   const GLfloat maxDepth = ctx->DepthMaxF;
 #define FixedToDepth(F)  ((F) >> fixedToDepthShift)
 #endif
    EdgeT eMaj, eTop, eBot;
    GLfloat oneOverArea;
    const SWvertex *vMin, *vMid, *vMax;  /* Y(vMin)<=Y(vMid)<=Y(vMax) */
    float bf = SWRAST_CONTEXT(ctx)->_backface_sign;
+   GLboolean tiny;
 
    /* find the order of the 3 vertices along the Y axis */
    {
          return;
 
       /* check for very tiny triangle */
-      if (area * area < (0.05F * 0.05F))  /* square to ensure positive value */
+      if (area * area < (0.05F * 0.05F)) { /* square to ensure positive value */
          oneOverArea = 1.0F / 0.05F;  /* a close-enough value */
-      else
+         tiny = GL_TRUE;
+      }
+      else {
          oneOverArea = 1.0F / area;
+         tiny = GL_FALSE;
+      }
    }
 
 #ifndef DO_OCCLUSION_TEST
       GLfloat dvdx[MAX_TEXTURE_UNITS], dvdy[MAX_TEXTURE_UNITS];
 #endif
 
+#ifdef INTERP_LAMBDA
+#ifndef INTERP_TEX
+#error "Mipmapping without texturing doesn't make sense."
+#endif
+      GLfloat lambda_nominator;
+#endif /* INTERP_LAMBDA */
+
+#ifdef INTERP_MULTILAMBDA
+#ifndef INTERP_MULTITEX
+#error "Multi-Mipmapping without multi-texturing doesn't make sense."
+#endif
+      GLfloat lambda_nominator[MAX_TEXTURE_UNITS];
+#endif /* INTERP_MULTILAMBDA */
+
+
       /*
        * Execute user-supplied setup code
        */
       }
 #endif
 #ifdef INTERP_RGB
-      {
+      if (tiny) {
+         /* This is kind of a hack to eliminate RGB color over/underflow
+          * problems when rendering very tiny triangles.  We're not doing
+          * anything with alpha or specular color at this time.
+          */
+         drdx = drdy = 0.0;  fdrdx = 0;
+         dgdx = dgdy = 0.0;  fdgdx = 0;
+         dbdx = dbdy = 0.0;  fdbdx = 0;
+      }
+      else {
          GLfloat eMaj_dr, eBot_dr;
-         eMaj_dr = (GLint) vMax->color[0]
-                 - (GLint) vMin->color[0];
-         eBot_dr = (GLint) vMid->color[0]
-                 - (GLint) vMin->color[0];
+         GLfloat eMaj_dg, eBot_dg;
+         GLfloat eMaj_db, eBot_db;
+         eMaj_dr = (GLint) vMax->color[0] - (GLint) vMin->color[0];
+         eBot_dr = (GLint) vMid->color[0] - (GLint) vMin->color[0];
          drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
          fdrdx = SignedFloatToFixed(drdx);
          drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
-      }
-      {
-         GLfloat eMaj_dg, eBot_dg;
-         eMaj_dg = (GLint) vMax->color[1]
-                 - (GLint) vMin->color[1];
-        eBot_dg = (GLint) vMid->color[1]
-                 - (GLint) vMin->color[1];
+         eMaj_dg = (GLint) vMax->color[1] - (GLint) vMin->color[1];
+        eBot_dg = (GLint) vMid->color[1] - (GLint) vMin->color[1];
          dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
          fdgdx = SignedFloatToFixed(dgdx);
          dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
-      }
-      {
-         GLfloat eMaj_db, eBot_db;
-         eMaj_db = (GLint) vMax->color[2]
-                 - (GLint) vMin->color[2];
-         eBot_db = (GLint) vMid->color[2]
-                 - (GLint) vMin->color[2];
+         eMaj_db = (GLint) vMax->color[2] - (GLint) vMin->color[2];
+         eBot_db = (GLint) vMid->color[2] - (GLint) vMin->color[2];
          dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
          fdbdx = SignedFloatToFixed(dbdx);
         dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
 #ifdef INTERP_SPEC
       {
          GLfloat eMaj_dsr, eBot_dsr;
-         eMaj_dsr = (GLint) vMax->specular[0]
-                  - (GLint) vMin->specular[0];
-         eBot_dsr = (GLint) vMid->specular[0]
-                  - (GLint) vMin->specular[0];
+         eMaj_dsr = (GLint) vMax->specular[0] - (GLint) vMin->specular[0];
+         eBot_dsr = (GLint) vMid->specular[0] - (GLint) vMin->specular[0];
          dsrdx = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
          fdsrdx = SignedFloatToFixed(dsrdx);
          dsrdy = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
       }
       {
          GLfloat eMaj_dsg, eBot_dsg;
-         eMaj_dsg = (GLint) vMax->specular[1]
-                  - (GLint) vMin->specular[1];
-        eBot_dsg = (GLint) vMid->specular[1]
-                  - (GLint) vMin->specular[1];
+         eMaj_dsg = (GLint) vMax->specular[1] - (GLint) vMin->specular[1];
+        eBot_dsg = (GLint) vMid->specular[1] - (GLint) vMin->specular[1];
          dsgdx = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
          fdsgdx = SignedFloatToFixed(dsgdx);
          dsgdy = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
       }
       {
          GLfloat eMaj_dsb, eBot_dsb;
-         eMaj_dsb = (GLint) vMax->specular[2]
-                  - (GLint) vMin->specular[2];
-         eBot_dsb = (GLint) vMid->specular[2]
-                  - (GLint) vMin->specular[2];
+         eMaj_dsb = (GLint) vMax->specular[2] - (GLint) vMin->specular[2];
+         eBot_dsb = (GLint) vMid->specular[2] - (GLint) vMin->specular[2];
          dsbdx = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
          fdsbdx = SignedFloatToFixed(dsbdx);
         dsbdy = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
 #ifdef INTERP_ALPHA
       {
          GLfloat eMaj_da, eBot_da;
-         eMaj_da = (GLint) vMax->color[3]
-                 - (GLint) vMin->color[3];
-         eBot_da = (GLint) vMid->color[3]
-                 - (GLint) vMin->color[3];
+         eMaj_da = (GLint) vMax->color[3] - (GLint) vMin->color[3];
+         eBot_da = (GLint) vMid->color[3] - (GLint) vMin->color[3];
          dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
          fdadx = SignedFloatToFixed(dadx);
          dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
 #ifdef INTERP_INDEX
       {
          GLfloat eMaj_di, eBot_di;
-         eMaj_di = (GLint) vMax->index
-                 - (GLint) vMin->index;
-         eBot_di = (GLint) vMid->index
-                 - (GLint) vMin->index;
+         eMaj_di = (GLint) vMax->index - (GLint) vMin->index;
+         eBot_di = (GLint) vMid->index - (GLint) vMin->index;
          didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
          fdidx = SignedFloatToFixed(didx);
          didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
          dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
          dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
 
-
         eMaj_dt = vMax->texcoord[0][1] * wMax - vMin->texcoord[0][1] * wMin;
         eBot_dt = vMid->texcoord[0][1] * wMid - vMin->texcoord[0][1] * wMin;
         dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
         dudx = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
         dudy = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
 
-
         eMaj_dv = vMax->texcoord[0][3] * wMax - vMin->texcoord[0][3] * wMin;
         eBot_dv = vMid->texcoord[0][3] * wMid - vMin->texcoord[0][3] * wMin;
         dvdx = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
                dsdy[u] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
 
               eMaj_dt = vMax->texcoord[u][1] * wMax
-                 - vMin->texcoord[u][1] * wMin;
+                      - vMin->texcoord[u][1] * wMin;
               eBot_dt = vMid->texcoord[u][1] * wMid
-                 - vMin->texcoord[u][1] * wMin;
+                      - vMin->texcoord[u][1] * wMin;
               dtdx[u] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
               dtdy[u] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
               
               eMaj_du = vMax->texcoord[u][2] * wMax
-                 - vMin->texcoord[u][2] * wMin;
+                       - vMin->texcoord[u][2] * wMin;
               eBot_du = vMid->texcoord[u][2] * wMid
-                 - vMin->texcoord[u][2] * wMin;
+                       - vMin->texcoord[u][2] * wMin;
               dudx[u] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
               dudy[u] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
               
               eMaj_dv = vMax->texcoord[u][3] * wMax
-                 - vMin->texcoord[u][3] * wMin;
+                       - vMin->texcoord[u][3] * wMin;
               eBot_dv = vMid->texcoord[u][3] * wMid
-                 - vMin->texcoord[u][3] * wMin;
+                       - vMin->texcoord[u][3] * wMin;
               dvdx[u] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
               dvdy[u] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
             }
                if (ffi<0) ffi = 0;
 #endif
 
+#ifdef INTERP_LAMBDA
+/*
+ * The lambda value is:
+ *        log_2(sqrt(f(n))) = 1/2*log_2(f(n)), where f(n) is a function
+ *     defined by
+ *        f(n):=  dudx * dudx + dudy * dudy  +  dvdx * dvdx + dvdy * dvdy;
+ *     and each of this terms is resp.
+ *        dudx = dsdx * invQ(n) * tex_width;
+ *        dudy = dsdy * invQ(n) * tex_width;
+ *        dvdx = dtdx * invQ(n) * tex_height;
+ *        dvdy = dtdy * invQ(n) * tex_height;
+ *     Therefore the function lambda can be represented (by factoring out) as:
+ *        f(n) = lambda_nominator * invQ(n) * invQ(n),
+ *     which saves some computation time.
+ */
+              {
+                  GLfloat dudx = dsdx /* * invQ*/ * twidth;
+                  GLfloat dudy = dsdy /* * invQ*/ * twidth;
+                  GLfloat dvdx = dtdx /* * invQ*/ * theight;
+                  GLfloat dvdy = dtdy /* * invQ*/ * theight;
+                  GLfloat r1 = dudx * dudx + dudy * dudy;
+                  GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
+                  GLfloat rho2 = r1 + r2; /* was:  rho2 = MAX2(r1,r2); */
+                  lambda_nominator = rho2;
+              }
+              
+              /* set DEST to log_(base 2) of sqrt(rho) */ 
+               /* 1.442695 = 1/log(2) */
+#define COMPUTE_LAMBDA(DEST, X)  \
+   DEST = log( lambda_nominator * (X)*(X) ) * 1.442695F * 0.5F
+#endif
+
+#ifdef INTERP_MULTILAMBDA
+/*
+ *  Read the comment for INTERP_LAMBDA, but apply to each texture unit 
+ */
+              {
+                  GLuint unit;
+                  for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+                     if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+                        GLfloat dudx = dsdx[unit] /* * invQ*/ * twidth[unit];
+                        GLfloat dudy = dsdy[unit] /* * invQ*/ * twidth[unit];
+                        GLfloat dvdx = dtdx[unit] /* * invQ*/ * theight[unit];
+                        GLfloat dvdy = dtdy[unit] /* * invQ*/ * theight[unit];
+                        GLfloat r1 = dudx * dudx + dudy * dudy;
+                        GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
+                        GLfloat rho2 = r1 + r2; /* used to be:  rho2 = MAX2(r1,r2); */
+                        lambda_nominator[unit] = rho2;
+                     }
+                  }
+              }
+              /* set DEST to log_(base 2) of sqrt(rho) */ 
+#define COMPUTE_MULTILAMBDA(DEST, X, unit)  \
+   DEST = log( lambda_nominator[unit] * (X)*(X) ) * 1.442695F * 0.5F
+#endif
+
+
                INNER_LOOP( left, right, iy );
 
                /*
 #undef INTERP_INT_TEX
 #undef INTERP_TEX
 #undef INTERP_MULTITEX
+#undef INTERP_LAMBDA
+#undef COMPUTE_LAMBDA
+#undef INTERP_MULTILAMBDA
+#undef COMPUTE_MULTILAMBDA
 
 #undef S_SCALE
 #undef T_SCALE