home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / triangle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-04  |  85.2 KB  |  1,736 lines

  1. /* $Id: triangle.c,v 3.10 1998/07/09 03:16:24 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: triangle.c,v $
  26.  * Revision 3.10  1998/07/09 03:16:24  brianp
  27.  * added Marten's latest texture triangle code
  28.  *
  29.  * Revision 3.9  1998/06/24 02:52:05  brianp
  30.  * fixed texture coord interp problems.  lots of code clean-up
  31.  *
  32.  * Revision 3.8  1998/06/18 02:49:35  brianp
  33.  * added Marten Stromberg's optimized textured triangle code
  34.  *
  35.  * Revision 3.7  1998/06/07 22:18:52  brianp
  36.  * implemented GL_EXT_multitexture extension
  37.  *
  38.  * Revision 3.6  1998/05/31 23:50:36  brianp
  39.  * cleaned up a few Solaris compiler warnings
  40.  *
  41.  * Revision 3.5  1998/04/01 02:58:52  brianp
  42.  * applied Miklos Fazekas's 3-31-98 Macintosh changes
  43.  *
  44.  * Revision 3.4  1998/03/27 04:26:44  brianp
  45.  * fixed G++ warnings
  46.  *
  47.  * Revision 3.3  1998/02/20 04:54:02  brianp
  48.  * implemented GL_SGIS_multitexture
  49.  *
  50.  * Revision 3.2  1998/02/04 00:44:29  brianp
  51.  * fixed casts and conditional expression problems for Amiga StormC compiler
  52.  *
  53.  * Revision 3.1  1998/02/02 03:09:34  brianp
  54.  * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
  55.  *
  56.  * Revision 3.0  1998/01/31 21:05:24  brianp
  57.  * initial rev
  58.  *
  59.  */
  60.  
  61.  
  62. /*
  63.  * Triangle rasterizers
  64.  */
  65.  
  66.  
  67. #ifdef PC_HEADER
  68. #include "all.h"
  69. #else
  70. #include <assert.h>
  71. #include <math.h>
  72. #include <stdio.h>
  73. #include "context.h"
  74. #include "depth.h"
  75. #include "feedback.h"
  76. #include "macros.h"
  77. #include "span.h"
  78. #include "texstate.h"
  79. #include "triangle.h"
  80. #include "types.h"
  81. #include "vb.h"
  82. #endif
  83.  
  84.  
  85. /*
  86.  * Put triangle in feedback buffer.
  87.  */
  88. static void feedback_triangle( GLcontext *ctx,
  89.                                GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  90. {
  91.    struct vertex_buffer *VB = ctx->VB;
  92.    GLfloat color[4];
  93.    GLuint i;
  94.    GLuint texSet = ctx->Texture.CurrentTransformSet;
  95.  
  96.    FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN );
  97.    FEEDBACK_TOKEN( ctx, (GLfloat) 3 );        /* three vertices */
  98.  
  99.    if (ctx->Light.ShadeModel==GL_FLAT) {
  100.       /* flat shading - same color for each vertex */
  101.       color[0] = (GLfloat) VB->Color[pv][0] / 255.0;
  102.       color[1] = (GLfloat) VB->Color[pv][1] / 255.0;
  103.       color[2] = (GLfloat) VB->Color[pv][2] / 255.0;
  104.       color[3] = (GLfloat) VB->Color[pv][3] / 255.0;
  105.    }
  106.  
  107.    for (i=0;i<3;i++) {
  108.       GLfloat x, y, z, w;
  109.       GLfloat tc[4];
  110.       GLuint v;
  111.       GLfloat invq;
  112.  
  113.       if (i==0)       v = v0;
  114.       else if (i==1)  v = v1;
  115.       else            v = v2;
  116.  
  117.       x = VB->Win[v][0];
  118.       y = VB->Win[v][1];
  119.       z = VB->Win[v][2] / DEPTH_SCALE;
  120.       w = VB->Clip[v][3];
  121.  
  122.       if (ctx->Light.ShadeModel==GL_SMOOTH) {
  123.          /* smooth shading - different color for each vertex */
  124.          color[0] = (GLfloat) VB->Color[v][0] / 255.0;
  125.          color[1] = (GLfloat) VB->Color[v][1] / 255.0;
  126.          color[2] = (GLfloat) VB->Color[v][2] / 255.0;
  127.          color[3] = (GLfloat) VB->Color[v][3] / 255.0;
  128.       }
  129.  
  130.       if (VB->MultiTexCoord[texSet][v][3]==0.0)
  131.          invq =  1.0;
  132.       else
  133.          invq = 1.0F / VB->MultiTexCoord[texSet][v][3];
  134.       tc[0] = VB->MultiTexCoord[texSet][v][0] * invq;
  135.       tc[1] = VB->MultiTexCoord[texSet][v][1] * invq;
  136.       tc[2] = VB->MultiTexCoord[texSet][v][2] * invq;
  137.       tc[3] = VB->MultiTexCoord[texSet][v][3];
  138.  
  139.       gl_feedback_vertex( ctx, x, y, z, w, color, (GLfloat) VB->Index[v], tc );
  140.    }
  141. }
  142.  
  143.  
  144.  
  145. /*
  146.  * Put triangle in selection buffer.
  147.  */
  148. static void select_triangle( GLcontext *ctx,
  149.                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  150. {
  151.    struct vertex_buffer *VB = ctx->VB;
  152.    (void) pv;
  153.    gl_update_hitflag( ctx, VB->Win[v0][2] / DEPTH_SCALE );
  154.    gl_update_hitflag( ctx, VB->Win[v1][2] / DEPTH_SCALE );
  155.    gl_update_hitflag( ctx, VB->Win[v2][2] / DEPTH_SCALE );
  156. }
  157.  
  158.  
  159.  
  160. /*
  161.  * Render a flat-shaded color index triangle.
  162.  */
  163. static void flat_ci_triangle( GLcontext *ctx,
  164.                               GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  165. {
  166. #ifdef DBGTRI
  167.         printf("flat_ci_triangle\n");
  168. #endif
  169. #define INTERP_Z 1
  170.  
  171. #define SETUP_CODE                              \
  172.    GLuint index = VB->Index[pv];                \
  173.    if (!VB->MonoColor) {                        \
  174.       /* set the color index */                 \
  175.       (*ctx->Driver.Index)( ctx, index );       \
  176.    }
  177.  
  178. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  179.         {                                                       \
  180.            GLint i, n = RIGHT-LEFT;                             \
  181.            GLdepth zspan[MAX_WIDTH];                            \
  182.            if (n>0) {                                           \
  183.               for (i=0;i<n;i++) {                               \
  184.                  zspan[i] = FixedToDepth(ffz);                  \
  185.                  ffz += fdzdx;                                  \
  186.               }                                                 \
  187.               gl_write_monoindex_span( ctx, n, LEFT, Y,         \
  188.                                     zspan, index, GL_POLYGON ); \
  189.            }                                                    \
  190.         }
  191.  
  192. #include "tritemp.h"          
  193. }
  194.  
  195.  
  196.  
  197. /*
  198.  * Render a smooth-shaded color index triangle.
  199.  */
  200. static void smooth_ci_triangle( GLcontext *ctx,
  201.                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  202. {
  203. #ifdef DBGTRI
  204.         printf("smooth_ci_triangle\n");
  205. #endif
  206.    (void) pv;
  207. #define INTERP_Z 1
  208. #define INTERP_INDEX 1
  209.  
  210. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  211.         {                                                       \
  212.            GLint i, n = RIGHT-LEFT;                             \
  213.            GLdepth zspan[MAX_WIDTH];                            \
  214.            GLuint index[MAX_WIDTH];                             \
  215.            if (n>0) {                                           \
  216.               for (i=0;i<n;i++) {                               \
  217.                  zspan[i] = FixedToDepth(ffz);                  \
  218.                  index[i] = FixedToInt(ffi);                    \
  219.                  ffz += fdzdx;                                  \
  220.                  ffi += fdidx;                                  \
  221.               }                                                 \
  222.               gl_write_index_span( ctx, n, LEFT, Y, zspan,      \
  223.                                    index, GL_POLYGON );         \
  224.            }                                                    \
  225.         }
  226.  
  227. #include "tritemp.h"
  228. }
  229.  
  230.  
  231.  
  232. /*
  233.  * Render a flat-shaded RGBA triangle.
  234.  */
  235. static void flat_rgba_triangle( GLcontext *ctx,
  236.                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  237. {
  238. #ifdef DBGTRI
  239.         printf("flat_rgba_triangle\n");
  240. #endif
  241. #define INTERP_Z 1
  242.  
  243. #define SETUP_CODE                              \
  244.    if (!VB->MonoColor) {                        \
  245.       /* set the color */                       \
  246.       GLubyte r = VB->Color[pv][0];             \
  247.       GLubyte g = VB->Color[pv][1];             \
  248.       GLubyte b = VB->Color[pv][2];             \
  249.       GLubyte a = VB->Color[pv][3];             \
  250.       (*ctx->Driver.Color)( ctx, r, g, b, a );  \
  251.    }
  252.  
  253. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  254.         {                                                       \
  255.            GLint i, n = RIGHT-LEFT;                             \
  256.            GLdepth zspan[MAX_WIDTH];                            \
  257.            if (n>0) {                                           \
  258.               for (i=0;i<n;i++) {                               \
  259.                  zspan[i] = FixedToDepth(ffz);                  \
  260.                  ffz += fdzdx;                                  \
  261.               }                                                 \
  262.               gl_write_monocolor_span( ctx, n, LEFT, Y, zspan,  \
  263.                              VB->Color[pv][0], VB->Color[pv][1],\
  264.                              VB->Color[pv][2], VB->Color[pv][3],\
  265.                              GL_POLYGON );                      \
  266.            }                                                    \
  267.         }
  268.  
  269. #include "tritemp.h"
  270. }
  271.  
  272.  
  273.  
  274. /*
  275.  * Render a smooth-shaded RGBA triangle.
  276.  */
  277. static void smooth_rgba_triangle( GLcontext *ctx,
  278.                                   GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  279. {
  280. #ifdef DBGTRI
  281.         printf("smooth_rgba_triangle\n");
  282. #endif
  283.    (void) pv;
  284. #define INTERP_Z 1
  285. #define INTERP_RGB 1
  286. #define INTERP_ALPHA 1
  287.  
  288. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  289.         {                                                       \
  290.            GLint i, n = RIGHT-LEFT;                             \
  291.            GLdepth zspan[MAX_WIDTH];                            \
  292.            GLubyte rgba[MAX_WIDTH][4];                          \
  293.            if (n>0) {                                           \
  294.               for (i=0;i<n;i++) {                               \
  295.                  zspan[i] = FixedToDepth(ffz);                  \
  296.                  rgba[i][RCOMP] = FixedToInt(ffr);              \
  297.                  rgba[i][GCOMP] = FixedToInt(ffg);              \
  298.                  rgba[i][BCOMP] = FixedToInt(ffb);              \
  299.                  rgba[i][ACOMP] = FixedToInt(ffa);              \
  300.                  ffz += fdzdx;                                  \
  301.                  ffr += fdrdx;                                  \
  302.                  ffg += fdgdx;                                  \
  303.                  ffb += fdbdx;                                  \
  304.                  ffa += fdadx;                                  \
  305.               }                                                 \
  306.               gl_write_rgba_span( ctx, n, LEFT, Y, zspan,       \
  307.                                    rgba, GL_POLYGON );          \
  308.            }                                                    \
  309.         }
  310.  
  311. #include "tritemp.h"
  312. }
  313.  
  314.  
  315. /*
  316.  * Render an RGB, GL_DECAL, textured triangle.
  317.  * Interpolate S,T only w/out mipmapping or perspective correction.
  318.  */
  319. static void simple_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  320.                                       GLuint v2, GLuint pv )
  321. {
  322. #ifdef DBGTRI
  323.         printf("simple_textured_triangle\n");
  324. #endif
  325. #define INTERP_INT_ST 1
  326. #define S_SCALE twidth
  327. #define T_SCALE theight
  328. #define SETUP_CODE                                                      \
  329.    struct gl_texture_object *obj = ctx->Texture.Set[0].Current2D;       \
  330.    GLint b = obj->BaseLevel;                                            \
  331.    GLfloat twidth = (GLfloat) obj->Image[b]->Width;                     \
  332.    GLfloat theight = (GLfloat) obj->Image[b]->Height;                   \
  333.    GLint twidth_log2 = obj->Image[b]->WidthLog2;                        \
  334.    GLubyte *texture = obj->Image[b]->Data;                              \
  335.    GLint smask = obj->Image[b]->Width - 1;                              \
  336.    GLint tmask = obj->Image[b]->Height - 1;
  337.    (void) pv;
  338.  
  339. #ifdef USE_X86_ASM
  340. # define RGB_TEX *(GLint *)rgba[i] = *(GLint *)(texture + pos) | 0xff000000
  341. #else
  342. # define RGB_TEX                         \
  343.         rgba[i][RCOMP] = texture[pos];   \
  344.         rgba[i][GCOMP] = texture[pos+1]; \
  345.         rgba[i][BCOMP] = texture[pos+2]; \
  346.         rgba[i][ACOMP] = 255
  347. #endif
  348.  
  349.  
  350.  
  351. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  352.         {                                                       \
  353.            GLint i, n = RIGHT-LEFT;                             \
  354.            GLubyte rgba[MAX_WIDTH][4];                          \
  355.            if (n>0) {                                           \
  356.               ffs -= FIXED_HALF; /* off-by-one error? */        \
  357.               fft -= FIXED_HALF;                                \
  358.               for (i=0;i<n;i++) {                               \
  359.                  GLint s = FixedToInt(ffs) & smask;             \
  360.                  GLint t = FixedToInt(fft) & tmask;             \
  361.                  GLint pos = (t << twidth_log2) + s;            \
  362.                  pos = pos + pos  + pos;  /* multiply by 3 */   \
  363.                  RGB_TEX;                                       \
  364.                  ffs += fdsdx;                                  \
  365.                  fft += fdtdx;                                  \
  366.               }                                                 \
  367.               (*ctx->Driver.WriteRGBASpan)( ctx, n, LEFT, Y,    \
  368.                         (CONST GLubyte(*)[4])rgba, NULL );      \
  369.            }                                                    \
  370.         }
  371.  
  372. #include "tritemp.h"
  373. }
  374.  
  375.  
  376.  
  377. /*
  378.  * Render an RGB, GL_DECAL, textured triangle.
  379.  * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
  380.  * perspective correction.
  381.  */
  382. static void simple_z_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  383.                                         GLuint v2, GLuint pv )
  384. {
  385. #ifdef DBGTRI
  386.         printf("simple_z_textured_triangle\n");
  387. #endif
  388. #define INTERP_Z 1
  389. #define INTERP_INT_ST 1
  390. #define S_SCALE twidth
  391. #define T_SCALE theight
  392. #define SETUP_CODE                                                      \
  393.    struct gl_texture_object *obj = ctx->Texture.Set[0].Current2D;       \
  394.    GLint b = obj->BaseLevel;                                            \
  395.    GLfloat twidth = (GLfloat) obj->Image[b]->Width;                     \
  396.    GLfloat theight = (GLfloat) obj->Image[b]->Height;                   \
  397.    GLint twidth_log2 = obj->Image[b]->WidthLog2;                        \
  398.    GLubyte *texture = obj->Image[b]->Data;                              \
  399.    GLint smask = obj->Image[b]->Width - 1;                              \
  400.    GLint tmask = obj->Image[b]->Height - 1;
  401.    (void) pv;
  402.  
  403. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  404.         {                                                       \
  405.            GLint i, n = RIGHT-LEFT;                             \
  406.            GLubyte rgba[MAX_WIDTH][4];                          \
  407.            GLubyte mask[MAX_WIDTH];                             \
  408.            if (n>0) {                                           \
  409.               ffs -= FIXED_HALF; /* off-by-one error? */        \
  410.               fft -= FIXED_HALF;                                \
  411.               for (i=0;i<n;i++) {                               \
  412.                  GLdepth z = FixedToDepth(ffz);                 \
  413.                  if (z < zRow[i]) {                             \
  414.                     GLint s = FixedToInt(ffs) & smask;          \
  415.                     GLint t = FixedToInt(fft) & tmask;          \
  416.                     GLint pos = (t << twidth_log2) + s;         \
  417.                     pos = pos + pos  + pos;  /* multiply by 3 */\
  418.                     RGB_TEX;                                    \
  419.                     zRow[i] = z;                                \
  420.                     mask[i] = 1;                                \
  421.                  }                                              \
  422.                  else {                                         \
  423.                     mask[i] = 0;                                \
  424.                  }                                              \
  425.                  ffz += fdzdx;                                  \
  426.                  ffs += fdsdx;                                  \
  427.                  fft += fdtdx;                                  \
  428.               }                                                 \
  429.               (*ctx->Driver.WriteRGBASpan)( ctx, n, LEFT, Y,    \
  430.                         (CONST GLubyte(*)[4])rgba, mask );      \
  431.            }                                                    \
  432.         }
  433.  
  434. #include "tritemp.h"
  435. }
  436.  
  437.  
  438. /*
  439.  * Render an RGB/RGBA textured triangle without perspective correction.
  440.  */
  441. static void affine_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  442.                                       GLuint v2, GLuint pv )
  443. {
  444. #ifdef DBGTRI
  445.         printf("affine_textured_triangle\n");
  446. #endif
  447. #define INTERP_Z 1
  448. #define INTERP_RGB 1
  449. #define INTERP_ALPHA 1
  450. #define INTERP_INT_ST 1
  451. #define S_SCALE twidth
  452. #define T_SCALE theight
  453. #define SETUP_CODE                                                      \
  454.    struct gl_texture_set *set = ctx->Texture.Set+0;                     \
  455.    struct gl_texture_object *obj = set->Current2D;                      \
  456.    GLint b = obj->BaseLevel;                                            \
  457.    GLfloat twidth = (GLfloat) obj->Image[b]->Width;                     \
  458.    GLfloat theight = (GLfloat) obj->Image[b]->Height;                   \
  459.    GLint twidth_log2 = obj->Image[b]->WidthLog2;                        \
  460.    GLubyte *texture = obj->Image[b]->Data;                              \
  461.    GLint smask = obj->Image[b]->Width - 1;                              \
  462.    GLint tmask = obj->Image[b]->Height - 1;                             \
  463.    GLint format = obj->Image[b]->Format;                                \
  464.    GLint filter = obj->MinFilter;                                       \
  465.    GLint envmode = set->EnvMode;                                        \
  466.    GLint comp, tbytesline;                                              \
  467.    GLfixed er, eg, eb, ea;                                              \
  468.    GLint tr, tg, tb, ta;                                                \
  469.    if (envmode == GL_BLEND || envmode == GL_ADD) {                      \
  470.       /* potential off-by-one error here? (1.0f -> 2048 -> 0) */        \
  471.       er = FloatToFixed(set->EnvColor[0]);                              \
  472.       eg = FloatToFixed(set->EnvColor[1]);                              \
  473.       eb = FloatToFixed(set->EnvColor[2]);                              \
  474.       ea = FloatToFixed(set->EnvColor[3]);                              \
  475.    }                                                                    \
  476.    switch (format) {                                                    \
  477.    case GL_ALPHA:                                                       \
  478.    case GL_LUMINANCE:                                                   \
  479.    case GL_INTENSITY:                                                   \
  480.       comp = 1;                                                         \
  481.       break;                                                            \
  482.    case GL_LUMINANCE_ALPHA:                                             \
  483.       comp = 2;                                                         \
  484.       break;                                                            \
  485.    case GL_RGB:                                                         \
  486.       comp = 3;                                                         \
  487.       break;                                                            \
  488.    case GL_RGBA:                                                        \
  489.       comp = 4;                                                         \
  490.       break;                                                            \
  491.    default:                                                             \
  492.       gl_problem(NULL, "Bad texture format in affine_texture_triangle");\
  493.       return;                                                           \
  494.    }                                                                    \
  495.    tbytesline = obj->Image[b]->Width * comp;
  496.    (void) pv;
  497.  
  498.   /* Instead of defining a function for each mode, a test is done 
  499.    * between the outer and inner loops. This is to reduce code size
  500.    * and complexity. Observe that an optimizing compiler kills 
  501.    * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
  502.    */ 
  503.  
  504. #define NEAREST_RGB    \
  505.         tr = tex00[0]; \
  506.         tg = tex00[1]; \
  507.         tb = tex00[2]; \
  508.         ta = 0xff
  509.  
  510. #define LINEAR_RGB                                                    \
  511.         tr = (ti * (si * tex00[0] + sf * tex01[0]) +                    \
  512.               tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
  513.         tg = (ti * (si * tex00[1] + sf * tex01[1]) +                    \
  514.               tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
  515.         tb = (ti * (si * tex00[2] + sf * tex01[2]) +                    \
  516.               tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
  517.         ta = 0xff
  518.  
  519. #define NEAREST_RGBA   \
  520.         tr = tex00[0]; \
  521.         tg = tex00[1]; \
  522.         tb = tex00[2]; \
  523.         ta = tex00[3]
  524.  
  525. #define LINEAR_RGBA                                                   \
  526.         tr = (ti * (si * tex00[0] + sf * tex01[0]) +                    \
  527.               tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
  528.         tg = (ti * (si * tex00[1] + sf * tex01[1]) +                    \
  529.               tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
  530.         tb = (ti * (si * tex00[2] + sf * tex01[2]) +                    \
  531.               tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
  532.         ta = (ti * (si * tex00[3] + sf * tex01[3]) +                    \
  533.               tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
  534.  
  535. #define MODULATE                                     \
  536.         dest[0] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
  537.         dest[1] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
  538.         dest[2] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
  539.         dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
  540.  
  541. #define DECAL                                                                            \
  542.         dest[0] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
  543.         dest[1] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
  544.         dest[2] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
  545.         dest[3] = FixedToInt(ffa)
  546.  
  547. #define BLEND                                                           \
  548.         dest[0] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
  549.         dest[1] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
  550.         dest[2] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
  551.         dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
  552.  
  553. #define REPLACE       \
  554.         dest[0] = tr; \
  555.         dest[1] = tg; \
  556.         dest[2] = tb; \
  557.         dest[3] = ta
  558.  
  559. #define ADD                                                      \
  560.         dest[0] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
  561.         dest[1] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
  562.         dest[2] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
  563.         dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
  564.  
  565. /* shortcuts */
  566.  
  567. #if defined(USE_X86_ASM)
  568. /* assumes (i) unaligned load capacity, and (ii) little endian: */
  569. # define NEAREST_RGB_REPLACE  *(GLint *)dest = (*(GLint *)tex00 & 0x00ffffff) \
  570.                                                | ((ffa << (24 - FIXED_SHIFT)) & 0xff000000)
  571. #else
  572. # define NEAREST_RGB_REPLACE  NEAREST_RGB;REPLACE
  573. #endif
  574. #define NEAREST_RGBA_REPLACE  *(GLint *)dest = *(GLint *)tex00
  575.  
  576. #define SPAN1(DO_TEX,COMP)                                 \
  577.         for (i=0;i<n;i++) {                                \
  578.            GLint s = FixedToInt(ffs) & smask;              \
  579.            GLint t = FixedToInt(fft) & tmask;              \
  580.            GLint pos = (t << twidth_log2) + s;             \
  581.            GLubyte *tex00 = texture + COMP * pos;          \
  582.            zspan[i] = FixedToDepth(ffz);                   \
  583.            DO_TEX;                                         \
  584.            ffz += fdzdx;                                   \
  585.            ffr += fdrdx;                                   \
  586.            ffg += fdgdx;                                   \
  587.            ffb += fdbdx;                                   \
  588.            ffa += fdadx;                                   \
  589.            ffs += fdsdx;                                   \
  590.            fft += fdtdx;                                   \
  591.            dest += 4;                                      \
  592.         }
  593.  
  594. #define SPAN2(DO_TEX,COMP)                                 \
  595.         for (i=0;i<n;i++) {                                \
  596.            GLint s = FixedToInt(ffs) & smask;              \
  597.            GLint t = FixedToInt(fft) & tmask;              \
  598.            GLint sf = ffs & FIXED_FRAC_MASK;               \
  599.            GLint tf = fft & FIXED_FRAC_MASK;               \
  600.            GLint si = FIXED_FRAC_MASK - sf;                \
  601.            GLint ti = FIXED_FRAC_MASK - tf;                \
  602.            GLint pos = (t << twidth_log2) + s;             \
  603.            GLubyte *tex00 = texture + COMP * pos;          \
  604.            GLubyte *tex10 = tex00 + tbytesline;            \
  605.            GLubyte *tex01 = tex00 + COMP;                  \
  606.            GLubyte *tex11 = tex10 + COMP;                  \
  607.            zspan[i] = FixedToDepth(ffz);                   \
  608.            DO_TEX;                                         \
  609.            ffz += fdzdx;                                   \
  610.            ffr += fdrdx;                                   \
  611.            ffg += fdgdx;                                   \
  612.            ffb += fdbdx;                                   \
  613.            ffa += fdadx;                                   \
  614.            ffs += fdsdx;                                   \
  615.            fft += fdtdx;                                   \
  616.            dest += 4;                                      \
  617.         }
  618.  
  619. /* here comes the heavy part.. (something for the compiler to chew on) */
  620. #define INNER_LOOP( LEFT, RIGHT, Y )                       \
  621.         {                                                  \
  622.            GLint i, n = RIGHT-LEFT;                        \
  623.            GLdepth zspan[MAX_WIDTH];                       \
  624.            GLubyte rgba[MAX_WIDTH][4];                     \
  625.            if (n>0) {                                      \
  626.               GLubyte *dest = rgba[0];                     \
  627.               ffs -= FIXED_HALF; /* off-by-one error? */   \
  628.               fft -= FIXED_HALF;                           \
  629.               switch (filter) {                            \
  630.               case GL_NEAREST:                             \
  631.                  switch (format) {                         \
  632.                  case GL_RGB:                              \
  633.                     switch (envmode) {                     \
  634.                     case GL_MODULATE:                      \
  635.                        SPAN1(NEAREST_RGB;MODULATE,3);      \
  636.                        break;                              \
  637.                     case GL_DECAL:                         \
  638.                     case GL_REPLACE:                       \
  639.                        SPAN1(NEAREST_RGB_REPLACE,3);       \
  640.                        break;                              \
  641.                     case GL_BLEND:                         \
  642.                        SPAN1(NEAREST_RGB;BLEND,3);         \
  643.                        break;                              \
  644.                     case GL_ADD:                           \
  645.                        SPAN1(NEAREST_RGB;ADD,3);           \
  646.                        break;                              \
  647.                     }                                      \
  648.                     break;                                 \
  649.                  case GL_RGBA:                             \
  650.                     switch(envmode) {                      \
  651.                     case GL_MODULATE:                      \
  652.                        SPAN1(NEAREST_RGBA;MODULATE,4);     \
  653.                        break;                              \
  654.                     case GL_DECAL:                         \
  655.                        SPAN1(NEAREST_RGBA;DECAL,4);        \
  656.                        break;                              \
  657.                     case GL_BLEND:                         \
  658.                        SPAN1(NEAREST_RGBA;BLEND,4);        \
  659.                        break;                              \
  660.                     case GL_REPLACE:                       \
  661.                        SPAN1(NEAREST_RGBA_REPLACE,4);      \
  662.                        break;                              \
  663.                     case GL_ADD:                           \
  664.                        SPAN1(NEAREST_RGBA;ADD,4);          \
  665.                        break;                              \
  666.                     }                                      \
  667.                     break;                                 \
  668.                  }                                         \
  669.                  break;                                    \
  670.               case GL_LINEAR:                              \
  671.                  ffs -= FIXED_HALF;                        \
  672.                  fft -= FIXED_HALF;                        \
  673.                  switch (format) {                         \
  674.                  case GL_RGB:                              \
  675.                     switch (envmode) {                     \
  676.                     case GL_MODULATE:                      \
  677.                        SPAN2(LINEAR_RGB;MODULATE,3);       \
  678.                        break;                              \
  679.                     case GL_DECAL:                         \
  680.                     case GL_REPLACE:                       \
  681.                        SPAN2(LINEAR_RGB;REPLACE,3);        \
  682.                        break;                              \
  683.                     case GL_BLEND:                         \
  684.                        SPAN2(LINEAR_RGB;BLEND,3);          \
  685.                        break;                              \
  686.                     case GL_ADD:                           \
  687.                        SPAN2(LINEAR_RGB;ADD,3);            \
  688.                        break;                              \
  689.                     }                                      \
  690.                     break;                                 \
  691.                  case GL_RGBA:                             \
  692.                     switch (envmode) {                     \
  693.                     case GL_MODULATE:                      \
  694.                        SPAN2(LINEAR_RGBA;MODULATE,4);      \
  695.                        break;                              \
  696.                     case GL_DECAL:                         \
  697.                        SPAN2(LINEAR_RGBA;DECAL,4);         \
  698.                        break;                              \
  699.                     case GL_BLEND:                         \
  700.                        SPAN2(LINEAR_RGBA;BLEND,4);         \
  701.                        break;                              \
  702.                     case GL_REPLACE:                       \
  703.                        SPAN2(LINEAR_RGBA;REPLACE,4);       \
  704.                        break;                              \
  705.                     case GL_ADD:                           \
  706.                        SPAN2(LINEAR_RGBA;ADD,4);           \
  707.                        break;                              \
  708.                     }                                      \
  709.                     break;                                 \
  710.                  }                                         \
  711.                  break;                                    \
  712.               }                                            \
  713.               gl_write_rgba_span(ctx, n, LEFT, Y, (const GLdepth*)zspan,   \
  714.                                  rgba, GL_POLYGON);        \
  715.               /* explicit kill of variables: */            \
  716.               ffr = ffg = ffb = ffa = 0;                   \
  717.            }                                               \
  718.         }
  719.  
  720. #include "tritemp.h"
  721. #undef SPAN1
  722. #undef SPAN2
  723. }
  724.  
  725.  
  726. /*
  727.  * Render an perspective corrected RGB/RGBA textured triangle.
  728.  * The Q (aka V in Mesa) coordinate must be zero such that the divide
  729.  * by interpolated Q/W comes out right.
  730.  */
  731. static void persp_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  732.                                      GLuint v2, GLuint pv )
  733. {
  734.  
  735. #ifdef DBGTRI
  736.         printf("persp_textured_triangle\n");
  737. #endif
  738. #define INTERP_Z 1
  739. #define INTERP_RGB 1
  740. #define INTERP_ALPHA 1
  741. #define INTERP_STUV 1
  742. #define SETUP_CODE                                                      \
  743.    struct gl_texture_set *set = ctx->Texture.Set+0;                     \
  744.    struct gl_texture_object *obj = set->Current2D;                      \
  745.    GLint b = obj->BaseLevel;                                            \
  746.    GLfloat twidth = (GLfloat) obj->Image[b]->Width;                     \
  747.    GLfloat theight = (GLfloat) obj->Image[b]->Height;                   \
  748.    GLint twidth_log2 = obj->Image[b]->WidthLog2;                        \
  749.    GLubyte *texture = obj->Image[b]->Data;                              \
  750.    GLint smask = (obj->Image[b]->Width - 1);                            \
  751.    GLint tmask = (obj->Image[b]->Height - 1);                           \
  752.    GLint format = obj->Image[b]->Format;                                \
  753.    GLint filter = obj->MinFilter;                                       \
  754.    GLint envmode = set->EnvMode;                                        \
  755.    GLfloat sscale, tscale;                                              \
  756.    GLint comp, tbytesline;                                              \
  757.    GLfixed er, eg, eb, ea;                                              \
  758.    GLint tr, tg, tb, ta;                                                \
  759.    if (envmode == GL_BLEND || envmode == GL_ADD) {                      \
  760.       er = FloatToFixed(set->EnvColor[0]);                              \
  761.       eg = FloatToFixed(set->EnvColor[1]);                              \
  762.       eb = FloatToFixed(set->EnvColor[2]);                              \
  763.       ea = FloatToFixed(set->EnvColor[3]);                              \
  764.    }                                                                    \
  765.    switch (format) {                                                    \
  766.    case GL_ALPHA:                                                       \
  767.    case GL_LUMINANCE:                                                   \
  768.    case GL_INTENSITY:                                                   \
  769.       comp = 1;                                                         \
  770.       break;                                                            \
  771.    case GL_LUMINANCE_ALPHA:                                             \
  772.       comp = 2;                                                         \
  773.       break;                                                            \
  774.    case GL_RGB:                                                         \
  775.       comp = 3;                                                         \
  776.       break;                                                            \
  777.    case GL_RGBA:                                                        \
  778.       comp = 4;                                                         \
  779.       break;                                                            \
  780.    default:                                                             \
  781.       gl_problem(NULL, "Bad texture format in persp_texture_triangle"); \
  782.       return;                                                           \
  783.    }                                                                    \
  784.    if (filter == GL_NEAREST) {                                          \
  785.       sscale = twidth;                                                  \
  786.       tscale = theight;                                                 \
  787.    }                                                                    \
  788.    else {                                                               \
  789.       sscale = FIXED_SCALE * twidth;                                    \
  790.       tscale = FIXED_SCALE * theight;                                   \
  791.    }                                                                    \
  792.    tbytesline = obj->Image[b]->Width * comp;
  793.    (void) pv;
  794.  
  795. #define SPAN1(DO_TEX,COMP)                                 \
  796.         for (i=0;i<n;i++) {                                \
  797.            GLfloat invQ = 1.0f / vv;                       \
  798.            GLint s = (int)(SS * invQ) & smask;             \
  799.            GLint t = (int)(TT * invQ) & tmask;             \
  800.            GLint pos = COMP * ((t << twidth_log2) + s);    \
  801.            GLubyte *tex00 = texture + pos;                 \
  802.            zspan[i] = FixedToDepth(ffz);                   \
  803.            DO_TEX;                                         \
  804.            ffz += fdzdx;                                   \
  805.            ffr += fdrdx;                                   \
  806.            ffg += fdgdx;                                   \
  807.            ffb += fdbdx;                                   \
  808.            ffa += fdadx;                                   \
  809.            SS += dSdx;                                     \
  810.            TT += dTdx;                                     \
  811.            vv += dvdx;                                     \
  812.            dest += 4;                                      \
  813.         }
  814.  
  815. #define SPAN2(DO_TEX,COMP)                                 \
  816.         for (i=0;i<n;i++) {                                \
  817.            GLfloat invQ = 1.0f / vv;                       \
  818.            GLfixed ffs = (int)(SS * invQ);                 \
  819.            GLfixed fft = (int)(TT * invQ);                 \
  820.            GLint s = FixedToInt(ffs) & smask;              \
  821.            GLint t = FixedToInt(fft) & tmask;              \
  822.            GLint sf = ffs & FIXED_FRAC_MASK;               \
  823.            GLint tf = fft & FIXED_FRAC_MASK;               \
  824.            GLint si = FIXED_FRAC_MASK - sf;                \
  825.            GLint ti = FIXED_FRAC_MASK - tf;                \
  826.            GLint pos = COMP * ((t << twidth_log2) + s);    \
  827.            GLubyte *tex00 = texture + pos;                 \
  828.            GLubyte *tex10 = tex00 + tbytesline;            \
  829.            GLubyte *tex01 = tex00 + COMP;                  \
  830.            GLubyte *tex11 = tex10 + COMP;                  \
  831.            zspan[i] = FixedToDepth(ffz);                   \
  832.            DO_TEX;                                         \
  833.            ffz += fdzdx;                                   \
  834.            ffr += fdrdx;                                   \
  835.            ffg += fdgdx;                                   \
  836.            ffb += fdbdx;                                   \
  837.            ffa += fdadx;                                   \
  838.            SS += dSdx;                                     \
  839.            TT += dTdx;                                     \
  840.            vv += dvdx;                                     \
  841.            dest += 4;                                      \
  842.         }
  843.  
  844. #define INNER_LOOP( LEFT, RIGHT, Y )                       \
  845.         {                                                  \
  846.            GLint i, n = RIGHT-LEFT;                        \
  847.            GLdepth zspan[MAX_WIDTH];                       \
  848.            GLubyte rgba[MAX_WIDTH][4];                     \
  849.            (void)uu; /* please GCC */                      \
  850.            if (n>0) {                                      \
  851.               GLfloat SS = ss * sscale;                    \
  852.               GLfloat TT = tt * tscale;                    \
  853.               GLfloat dSdx = dsdx * sscale;                \
  854.               GLfloat dTdx = dtdx * tscale;                \
  855.               GLubyte *dest = rgba[0];                     \
  856.               switch (filter) {                            \
  857.               case GL_NEAREST:                             \
  858.                  switch (format) {                         \
  859.                  case GL_RGB:                              \
  860.                     switch (envmode) {                     \
  861.                     case GL_MODULATE:                      \
  862.                        SPAN1(NEAREST_RGB;MODULATE,3);      \
  863.                        break;                              \
  864.                     case GL_DECAL:                         \
  865.                     case GL_REPLACE:                       \
  866.                        SPAN1(NEAREST_RGB_REPLACE,3);       \
  867.                        break;                              \
  868.                     case GL_BLEND:                         \
  869.                        SPAN1(NEAREST_RGB;BLEND,3);         \
  870.                        break;                              \
  871.                     case GL_ADD:                           \
  872.                        SPAN1(NEAREST_RGB;ADD,3);           \
  873.                        break;                              \
  874.                     }                                      \
  875.                     break;                                 \
  876.                  case GL_RGBA:                             \
  877.                     switch(envmode) {                      \
  878.                     case GL_MODULATE:                      \
  879.                        SPAN1(NEAREST_RGBA;MODULATE,4);     \
  880.                        break;                              \
  881.                     case GL_DECAL:                         \
  882.                        SPAN1(NEAREST_RGBA;DECAL,4);        \
  883.                        break;                              \
  884.                     case GL_BLEND:                         \
  885.                        SPAN1(NEAREST_RGBA;BLEND,4);        \
  886.                        break;                              \
  887.                     case GL_REPLACE:                       \
  888.                        SPAN1(NEAREST_RGBA_REPLACE,4);      \
  889.                        break;                              \
  890.                     case GL_ADD:                           \
  891.                        SPAN1(NEAREST_RGBA;ADD,4);          \
  892.                        break;                              \
  893.                     }                                      \
  894.                     break;                                 \
  895.                  }                                         \
  896.                  break;                                    \
  897.               case GL_LINEAR:                              \
  898.                  SS -= 0.5f * FIXED_SCALE * vv;            \
  899.                  TT -= 0.5f * FIXED_SCALE * vv;            \
  900.                  switch (format) {                         \
  901.                  case GL_RGB:                              \
  902.                     switch (envmode) {                     \
  903.                     case GL_MODULATE:                      \
  904.                        SPAN2(LINEAR_RGB;MODULATE,3);       \
  905.                        break;                              \
  906.                     case GL_DECAL:                         \
  907.                     case GL_REPLACE:                       \
  908.                        SPAN2(LINEAR_RGB;REPLACE,3);        \
  909.                        break;                              \
  910.                     case GL_BLEND:                         \
  911.                        SPAN2(LINEAR_RGB;BLEND,3);          \
  912.                        break;                              \
  913.                     case GL_ADD:                           \
  914.                        SPAN2(LINEAR_RGB;ADD,3);            \
  915.                        break;                              \
  916.                     }                                      \
  917.                     break;                                 \
  918.                  case GL_RGBA:                             \
  919.                     switch (envmode) {                     \
  920.                     case GL_MODULATE:                      \
  921.                        SPAN2(LINEAR_RGBA;MODULATE,4);      \
  922.                        break;                              \
  923.                     case GL_DECAL:                         \
  924.                        SPAN2(LINEAR_RGBA;DECAL,4);         \
  925.                        break;                              \
  926.                     case GL_BLEND:                         \
  927.                        SPAN2(LINEAR_RGBA;BLEND,4);         \
  928.                        break;                              \
  929.                     case GL_REPLACE:                       \
  930.                        SPAN2(LINEAR_RGBA;REPLACE,4);       \
  931.                        break;                              \
  932.                     case GL_ADD:                           \
  933.                        SPAN2(LINEAR_RGBA;ADD,4);           \
  934.                        break;                              \
  935.                     }                                      \
  936.                     break;                                 \
  937.                  }                                         \
  938.                  break;                                    \
  939.               }                                            \
  940.               gl_write_rgba_span( ctx, n, LEFT, Y, (const GLdepth*)zspan,  \
  941.                                   rgba, GL_POLYGON );      \
  942.               ffr = ffg = ffb = ffa = 0;                   \
  943.            }                                               \
  944.         }
  945.  
  946.  
  947. #include "tritemp.h"
  948. #undef SPAN1
  949. #undef SPAN2
  950. }
  951.  
  952. #include <stdio.h>
  953. /*
  954.  * Render a smooth-shaded, textured, RGBA triangle.
  955.  * Interpolate S,T,U with perspective correction, w/out mipmapping.
  956.  * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
  957.  * R is already used for red.
  958.  */
  959. static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  960.                                        GLuint v2, GLuint pv )
  961. {
  962. #ifdef DBGTRI
  963.         printf("general_textured_triangle\n");
  964. #endif
  965. #define INTERP_Z 1
  966. #define INTERP_RGB 1
  967. #define INTERP_ALPHA 1
  968. #define INTERP_STUV 1
  969. #define SETUP_CODE                                              \
  970.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);     \
  971.    GLint r, g, b, a;                                            \
  972.    if (flat_shade) {                                            \
  973.       r = VB->Color[pv][0];                                     \
  974.       g = VB->Color[pv][1];                                     \
  975.       b = VB->Color[pv][2];                                     \
  976.       a = VB->Color[pv][3];                                     \
  977.    }
  978. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  979.         {                                                       \
  980.            GLint i, n = RIGHT-LEFT;                             \
  981.            GLdepth zspan[MAX_WIDTH];                            \
  982.            GLubyte rgba[MAX_WIDTH][4];                          \
  983.            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];    \
  984.            if (n>0) {                                           \
  985.               if (flat_shade) {                                 \
  986.                  for (i=0;i<n;i++) {                            \
  987.                     GLdouble invQ = 1.0 / vv;                   \
  988.                     zspan[i] = FixedToDepth(ffz);               \
  989.                     rgba[i][RCOMP] = r;                         \
  990.                     rgba[i][GCOMP] = g;                         \
  991.                     rgba[i][BCOMP] = b;                         \
  992.                     rgba[i][ACOMP] = a;                         \
  993.                     s[i] = ss*invQ;                             \
  994.                     t[i] = tt*invQ;                             \
  995.                     u[i] = uu*invQ;                             \
  996.                     ffz += fdzdx;                               \
  997.                     ss += dsdx;                                 \
  998.                     tt += dtdx;                                 \
  999.                     uu += dudx;                                 \
  1000.                     vv += dvdx;                                 \
  1001.                  }                                              \
  1002.               }                                                 \
  1003.               else {                                            \
  1004.                  for (i=0;i<n;i++) {                            \
  1005.                     GLdouble invQ = 1.0 / vv;                   \
  1006.                     zspan[i] = FixedToDepth(ffz);               \
  1007.                     rgba[i][RCOMP] = FixedToInt(ffr);           \
  1008.                     rgba[i][GCOMP] = FixedToInt(ffg);           \
  1009.                     rgba[i][BCOMP] = FixedToInt(ffb);           \
  1010.                     rgba[i][ACOMP] = FixedToInt(ffa);           \
  1011.                     s[i] = ss*invQ;                             \
  1012.                     t[i] = tt*invQ;                             \
  1013.                     u[i] = uu*invQ;                             \
  1014.                     ffz += fdzdx;                               \
  1015.                     ffr += fdrdx;                               \
  1016.                     ffg += fdgdx;                               \
  1017.                     ffb += fdbdx;                               \
  1018.                     ffa += fdadx;                               \
  1019.                     ss += dsdx;                                 \
  1020.                     tt += dtdx;                                 \
  1021.                     uu += dudx;                                 \
  1022.                     vv += dvdx;                                 \
  1023.                  }                                              \
  1024.               }                                                 \
  1025.               gl_write_texture_span( ctx, n, LEFT, Y, (const GLdepth*)zspan,    \
  1026.  (const GLfloat*)s, (const GLfloat*)t, (const GLfloat*)u, NULL,             \
  1027.                                      rgba, NULL, GL_POLYGON );  \
  1028.            }                                                    \
  1029.         }
  1030.  
  1031. #include "tritemp.h"
  1032. }
  1033.  
  1034.  
  1035. /*
  1036.  * Render a smooth-shaded, textured, RGBA triangle with separate specular
  1037.  * color interpolation.
  1038.  * Interpolate S,T,U with perspective correction, w/out mipmapping.
  1039.  * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
  1040.  * R is already used for red.
  1041.  */
  1042. static void general_textured_spec_triangle1( GLcontext *ctx, GLuint v0,
  1043.                                              GLuint v1, GLuint v2, GLuint pv,
  1044.                                              GLdepth zspan[MAX_WIDTH],
  1045.                                              GLubyte rgba[MAX_WIDTH][4],
  1046.                                              GLubyte spec[MAX_WIDTH][4] )
  1047. {
  1048. #ifdef DBGTRI
  1049.         printf("general_textured_spec_triangle1\n");
  1050. #endif
  1051. #define INTERP_Z 1
  1052. #define INTERP_RGB 1
  1053. #define INTERP_SPEC 1
  1054. #define INTERP_ALPHA 1
  1055. #define INTERP_STUV 1
  1056. #define SETUP_CODE                                              \
  1057.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);     \
  1058.    GLint r, g, b, a, sr, sg, sb;                                \
  1059.    if (flat_shade) {                                            \
  1060.       r = VB->Color[pv][0];                                     \
  1061.       g = VB->Color[pv][1];                                     \
  1062.       b = VB->Color[pv][2];                                     \
  1063.       a = VB->Color[pv][3];                                     \
  1064.       sr = VB->Specular[pv][0];                                 \
  1065.       sg = VB->Specular[pv][1];                                 \
  1066.       sb = VB->Specular[pv][2];                                 \
  1067.    }
  1068. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  1069.         {                                                       \
  1070.            GLint i, n = RIGHT-LEFT;                             \
  1071.            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];    \
  1072.            if (n>0) {                                           \
  1073.               if (flat_shade) {                                 \
  1074.                  for (i=0;i<n;i++) {                            \
  1075.                     GLdouble invQ = 1.0 / vv;                   \
  1076.                     zspan[i] = FixedToDepth(ffz);               \
  1077.                     rgba[i][RCOMP] = r;                         \
  1078.                     rgba[i][GCOMP] = g;                         \
  1079.                     rgba[i][BCOMP] = b;                         \
  1080.                     rgba[i][ACOMP] = a;                         \
  1081.                     spec[i][RCOMP] = sr;                        \
  1082.                     spec[i][GCOMP] = sg;                        \
  1083.                     spec[i][BCOMP] = sb;                        \
  1084.                     s[i] = ss*invQ;                             \
  1085.                     t[i] = tt*invQ;                             \
  1086.                     u[i] = uu*invQ;                             \
  1087.                     ffz += fdzdx;                               \
  1088.                     ss += dsdx;                                 \
  1089.                     tt += dtdx;                                 \
  1090.                     uu += dudx;                                 \
  1091.                     vv += dvdx;                                 \
  1092.                  }                                              \
  1093.               }                                                 \
  1094.               else {                                            \
  1095.                  for (i=0;i<n;i++) {                            \
  1096.                     GLdouble invQ = 1.0 / vv;                   \
  1097.                     zspan[i] = FixedToDepth(ffz);               \
  1098.                     rgba[i][RCOMP] = FixedToInt(ffr);           \
  1099.                     rgba[i][GCOMP] = FixedToInt(ffg);           \
  1100.                     rgba[i][BCOMP] = FixedToInt(ffb);           \
  1101.                     rgba[i][ACOMP] = FixedToInt(ffa);           \
  1102.                     spec[i][RCOMP] = FixedToInt(ffsr);          \
  1103.                     spec[i][GCOMP] = FixedToInt(ffsg);          \
  1104.                     spec[i][BCOMP] = FixedToInt(ffsb);          \
  1105.                     s[i] = ss*invQ;                             \
  1106.                     t[i] = tt*invQ;                             \
  1107.                     u[i] = uu*invQ;                             \
  1108.                     ffz += fdzdx;                               \
  1109.                     ffr += fdrdx;                               \
  1110.                     ffg += fdgdx;                               \
  1111.                     ffb += fdbdx;                               \
  1112.                     ffa += fdadx;                               \
  1113.                     ffsr += fdsrdx;                             \
  1114.                     ffsg += fdsgdx;                             \
  1115.                     ffsb += fdsbdx;                             \
  1116.                     ss += dsdx;                                 \
  1117.                     tt += dtdx;                                 \
  1118.                     uu += dudx;                                 \
  1119.                     vv += dvdx;                                 \
  1120.                  }                                              \
  1121.               }                                                 \
  1122.               gl_write_texture_span( ctx, n, LEFT, Y, (const GLdepth*)zspan,    \
  1123.  (const GLfloat*)s, (const GLfloat*)t, (const GLfloat*)u, NULL,             \
  1124.                                      rgba, (CONST GLubyte(*)[4])spec, GL_POLYGON );  \
  1125.            }                                                    \
  1126.         }
  1127.  
  1128. #include "tritemp.h"
  1129. }
  1130.  
  1131.  
  1132.  
  1133. /*
  1134.  * Compute the lambda value (texture level value) for a fragment.
  1135.  */
  1136. static GLfloat compute_lambda( GLfloat s, GLfloat dsdx, GLfloat dsdy,
  1137.                                GLfloat t, GLfloat dtdx, GLfloat dtdy,
  1138.                                GLfloat invQ, GLfloat dqdx, GLfloat dqdy,
  1139.                                GLfloat width, GLfloat height ) 
  1140. {
  1141.    GLfloat dudx, dudy, dvdx, dvdy;
  1142.    GLfloat r1, r2, rho2;
  1143.    GLfloat invQ_width = invQ * width;
  1144.    GLfloat invQ_height = invQ * height;
  1145.  
  1146.    dudx = (dsdx - s*dqdx) * invQ_width;
  1147.    dudy = (dsdy - s*dqdy) * invQ_width;
  1148.    dvdx = (dtdx - t*dqdx) * invQ_height;
  1149.    dvdy = (dtdy - t*dqdy) * invQ_height;
  1150.  
  1151.    r1 = dudx * dudx + dudy * dudy;
  1152.    r2 = dvdx * dvdx + dvdy * dvdy;
  1153.  
  1154.    rho2 = r1 + r2;     /* used to be:  rho2 = MAX2(r1,r2); */
  1155.    ASSERT( rho2 >= 0.0 );
  1156.  
  1157.    /* return log base 2 of rho */
  1158.    return log(rho2) * 1.442695 * 0.5;       /* 1.442695 = 1/log(2) */
  1159. }
  1160.  
  1161.  
  1162.  
  1163. /*
  1164.  * Render a smooth-shaded, textured, RGBA triangle.
  1165.  * Interpolate S,T,U with perspective correction and compute lambda for
  1166.  * each fragment.  Lambda is used to determine whether to use the
  1167.  * minification or magnification filter.  If minification and using
  1168.  * mipmaps, lambda is also used to select the texture level of detail.
  1169.  */
  1170. static void lambda_textured_triangle1( GLcontext *ctx, GLuint v0, GLuint v1,
  1171.                                        GLuint v2, GLuint pv,
  1172.                                        GLfloat s[MAX_WIDTH],
  1173.                                        GLfloat t[MAX_WIDTH],
  1174.                                        GLfloat u[MAX_WIDTH] )
  1175. {
  1176. #ifdef DBGTRI
  1177.         printf("lambda_textured_triangle1\n");
  1178. #endif
  1179. #define INTERP_Z 1
  1180. #define INTERP_RGB 1
  1181. #define INTERP_ALPHA 1
  1182. #define INTERP_STUV 1
  1183.  
  1184. #define SETUP_CODE                                                      \
  1185.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);             \
  1186.    GLint r, g, b, a;                                                    \
  1187.    GLfloat twidth, theight;                                             \
  1188.    if (ctx->Texture.Enabled & TEXTURE0_3D) {                            \
  1189.       twidth = (GLfloat) ctx->Texture.Set[0].Current3D->Image[0]->Width;        \
  1190.       theight = (GLfloat) ctx->Texture.Set[0].Current3D->Image[0]->Height;      \
  1191.    }                                                                    \
  1192.    else if (ctx->Texture.Enabled & TEXTURE0_2D) {                       \
  1193.       twidth = (GLfloat) ctx->Texture.Set[0].Current2D->Image[0]->Width;        \
  1194.       theight = (GLfloat) ctx->Texture.Set[0].Current2D->Image[0]->Height;      \
  1195.    }                                                                    \
  1196.    else {                                                               \
  1197.       twidth = (GLfloat) ctx->Texture.Set[0].Current1D->Image[0]->Width;        \
  1198.       theight = 1.0;                                                    \
  1199.    }                                                                    \
  1200.    if (flat_shade) {                                                    \
  1201.       r = VB->Color[pv][0];                                             \
  1202.       g = VB->Color[pv][1];                                             \
  1203.       b = VB->Color[pv][2];                                             \
  1204.       a = VB->Color[pv][3];                                             \
  1205.    }
  1206.  
  1207. #define INNER_LOOP( LEFT, RIGHT, Y )                                    \
  1208.         {                                                               \
  1209.            GLint i, n = RIGHT-LEFT;                                     \
  1210.            GLdepth zspan[MAX_WIDTH];                                    \
  1211.            GLubyte rgba[MAX_WIDTH][4];                                  \
  1212.            GLfloat lambda[MAX_WIDTH];                                   \
  1213.            if (n>0) {                                                   \
  1214.               if (flat_shade) {                                         \
  1215.                  for (i=0;i<n;i++) {                                    \
  1216.                     GLdouble invQ = 1.0 / vv;                           \
  1217.                     zspan[i] = FixedToDepth(ffz);                       \
  1218.                     rgba[i][RCOMP] = r;                                 \
  1219.                     rgba[i][GCOMP] = g;                                 \
  1220.                     rgba[i][BCOMP] = b;                                 \
  1221.                     rgba[i][ACOMP] = a;                                 \
  1222.                     s[i] = ss*invQ;                                     \
  1223.                     t[i] = tt*invQ;                                     \
  1224.                     u[i] = uu*invQ;                                     \
  1225.                     lambda[i] = compute_lambda( s[i], dsdx, dsdy,       \
  1226.                                                 t[i], dtdx, dtdy,       \
  1227.                                                 invQ, dvdx, dvdy,       \
  1228.                                                 twidth, theight );      \
  1229.                     ffz += fdzdx;                                       \
  1230.                     ss += dsdx;                                         \
  1231.                     tt += dtdx;                                         \
  1232.                     uu += dudx;                                         \
  1233.                     vv += dvdx;                                         \
  1234.                  }                                                      \
  1235.               }                                                         \
  1236.               else {                                                    \
  1237.                  for (i=0;i<n;i++) {                                    \
  1238.                     GLdouble invQ = 1.0 / vv;                           \
  1239.                     zspan[i] = FixedToDepth(ffz);                       \
  1240.                     rgba[i][RCOMP] = FixedToInt(ffr);                   \
  1241.                     rgba[i][GCOMP] = FixedToInt(ffg);                   \
  1242.                     rgba[i][BCOMP] = FixedToInt(ffb);                   \
  1243.                     rgba[i][ACOMP] = FixedToInt(ffa);                   \
  1244.                     s[i] = ss*invQ;                                     \
  1245.                     t[i] = tt*invQ;                                     \
  1246.                     u[i] = uu*invQ;                                     \
  1247.                     lambda[i] = compute_lambda( s[i], dsdx, dsdy,       \
  1248.                                                 t[i], dtdx, dtdy,       \
  1249.                                                 invQ, dvdx, dvdy,       \
  1250.                                                 twidth, theight );      \
  1251.                     ffz += fdzdx;                                       \
  1252.                     ffr += fdrdx;                                       \
  1253.                     ffg += fdgdx;                                       \
  1254.                     ffb += fdbdx;                                       \
  1255.                     ffa += fdadx;                                       \
  1256.                     ss += dsdx;                                         \
  1257.                     tt += dtdx;                                         \
  1258.                     uu += dudx;                                         \
  1259.                     vv += dvdx;                                         \
  1260.                  }                                                      \
  1261.               }                                                         \
  1262.               gl_write_texture_span( ctx, n, LEFT, Y, (const GLdepth*)zspan,            \
  1263.  (const GLfloat*)s, (const GLfloat*)t, (const GLfloat*)u, lambda,                   \
  1264.                                      rgba, NULL, GL_POLYGON );          \
  1265.            }                                                            \
  1266.         }
  1267.  
  1268. #include "tritemp.h"
  1269. }
  1270.  
  1271.  
  1272.  
  1273. /*
  1274.  * Render a smooth-shaded, textured, RGBA triangle with separate specular
  1275.  * interpolation.
  1276.  * Interpolate S,T,U with perspective correction and compute lambda for
  1277.  * each fragment.  Lambda is used to determine whether to use the
  1278.  * minification or magnification filter.  If minification and using
  1279.  * mipmaps, lambda is also used to select the texture level of detail.
  1280.  */
  1281. static void lambda_textured_spec_triangle1( GLcontext *ctx, GLuint v0,
  1282.                                             GLuint v1, GLuint v2, GLuint pv,
  1283.                                             GLfloat s[MAX_WIDTH],
  1284.                                             GLfloat t[MAX_WIDTH],
  1285.                                             GLfloat u[MAX_WIDTH] )
  1286. {
  1287. #ifdef DBGTRI
  1288.         printf("lambda_textured_spec_triangle1\n");
  1289. #endif
  1290. #define INTERP_Z 1
  1291. #define INTERP_RGB 1
  1292. #define INTERP_SPEC 1
  1293. #define INTERP_ALPHA 1
  1294. #define INTERP_STUV 1
  1295.  
  1296. #define SETUP_CODE                                                      \
  1297.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);             \
  1298.    GLint r, g, b, a, sr, sg, sb;                                        \
  1299.    GLfloat twidth, theight;                                             \
  1300.    if (ctx->Texture.Enabled & TEXTURE0_3D) {                            \
  1301.       twidth = (GLfloat) ctx->Texture.Set[0].Current3D->Image[0]->Width;        \
  1302.       theight = (GLfloat) ctx->Texture.Set[0].Current3D->Image[0]->Height;      \
  1303.    }                                                                    \
  1304.    else if (ctx->Texture.Enabled & TEXTURE0_2D) {                       \
  1305.       twidth = (GLfloat) ctx->Texture.Set[0].Current2D->Image[0]->Width;        \
  1306.       theight = (GLfloat) ctx->Texture.Set[0].Current2D->Image[0]->Height;      \
  1307.    }                                                                    \
  1308.    else {                                                               \
  1309.       twidth = (GLfloat) ctx->Texture.Set[0].Current1D->Image[0]->Width;        \
  1310.       theight = 1.0;                                                    \
  1311.    }                                                                    \
  1312.    if (flat_shade) {                                                    \
  1313.       r = VB->Color[pv][0];                                             \
  1314.       g = VB->Color[pv][1];                                             \
  1315.       b = VB->Color[pv][2];                                             \
  1316.       a = VB->Color[pv][3];                                             \
  1317.       sr = VB->Specular[pv][0];                                         \
  1318.       sg = VB->Specular[pv][1];                                         \
  1319.       sb = VB->Specular[pv][2];                                         \
  1320.    }
  1321.  
  1322. #define INNER_LOOP( LEFT, RIGHT, Y )                                    \
  1323.         {                                                               \
  1324.            GLint i, n = RIGHT-LEFT;                                     \
  1325.            GLdepth zspan[MAX_WIDTH];                                    \
  1326.            GLubyte spec[MAX_WIDTH][4];                                  \
  1327.            GLubyte rgba[MAX_WIDTH][4];                                  \
  1328.            GLfloat lambda[MAX_WIDTH];                                   \
  1329.            if (n>0) {                                                   \
  1330.               if (flat_shade) {                                         \
  1331.                  for (i=0;i<n;i++) {                                    \
  1332.                     GLdouble invQ = 1.0 / vv;                           \
  1333.                     zspan[i] = FixedToDepth(ffz);                       \
  1334.                     rgba[i][RCOMP] = r;                                 \
  1335.                     rgba[i][GCOMP] = g;                                 \
  1336.                     rgba[i][BCOMP] = b;                                 \
  1337.                     rgba[i][ACOMP] = a;                                 \
  1338.                     spec[i][RCOMP] = sr;                                \
  1339.                     spec[i][GCOMP] = sg;                                \
  1340.                     spec[i][BCOMP] = sb;                                \
  1341.                     s[i] = ss*invQ;                                     \
  1342.                     t[i] = tt*invQ;                                     \
  1343.                     u[i] = uu*invQ;                                     \
  1344.                     lambda[i] = compute_lambda( s[i], dsdx, dsdy,       \
  1345.                                                 t[i], dtdx, dtdy,       \
  1346.                                                 invQ, dvdx, dvdy,       \
  1347.                                                 twidth, theight );      \
  1348.                     ffz += fdzdx;                                       \
  1349.                     ss += dsdx;                                         \
  1350.                     tt += dtdx;                                         \
  1351.                     uu += dudx;                                         \
  1352.                     vv += dvdx;                                         \
  1353.                  }                                                      \
  1354.               }                                                         \
  1355.               else {                                                    \
  1356.                  for (i=0;i<n;i++) {                                    \
  1357.                     GLdouble invQ = 1.0 / vv;                           \
  1358.                     zspan[i] = FixedToDepth(ffz);                       \
  1359.                     rgba[i][RCOMP] = FixedToInt(ffr);                   \
  1360.                     rgba[i][GCOMP] = FixedToInt(ffg);                   \
  1361.                     rgba[i][BCOMP] = FixedToInt(ffb);                   \
  1362.                     rgba[i][ACOMP] = FixedToInt(ffa);                   \
  1363.                     spec[i][RCOMP] = FixedToInt(ffsr);                  \
  1364.                     spec[i][GCOMP] = FixedToInt(ffsg);                  \
  1365.                     spec[i][BCOMP] = FixedToInt(ffsb);                  \
  1366.                     s[i] = ss*invQ;                                     \
  1367.                     t[i] = tt*invQ;                                     \
  1368.                     u[i] = uu*invQ;                                     \
  1369.                     lambda[i] = compute_lambda( s[i], dsdx, dsdy,       \
  1370.                                                 t[i], dtdx, dtdy,       \
  1371.                                                 invQ, dvdx, dvdy,       \
  1372.                                                 twidth, theight );      \
  1373.                     ffz += fdzdx;                                       \
  1374.                     ffr += fdrdx;                                       \
  1375.                     ffg += fdgdx;                                       \
  1376.                     ffb += fdbdx;                                       \
  1377.                     ffa += fdadx;                                       \
  1378.                     ffsr += fdsrdx;                                     \
  1379.                     ffsg += fdsgdx;                                     \
  1380.                     ffsb += fdsbdx;                                     \
  1381.                     ss += dsdx;                                         \
  1382.                     tt += dtdx;                                         \
  1383.                     uu += dudx;                                         \
  1384.                     vv += dvdx;                                         \
  1385.                  }                                                      \
  1386.               }                                                         \
  1387.               gl_write_texture_span( ctx, n, LEFT, Y, (const GLdepth*)zspan,            \
  1388.  (const GLfloat*)s, (const GLfloat*)t, (const GLfloat*)u, lambda,                   \
  1389.                                      rgba, (CONST GLubyte(*)[4])spec, GL_POLYGON );          \
  1390.            }                                                            \
  1391.         }
  1392.  
  1393. #include "tritemp.h"
  1394. }
  1395.  
  1396.  
  1397.  
  1398. /*
  1399.  * This is the big one!
  1400.  * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
  1401.  * Yup, it's slow.
  1402.  */
  1403. static void lambda_multitextured_triangle1( GLcontext *ctx, GLuint v0,
  1404.                                       GLuint v1, GLuint v2, GLuint pv,
  1405.                                       GLubyte rgba[MAX_WIDTH][4],
  1406.                                       GLfloat s[MAX_TEX_COORD_SETS][MAX_WIDTH],
  1407.                                       GLfloat t[MAX_TEX_COORD_SETS][MAX_WIDTH] )
  1408. {
  1409. #ifdef DBGTRI
  1410.         printf("lambda_multitextured_triangle1\n");
  1411. #endif
  1412. #define INTERP_Z 1
  1413. #define INTERP_RGB 1
  1414. #define INTERP_ALPHA 1
  1415. #define INTERP_STUV 1
  1416. #define INTERP_STUV1 1
  1417.  
  1418. #define SETUP_CODE                                                      \
  1419.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);             \
  1420.    GLint r, g, b, a;                                                    \
  1421.    GLfloat twidth0, theight0;                                           \
  1422.    GLfloat twidth1, theight1;                                           \
  1423.    if (ctx->Texture.Enabled & TEXTURE0_3D) {                            \
  1424.       twidth0 = (GLfloat) ctx->Texture.Set[0].Current3D->Image[0]->Width;       \
  1425.       theight0 = (GLfloat) ctx->Texture.Set[0].Current3D->Image[0]->Height;     \
  1426.    }                                                                    \
  1427.    else if (ctx->Texture.Enabled & TEXTURE0_2D) {                       \
  1428.       twidth0 = (GLfloat) ctx->Texture.Set[0].Current2D->Image[0]->Width;       \
  1429.       theight0 = (GLfloat) ctx->Texture.Set[0].Current2D->Image[0]->Height;     \
  1430.    }                                                                    \
  1431.    else if (ctx->Texture.Enabled & TEXTURE0_1D) {                       \
  1432.       twidth0 = (GLfloat) ctx->Texture.Set[0].Current1D->Image[0]->Width;       \
  1433.       theight0 = 1.0;                                                   \
  1434.    }                                                                    \
  1435.    if (ctx->Texture.Enabled & TEXTURE1_3D) {                            \
  1436.       twidth1 = (GLfloat) ctx->Texture.Set[1].Current3D->Image[0]->Width;       \
  1437.       theight1 = (GLfloat) ctx->Texture.Set[1].Current3D->Image[0]->Height;     \
  1438.    }                                                                    \
  1439.    else if (ctx->Texture.Enabled & TEXTURE1_2D) {                       \
  1440.       twidth1 = (GLfloat) ctx->Texture.Set[1].Current2D->Image[0]->Width;       \
  1441.       theight1 = (GLfloat) ctx->Texture.Set[1].Current2D->Image[0]->Height;     \
  1442.    }                                                                    \
  1443.    else if (ctx->Texture.Enabled & TEXTURE1_1D) {                       \
  1444.       twidth1 = (GLfloat) ctx->Texture.Set[1].Current1D->Image[0]->Width;       \
  1445.       theight1 = 1.0;                                                   \
  1446.    }                                                                    \
  1447.    if (flat_shade) {                                                    \
  1448.       r = VB->Color[pv][0];                                             \
  1449.       g = VB->Color[pv][1];                                             \
  1450.       b = VB->Color[pv][2];                                             \
  1451.       a = VB->Color[pv][3];                                             \
  1452.    }
  1453.  
  1454. #define INNER_LOOP( LEFT, RIGHT, Y )                                    \
  1455.         {                                                               \
  1456.            GLint i, n = RIGHT-LEFT;                                     \
  1457.            GLdepth zspan[MAX_WIDTH];                                    \
  1458.            GLfloat u[MAX_TEX_COORD_SETS][MAX_WIDTH];                    \
  1459.            GLfloat lambda[MAX_TEX_COORD_SETS][MAX_WIDTH];               \
  1460.            if (n>0) {                                                   \
  1461.               if (flat_shade) {                                         \
  1462.                  for (i=0;i<n;i++) {                                    \
  1463.                     GLdouble invQ = 1.0 / vv;                           \
  1464.                     GLdouble invQ1 = 1.0 / vv1;                         \
  1465.                     zspan[i] = FixedToDepth(ffz);                       \
  1466.                     rgba[i][RCOMP] = r;                                 \
  1467.                     rgba[i][GCOMP] = g;                                 \
  1468.                     rgba[i][BCOMP] = b;                                 \
  1469.                     rgba[i][ACOMP] = a;                                 \
  1470.                     s[0][i] = ss*invQ;                                  \
  1471.                     t[0][i] = tt*invQ;                                  \
  1472.                     u[0][i] = uu*invQ;                                  \
  1473.                     lambda[0][i] = compute_lambda( s[0][i], dsdx, dsdy, \
  1474.                                                    t[0][i], dtdx, dtdy, \
  1475.                                                    invQ, dvdx, dvdy,    \
  1476.                                                    twidth0, theight0 ); \
  1477.                     s[1][i] = ss1*invQ1;                                \
  1478.                     t[1][i] = tt1*invQ1;                                \
  1479.                     u[1][i] = uu1*invQ1;                                \
  1480.                     lambda[1][i] = compute_lambda( s[1][i], ds1dx, ds1dy,       \
  1481.                                                    t[1][i], dt1dx, dt1dy,       \
  1482.                                                    invQ, dvdx, dvdy,    \
  1483.                                                    twidth1, theight1 ); \
  1484.                     ffz += fdzdx;                                       \
  1485.                     ss += dsdx;                                         \
  1486.                     tt += dtdx;                                         \
  1487.                     uu += dudx;                                         \
  1488.                     vv += dvdx;                                         \
  1489.                     ss1 += ds1dx;                                       \
  1490.                     tt1 += dt1dx;                                       \
  1491.                     uu1 += du1dx;                                       \
  1492.                     vv1 += dv1dx;                                       \
  1493.                  }                                                      \
  1494.               }                                                         \
  1495.               else {                                                    \
  1496.                  for (i=0;i<n;i++) {                                    \
  1497.                     GLdouble invQ = 1.0 / vv;                           \
  1498.                     GLdouble invQ1 = 1.0 / vv1;                         \
  1499.                     zspan[i] = FixedToDepth(ffz);                       \
  1500.                     rgba[i][RCOMP] = FixedToInt(ffr);                   \
  1501.                     rgba[i][GCOMP] = FixedToInt(ffg);                   \
  1502.                     rgba[i][BCOMP] = FixedToInt(ffb);                   \
  1503.                     rgba[i][ACOMP] = FixedToInt(ffa);                   \
  1504.                     s[0][i] = ss*invQ;                                  \
  1505.                     t[0][i] = tt*invQ;                                  \
  1506.                     u[0][i] = uu*invQ;                                  \
  1507.                     lambda[0][i] = compute_lambda( s[0][i], dsdx, dsdy, \
  1508.                                                    t[0][i], dtdx, dtdy, \
  1509.                                                    invQ, dvdx, dvdy,    \
  1510.                                                    twidth0, theight0 ); \
  1511.                     s[1][i] = ss1*invQ1;                                \
  1512.                     t[1][i] = tt1*invQ1;                                \
  1513.                     u[1][i] = uu1*invQ1;                                \
  1514.                     lambda[1][i] = compute_lambda( s[1][i], ds1dx, ds1dy,       \
  1515.                                                    t[1][i], dt1dx, dt1dy,       \
  1516.                                                    invQ1, dvdx, dvdy,   \
  1517.                                                    twidth1, theight1 ); \
  1518.                     ffz += fdzdx;                                       \
  1519.                     ffr += fdrdx;                                       \
  1520.                     ffg += fdgdx;                                       \
  1521.                     ffb += fdbdx;                                       \
  1522.                     ffa += fdadx;                                       \
  1523.                     ss += dsdx;                                         \
  1524.                     tt += dtdx;                                         \
  1525.                     uu += dudx;                                         \
  1526.                     vv += dvdx;                                         \
  1527.                     ss1 += ds1dx;                                       \
  1528.                     tt1 += dt1dx;                                       \
  1529.                     uu1 += du1dx;                                       \
  1530.                     vv1 += dv1dx;                                       \
  1531.                  }                                                      \
  1532.               }                                                         \
  1533.               gl_write_multitexture_span( ctx, 2, n, LEFT, Y, (const GLdepth*)zspan,    \
  1534.          (CONST GLfloat(*)[MAX_WIDTH])s, (CONST GLfloat(*)[MAX_WIDTH])t, (CONST GLfloat(*)[MAX_WIDTH])u, lambda,              \
  1535.                                           rgba, NULL, GL_POLYGON );     \
  1536.            }                                                            \
  1537.         }
  1538.  
  1539. #include "tritemp.h"
  1540. }
  1541.  
  1542.  
  1543. /*
  1544.  * These wrappers are needed to deal with the 32KB / stack frame limit
  1545.  * on Mac / PowerPC systems.
  1546.  */
  1547.  
  1548. static void general_textured_spec_triangle(GLcontext *ctx, GLuint v0,
  1549.                                            GLuint v1, GLuint v2, GLuint pv)
  1550. {
  1551.    GLdepth zspan[MAX_WIDTH];
  1552.    GLubyte rgba[MAX_WIDTH][4], spec[MAX_WIDTH][4];
  1553.    general_textured_spec_triangle1(ctx,v0,v1,v2,pv,zspan,rgba,spec);
  1554. }
  1555.  
  1556. static void lambda_textured_triangle( GLcontext *ctx, GLuint v0,
  1557.                                       GLuint v1, GLuint v2, GLuint pv )
  1558. {
  1559.    GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];
  1560.    lambda_textured_triangle1(ctx,v0,v1,v2,pv,s,t,u);
  1561. }
  1562.  
  1563. static void lambda_textured_spec_triangle( GLcontext *ctx, GLuint v0,
  1564.                                            GLuint v1, GLuint v2, GLuint pv )
  1565. {
  1566.    GLfloat s[MAX_WIDTH];
  1567.    GLfloat t[MAX_WIDTH];
  1568.    GLfloat u[MAX_WIDTH];
  1569.    lambda_textured_spec_triangle1(ctx,v0,v1,v2,pv,s,t,u);
  1570. }
  1571.  
  1572. static void lambda_multitextured_triangle( GLcontext *ctx, GLuint v0,
  1573.                                            GLuint v1, GLuint v2, GLuint pv)
  1574. {
  1575.    GLubyte rgba[MAX_WIDTH][4];
  1576.    GLfloat s[MAX_TEX_COORD_SETS][MAX_WIDTH];
  1577.    GLfloat t[MAX_TEX_COORD_SETS][MAX_WIDTH];
  1578.    lambda_multitextured_triangle1(ctx,v0,v1,v2,pv,rgba,s,t);
  1579. }
  1580.  
  1581.  
  1582.  
  1583. /*
  1584.  * Null rasterizer for measuring transformation speed.
  1585.  */
  1586. static void null_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  1587.                            GLuint v2, GLuint pv )
  1588. {
  1589.    (void) ctx;
  1590.    (void) v0;
  1591.    (void) v1;
  1592.    (void) v2;
  1593.    (void) pv;
  1594. }
  1595.  
  1596.  
  1597. #if 0
  1598. # define dputs(s) puts(s)
  1599. #else
  1600. # define dputs(s)
  1601. #endif
  1602.  
  1603. /*
  1604.  * Determine which triangle rendering function to use given the current
  1605.  * rendering context.
  1606.  */
  1607. void gl_set_triangle_function( GLcontext *ctx )
  1608. {
  1609.    GLboolean rgbmode = ctx->Visual->RGBAflag;
  1610.  
  1611.    if (ctx->RenderMode==GL_RENDER) {
  1612.       if (ctx->NoRaster) {
  1613.          ctx->Driver.TriangleFunc = null_triangle;
  1614.          return;
  1615.       }
  1616.       if (ctx->Driver.TriangleFunc) {
  1617.          /* Device driver will draw triangles. */
  1618.       }
  1619.       else if (ctx->Texture.Enabled) {
  1620.          /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
  1621.          int format, filter;
  1622.          const struct gl_texture_object *current2Dtex = ctx->Texture.Set[0].Current2D;
  1623.          const struct gl_texture_image *image;
  1624.          /* First see if we can used an optimized 2-D texture function */
  1625.          if (ctx->Texture.Enabled==TEXTURE0_2D
  1626.              && ctx->Texture.Set[0].Current
  1627.              && ctx->Texture.Set[0].Current->Complete
  1628.              && current2Dtex->WrapS==GL_REPEAT
  1629.              && current2Dtex->WrapT==GL_REPEAT
  1630.              && (image = current2Dtex->Image[current2Dtex->BaseLevel])  /* correct? */
  1631.              && image->Border==0
  1632.              && ((format = image->Format)==GL_RGB
  1633.                  || format==GL_RGBA)
  1634.              /* && ctx->TextureMatrixType[0]==MATRIX_IDENTITY  -- OK? */
  1635.              && (filter = current2Dtex->MinFilter)==current2Dtex->MagFilter
  1636.              && ctx->Light.Model.ColorControl==GL_SINGLE_COLOR) {
  1637.  
  1638.             if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
  1639.              
  1640.                if (filter==GL_NEAREST
  1641.                    && format==GL_RGB
  1642.                    && (ctx->Texture.Set[0].EnvMode==GL_REPLACE
  1643.                        || ctx->Texture.Set[0].EnvMode==GL_DECAL)
  1644.                    && ((ctx->RasterMask==DEPTH_BIT
  1645.                         && ctx->Depth.Func==GL_LESS
  1646.                         && ctx->Depth.Mask==GL_TRUE)
  1647.                        || ctx->RasterMask==0)
  1648.                    && ctx->Polygon.StippleFlag==GL_FALSE) {
  1649.  
  1650.                   if (ctx->RasterMask==DEPTH_BIT) {
  1651.                      ctx->Driver.TriangleFunc = simple_z_textured_triangle;
  1652.                      dputs("simple_z_textured_triangle");
  1653.                   }
  1654.                   else {
  1655.                      ctx->Driver.TriangleFunc = simple_textured_triangle;
  1656.                      dputs("simple_textured_triangle");
  1657.                   }
  1658.                }
  1659.                else {
  1660.                   ctx->Driver.TriangleFunc = affine_textured_triangle;
  1661.                   dputs("affine_textured_triangle");
  1662.                }
  1663.             }
  1664.             else {
  1665.                ctx->Driver.TriangleFunc = persp_textured_triangle;
  1666.                dputs("persp_textured_triangle");
  1667.             }
  1668.          }
  1669.          else {
  1670.             /* More complicated textures (mipmap, multi-tex, sep specular) */
  1671.             GLboolean needLambda = GL_FALSE;
  1672.             /* if mag filter != min filter we need to compute lambda */
  1673.             GLuint i;
  1674.             for (i=0;i<MAX_TEX_SETS;i++) {
  1675.                GLuint mask = (TEXTURE0_1D|TEXTURE0_2D|TEXTURE0_3D) << (i*4);
  1676.                if (ctx->Texture.Enabled & mask) {
  1677.                   if (ctx->Texture.Set[i].Current->MinFilter != 
  1678.                       ctx->Texture.Set[i].Current->MagFilter) {
  1679.                      needLambda = GL_TRUE;
  1680.                   }
  1681.                }
  1682.             }
  1683.             if (ctx->Texture.Enabled >= TEXTURE1_1D) {
  1684.                /* multi-texture! */
  1685.                ctx->Driver.TriangleFunc = lambda_multitextured_triangle;
  1686.                dputs("lambda_multitextured_triangle");
  1687.             }
  1688.             else if (ctx->Light.Model.ColorControl==GL_SINGLE_COLOR) {
  1689.                if (needLambda) {
  1690.                   ctx->Driver.TriangleFunc = lambda_textured_triangle;
  1691.                   dputs("lambda_textured_triangle");
  1692.                }
  1693.                else {
  1694.                   ctx->Driver.TriangleFunc = general_textured_triangle;
  1695.                   dputs("general_textured_triangle");
  1696.                }
  1697.             }
  1698.             else {
  1699.                /* seprate specular color interpolation */
  1700.                if (needLambda) {
  1701.                   ctx->Driver.TriangleFunc = lambda_textured_spec_triangle;
  1702.                   dputs("lambda_textured_spec_triangle");
  1703.                }
  1704.                else {
  1705.                   ctx->Driver.TriangleFunc = general_textured_spec_triangle;
  1706.                   dputs("general_textured_spec_triangle");
  1707.                }
  1708.             }
  1709.          }
  1710.       }
  1711.       else {
  1712.          if (ctx->Light.ShadeModel==GL_SMOOTH) {
  1713.             /* smooth shaded, no texturing, stippled or some raster ops */
  1714.             if (rgbmode)
  1715.                ctx->Driver.TriangleFunc = smooth_rgba_triangle;
  1716.             else
  1717.                ctx->Driver.TriangleFunc = smooth_ci_triangle;
  1718.          }
  1719.          else {
  1720.             /* flat shaded, no texturing, stippled or some raster ops */
  1721.             if (rgbmode)
  1722.                ctx->Driver.TriangleFunc = flat_rgba_triangle;
  1723.             else
  1724.                ctx->Driver.TriangleFunc = flat_ci_triangle;
  1725.          }
  1726.       }
  1727.    }
  1728.    else if (ctx->RenderMode==GL_FEEDBACK) {
  1729.       ctx->Driver.TriangleFunc = feedback_triangle;
  1730.    }
  1731.    else {
  1732.       /* GL_SELECT mode */
  1733.       ctx->Driver.TriangleFunc = select_triangle;
  1734.    }
  1735. }
  1736.