Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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