home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / triangle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  45.0 KB  |  1,006 lines

  1. /* $Id: triangle.c,v 1.30 1997/08/27 01:20:05 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1997  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 1.30  1997/08/27 01:20:05  brianp
  27.  * moved texture completeness test out one level (Karl Anders Oygard)
  28.  *
  29.  * Revision 1.29  1997/07/24 01:26:05  brianp
  30.  * changed precompiled header symbol from PCH to PC_HEADER
  31.  *
  32.  * Revision 1.28  1997/07/21 22:18:10  brianp
  33.  * fixed bug in compute_lambda() thanks to Magnus Lundin
  34.  *
  35.  * Revision 1.27  1997/06/23 00:40:03  brianp
  36.  * added a DEFARRAY/UNDEFARRAY for the Mac
  37.  *
  38.  * Revision 1.26  1997/06/20 02:51:38  brianp
  39.  * changed color components from GLfixed to GLubyte
  40.  *
  41.  * Revision 1.25  1997/06/03 01:38:22  brianp
  42.  * fixed divide by zero problem in feedback function (William Mitchell)
  43.  *
  44.  * Revision 1.24  1997/05/28 03:26:49  brianp
  45.  * added precompiled header (PCH) support
  46.  *
  47.  * Revision 1.23  1997/05/17 03:40:55  brianp
  48.  * refined textured triangle selection code (Mats Lofkvist)
  49.  *
  50.  * Revision 1.22  1997/05/03 00:51:02  brianp
  51.  * removed calls to gl_texturing_enabled()
  52.  *
  53.  * Revision 1.21  1997/04/14 21:38:15  brianp
  54.  * fixed a typo (dtdx instead of dudx) in lambda_textured_triangle()
  55.  *
  56.  * Revision 1.20  1997/04/14 02:00:39  brianp
  57.  * #include "texstate.h" instead of "texture.h"
  58.  *
  59.  * Revision 1.19  1997/04/12 12:27:16  brianp
  60.  * replaced ctx->TriangleFunc with ctx->Driver.TriangleFunc
  61.  *
  62.  * Revision 1.18  1997/04/02 03:12:06  brianp
  63.  * replaced ctx->IdentityTexMat with ctx->TextureMatrixType
  64.  *
  65.  * Revision 1.17  1997/03/13 03:05:31  brianp
  66.  * removed unused shift variable in feedback_triangle()
  67.  *
  68.  * Revision 1.16  1997/03/08 02:04:27  brianp
  69.  * better implementation of feedback function
  70.  *
  71.  * Revision 1.15  1997/03/04 18:54:13  brianp
  72.  * renamed mipmap_textured_triangle() to lambda_textured_triangle()
  73.  * better comments about lambda and mipmapping
  74.  *
  75.  * Revision 1.14  1997/02/20 23:47:35  brianp
  76.  * triangle feedback colors were wrong when using smooth shading
  77.  *
  78.  * Revision 1.13  1997/02/19 10:24:26  brianp
  79.  * use a GLdouble instead of a GLfloat for wwvvInv (perspective correction)
  80.  *
  81.  * Revision 1.12  1997/02/09 19:53:43  brianp
  82.  * now use TEXTURE_xD enable constants
  83.  *
  84.  * Revision 1.11  1997/02/09 18:51:02  brianp
  85.  * added GL_EXT_texture3D support
  86.  *
  87.  * Revision 1.10  1997/01/16 03:36:43  brianp
  88.  * added #include "texture.h"
  89.  *
  90.  * Revision 1.9  1997/01/09 19:50:49  brianp
  91.  * now call gl_texturing_enabled()
  92.  *
  93.  * Revision 1.8  1996/12/20 20:23:30  brianp
  94.  * the test for using general_textured_triangle() was wrong
  95.  *
  96.  * Revision 1.7  1996/12/12 22:37:30  brianp
  97.  * projective textures didn't work right
  98.  *
  99.  * Revision 1.6  1996/11/08 02:21:21  brianp
  100.  * added null drawing function for GL_NO_RASTER
  101.  *
  102.  * Revision 1.5  1996/10/01 03:31:17  brianp
  103.  * use new FixedToDepth() macro
  104.  *
  105.  * Revision 1.4  1996/09/27 01:30:37  brianp
  106.  * removed unneeded INTERP_ALPHA from flat_rgba_triangle()
  107.  *
  108.  * Revision 1.3  1996/09/15 14:19:16  brianp
  109.  * now use GLframebuffer and GLvisual
  110.  *
  111.  * Revision 1.2  1996/09/15 01:48:58  brianp
  112.  * removed #define NULL 0
  113.  *
  114.  * Revision 1.1  1996/09/13 01:38:16  brianp
  115.  * Initial revision
  116.  *
  117.  */
  118.  
  119.  
  120. /*
  121.  * Triangle rasterizers
  122.  */
  123.  
  124.  
  125. #ifdef PC_HEADER
  126. #include "all.h"
  127. #else
  128. #include <assert.h>
  129. #include <math.h>
  130. #include <stdio.h>
  131. #include "depth.h"
  132. #include "feedback.h"
  133. #include "macros.h"
  134. #include "span.h"
  135. #include "texstate.h"
  136. #include "triangle.h"
  137. #include "types.h"
  138. #include "vb.h"
  139. #endif
  140.  
  141. #define BOOL_TO_FLOAT(X)        ( (GLfloat)(GLint) (X) )
  142. #define BOOL_TO_DOUBLE(X)        ( (GLdouble)(GLint) (X) )
  143.  
  144.  
  145. /*
  146.  * Put triangle in feedback buffer.
  147.  */
  148. static void feedback_triangle( GLcontext *ctx,
  149.                                GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  150. {
  151.    struct vertex_buffer *VB = ctx->VB;
  152.    GLfloat color[4];
  153.    GLuint i;
  154.    GLfloat invRedScale   = ctx->Visual->InvRedScale;
  155.    GLfloat invGreenScale = ctx->Visual->InvGreenScale;
  156.    GLfloat invBlueScale  = ctx->Visual->InvBlueScale;
  157.    GLfloat invAlphaScale = ctx->Visual->InvAlphaScale;
  158.  
  159.    FEEDBACK_TOKEN( ctx, BOOL_TO_FLOAT(GL_POLYGON_TOKEN) );
  160.    FEEDBACK_TOKEN( ctx, (GLfloat) 3 );        /* three vertices */
  161.  
  162.    if (ctx->Light.ShadeModel==GL_FLAT) {
  163.       /* flat shading - same color for each vertex */
  164.       color[0] = (GLfloat) VB->Color[pv][0] * invRedScale;
  165.       color[1] = (GLfloat) VB->Color[pv][1] * invGreenScale;
  166.       color[2] = (GLfloat) VB->Color[pv][2] * invBlueScale;
  167.       color[3] = (GLfloat) VB->Color[pv][3] * invAlphaScale;
  168.    }
  169.  
  170.    for (i=0;i<3;i++) {
  171.       GLfloat x, y, z, w;
  172.       GLfloat tc[4];
  173.       GLuint v;
  174.       GLfloat invq;
  175.  
  176.       if (i==0)       v = v0;
  177.       else if (i==1)  v = v1;
  178.       else            v = v2;
  179.  
  180.       x = VB->Win[v][0];
  181.       y = VB->Win[v][1];
  182.       z = VB->Win[v][2] / DEPTH_SCALE;
  183.       w = VB->Clip[v][3];
  184.  
  185.       if (ctx->Light.ShadeModel==GL_SMOOTH) {
  186.          /* smooth shading - different color for each vertex */
  187.          color[0] = VB->Color[v][0] * invRedScale;
  188.          color[1] = VB->Color[v][1] * invGreenScale;
  189.          color[2] = VB->Color[v][2] * invBlueScale;
  190.          color[3] = VB->Color[v][3] * invAlphaScale;
  191.       }
  192.  
  193.       invq = (VB->TexCoord[v][3]==0.0) ? 1.0 : (1.0F / VB->TexCoord[v][3]);
  194.       tc[0] = VB->TexCoord[v][0] * invq;
  195.       tc[1] = VB->TexCoord[v][1] * invq;
  196.       tc[2] = VB->TexCoord[v][2] * invq;
  197.       tc[3] = VB->TexCoord[v][3];
  198.  
  199.       gl_feedback_vertex( ctx, x, y, z, w, color, (GLfloat) VB->Index[v], tc );
  200.    }
  201. }
  202.  
  203.  
  204.  
  205. /*
  206.  * Put triangle in selection buffer.
  207.  */
  208. static void select_triangle( GLcontext *ctx,
  209.                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  210. {
  211.    struct vertex_buffer *VB = ctx->VB;
  212.  
  213.    gl_update_hitflag( ctx, VB->Win[v0][2] / DEPTH_SCALE );
  214.    gl_update_hitflag( ctx, VB->Win[v1][2] / DEPTH_SCALE );
  215.    gl_update_hitflag( ctx, VB->Win[v2][2] / DEPTH_SCALE );
  216. }
  217.  
  218.  
  219.  
  220. /*
  221.  * Render a flat-shaded color index triangle.
  222.  */
  223. static void flat_ci_triangle( GLcontext *ctx,
  224.                               GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  225. {
  226. #define INTERP_Z 1
  227.  
  228. #define SETUP_CODE                              \
  229.    GLuint index = VB->Index[pv];                \
  230.    if (!VB->MonoColor) {                        \
  231.       /* set the color index */                 \
  232.       (*ctx->Driver.Index)( ctx, index );       \
  233.    }
  234.  
  235. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  236.         {                                                       \
  237.            GLint i, n = RIGHT-LEFT;                             \
  238.            GLdepth zspan[MAX_WIDTH];                            \
  239.            if (n>0) {                                           \
  240.               for (i=0;i<n;i++) {                               \
  241.                  zspan[i] = FixedToDepth(ffz);                  \
  242.                  ffz += fdzdx;                                  \
  243.               }                                                 \
  244.               gl_write_monoindex_span( ctx, n, LEFT, Y,         \
  245.                                     zspan, index, GL_POLYGON ); \
  246.            }                                                    \
  247.         }
  248.  
  249. #include "tritemp.h"          
  250. }
  251.  
  252.  
  253.  
  254. /*
  255.  * Render a smooth-shaded color index triangle.
  256.  */
  257. static void smooth_ci_triangle( GLcontext *ctx,
  258.                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  259. {
  260. #define INTERP_Z 1
  261. #define INTERP_INDEX 1
  262.  
  263. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  264.         {                                                       \
  265.            GLint i, n = RIGHT-LEFT;                             \
  266.            GLdepth zspan[MAX_WIDTH];                            \
  267.            GLuint index[MAX_WIDTH];                             \
  268.            if (n>0) {                                           \
  269.               for (i=0;i<n;i++) {                               \
  270.                  zspan[i] = FixedToDepth(ffz);                  \
  271.                  index[i] = FixedToInt(ffi);                    \
  272.                  ffz += fdzdx;                                  \
  273.                  ffi += fdidx;                                  \
  274.               }                                                 \
  275.               gl_write_index_span( ctx, n, LEFT, Y, zspan,      \
  276.                                    index, GL_POLYGON );         \
  277.            }                                                    \
  278.         }
  279.  
  280. #include "tritemp.h"
  281. }
  282.  
  283.  
  284.  
  285. /*
  286.  * Render a flat-shaded RGBA triangle.
  287.  */
  288. static void flat_rgba_triangle( GLcontext *ctx,
  289.                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  290. {
  291. #define INTERP_Z 1
  292.  
  293. #define SETUP_CODE                              \
  294.    if (!VB->MonoColor) {                        \
  295.       /* set the color */                       \
  296.       GLubyte r = VB->Color[pv][0];             \
  297.       GLubyte g = VB->Color[pv][1];             \
  298.       GLubyte b = VB->Color[pv][2];             \
  299.       GLubyte a = VB->Color[pv][3];             \
  300.       (*ctx->Driver.Color)( ctx, r, g, b, a );  \
  301.    }
  302.  
  303. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  304.         {                                                       \
  305.            GLint i, n = RIGHT-LEFT;                             \
  306.            GLdepth zspan[MAX_WIDTH];                            \
  307.            if (n>0) {                                           \
  308.               for (i=0;i<n;i++) {                               \
  309.                  zspan[i] = FixedToDepth(ffz);                  \
  310.                  ffz += fdzdx;                                  \
  311.               }                                                 \
  312.               gl_write_monocolor_span( ctx, n, LEFT, Y, zspan,  \
  313.                              VB->Color[pv][0], VB->Color[pv][1],\
  314.                              VB->Color[pv][2], VB->Color[pv][3],\
  315.                              GL_POLYGON );                      \
  316.            }                                                    \
  317.         }
  318.  
  319. #include "tritemp.h"
  320. }
  321.  
  322.  
  323.  
  324. /*
  325.  * Render a smooth-shaded RGBA triangle.
  326.  */
  327. static void smooth_rgba_triangle( GLcontext *ctx,
  328.                                   GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  329. {
  330. #define INTERP_Z 1
  331. #define INTERP_RGB 1
  332. #define INTERP_ALPHA 1
  333.  
  334. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  335.         {                                                       \
  336.            GLint i, n = RIGHT-LEFT;                             \
  337.            GLdepth zspan[MAX_WIDTH];                            \
  338.            GLubyte red[MAX_WIDTH], green[MAX_WIDTH];            \
  339.            GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];           \
  340.            if (n>0) {                                           \
  341.               for (i=0;i<n;i++) {                               \
  342.                  zspan[i] = FixedToDepth(ffz);                  \
  343.                  red[i]   = FixedToInt(ffr);                    \
  344.                  green[i] = FixedToInt(ffg);                    \
  345.                  blue[i]  = FixedToInt(ffb);                    \
  346.                  alpha[i] = FixedToInt(ffa);                    \
  347.                  ffz += fdzdx;                                  \
  348.                  ffr += fdrdx;                                  \
  349.                  ffg += fdgdx;                                  \
  350.                  ffb += fdbdx;                                  \
  351.                  ffa += fdadx;                                  \
  352.               }                                                 \
  353.               gl_write_color_span( ctx, n, LEFT, Y, zspan,      \
  354.                                    red, green, blue, alpha,     \
  355.                                    GL_POLYGON );                \
  356.            }                                                    \
  357.         }
  358.  
  359. #include "tritemp.h"
  360. }
  361.  
  362.  
  363.  
  364. /*
  365.  * Render an RGB, GL_DECAL, textured triangle.
  366.  * Interpolate S,T only w/out mipmapping or perspective correction.
  367.  */
  368. static void simple_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  369.                                       GLuint v2, GLuint pv )
  370. {
  371. #define INTERP_ST 1
  372. #define S_SCALE twidth
  373. #define T_SCALE theight
  374. #define SETUP_CODE                                                      \
  375.    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;  \
  376.    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
  377.    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;     \
  378.    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;           \
  379.    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;           \
  380.    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
  381.  
  382. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  383.         {                                                       \
  384.            GLint i, n = RIGHT-LEFT;                             \
  385.            GLubyte red[MAX_WIDTH], green[MAX_WIDTH];            \
  386.            GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];           \
  387.            if (n>0) {                                           \
  388.               for (i=0;i<n;i++) {                               \
  389.                  GLint s = FixedToInt(ffs) & smask;             \
  390.                  GLint t = FixedToInt(fft) & tmask;             \
  391.                  GLint pos = (t << twidth_log2) + s;            \
  392.                  pos = pos + pos  + pos;  /* multiply by 3 */   \
  393.                  red[i]   = texture[pos];                       \
  394.                  green[i] = texture[pos+1];                     \
  395.                  blue[i]  = texture[pos+2];                     \
  396.                  alpha[i] = 255;                                \
  397.                  ffs += fdsdx;                                  \
  398.                  fft += fdtdx;                                  \
  399.               }                                                 \
  400.               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,   \
  401.                              red, green, blue, alpha, NULL );   \
  402.            }                                                    \
  403.         }
  404.  
  405. #include "tritemp.h"
  406. }
  407.  
  408.  
  409.  
  410. /*
  411.  * Render an RGB, GL_DECAL, textured triangle.
  412.  * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
  413.  * perspective correction.
  414.  */
  415. static void simple_z_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  416.                                       GLuint v2, GLuint pv )
  417. {
  418. #define INTERP_Z 1
  419. #define INTERP_ST 1
  420. #define S_SCALE twidth
  421. #define T_SCALE theight
  422. #define SETUP_CODE                                                      \
  423.    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;  \
  424.    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
  425.    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;     \
  426.    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;           \
  427.    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;           \
  428.    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
  429.  
  430. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  431.         {                                                       \
  432.            GLint i, n = RIGHT-LEFT;                             \
  433.            GLubyte red[MAX_WIDTH], green[MAX_WIDTH];            \
  434.            GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];           \
  435.            GLubyte mask[MAX_WIDTH];                             \
  436.            if (n>0) {                                           \
  437.               for (i=0;i<n;i++) {                               \
  438.                  GLdepth z = FixedToDepth(ffz);                 \
  439.                  if (z < zRow[i]) {                             \
  440.                     GLint s = FixedToInt(ffs) & smask;          \
  441.                     GLint t = FixedToInt(fft) & tmask;          \
  442.                     GLint pos = (t << twidth_log2) + s;         \
  443.                     pos = pos + pos  + pos;  /* multiply by 3 */\
  444.                     red[i]   = texture[pos];                    \
  445.                     green[i] = texture[pos+1];                  \
  446.                     blue[i]  = texture[pos+2];                  \
  447.                     alpha[i] = 255;                             \
  448.                     zRow[i] = z;                                \
  449.                     mask[i] = 1;                                \
  450.                  }                                              \
  451.                  else {                                         \
  452.                     mask[i] = 0;                                \
  453.                  }                                              \
  454.                  ffz += fdzdx;                                  \
  455.                  ffs += fdsdx;                                  \
  456.                  fft += fdtdx;                                  \
  457.               }                                                 \
  458.               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,   \
  459.                              red, green, blue, alpha, mask );   \
  460.            }                                                    \
  461.         }
  462.  
  463. #include "tritemp.h"
  464. }
  465.  
  466.  
  467. /* temporary bugfix for StormCPPC */
  468.  
  469. #if defined(__STORM__) && defined(__PPC__)
  470.            GLdepth g_zspan[MAX_WIDTH];
  471.            GLubyte g_red[MAX_WIDTH], g_green[MAX_WIDTH];
  472.            GLubyte g_blue[MAX_WIDTH], g_alpha[MAX_WIDTH];
  473.            GLfloat g_s[MAX_WIDTH], g_t[MAX_WIDTH], g_u[MAX_WIDTH];
  474. #endif
  475.  
  476.  
  477. #if defined(__STORM__) && defined(__PPC__)
  478.  
  479. /*
  480.  * Render a smooth-shaded, textured, RGBA triangle.
  481.  * Interpolate S,T,U with perspective correction, w/out mipmapping.
  482.  * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
  483.  * R is already used for red.
  484.  */
  485. static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  486.                                        GLuint v2, GLuint pv )
  487. {
  488. #define INTERP_Z 1
  489. #define INTERP_RGB 1
  490. #define INTERP_ALPHA 1
  491. #define INTERP_STW 1
  492. #define INTERP_UV 1
  493. #define SETUP_CODE                                              \
  494.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);     \
  495.    GLint r, g, b, a;                                            \
  496.    if (flat_shade) {                                            \
  497.       r = VB->Color[pv][0];                                     \
  498.       g = VB->Color[pv][1];                                     \
  499.       b = VB->Color[pv][2];                                     \
  500.       a = VB->Color[pv][3];                                     \
  501.    }
  502. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  503.         {                                                       \
  504.            GLint i, n = RIGHT-LEFT;                             \
  505.            if (n>0) {                                           \
  506.               if (flat_shade) {                                 \
  507.                  for (i=0;i<n;i++) {                            \
  508.                     GLdouble wwvvInv = 1.0 / (ww*vv);           \
  509.                     g_zspan[i] = FixedToDepth(ffz);               \
  510.                     g_red[i]   = r;                               \
  511.                     g_green[i] = g;                               \
  512.                     g_blue[i]  = b;                               \
  513.                     g_alpha[i] = a;                               \
  514.                     g_s[i] = ss*wwvvInv;                          \
  515.                     g_t[i] = tt*wwvvInv;                          \
  516.                     g_u[i] = uu*wwvvInv;                          \
  517.                     ffz += fdzdx;                               \
  518.                     ss += dsdx;                                 \
  519.                     tt += dtdx;                                 \
  520.                     uu += dudx;                                 \
  521.                     vv += dvdx;                                 \
  522.                     ww += dwdx;                                 \
  523.                  }                                              \
  524.               }                                                 \
  525.               else {                                            \
  526.                  for (i=0;i<n;i++) {                            \
  527.                     GLdouble wwvvInv = 1.0 / (ww*vv);           \
  528.                     g_zspan[i] = FixedToDepth(ffz);               \
  529.                     g_red[i]   = FixedToInt(ffr);                 \
  530.                     g_green[i] = FixedToInt(ffg);                 \
  531.                     g_blue[i]  = FixedToInt(ffb);                 \
  532.                     g_alpha[i] = FixedToInt(ffa);                 \
  533.                     g_s[i] = ss*wwvvInv;                          \
  534.                     g_t[i] = tt*wwvvInv;                          \
  535.                     g_u[i] = uu*wwvvInv;                          \
  536.                     ffz += fdzdx;                               \
  537.                     ffr += fdrdx;                               \
  538.                     ffg += fdgdx;                               \
  539.                     ffb += fdbdx;                               \
  540.                     ffa += fdadx;                               \
  541.                     ss += dsdx;                                 \
  542.                     tt += dtdx;                                 \
  543.                     uu += dudx;                                 \
  544.                     ww += dwdx;                                 \
  545.                     vv += dvdx;                                 \
  546.                  }                                              \
  547.               }                                                 \
  548.               gl_write_texture_span( ctx, n, LEFT, Y, g_zspan,    \
  549.                                      g_s, g_t, g_u, NULL,             \
  550.                                      g_red, g_green, g_blue, g_alpha,   \
  551.                                      GL_POLYGON );              \
  552.            }                                                    \
  553.         }
  554.  
  555. #include "tritemp.h"
  556. }
  557.  
  558. #else
  559.  
  560. /*
  561.  * Render a smooth-shaded, textured, RGBA triangle.
  562.  * Interpolate S,T,U with perspective correction, w/out mipmapping.
  563.  * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
  564.  * R is already used for red.
  565.  */
  566. static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  567.                                        GLuint v2, GLuint pv )
  568. {
  569. #define INTERP_Z 1
  570. #define INTERP_RGB 1
  571. #define INTERP_ALPHA 1
  572. #define INTERP_STW 1
  573. #define INTERP_UV 1
  574. #define SETUP_CODE                                              \
  575.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);     \
  576.    GLint r, g, b, a;                                            \
  577.    if (flat_shade) {                                            \
  578.       r = VB->Color[pv][0];                                     \
  579.       g = VB->Color[pv][1];                                     \
  580.       b = VB->Color[pv][2];                                     \
  581.       a = VB->Color[pv][3];                                     \
  582.    }
  583. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  584.         {                                                       \
  585.            GLint i, n = RIGHT-LEFT;                             \
  586.            GLdepth zspan[MAX_WIDTH];                            \
  587.            GLubyte red[MAX_WIDTH], green[MAX_WIDTH];            \
  588.            GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];           \
  589.            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];    \
  590.            if (n>0) {                                           \
  591.               if (flat_shade) {                                 \
  592.                  for (i=0;i<n;i++) {                            \
  593.                     GLdouble wwvvInv = 1.0 / (ww*vv);           \
  594.                     zspan[i] = FixedToDepth(ffz);               \
  595.                     red[i]   = r;                               \
  596.                     green[i] = g;                               \
  597.                     blue[i]  = b;                               \
  598.                     alpha[i] = a;                               \
  599.                     s[i] = ss*wwvvInv;                          \
  600.                     t[i] = tt*wwvvInv;                          \
  601.                     u[i] = uu*wwvvInv;                          \
  602.                     ffz += fdzdx;                               \
  603.                     ss += dsdx;                                 \
  604.                     tt += dtdx;                                 \
  605.                     uu += dudx;                                 \
  606.                     vv += dvdx;                                 \
  607.                     ww += dwdx;                                 \
  608.                  }                                              \
  609.               }                                                 \
  610.               else {                                            \
  611.                  for (i=0;i<n;i++) {                            \
  612.                     GLdouble wwvvInv = 1.0 / (ww*vv);           \
  613.                     zspan[i] = FixedToDepth(ffz);               \
  614.                     red[i]   = FixedToInt(ffr);                 \
  615.                     green[i] = FixedToInt(ffg);                 \
  616.                     blue[i]  = FixedToInt(ffb);                 \
  617.                     alpha[i] = FixedToInt(ffa);                 \
  618.                     s[i] = ss*wwvvInv;                          \
  619.                     t[i] = tt*wwvvInv;                          \
  620.                     u[i] = uu*wwvvInv;                          \
  621.                     ffz += fdzdx;                               \
  622.                     ffr += fdrdx;                               \
  623.                     ffg += fdgdx;                               \
  624.                     ffb += fdbdx;                               \
  625.                     ffa += fdadx;                               \
  626.                     ss += dsdx;                                 \
  627.                     tt += dtdx;                                 \
  628.                     uu += dudx;                                 \
  629.                     ww += dwdx;                                 \
  630.                     vv += dvdx;                                 \
  631.                  }                                              \
  632.               }                                                 \
  633.               gl_write_texture_span( ctx, n, LEFT, Y, zspan,    \
  634.                                      s, t, u, NULL,             \
  635.                                      red, green, blue, alpha,   \
  636.                                      GL_POLYGON );              \
  637.            }                                                    \
  638.         }
  639.  
  640. #include "tritemp.h"
  641. }
  642.  
  643.  
  644. #endif
  645.  
  646.  
  647. /*
  648.  * Compute the lambda value (texture level value) for a fragment.
  649.  */
  650. static GLfloat compute_lambda( GLfloat s, GLfloat t,
  651.                                GLfloat dsdx, GLfloat dsdy,
  652.                                GLfloat dtdx, GLfloat dtdy,
  653.                                GLfloat w, GLfloat dwdx, GLfloat dwdy,
  654.                                GLfloat width, GLfloat height ) 
  655. {
  656.    /* TODO: this function can probably be optimized a bit */
  657.    GLfloat invw = 1.0 / w;
  658.    GLfloat dudx, dudy, dvdx, dvdy;
  659.    GLfloat r1, r2, rho2;
  660.  
  661.    dudx = (dsdx - s*dwdx) * invw * width;
  662.    dudy = (dsdy - s*dwdy) * invw * width;
  663.    dvdx = (dtdx - t*dwdx) * invw * height;
  664.    dvdy = (dtdy - t*dwdy) * invw * height;
  665.  
  666.    r1 = dudx * dudx + dudy * dudy;
  667.    r2 = dvdx * dvdx + dvdy * dvdy;
  668.  
  669.    /* rho2 = MAX2(r1,r2); */
  670.    rho2 = r1 + r2;
  671.    if (rho2 <= 0.0F) {
  672.       return 0.0F;
  673.    }
  674.    else {
  675.       /* return log base 2 of rho */
  676.       return log(rho2) * 1.442695 * 0.5;       /* 1.442695 = 1/log(2) */
  677.    }
  678. }
  679.  
  680.  
  681. #if defined(__STORM__) && defined(__PPC__)
  682.  
  683. /*
  684.  * Render a smooth-shaded, textured, RGBA triangle.
  685.  * Interpolate S,T,U with perspective correction and compute lambda for
  686.  * each fragment.  Lambda is used to determine whether to use the
  687.  * minification or magnification filter.  If minification and using
  688.  * mipmaps, lambda is also used to select the texture level of detail.
  689.  */
  690. static void lambda_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  691.                                       GLuint v2, GLuint pv )
  692. {
  693. #define INTERP_Z 1
  694. #define INTERP_RGB 1
  695. #define INTERP_ALPHA 1
  696. #define INTERP_STW 1
  697. #define INTERP_UV 1
  698.  
  699. #define SETUP_CODE                                                      \
  700.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);             \
  701.    GLint r, g, b, a;                                                    \
  702.    GLfloat twidth, theight;                                             \
  703.    if (ctx->Texture.Enabled & TEXTURE_3D) {                             \
  704.       twidth = (GLfloat) ctx->Texture.Current3D->Image[0]->Width;       \
  705.       theight = (GLfloat) ctx->Texture.Current3D->Image[0]->Height;     \
  706.    }                                                                    \
  707.    else if (ctx->Texture.Enabled & TEXTURE_2D) {                        \
  708.       twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;       \
  709.       theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;     \
  710.    }                                                                    \
  711.    else {                                                               \
  712.       twidth = (GLfloat) ctx->Texture.Current1D->Image[0]->Width;       \
  713.       theight = 1.0;                                                    \
  714.    }                                                                    \
  715.    if (flat_shade) {                                                    \
  716.       r = VB->Color[pv][0];                                             \
  717.       g = VB->Color[pv][1];                                             \
  718.       b = VB->Color[pv][2];                                             \
  719.       a = VB->Color[pv][3];                                             \
  720.    }
  721.  
  722. #define INNER_LOOP( LEFT, RIGHT, Y )                                    \
  723.         {                                                               \
  724.            GLint i, n = RIGHT-LEFT;                                     \
  725.            DEFARRAY(GLfloat,lambda,MAX_WIDTH);                          \
  726.            if (n>0) {                                                   \
  727.               if (flat_shade) {                                         \
  728.                  for (i=0;i<n;i++) {                                    \
  729.                     GLdouble wwvvInv = 1.0 / (ww*vv);                   \
  730.                     g_zspan[i] = FixedToDepth(ffz);                       \
  731.                     g_red[i]   = r;                                       \
  732.                     g_green[i] = g;                                       \
  733.                     g_blue[i]  = b;                                       \
  734.                     g_alpha[i] = a;                                       \
  735.                     g_s[i] = ss*wwvvInv;                                  \
  736.                     g_t[i] = tt*wwvvInv;                                  \
  737.                     g_u[i] = uu*wwvvInv;                                  \
  738.                     lambda[i] = compute_lambda( g_s[i], g_t[i],             \
  739.                                                 dsdx, dsdy,             \
  740.                                                 dtdx, dtdy, ww,         \
  741.                                                 dwdx, dwdy,             \
  742.                                                 twidth, theight );      \
  743.                     ffz += fdzdx;                                       \
  744.                     ss += dsdx;                                         \
  745.                     tt += dtdx;                                         \
  746.                     uu += dudx;                                         \
  747.                     vv += dvdx;                                         \
  748.                     ww += dwdx;                                         \
  749.                  }                                                      \
  750.               }                                                         \
  751.               else {                                                    \
  752.                  for (i=0;i<n;i++) {                                    \
  753.                     GLdouble wwvvInv = 1.0 / (ww*vv);                   \
  754.                     g_zspan[i] = FixedToDepth(ffz);                       \
  755.                     g_red[i]   = FixedToInt(ffr);                         \
  756.                     g_green[i] = FixedToInt(ffg);                         \
  757.                     g_blue[i]  = FixedToInt(ffb);                         \
  758.                     g_alpha[i] = FixedToInt(ffa);                         \
  759.                     g_s[i] = ss*wwvvInv;                                  \
  760.                     g_t[i] = tt*wwvvInv;                                  \
  761.                     g_u[i] = uu*wwvvInv;                                  \
  762.                     lambda[i] = compute_lambda( g_s[i], g_t[i],             \
  763.                                                 dsdx, dsdy,             \
  764.                                                 dtdx, dtdy, ww,         \
  765.                                                 dwdx, dwdy,             \
  766.                                                 twidth, theight );      \
  767.                     ffz += fdzdx;                                       \
  768.                     ffr += fdrdx;                                       \
  769.                     ffg += fdgdx;                                       \
  770.                     ffb += fdbdx;                                       \
  771.                     ffa += fdadx;                                       \
  772.                     ss += dsdx;                                         \
  773.                     tt += dtdx;                                         \
  774.                     uu += dudx;                                         \
  775.                     vv += dvdx;                                         \
  776.                     ww += dwdx;                                         \
  777.                  }                                                      \
  778.               }                                                         \
  779.               gl_write_texture_span( ctx, n, LEFT, Y, g_zspan,            \
  780.                                      g_s, g_t, g_u, lambda,                   \
  781.                                      g_red, g_green, g_blue, g_alpha,           \
  782.                                      GL_POLYGON );                      \
  783.            }                                                            \
  784.            UNDEFARRAY(lambda);                                          \
  785.         }
  786.  
  787. #include "tritemp.h"
  788. }
  789.  
  790. #else
  791.  
  792. /*
  793.  * Render a smooth-shaded, textured, RGBA triangle.
  794.  * Interpolate S,T,U with perspective correction and compute lambda for
  795.  * each fragment.  Lambda is used to determine whether to use the
  796.  * minification or magnification filter.  If minification and using
  797.  * mipmaps, lambda is also used to select the texture level of detail.
  798.  */
  799. static void lambda_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  800.                                       GLuint v2, GLuint pv )
  801. {
  802. #define INTERP_Z 1
  803. #define INTERP_RGB 1
  804. #define INTERP_ALPHA 1
  805. #define INTERP_STW 1
  806. #define INTERP_UV 1
  807.  
  808. #define SETUP_CODE                                                      \
  809.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);             \
  810.    GLint r, g, b, a;                                                    \
  811.    GLfloat twidth, theight;                                             \
  812.    if (ctx->Texture.Enabled & TEXTURE_3D) {                             \
  813.       twidth = (GLfloat) ctx->Texture.Current3D->Image[0]->Width;       \
  814.       theight = (GLfloat) ctx->Texture.Current3D->Image[0]->Height;     \
  815.    }                                                                    \
  816.    else if (ctx->Texture.Enabled & TEXTURE_2D) {                        \
  817.       twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;       \
  818.       theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;     \
  819.    }                                                                    \
  820.    else {                                                               \
  821.       twidth = (GLfloat) ctx->Texture.Current1D->Image[0]->Width;       \
  822.       theight = 1.0;                                                    \
  823.    }                                                                    \
  824.    if (flat_shade) {                                                    \
  825.       r = VB->Color[pv][0];                                             \
  826.       g = VB->Color[pv][1];                                             \
  827.       b = VB->Color[pv][2];                                             \
  828.       a = VB->Color[pv][3];                                             \
  829.    }
  830.  
  831. #define INNER_LOOP( LEFT, RIGHT, Y )                                    \
  832.         {                                                               \
  833.            GLint i, n = RIGHT-LEFT;                                     \
  834.            GLdepth zspan[MAX_WIDTH];                                    \
  835.            GLubyte red[MAX_WIDTH], green[MAX_WIDTH];                    \
  836.            GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];                   \
  837.            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];            \
  838.            DEFARRAY(GLfloat,lambda,MAX_WIDTH);                          \
  839.            if (n>0) {                                                   \
  840.               if (flat_shade) {                                         \
  841.                  for (i=0;i<n;i++) {                                    \
  842.                     GLdouble wwvvInv = 1.0 / (ww*vv);                   \
  843.                     zspan[i] = FixedToDepth(ffz);                       \
  844.                     red[i]   = r;                                       \
  845.                     green[i] = g;                                       \
  846.                     blue[i]  = b;                                       \
  847.                     alpha[i] = a;                                       \
  848.                     s[i] = ss*wwvvInv;                                  \
  849.                     t[i] = tt*wwvvInv;                                  \
  850.                     u[i] = uu*wwvvInv;                                  \
  851.                     lambda[i] = compute_lambda( s[i], t[i],             \
  852.                                                 dsdx, dsdy,             \
  853.                                                 dtdx, dtdy, ww,         \
  854.                                                 dwdx, dwdy,             \
  855.                                                 twidth, theight );      \
  856.                     ffz += fdzdx;                                       \
  857.                     ss += dsdx;                                         \
  858.                     tt += dtdx;                                         \
  859.                     uu += dudx;                                         \
  860.                     vv += dvdx;                                         \
  861.                     ww += dwdx;                                         \
  862.                  }                                                      \
  863.               }                                                         \
  864.               else {                                                    \
  865.                  for (i=0;i<n;i++) {                                    \
  866.                     GLdouble wwvvInv = 1.0 / (ww*vv);                   \
  867.                     zspan[i] = FixedToDepth(ffz);                       \
  868.                     red[i]   = FixedToInt(ffr);                         \
  869.                     green[i] = FixedToInt(ffg);                         \
  870.                     blue[i]  = FixedToInt(ffb);                         \
  871.                     alpha[i] = FixedToInt(ffa);                         \
  872.                     s[i] = ss*wwvvInv;                                  \
  873.                     t[i] = tt*wwvvInv;                                  \
  874.                     u[i] = uu*wwvvInv;                                  \
  875.                     lambda[i] = compute_lambda( s[i], t[i],             \
  876.                                                 dsdx, dsdy,             \
  877.                                                 dtdx, dtdy, ww,         \
  878.                                                 dwdx, dwdy,             \
  879.                                                 twidth, theight );      \
  880.                     ffz += fdzdx;                                       \
  881.                     ffr += fdrdx;                                       \
  882.                     ffg += fdgdx;                                       \
  883.                     ffb += fdbdx;                                       \
  884.                     ffa += fdadx;                                       \
  885.                     ss += dsdx;                                         \
  886.                     tt += dtdx;                                         \
  887.                     uu += dudx;                                         \
  888.                     vv += dvdx;                                         \
  889.                     ww += dwdx;                                         \
  890.                  }                                                      \
  891.               }                                                         \
  892.               gl_write_texture_span( ctx, n, LEFT, Y, zspan,            \
  893.                                      s, t, u, lambda,                   \
  894.                                      red, green, blue, alpha,           \
  895.                                      GL_POLYGON );                      \
  896.            }                                                            \
  897.            UNDEFARRAY(lambda);                                          \
  898.         }
  899.  
  900. #include "tritemp.h"
  901. }
  902.  
  903. #endif
  904.  
  905.  
  906. /*
  907.  * Null rasterizer for measuring transformation speed.
  908.  */
  909. static void null_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  910.                            GLuint v2, GLuint pv )
  911. {
  912. }
  913.  
  914.  
  915.  
  916. /*
  917.  * Determine which triangle rendering function to use given the current
  918.  * rendering context.
  919.  */
  920. void gl_set_triangle_function( GLcontext *ctx )
  921. {
  922.    GLboolean rgbmode = ctx->Visual->RGBAflag;
  923.  
  924.    if (ctx->RenderMode==GL_RENDER) {
  925.       if (ctx->NoRaster) {
  926.          ctx->Driver.TriangleFunc = null_triangle;
  927.          return;
  928.       }
  929.       if (ctx->Driver.TriangleFunc) {
  930.          /* Device driver will draw triangles. */
  931.       }
  932.       else if (ctx->Texture.Enabled
  933.                && ctx->Texture.Current
  934.                && ctx->Texture.Current->Complete) {
  935.          if (   (ctx->Texture.Enabled==TEXTURE_2D)
  936.              && ctx->Texture.Current2D->MinFilter==GL_NEAREST
  937.              && ctx->Texture.Current2D->MagFilter==GL_NEAREST
  938.              && ctx->Texture.Current2D->WrapS==GL_REPEAT
  939.              && ctx->Texture.Current2D->WrapT==GL_REPEAT
  940.              && ctx->Texture.Current2D->Image[0]->Format==GL_RGB
  941.              && ctx->Texture.Current2D->Image[0]->Border==0
  942.              && (ctx->Texture.EnvMode==GL_DECAL
  943.                  || ctx->Texture.EnvMode==GL_REPLACE)
  944.              && ctx->Hint.PerspectiveCorrection==GL_FASTEST
  945.              && ctx->TextureMatrixType==MATRIX_IDENTITY
  946.              && ((ctx->RasterMask==DEPTH_BIT
  947.                   && ctx->Depth.Func==GL_LESS
  948.                   && ctx->Depth.Mask==GL_TRUE)
  949.                  || ctx->RasterMask==0)
  950.              && ctx->Polygon.StippleFlag==GL_FALSE
  951.              && ctx->Visual->EightBitColor) {
  952.             if (ctx->RasterMask==DEPTH_BIT) {
  953.                ctx->Driver.TriangleFunc = simple_z_textured_triangle;
  954.             }
  955.             else {
  956.                ctx->Driver.TriangleFunc = simple_textured_triangle;
  957.             }
  958.          }
  959.          else {
  960.             GLboolean needLambda = GL_TRUE;
  961.             /* if mag filter == min filter we're not mipmapping */
  962.             if (ctx->Texture.Enabled & TEXTURE_3D) {
  963.                if (ctx->Texture.Current3D->MinFilter==
  964.                    ctx->Texture.Current3D->MagFilter) {
  965.                   needLambda = GL_FALSE;
  966.                }
  967.             }
  968.             else if (ctx->Texture.Enabled & TEXTURE_2D) {
  969.                if (ctx->Texture.Current2D->MinFilter==
  970.                    ctx->Texture.Current2D->MagFilter) {
  971.                   needLambda = GL_FALSE;
  972.                }
  973.             }
  974.             else if (ctx->Texture.Enabled & TEXTURE_1D) {
  975.                if (ctx->Texture.Current1D->MinFilter==
  976.                    ctx->Texture.Current1D->MagFilter) {
  977.                   needLambda = GL_FALSE;
  978.                }
  979.             }
  980.             ctx->Driver.TriangleFunc = needLambda ? (triangle_func)lambda_textured_triangle
  981.                                                   : (triangle_func)general_textured_triangle;
  982.          }
  983.       }
  984.       else {
  985.          if (ctx->Light.ShadeModel==GL_SMOOTH) {
  986.             /* smooth shaded, no texturing, stippled or some raster ops */
  987.             ctx->Driver.TriangleFunc = rgbmode ? (triangle_func)smooth_rgba_triangle
  988.                                                : (triangle_func)smooth_ci_triangle;
  989.          }
  990.          else {
  991.             /* flat shaded, no texturing, stippled or some raster ops */
  992.             ctx->Driver.TriangleFunc = rgbmode ? (triangle_func)flat_rgba_triangle
  993.                                                : (triangle_func)flat_ci_triangle;
  994.          }
  995.       }
  996.    }
  997.    else if (ctx->RenderMode==GL_FEEDBACK) {
  998.       ctx->Driver.TriangleFunc = feedback_triangle;
  999.    }
  1000.    else {
  1001.       /* GL_SELECT mode */
  1002.       ctx->Driver.TriangleFunc = select_triangle;
  1003.    }
  1004. }
  1005.  
  1006.