Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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