home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / OLD / s_triangle.c < prev    next >
C/C++ Source or Header  |  2002-11-13  |  38KB  |  1,151 lines

  1. /* $Id: s_triangle.c,v 1.65 2002/11/13 16:51:01 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * When the device driver doesn't implement triangle rasterization it
  30.  * can hook in _swrast_Triangle, which eventually calls one of these
  31.  * functions to draw triangles.
  32.  */
  33.  
  34. #include "glheader.h"
  35. #include "context.h"
  36. #include "colormac.h"
  37. #include "imports.h"
  38. #include "macros.h"
  39. #include "mmath.h"
  40. #include "texformat.h"
  41. #include "teximage.h"
  42. #include "texstate.h"
  43.  
  44. #include "s_aatriangle.h"
  45. #include "s_context.h"
  46. #include "s_depth.h"
  47. #include "s_feedback.h"
  48. #include "s_span.h"
  49. #include "s_triangle.h"
  50.  
  51.  
  52. /*
  53.  * Just used for feedback mode.
  54.  */
  55. GLboolean _mesa_cull_triangle( GLcontext *ctx,
  56.                 const SWvertex *v0,
  57.                 const SWvertex *v1,
  58.                 const SWvertex *v2 )
  59. {
  60.    GLfloat ex = v1->win[0] - v0->win[0];
  61.    GLfloat ey = v1->win[1] - v0->win[1];
  62.    GLfloat fx = v2->win[0] - v0->win[0];
  63.    GLfloat fy = v2->win[1] - v0->win[1];
  64.    GLfloat c = ex*fy-ey*fx;
  65.  
  66.    if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0)
  67.       return 0;
  68.  
  69.    return 1;
  70. }
  71.  
  72.  
  73.  
  74. /*
  75.  * Render a flat-shaded color index triangle.
  76.  */
  77. #define NAME flat_ci_triangle
  78. #define INTERP_Z 1
  79. #define INTERP_FOG 1
  80. #define SETUP_CODE            \
  81.    span.interpMask |= SPAN_INDEX;    \
  82.    span.index = IntToFixed(v2->index);    \
  83.    span.indexStep = 0;
  84. #define RENDER_SPAN( span )  _mesa_write_index_span(ctx, &span);
  85. #include "s_tritemp.h"
  86.  
  87.  
  88.  
  89. /*
  90.  * Render a smooth-shaded color index triangle.
  91.  */
  92. #define NAME smooth_ci_triangle
  93. #define INTERP_Z 1
  94. #define INTERP_FOG 1
  95. #define INTERP_INDEX 1
  96. #define RENDER_SPAN( span )  _mesa_write_index_span(ctx, &span);
  97. #include "s_tritemp.h"
  98.  
  99.  
  100.  
  101. /*
  102.  * Render a flat-shaded RGBA triangle.
  103.  */
  104. #define NAME flat_rgba_triangle
  105. #define INTERP_Z 1
  106. #define INTERP_FOG 1
  107. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  108. #define SETUP_CODE                \
  109.    ASSERT(ctx->Texture._EnabledUnits == 0);    \
  110.    ASSERT(ctx->Light.ShadeModel==GL_FLAT);    \
  111.    span.interpMask |= SPAN_RGBA;        \
  112.    span.red = ChanToFixed(v2->color[0]);    \
  113.    span.green = ChanToFixed(v2->color[1]);    \
  114.    span.blue = ChanToFixed(v2->color[2]);    \
  115.    span.alpha = ChanToFixed(v2->color[3]);    \
  116.    span.redStep = 0;                \
  117.    span.greenStep = 0;                \
  118.    span.blueStep = 0;                \
  119.    span.alphaStep = 0;
  120. #define RENDER_SPAN( span )  _mesa_write_rgba_span(ctx, &span);
  121. #include "s_tritemp.h"
  122.  
  123.  
  124.  
  125. /*
  126.  * Render a smooth-shaded RGBA triangle.
  127.  */
  128. #define NAME smooth_rgba_triangle
  129. #define INTERP_Z 1
  130. #define INTERP_FOG 1
  131. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  132. #define INTERP_RGB 1
  133. #define INTERP_ALPHA 1
  134. #define SETUP_CODE                \
  135.    {                        \
  136.       /* texturing must be off */        \
  137.       ASSERT(ctx->Texture._EnabledUnits == 0);    \
  138.       ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);    \
  139.    }
  140. #define RENDER_SPAN( span )  _mesa_write_rgba_span(ctx, &span);
  141. #include "s_tritemp.h"
  142.  
  143.  
  144.  
  145. /*
  146.  * Render an RGB, GL_DECAL, textured triangle.
  147.  * Interpolate S,T only w/out mipmapping or perspective correction.
  148.  *
  149.  * No fog.
  150.  */
  151. #define NAME simple_textured_triangle
  152. #define INTERP_INT_TEX 1
  153. #define S_SCALE twidth
  154. #define T_SCALE theight
  155.  
  156. #define SETUP_CODE                            \
  157.    SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
  158.    struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;    \
  159.    const GLint b = obj->BaseLevel;                    \
  160.    const GLfloat twidth = (GLfloat) obj->Image[b]->Width;        \
  161.    const GLfloat theight = (GLfloat) obj->Image[b]->Height;        \
  162.    const GLint twidth_log2 = obj->Image[b]->WidthLog2;            \
  163.    const GLchan *texture = (const GLchan *) obj->Image[b]->Data;    \
  164.    const GLint smask = obj->Image[b]->Width - 1;            \
  165.    const GLint tmask = obj->Image[b]->Height - 1;            \
  166.    if (!texture) {                            \
  167.       /* this shouldn't happen */                    \
  168.       return;                                \
  169.    }
  170.  
  171. #define RENDER_SPAN( span  )                        \
  172.    GLuint i;                                \
  173.    span.intTex[0] -= FIXED_HALF; /* off-by-one error? */        \
  174.    span.intTex[1] -= FIXED_HALF;                    \
  175.    for (i = 0; i < span.end; i++) {                    \
  176.       GLint s = FixedToInt(span.intTex[0]) & smask;            \
  177.       GLint t = FixedToInt(span.intTex[1]) & tmask;            \
  178.       GLint pos = (t << twidth_log2) + s;                \
  179.       pos = pos + pos + pos;  /* multiply by 3 */            \
  180.       span.array->rgb[i][RCOMP] = texture[pos];                \
  181.       span.array->rgb[i][GCOMP] = texture[pos+1];            \
  182.       span.array->rgb[i][BCOMP] = texture[pos+2];            \
  183.       span.intTex[0] += span.intTexStep[0];                \
  184.       span.intTex[1] += span.intTexStep[1];                \
  185.    }                                    \
  186.    (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y,    \
  187.                                   (CONST GLchan (*)[3]) span.array->rgb,\
  188.                                   NULL );
  189. #include "s_tritemp.h"
  190.  
  191.  
  192.  
  193. /*
  194.  * Render an RGB, GL_DECAL, textured triangle.
  195.  * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
  196.  * perspective correction.
  197.  *
  198.  * No fog.
  199.  */
  200. #define NAME simple_z_textured_triangle
  201. #define INTERP_Z 1
  202. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  203. #define INTERP_INT_TEX 1
  204. #define S_SCALE twidth
  205. #define T_SCALE theight
  206.  
  207. #define SETUP_CODE                            \
  208.    SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
  209.    struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;    \
  210.    const GLint b = obj->BaseLevel;                    \
  211.    const GLfloat twidth = (GLfloat) obj->Image[b]->Width;        \
  212.    const GLfloat theight = (GLfloat) obj->Image[b]->Height;        \
  213.    const GLint twidth_log2 = obj->Image[b]->WidthLog2;            \
  214.    const GLchan *texture = (const GLchan *) obj->Image[b]->Data;    \
  215.    const GLint smask = obj->Image[b]->Width - 1;            \
  216.    const GLint tmask = obj->Image[b]->Height - 1;            \
  217.    if (!texture) {                            \
  218.       /* this shouldn't happen */                    \
  219.       return;                                \
  220.    }
  221.  
  222. #define RENDER_SPAN( span )                        \
  223.    GLuint i;                                    \
  224.    span.intTex[0] -= FIXED_HALF; /* off-by-one error? */        \
  225.    span.intTex[1] -= FIXED_HALF;                    \
  226.    for (i = 0; i < span.end; i++) {                    \
  227.       const GLdepth z = FixedToDepth(span.z);                \
  228.       if (z < zRow[i]) {                        \
  229.          GLint s = FixedToInt(span.intTex[0]) & smask;            \
  230.          GLint t = FixedToInt(span.intTex[1]) & tmask;            \
  231.          GLint pos = (t << twidth_log2) + s;                \
  232.          pos = pos + pos + pos;  /* multiply by 3 */            \
  233.          span.array->rgb[i][RCOMP] = texture[pos];            \
  234.          span.array->rgb[i][GCOMP] = texture[pos+1];            \
  235.          span.array->rgb[i][BCOMP] = texture[pos+2];            \
  236.          zRow[i] = z;                            \
  237.          span.array->mask[i] = 1;                    \
  238.       }                                    \
  239.       else {                                \
  240.          span.array->mask[i] = 0;                    \
  241.       }                                    \
  242.       span.intTex[0] += span.intTexStep[0];                \
  243.       span.intTex[1] += span.intTexStep[1];                \
  244.       span.z += span.zStep;                        \
  245.    }                                    \
  246.    (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y,    \
  247.                                   (CONST GLchan (*)[3]) span.array->rgb,\
  248.                                   span.array->mask );
  249. #include "s_tritemp.h"
  250.  
  251.  
  252.  
  253. #if CHAN_TYPE != GL_FLOAT
  254.  
  255. struct affine_info
  256. {
  257.    GLenum filter;
  258.    GLenum format;
  259.    GLenum envmode;
  260.    GLint smask, tmask;
  261.    GLint twidth_log2;
  262.    const GLchan *texture;
  263.    GLfixed er, eg, eb, ea;
  264.    GLint tbytesline, tsize;
  265. };
  266.  
  267.  
  268. /* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA
  269.  * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
  270.  * texture env modes.
  271.  */
  272. static INLINE void
  273. affine_span(GLcontext *ctx, struct sw_span *span,
  274.             struct affine_info *info)
  275. {
  276.    GLchan sample[4];  /* the filtered texture sample */
  277.  
  278.    /* Instead of defining a function for each mode, a test is done
  279.     * between the outer and inner loops. This is to reduce code size
  280.     * and complexity. Observe that an optimizing compiler kills
  281.     * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
  282.     */
  283.  
  284. #define NEAREST_RGB            \
  285.    sample[RCOMP] = tex00[RCOMP];    \
  286.    sample[GCOMP] = tex00[GCOMP];    \
  287.    sample[BCOMP] = tex00[BCOMP];    \
  288.    sample[ACOMP] = CHAN_MAX
  289.  
  290. #define LINEAR_RGB                            \
  291.    sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) +        \
  292.              tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;    \
  293.    sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) +        \
  294.              tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;    \
  295.    sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) +        \
  296.              tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;    \
  297.    sample[ACOMP] = CHAN_MAX
  298.  
  299. #define NEAREST_RGBA  COPY_CHAN4(sample, tex00)
  300.  
  301. #define LINEAR_RGBA                            \
  302.    sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) +        \
  303.                tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\
  304.    sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) +        \
  305.                tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\
  306.    sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) +        \
  307.                tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\
  308.    sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) +        \
  309.                tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
  310.  
  311. #define MODULATE                              \
  312.    dest[RCOMP] = span->red   * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \
  313.    dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \
  314.    dest[BCOMP] = span->blue  * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \
  315.    dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8)
  316.  
  317. #define DECAL                                \
  318.    dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red +        \
  319.                ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT))    \
  320.                >> (FIXED_SHIFT + 8);                    \
  321.    dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green +        \
  322.                ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT))    \
  323.                >> (FIXED_SHIFT + 8);                    \
  324.    dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue +        \
  325.                ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT))    \
  326.                >> (FIXED_SHIFT + 8);                    \
  327.    dest[ACOMP] = FixedToInt(span->alpha)
  328.  
  329. #define BLEND                                \
  330.    dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red        \
  331.                + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8);    \
  332.    dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green        \
  333.                + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8);    \
  334.    dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue        \
  335.                + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8);    \
  336.    dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8)
  337.  
  338. #define REPLACE  COPY_CHAN4(dest, sample)
  339.  
  340. #define ADD                                \
  341.    {                                    \
  342.       GLint rSum = FixedToInt(span->red)   + (GLint) sample[RCOMP];    \
  343.       GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP];    \
  344.       GLint bSum = FixedToInt(span->blue)  + (GLint) sample[BCOMP];    \
  345.       dest[RCOMP] = MIN2(rSum, CHAN_MAX);                \
  346.       dest[GCOMP] = MIN2(gSum, CHAN_MAX);                \
  347.       dest[BCOMP] = MIN2(bSum, CHAN_MAX);                \
  348.       dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \
  349.   }
  350.  
  351. /* shortcuts */
  352.  
  353. #define NEAREST_RGB_REPLACE        \
  354.    NEAREST_RGB;                \
  355.    dest[0] = sample[0];            \
  356.    dest[1] = sample[1];            \
  357.    dest[2] = sample[2];            \
  358.    dest[3] = FixedToInt(span->alpha);
  359.  
  360. #define NEAREST_RGBA_REPLACE  COPY_CHAN4(dest, tex00)
  361.  
  362. #define SPAN_NEAREST(DO_TEX,COMP)                    \
  363.     for (i = 0; i < span->end; i++) {                \
  364.            /* Isn't it necessary to use FixedFloor below?? */        \
  365.            GLint s = FixedToInt(span->intTex[0]) & info->smask;        \
  366.            GLint t = FixedToInt(span->intTex[1]) & info->tmask;        \
  367.            GLint pos = (t << info->twidth_log2) + s;            \
  368.            const GLchan *tex00 = info->texture + COMP * pos;        \
  369.            DO_TEX;                            \
  370.            span->red += span->redStep;                    \
  371.        span->green += span->greenStep;                \
  372.            span->blue += span->blueStep;                \
  373.        span->alpha += span->alphaStep;                \
  374.        span->intTex[0] += span->intTexStep[0];            \
  375.        span->intTex[1] += span->intTexStep[1];            \
  376.            dest += 4;                            \
  377.     }
  378.  
  379. #define SPAN_LINEAR(DO_TEX,COMP)                    \
  380.     for (i = 0; i < span->end; i++) {                \
  381.            /* Isn't it necessary to use FixedFloor below?? */        \
  382.            GLint s = FixedToInt(span->intTex[0]) & info->smask;        \
  383.            GLint t = FixedToInt(span->intTex[1]) & info->tmask;        \
  384.            GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK;        \
  385.            GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK;        \
  386.            GLfixed si = FIXED_FRAC_MASK - sf;                \
  387.            GLfixed ti = FIXED_FRAC_MASK - tf;                \
  388.            GLint pos = (t << info->twidth_log2) + s;            \
  389.            const GLchan *tex00 = info->texture + COMP * pos;        \
  390.            const GLchan *tex10 = tex00 + info->tbytesline;        \
  391.            const GLchan *tex01 = tex00 + COMP;                \
  392.            const GLchan *tex11 = tex10 + COMP;                \
  393.            (void) ti;                            \
  394.            (void) si;                            \
  395.            if (t == info->tmask) {                    \
  396.               tex10 -= info->tsize;                    \
  397.               tex11 -= info->tsize;                    \
  398.            }                                \
  399.            if (s == info->smask) {                    \
  400.               tex01 -= info->tbytesline;                \
  401.               tex11 -= info->tbytesline;                \
  402.            }                                \
  403.            DO_TEX;                            \
  404.            span->red += span->redStep;                    \
  405.        span->green += span->greenStep;                \
  406.            span->blue += span->blueStep;                \
  407.        span->alpha += span->alphaStep;                \
  408.        span->intTex[0] += span->intTexStep[0];            \
  409.        span->intTex[1] += span->intTexStep[1];            \
  410.            dest += 4;                            \
  411.     }
  412.  
  413.  
  414.    GLuint i;
  415.    GLchan *dest = span->array->rgba[0];
  416.  
  417.    span->intTex[0] -= FIXED_HALF;
  418.    span->intTex[1] -= FIXED_HALF;
  419.    switch (info->filter) {
  420.    case GL_NEAREST:
  421.       switch (info->format) {
  422.       case GL_RGB:
  423.          switch (info->envmode) {
  424.          case GL_MODULATE:
  425.             SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
  426.             break;
  427.          case GL_DECAL:
  428.          case GL_REPLACE:
  429.             SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
  430.             break;
  431.          case GL_BLEND:
  432.             SPAN_NEAREST(NEAREST_RGB;BLEND,3);
  433.             break;
  434.          case GL_ADD:
  435.             SPAN_NEAREST(NEAREST_RGB;ADD,3);
  436.             break;
  437.          default:
  438.             _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR");
  439.             return;
  440.          }
  441.          break;
  442.       case GL_RGBA:
  443.          switch(info->envmode) {
  444.          case GL_MODULATE:
  445.             SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
  446.             break;
  447.          case GL_DECAL:
  448.             SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
  449.             break;
  450.          case GL_BLEND:
  451.             SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
  452.             break;
  453.          case GL_ADD:
  454.             SPAN_NEAREST(NEAREST_RGBA;ADD,4);
  455.             break;
  456.          case GL_REPLACE:
  457.             SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
  458.             break;
  459.          default:
  460.             _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR");
  461.             return;
  462.          }
  463.          break;
  464.       }
  465.       break;
  466.  
  467.    case GL_LINEAR:
  468.       span->intTex[0] -= FIXED_HALF;
  469.       span->intTex[1] -= FIXED_HALF;
  470.       switch (info->format) {
  471.       case GL_RGB:
  472.          switch (info->envmode) {
  473.          case GL_MODULATE:
  474.             SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
  475.             break;
  476.          case GL_DECAL:
  477.          case GL_REPLACE:
  478.             SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
  479.             break;
  480.          case GL_BLEND:
  481.             SPAN_LINEAR(LINEAR_RGB;BLEND,3);
  482.             break;
  483.          case GL_ADD:
  484.             SPAN_LINEAR(LINEAR_RGB;ADD,3);
  485.             break;
  486.          default:
  487.             _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR");
  488.             return;
  489.          }
  490.          break;
  491.       case GL_RGBA:
  492.          switch (info->envmode) {
  493.          case GL_MODULATE:
  494.             SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
  495.             break;
  496.          case GL_DECAL:
  497.             SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
  498.             break;
  499.          case GL_BLEND:
  500.             SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
  501.             break;
  502.          case GL_ADD:
  503.             SPAN_LINEAR(LINEAR_RGBA;ADD,4);
  504.             break;
  505.          case GL_REPLACE:
  506.             SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
  507.             break;
  508.          default:
  509.             _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR");
  510.             return;
  511.          }
  512.          break;
  513.       }
  514.       break;
  515.    }
  516.    span->interpMask &= ~SPAN_RGBA;
  517.    ASSERT(span->arrayMask & SPAN_RGBA);
  518.    _mesa_write_rgba_span(ctx, span);
  519.  
  520. #undef SPAN_NEAREST
  521. #undef SPAN_LINEAR
  522. }
  523.  
  524.  
  525.  
  526. /*
  527.  * Render an RGB/RGBA textured triangle without perspective correction.
  528.  */
  529. #define NAME affine_textured_triangle
  530. #define INTERP_Z 1
  531. #define INTERP_FOG 1
  532. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  533. #define INTERP_RGB 1
  534. #define INTERP_ALPHA 1
  535. #define INTERP_INT_TEX 1
  536. #define S_SCALE twidth
  537. #define T_SCALE theight
  538.  
  539. #define SETUP_CODE                            \
  540.    struct affine_info info;                        \
  541.    struct gl_texture_unit *unit = ctx->Texture.Unit+0;            \
  542.    struct gl_texture_object *obj = unit->Current2D;            \
  543.    const GLint b = obj->BaseLevel;                    \
  544.    const GLfloat twidth = (GLfloat) obj->Image[b]->Width;        \
  545.    const GLfloat theight = (GLfloat) obj->Image[b]->Height;        \
  546.    info.texture = (const GLchan *) obj->Image[b]->Data;            \
  547.    info.twidth_log2 = obj->Image[b]->WidthLog2;                \
  548.    info.smask = obj->Image[b]->Width - 1;                \
  549.    info.tmask = obj->Image[b]->Height - 1;                \
  550.    info.format = obj->Image[b]->Format;                    \
  551.    info.filter = obj->MinFilter;                    \
  552.    info.envmode = unit->EnvMode;                    \
  553.    span.arrayMask |= SPAN_RGBA;                        \
  554.                                     \
  555.    if (info.envmode == GL_BLEND) {                    \
  556.       /* potential off-by-one error here? (1.0f -> 2048 -> 0) */    \
  557.       info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF);    \
  558.       info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF);    \
  559.       info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF);    \
  560.       info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF);    \
  561.    }                                    \
  562.    if (!info.texture) {                            \
  563.       /* this shouldn't happen */                    \
  564.       return;                                \
  565.    }                                    \
  566.                                     \
  567.    switch (info.format) {                        \
  568.    case GL_ALPHA:                            \
  569.    case GL_LUMINANCE:                            \
  570.    case GL_INTENSITY:                            \
  571.       info.tbytesline = obj->Image[b]->Width;                \
  572.       break;                                \
  573.    case GL_LUMINANCE_ALPHA:                        \
  574.       info.tbytesline = obj->Image[b]->Width * 2;            \
  575.       break;                                \
  576.    case GL_RGB:                                \
  577.       info.tbytesline = obj->Image[b]->Width * 3;            \
  578.       break;                                \
  579.    case GL_RGBA:                            \
  580.       info.tbytesline = obj->Image[b]->Width * 4;            \
  581.       break;                                \
  582.    default:                                \
  583.       _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
  584.       return;                                \
  585.    }                                    \
  586.    info.tsize = obj->Image[b]->Height * info.tbytesline;
  587.  
  588. #define RENDER_SPAN( span )   affine_span(ctx, &span, &info);
  589.  
  590. #include "s_tritemp.h"
  591.  
  592.  
  593.  
  594. struct persp_info
  595. {
  596.    GLenum filter;
  597.    GLenum format;
  598.    GLenum envmode;
  599.    GLint smask, tmask;
  600.    GLint twidth_log2;
  601.    const GLchan *texture;
  602.    GLfixed er, eg, eb, ea;   /* texture env color */
  603.    GLint tbytesline, tsize;
  604. };
  605.  
  606.  
  607. static INLINE void
  608. fast_persp_span(GLcontext *ctx, struct sw_span *span,
  609.         struct persp_info *info)
  610. {
  611.    GLchan sample[4];  /* the filtered texture sample */
  612.  
  613.   /* Instead of defining a function for each mode, a test is done
  614.    * between the outer and inner loops. This is to reduce code size
  615.    * and complexity. Observe that an optimizing compiler kills
  616.    * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
  617.    */
  618. #define SPAN_NEAREST(DO_TEX,COMP)                    \
  619.     for (i = 0; i < span->end; i++) {                \
  620.            GLdouble invQ = tex_coord[2] ?                \
  621.                                  (1.0 / tex_coord[2]) : 1.0;            \
  622.            GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);        \
  623.            GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);        \
  624.            GLint s = IFLOOR(s_tmp) & info->smask;                \
  625.            GLint t = IFLOOR(t_tmp) & info->tmask;                \
  626.            GLint pos = (t << info->twidth_log2) + s;            \
  627.            const GLchan *tex00 = info->texture + COMP * pos;        \
  628.            DO_TEX;                            \
  629.            span->red += span->redStep;                    \
  630.        span->green += span->greenStep;                \
  631.            span->blue += span->blueStep;                \
  632.        span->alpha += span->alphaStep;                \
  633.        tex_coord[0] += tex_step[0];                    \
  634.        tex_coord[1] += tex_step[1];                    \
  635.        tex_coord[2] += tex_step[2];                    \
  636.            dest += 4;                            \
  637.     }
  638.  
  639. #define SPAN_LINEAR(DO_TEX,COMP)                    \
  640.     for (i = 0; i < span->end; i++) {                \
  641.            GLdouble invQ = tex_coord[2] ?                \
  642.                                  (1.0 / tex_coord[2]) : 1.0;            \
  643.            GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);        \
  644.            GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);        \
  645.            GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF;        \
  646.            GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF;            \
  647.            GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask;    \
  648.            GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask;    \
  649.            GLfixed sf = s_fix & FIXED_FRAC_MASK;            \
  650.            GLfixed tf = t_fix & FIXED_FRAC_MASK;            \
  651.            GLfixed si = FIXED_FRAC_MASK - sf;                \
  652.            GLfixed ti = FIXED_FRAC_MASK - tf;                \
  653.            GLint pos = (t << info->twidth_log2) + s;            \
  654.            const GLchan *tex00 = info->texture + COMP * pos;        \
  655.            const GLchan *tex10 = tex00 + info->tbytesline;        \
  656.            const GLchan *tex01 = tex00 + COMP;                \
  657.            const GLchan *tex11 = tex10 + COMP;                \
  658.            (void) ti;                            \
  659.            (void) si;                            \
  660.            if (t == info->tmask) {                    \
  661.               tex10 -= info->tsize;                    \
  662.               tex11 -= info->tsize;                    \
  663.            }                                \
  664.            if (s == info->smask) {                    \
  665.               tex01 -= info->tbytesline;                \
  666.               tex11 -= info->tbytesline;                \
  667.            }                                \
  668.            DO_TEX;                            \
  669.            span->red   += span->redStep;                \
  670.        span->green += span->greenStep;                \
  671.            span->blue  += span->blueStep;                \
  672.        span->alpha += span->alphaStep;                \
  673.        tex_coord[0] += tex_step[0];                    \
  674.        tex_coord[1] += tex_step[1];                    \
  675.        tex_coord[2] += tex_step[2];                    \
  676.            dest += 4;                            \
  677.     }
  678.  
  679.    GLuint i;
  680.    GLfloat tex_coord[3], tex_step[3];
  681.    GLchan *dest = span->array->rgba[0];
  682.  
  683.    tex_coord[0] = span->tex[0][0]  * (info->smask + 1);
  684.    tex_step[0] = span->texStepX[0][0] * (info->smask + 1);
  685.    tex_coord[1] = span->tex[0][1] * (info->tmask + 1);
  686.    tex_step[1] = span->texStepX[0][1] * (info->tmask + 1);
  687.    /* span->tex[0][2] only if 3D-texturing, here only 2D */
  688.    tex_coord[2] = span->tex[0][3];
  689.    tex_step[2] = span->texStepX[0][3];
  690.  
  691.    switch (info->filter) {
  692.    case GL_NEAREST:
  693.       switch (info->format) {
  694.       case GL_RGB:
  695.          switch (info->envmode) {
  696.          case GL_MODULATE:
  697.             SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
  698.             break;
  699.          case GL_DECAL:
  700.          case GL_REPLACE:
  701.             SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
  702.             break;
  703.          case GL_BLEND:
  704.             SPAN_NEAREST(NEAREST_RGB;BLEND,3);
  705.             break;
  706.          case GL_ADD:
  707.             SPAN_NEAREST(NEAREST_RGB;ADD,3);
  708.             break;
  709.          default:
  710.             _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR");
  711.             return;
  712.          }
  713.          break;
  714.       case GL_RGBA:
  715.          switch(info->envmode) {
  716.          case GL_MODULATE:
  717.             SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
  718.             break;
  719.          case GL_DECAL:
  720.             SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
  721.             break;
  722.          case GL_BLEND:
  723.             SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
  724.             break;
  725.          case GL_ADD:
  726.             SPAN_NEAREST(NEAREST_RGBA;ADD,4);
  727.             break;
  728.          case GL_REPLACE:
  729.             SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
  730.             break;
  731.          default:
  732.             _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR");
  733.             return;
  734.          }
  735.          break;
  736.       }
  737.       break;
  738.  
  739.    case GL_LINEAR:
  740.       switch (info->format) {
  741.       case GL_RGB:
  742.          switch (info->envmode) {
  743.          case GL_MODULATE:
  744.             SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
  745.             break;
  746.          case GL_DECAL:
  747.          case GL_REPLACE:
  748.             SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
  749.             break;
  750.          case GL_BLEND:
  751.             SPAN_LINEAR(LINEAR_RGB;BLEND,3);
  752.             break;
  753.          case GL_ADD:
  754.             SPAN_LINEAR(LINEAR_RGB;ADD,3);
  755.             break;
  756.          default:
  757.             _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR");
  758.             return;
  759.          }
  760.          break;
  761.       case GL_RGBA:
  762.          switch (info->envmode) {
  763.          case GL_MODULATE:
  764.             SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
  765.             break;
  766.          case GL_DECAL:
  767.             SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
  768.             break;
  769.          case GL_BLEND:
  770.             SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
  771.             break;
  772.          case GL_ADD:
  773.             SPAN_LINEAR(LINEAR_RGBA;ADD,4);
  774.             break;
  775.          case GL_REPLACE:
  776.             SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
  777.             break;
  778.          default:
  779.             _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR");
  780.             return;
  781.          }
  782.          break;
  783.       }
  784.       break;
  785.    }
  786.    
  787.    ASSERT(span->arrayMask & SPAN_RGBA);
  788.    _mesa_write_rgba_span(ctx, span);
  789.  
  790. #undef SPAN_NEAREST
  791. #undef SPAN_LINEAR
  792. }
  793.  
  794.  
  795. /*
  796.  * Render an perspective corrected RGB/RGBA textured triangle.
  797.  * The Q (aka V in Mesa) coordinate must be zero such that the divide
  798.  * by interpolated Q/W comes out right.
  799.  *
  800.  */
  801. #define NAME persp_textured_triangle
  802. #define INTERP_Z 1
  803. #define INTERP_FOG 1
  804. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  805. #define INTERP_RGB 1
  806. #define INTERP_ALPHA 1
  807. #define INTERP_TEX 1
  808.  
  809. #define SETUP_CODE                            \
  810.    struct persp_info info;                        \
  811.    const struct gl_texture_unit *unit = ctx->Texture.Unit+0;        \
  812.    const struct gl_texture_object *obj = unit->Current2D;        \
  813.    const GLint b = obj->BaseLevel;                    \
  814.    info.texture = (const GLchan *) obj->Image[b]->Data;            \
  815.    info.twidth_log2 = obj->Image[b]->WidthLog2;                \
  816.    info.smask = obj->Image[b]->Width - 1;                \
  817.    info.tmask = obj->Image[b]->Height - 1;                \
  818.    info.format = obj->Image[b]->Format;                    \
  819.    info.filter = obj->MinFilter;                    \
  820.    info.envmode = unit->EnvMode;                    \
  821.                                     \
  822.    if (info.envmode == GL_BLEND) {                    \
  823.       /* potential off-by-one error here? (1.0f -> 2048 -> 0) */    \
  824.       info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF);    \
  825.       info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF);    \
  826.       info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF);    \
  827.       info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF);    \
  828.    }                                    \
  829.    if (!info.texture) {                            \
  830.       /* this shouldn't happen */                    \
  831.       return;                                \
  832.    }                                    \
  833.                                     \
  834.    switch (info.format) {                        \
  835.    case GL_ALPHA:                            \
  836.    case GL_LUMINANCE:                            \
  837.    case GL_INTENSITY:                            \
  838.       info.tbytesline = obj->Image[b]->Width;                \
  839.       break;                                \
  840.    case GL_LUMINANCE_ALPHA:                        \
  841.       info.tbytesline = obj->Image[b]->Width * 2;            \
  842.       break;                                \
  843.    case GL_RGB:                                \
  844.       info.tbytesline = obj->Image[b]->Width * 3;            \
  845.       break;                                \
  846.    case GL_RGBA:                            \
  847.       info.tbytesline = obj->Image[b]->Width * 4;            \
  848.       break;                                \
  849.    default:                                \
  850.       _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\
  851.       return;                                \
  852.    }                                    \
  853.    info.tsize = obj->Image[b]->Height * info.tbytesline;
  854.  
  855. #define RENDER_SPAN( span )            \
  856.    span.interpMask &= ~SPAN_RGBA;        \
  857.    span.arrayMask |= SPAN_RGBA;            \
  858.    fast_persp_span(ctx, &span, &info);
  859.  
  860. #include "s_tritemp.h"
  861.  
  862.  
  863. #endif /* CHAN_BITS != GL_FLOAT */
  864.  
  865.                 
  866.  
  867.  
  868. /*
  869.  * Render a smooth-shaded, textured, RGBA triangle.
  870.  * Interpolate S,T,R with perspective correction, w/out mipmapping.
  871.  */
  872. #define NAME general_textured_triangle
  873. #define INTERP_Z 1
  874. #define INTERP_FOG 1
  875. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  876. #define INTERP_RGB 1
  877. #define INTERP_SPEC 1
  878. #define INTERP_ALPHA 1
  879. #define INTERP_TEX 1
  880. #define RENDER_SPAN( span )   _mesa_write_texture_span(ctx, &span);
  881. #include "s_tritemp.h"
  882.  
  883.  
  884.  
  885. /*
  886.  * This is the big one!
  887.  * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates.
  888.  * Yup, it's slow.
  889.  */
  890. #define NAME multitextured_triangle
  891. #define INTERP_Z 1
  892. #define INTERP_FOG 1
  893. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  894. #define INTERP_RGB 1
  895. #define INTERP_ALPHA 1
  896. #define INTERP_SPEC 1
  897. #define INTERP_MULTITEX 1
  898. #define RENDER_SPAN( span )   _mesa_write_texture_span(ctx, &span);
  899. #include "s_tritemp.h"
  900.  
  901.  
  902.  
  903. #define NAME occlusion_zless_triangle
  904. #define DO_OCCLUSION_TEST
  905. #define INTERP_Z 1
  906. #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
  907. #define SETUP_CODE            \
  908.    if (ctx->OcclusionResult) {        \
  909.       return;                \
  910.    }
  911. #define RENDER_SPAN( span )                \
  912.    GLuint i;                        \
  913.    for (i = 0; i < span.end; i++) {            \
  914.       GLdepth z = FixedToDepth(span.z);            \
  915.       if (z < zRow[i]) {                \
  916.          ctx->OcclusionResult = GL_TRUE;        \
  917.          return;                    \
  918.       }                            \
  919.       span.z += span.zStep;                \
  920.    }
  921. #include "s_tritemp.h"
  922.  
  923.  
  924.  
  925. static void
  926. nodraw_triangle( GLcontext *ctx,
  927.                  const SWvertex *v0,
  928.                  const SWvertex *v1,
  929.                  const SWvertex *v2 )
  930. {
  931.    (void) (ctx && v0 && v1 && v2);
  932. }
  933.  
  934.  
  935. /*
  936.  * This is used when separate specular color is enabled, but not
  937.  * texturing.  We add the specular color to the primary color,
  938.  * draw the triangle, then restore the original primary color.
  939.  * Inefficient, but seldom needed.
  940.  */
  941. void _swrast_add_spec_terms_triangle( GLcontext *ctx,
  942.                       const SWvertex *v0,
  943.                       const SWvertex *v1,
  944.                       const SWvertex *v2 )
  945. {
  946.    SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
  947.    SWvertex *ncv1 = (SWvertex *)v1;
  948.    SWvertex *ncv2 = (SWvertex *)v2;
  949. #if CHAN_TYPE == GL_FLOAT
  950.    GLfloat rSum, gSum, bSum;
  951. #else
  952.    GLint rSum, gSum, bSum;
  953. #endif
  954.    GLchan c[3][4];
  955.    /* save original colors */
  956.    COPY_CHAN4( c[0], ncv0->color );
  957.    COPY_CHAN4( c[1], ncv1->color );
  958.    COPY_CHAN4( c[2], ncv2->color );
  959.    /* sum v0 */
  960.    rSum = ncv0->color[0] + ncv0->specular[0];
  961.    gSum = ncv0->color[1] + ncv0->specular[1];
  962.    bSum = ncv0->color[2] + ncv0->specular[2];
  963.    ncv0->color[0] = MIN2(rSum, CHAN_MAX);
  964.    ncv0->color[1] = MIN2(gSum, CHAN_MAX);
  965.    ncv0->color[2] = MIN2(bSum, CHAN_MAX);
  966.    /* sum v1 */
  967.    rSum = ncv1->color[0] + ncv1->specular[0];
  968.    gSum = ncv1->color[1] + ncv1->specular[1];
  969.    bSum = ncv1->color[2] + ncv1->specular[2];
  970.    ncv1->color[0] = MIN2(rSum, CHAN_MAX);
  971.    ncv1->color[1] = MIN2(gSum, CHAN_MAX);
  972.    ncv1->color[2] = MIN2(bSum, CHAN_MAX);
  973.    /* sum v2 */
  974.    rSum = ncv2->color[0] + ncv2->specular[0];
  975.    gSum = ncv2->color[1] + ncv2->specular[1];
  976.    bSum = ncv2->color[2] + ncv2->specular[2];
  977.    ncv2->color[0] = MIN2(rSum, CHAN_MAX);
  978.    ncv2->color[1] = MIN2(gSum, CHAN_MAX);
  979.    ncv2->color[2] = MIN2(bSum, CHAN_MAX);
  980.    /* draw */
  981.    SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
  982.    /* restore original colors */
  983.    COPY_CHAN4( ncv0->color, c[0] );
  984.    COPY_CHAN4( ncv1->color, c[1] );
  985.    COPY_CHAN4( ncv2->color, c[2] );
  986. }
  987.  
  988.  
  989.  
  990. #ifdef DEBUG
  991.  
  992. /* record the current triangle function name */
  993. const char *_mesa_triFuncName = NULL;
  994.  
  995. #define USE(triFunc)                \
  996. do {                        \
  997.     _mesa_triFuncName = #triFunc;        \
  998.     /*printf("%s\n", _mesa_triFuncName);*/    \
  999.     swrast->Triangle = triFunc;            \
  1000. } while (0)
  1001.  
  1002. #else
  1003.  
  1004. #define USE(triFunc)  swrast->Triangle = triFunc;
  1005.  
  1006. #endif
  1007.  
  1008.  
  1009.  
  1010.  
  1011. /*
  1012.  * Determine which triangle rendering function to use given the current
  1013.  * rendering context.
  1014.  *
  1015.  * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
  1016.  * remove tests to this code.
  1017.  */
  1018. void
  1019. _swrast_choose_triangle( GLcontext *ctx )
  1020. {
  1021.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1022.    const GLboolean rgbmode = ctx->Visual.rgbMode;
  1023.  
  1024.    if (ctx->Polygon.CullFlag &&
  1025.        ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
  1026.       USE(nodraw_triangle);
  1027.       return;
  1028.    }
  1029.  
  1030.    if (ctx->RenderMode==GL_RENDER) {
  1031.  
  1032.       if (ctx->Polygon.SmoothFlag) {
  1033.          _mesa_set_aa_triangle_function(ctx);
  1034.          ASSERT(swrast->Triangle);
  1035.          return;
  1036.       }
  1037.  
  1038.       if (ctx->Depth.OcclusionTest &&
  1039.           ctx->Depth.Test &&
  1040.           ctx->Depth.Mask == GL_FALSE &&
  1041.           ctx->Depth.Func == GL_LESS &&
  1042.           !ctx->Stencil.Enabled) {
  1043.          if ((rgbmode &&
  1044.               ctx->Color.ColorMask[0] == 0 &&
  1045.               ctx->Color.ColorMask[1] == 0 &&
  1046.               ctx->Color.ColorMask[2] == 0 &&
  1047.               ctx->Color.ColorMask[3] == 0)
  1048.              ||
  1049.              (!rgbmode && ctx->Color.IndexMask == 0)) {
  1050.             USE(occlusion_zless_triangle);
  1051.             return;
  1052.          }
  1053.       }
  1054.  
  1055.       if (ctx->Texture._EnabledUnits) {
  1056.          /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
  1057.      const struct gl_texture_object *texObj2D;
  1058.          const struct gl_texture_image *texImg;
  1059.          GLenum minFilter, magFilter, envMode;
  1060.          GLint format;
  1061.          texObj2D = ctx->Texture.Unit[0].Current2D;
  1062.          texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL;
  1063.          format = texImg ? texImg->TexFormat->MesaFormat : -1;
  1064.          minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
  1065.          magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0;
  1066.          envMode = ctx->Texture.Unit[0].EnvMode;
  1067.  
  1068.          /* First see if we can used an optimized 2-D texture function */
  1069.          if (ctx->Texture._EnabledUnits == 1
  1070.              && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
  1071.              && texObj2D->WrapS==GL_REPEAT
  1072.          && texObj2D->WrapT==GL_REPEAT
  1073.              && texImg->Border==0
  1074.              && texImg->Width == texImg->RowStride
  1075.              && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA)
  1076.          && minFilter == magFilter
  1077.          && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
  1078.          && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
  1079.         if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
  1080.            if (minFilter == GL_NEAREST
  1081.            && format == MESA_FORMAT_RGB
  1082.            && (envMode == GL_REPLACE || envMode == GL_DECAL)
  1083.            && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
  1084.             && ctx->Depth.Func == GL_LESS
  1085.             && ctx->Depth.Mask == GL_TRUE)
  1086.                || swrast->_RasterMask == TEXTURE_BIT)
  1087.            && ctx->Polygon.StippleFlag == GL_FALSE) {
  1088.           if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
  1089.              USE(simple_z_textured_triangle);
  1090.           }
  1091.           else {
  1092.              USE(simple_textured_triangle);
  1093.           }
  1094.            }
  1095.            else {
  1096. #if (CHAN_BITS == 16 || CHAN_BITS == 32)
  1097.                   USE(general_textured_triangle);
  1098. #else
  1099.                   USE(affine_textured_triangle);
  1100. #endif
  1101.            }
  1102.         }
  1103.         else {
  1104. #if (CHAN_BITS == 16 || CHAN_BITS == 32)
  1105.                USE(general_textured_triangle);
  1106. #else
  1107.                USE(persp_textured_triangle);
  1108. #endif
  1109.         }
  1110.      }
  1111.          else {
  1112.             /* general case textured triangles */
  1113.             if (ctx->Texture._EnabledUnits > 1) {
  1114.                USE(multitextured_triangle);
  1115.             }
  1116.             else {
  1117.                USE(general_textured_triangle);
  1118.             }
  1119.          }
  1120.       }
  1121.       else {
  1122.          ASSERT(!ctx->Texture._EnabledUnits);
  1123.      if (ctx->Light.ShadeModel==GL_SMOOTH) {
  1124.         /* smooth shaded, no texturing, stippled or some raster ops */
  1125.             if (rgbmode) {
  1126.            USE(smooth_rgba_triangle);
  1127.             }
  1128.             else {
  1129.                USE(smooth_ci_triangle);
  1130.             }
  1131.      }
  1132.      else {
  1133.         /* flat shaded, no texturing, stippled or some raster ops */
  1134.             if (rgbmode) {
  1135.            USE(flat_rgba_triangle);
  1136.             }
  1137.             else {
  1138.                USE(flat_ci_triangle);
  1139.             }
  1140.      }
  1141.       }
  1142.    }
  1143.    else if (ctx->RenderMode==GL_FEEDBACK) {
  1144.       USE(_mesa_feedback_triangle);
  1145.    }
  1146.    else {
  1147.       /* GL_SELECT mode */
  1148.       USE(_mesa_select_triangle);
  1149.    }
  1150. }
  1151.