-/* $Id: s_tritemp.h,v 1.4 2000/11/19 23:10:26 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.0025F) /* square it to ensure positive value */
- oneOverArea = 1.0F / 0.0025F; /* a close-enough value */
- else
+ if (area * area < (0.05F * 0.05F)) { /* square to ensure positive value */
+ oneOverArea = 1.0F / 0.05F; /* a close-enough value */
+ tiny = GL_TRUE;
+ }
+ else {
oneOverArea = 1.0F / area;
+ tiny = GL_FALSE;
+ }
}
#ifndef DO_OCCLUSION_TEST
GLfixed vMax_fy = FloatToFixed(vMax->win[1] - 0.5F);
eMaj.fsy = FixedCeil(vMin_fy);
- eMaj.lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eMaj.fsy);
+ eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
if (eMaj.lines > 0) {
GLfloat dxdy = eMaj.dx / eMaj.dy;
eMaj.fdxdy = SignedFloatToFixed(dxdy);
}
eTop.fsy = FixedCeil(vMid_fy);
- eTop.lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eTop.fsy);
+ eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
if (eTop.lines > 0) {
GLfloat dxdy = eTop.dx / eTop.dy;
eTop.fdxdy = SignedFloatToFixed(dxdy);
}
eBot.fsy = FixedCeil(vMin_fy);
- eBot.lines = FixedToInt(vMid_fy + FIXED_ONE - FIXED_EPSILON - eBot.fsy);
+ eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
if (eBot.lines > 0) {
GLfloat dxdy = eBot.dx / eBot.dy;
eBot.fdxdy = SignedFloatToFixed(dxdy);
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