17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 47117f1b4Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 57117f1b4Smrg * 67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 87117f1b4Smrg * to deal in the Software without restriction, including without limitation 97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 117117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 127117f1b4Smrg * 137117f1b4Smrg * The above copyright notice and this permission notice shall be included 147117f1b4Smrg * in all copies or substantial portions of the Software. 157117f1b4Smrg * 167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 237117f1b4Smrg */ 247117f1b4Smrg 257117f1b4Smrg 267117f1b4Smrg/* 277117f1b4Smrg * When the device driver doesn't implement triangle rasterization it 287117f1b4Smrg * can hook in _swrast_Triangle, which eventually calls one of these 297117f1b4Smrg * functions to draw triangles. 307117f1b4Smrg */ 317117f1b4Smrg 32c1f859d4Smrg#include "main/glheader.h" 33c1f859d4Smrg#include "main/context.h" 347ec681f3Smrg 35c1f859d4Smrg#include "main/macros.h" 363464ebd5Sriastradh#include "main/mtypes.h" 373464ebd5Sriastradh#include "main/state.h" 38af69d88dSmrg#include "main/samplerobj.h" 3901e04c3fSmrg#include "main/stencil.h" 4001e04c3fSmrg#include "main/teximage.h" 413464ebd5Sriastradh#include "program/prog_instruction.h" 427117f1b4Smrg 437117f1b4Smrg#include "s_aatriangle.h" 447117f1b4Smrg#include "s_context.h" 457117f1b4Smrg#include "s_feedback.h" 467117f1b4Smrg#include "s_span.h" 477117f1b4Smrg#include "s_triangle.h" 487117f1b4Smrg 497117f1b4Smrg 504a49301eSmrg/** 514a49301eSmrg * Test if a triangle should be culled. Used for feedback and selection mode. 524a49301eSmrg * \return GL_TRUE if the triangle is to be culled, GL_FALSE otherwise. 537117f1b4Smrg */ 547117f1b4SmrgGLboolean 553464ebd5Sriastradh_swrast_culltriangle( struct gl_context *ctx, 567117f1b4Smrg const SWvertex *v0, 577117f1b4Smrg const SWvertex *v1, 587117f1b4Smrg const SWvertex *v2 ) 597117f1b4Smrg{ 604a49301eSmrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 61af69d88dSmrg GLfloat ex = v1->attrib[VARYING_SLOT_POS][0] - v0->attrib[VARYING_SLOT_POS][0]; 62af69d88dSmrg GLfloat ey = v1->attrib[VARYING_SLOT_POS][1] - v0->attrib[VARYING_SLOT_POS][1]; 63af69d88dSmrg GLfloat fx = v2->attrib[VARYING_SLOT_POS][0] - v0->attrib[VARYING_SLOT_POS][0]; 64af69d88dSmrg GLfloat fy = v2->attrib[VARYING_SLOT_POS][1] - v0->attrib[VARYING_SLOT_POS][1]; 657117f1b4Smrg GLfloat c = ex*fy-ey*fx; 667117f1b4Smrg 674a49301eSmrg if (c * swrast->_BackfaceSign * swrast->_BackfaceCullSign <= 0.0F) 684a49301eSmrg return GL_FALSE; 697117f1b4Smrg 704a49301eSmrg return GL_TRUE; 717117f1b4Smrg} 727117f1b4Smrg 737117f1b4Smrg 747117f1b4Smrg 757117f1b4Smrg/* 767117f1b4Smrg * Render a flat-shaded RGBA triangle. 777117f1b4Smrg */ 787117f1b4Smrg#define NAME flat_rgba_triangle 797117f1b4Smrg#define INTERP_Z 1 807117f1b4Smrg#define SETUP_CODE \ 8101e04c3fSmrg assert(ctx->Texture._EnabledCoordUnits == 0);\ 8201e04c3fSmrg assert(ctx->Light.ShadeModel==GL_FLAT); \ 837117f1b4Smrg span.interpMask |= SPAN_RGBA; \ 847117f1b4Smrg span.red = ChanToFixed(v2->color[0]); \ 857117f1b4Smrg span.green = ChanToFixed(v2->color[1]); \ 867117f1b4Smrg span.blue = ChanToFixed(v2->color[2]); \ 877117f1b4Smrg span.alpha = ChanToFixed(v2->color[3]); \ 887117f1b4Smrg span.redStep = 0; \ 897117f1b4Smrg span.greenStep = 0; \ 907117f1b4Smrg span.blueStep = 0; \ 917117f1b4Smrg span.alphaStep = 0; 927117f1b4Smrg#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); 937117f1b4Smrg#include "s_tritemp.h" 947117f1b4Smrg 957117f1b4Smrg 967117f1b4Smrg 977117f1b4Smrg/* 987117f1b4Smrg * Render a smooth-shaded RGBA triangle. 997117f1b4Smrg */ 1007117f1b4Smrg#define NAME smooth_rgba_triangle 1017117f1b4Smrg#define INTERP_Z 1 1027117f1b4Smrg#define INTERP_RGB 1 1037117f1b4Smrg#define INTERP_ALPHA 1 1047117f1b4Smrg#define SETUP_CODE \ 1057117f1b4Smrg { \ 1067117f1b4Smrg /* texturing must be off */ \ 10701e04c3fSmrg assert(ctx->Texture._EnabledCoordUnits == 0); \ 10801e04c3fSmrg assert(ctx->Light.ShadeModel==GL_SMOOTH); \ 1097117f1b4Smrg } 1107117f1b4Smrg#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); 1117117f1b4Smrg#include "s_tritemp.h" 1127117f1b4Smrg 1137117f1b4Smrg 1147117f1b4Smrg 1157117f1b4Smrg/* 1167117f1b4Smrg * Render an RGB, GL_DECAL, textured triangle. 1177117f1b4Smrg * Interpolate S,T only w/out mipmapping or perspective correction. 1187117f1b4Smrg * 1197117f1b4Smrg * No fog. No depth testing. 1207117f1b4Smrg */ 1217117f1b4Smrg#define NAME simple_textured_triangle 1227117f1b4Smrg#define INTERP_INT_TEX 1 1237117f1b4Smrg#define S_SCALE twidth 1247117f1b4Smrg#define T_SCALE theight 1257117f1b4Smrg 1267117f1b4Smrg#define SETUP_CODE \ 127c1f859d4Smrg struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \ 1284a49301eSmrg const struct gl_texture_object *obj = \ 129c1f859d4Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 1304a49301eSmrg const struct gl_texture_image *texImg = \ 13101e04c3fSmrg _mesa_base_tex_image(obj); \ 132af69d88dSmrg const struct swrast_texture_image *swImg = \ 133af69d88dSmrg swrast_texture_image_const(texImg); \ 1344a49301eSmrg const GLfloat twidth = (GLfloat) texImg->Width; \ 1354a49301eSmrg const GLfloat theight = (GLfloat) texImg->Height; \ 1364a49301eSmrg const GLint twidth_log2 = texImg->WidthLog2; \ 137af69d88dSmrg const GLubyte *texture = (const GLubyte *) swImg->ImageSlices[0]; \ 1384a49301eSmrg const GLint smask = texImg->Width - 1; \ 1394a49301eSmrg const GLint tmask = texImg->Height - 1; \ 14001e04c3fSmrg assert(texImg->TexFormat == MESA_FORMAT_BGR_UNORM8); \ 141c1f859d4Smrg if (!rb || !texture) { \ 1427117f1b4Smrg return; \ 1437117f1b4Smrg } 1447117f1b4Smrg 1457117f1b4Smrg#define RENDER_SPAN( span ) \ 1467117f1b4Smrg GLuint i; \ 147af69d88dSmrg GLubyte (*rgba)[4] = swrast->SpanArrays->rgba8; \ 1487117f1b4Smrg span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 1497117f1b4Smrg span.intTex[1] -= FIXED_HALF; \ 1507117f1b4Smrg for (i = 0; i < span.end; i++) { \ 1517117f1b4Smrg GLint s = FixedToInt(span.intTex[0]) & smask; \ 1527117f1b4Smrg GLint t = FixedToInt(span.intTex[1]) & tmask; \ 1537117f1b4Smrg GLint pos = (t << twidth_log2) + s; \ 1547117f1b4Smrg pos = pos + pos + pos; /* multiply by 3 */ \ 155af69d88dSmrg rgba[i][RCOMP] = texture[pos+2]; \ 156af69d88dSmrg rgba[i][GCOMP] = texture[pos+1]; \ 157af69d88dSmrg rgba[i][BCOMP] = texture[pos+0]; \ 158af69d88dSmrg rgba[i][ACOMP] = 0xff; \ 1597117f1b4Smrg span.intTex[0] += span.intTexStep[0]; \ 1607117f1b4Smrg span.intTex[1] += span.intTexStep[1]; \ 1617117f1b4Smrg } \ 162af69d88dSmrg _swrast_put_row(ctx, rb, GL_UNSIGNED_BYTE, span.end, \ 163af69d88dSmrg span.x, span.y, rgba, NULL); 1647117f1b4Smrg 1657117f1b4Smrg#include "s_tritemp.h" 1667117f1b4Smrg 1677117f1b4Smrg 1687117f1b4Smrg 1697117f1b4Smrg/* 1707117f1b4Smrg * Render an RGB, GL_DECAL, textured triangle. 1717117f1b4Smrg * Interpolate S,T, GL_LESS depth test, w/out mipmapping or 1727117f1b4Smrg * perspective correction. 1737117f1b4Smrg * Depth buffer bits must be <= sizeof(DEFAULT_SOFTWARE_DEPTH_TYPE) 1747117f1b4Smrg * 1757117f1b4Smrg * No fog. 1767117f1b4Smrg */ 1777117f1b4Smrg#define NAME simple_z_textured_triangle 1787117f1b4Smrg#define INTERP_Z 1 1797117f1b4Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1807117f1b4Smrg#define INTERP_INT_TEX 1 1817117f1b4Smrg#define S_SCALE twidth 1827117f1b4Smrg#define T_SCALE theight 1837117f1b4Smrg 1847117f1b4Smrg#define SETUP_CODE \ 185c1f859d4Smrg struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \ 1864a49301eSmrg const struct gl_texture_object *obj = \ 187c1f859d4Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 1884a49301eSmrg const struct gl_texture_image *texImg = \ 18901e04c3fSmrg _mesa_base_tex_image(obj); \ 190af69d88dSmrg const struct swrast_texture_image *swImg = \ 191af69d88dSmrg swrast_texture_image_const(texImg); \ 1924a49301eSmrg const GLfloat twidth = (GLfloat) texImg->Width; \ 1934a49301eSmrg const GLfloat theight = (GLfloat) texImg->Height; \ 1944a49301eSmrg const GLint twidth_log2 = texImg->WidthLog2; \ 195af69d88dSmrg const GLubyte *texture = (const GLubyte *) swImg->ImageSlices[0]; \ 1964a49301eSmrg const GLint smask = texImg->Width - 1; \ 1974a49301eSmrg const GLint tmask = texImg->Height - 1; \ 19801e04c3fSmrg assert(texImg->TexFormat == MESA_FORMAT_BGR_UNORM8); \ 199c1f859d4Smrg if (!rb || !texture) { \ 2007117f1b4Smrg return; \ 2017117f1b4Smrg } 2027117f1b4Smrg 2037117f1b4Smrg#define RENDER_SPAN( span ) \ 2047117f1b4Smrg GLuint i; \ 205af69d88dSmrg GLubyte (*rgba)[4] = swrast->SpanArrays->rgba8; \ 206af69d88dSmrg GLubyte *mask = swrast->SpanArrays->mask; \ 2077117f1b4Smrg span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 2087117f1b4Smrg span.intTex[1] -= FIXED_HALF; \ 2097117f1b4Smrg for (i = 0; i < span.end; i++) { \ 2107117f1b4Smrg const GLuint z = FixedToDepth(span.z); \ 2117117f1b4Smrg if (z < zRow[i]) { \ 2127117f1b4Smrg GLint s = FixedToInt(span.intTex[0]) & smask; \ 2137117f1b4Smrg GLint t = FixedToInt(span.intTex[1]) & tmask; \ 2147117f1b4Smrg GLint pos = (t << twidth_log2) + s; \ 2157117f1b4Smrg pos = pos + pos + pos; /* multiply by 3 */ \ 216af69d88dSmrg rgba[i][RCOMP] = texture[pos+2]; \ 217af69d88dSmrg rgba[i][GCOMP] = texture[pos+1]; \ 218af69d88dSmrg rgba[i][BCOMP] = texture[pos+0]; \ 219af69d88dSmrg rgba[i][ACOMP] = 0xff; \ 2207117f1b4Smrg zRow[i] = z; \ 221af69d88dSmrg mask[i] = 1; \ 2227117f1b4Smrg } \ 2237117f1b4Smrg else { \ 224af69d88dSmrg mask[i] = 0; \ 2257117f1b4Smrg } \ 2267117f1b4Smrg span.intTex[0] += span.intTexStep[0]; \ 2277117f1b4Smrg span.intTex[1] += span.intTexStep[1]; \ 2287117f1b4Smrg span.z += span.zStep; \ 2297117f1b4Smrg } \ 230af69d88dSmrg _swrast_put_row(ctx, rb, GL_UNSIGNED_BYTE, \ 231af69d88dSmrg span.end, span.x, span.y, rgba, mask); 2327117f1b4Smrg 2337117f1b4Smrg#include "s_tritemp.h" 2347117f1b4Smrg 2357117f1b4Smrg 2367117f1b4Smrg#if CHAN_TYPE != GL_FLOAT 2377117f1b4Smrg 2387117f1b4Smrgstruct affine_info 2397117f1b4Smrg{ 2407117f1b4Smrg GLenum filter; 2417117f1b4Smrg GLenum format; 2427117f1b4Smrg GLenum envmode; 2437117f1b4Smrg GLint smask, tmask; 2447117f1b4Smrg GLint twidth_log2; 2457117f1b4Smrg const GLchan *texture; 2467117f1b4Smrg GLfixed er, eg, eb, ea; 2477117f1b4Smrg GLint tbytesline, tsize; 2487117f1b4Smrg}; 2497117f1b4Smrg 2507117f1b4Smrg 251af69d88dSmrgstatic inline GLint 2527117f1b4Smrgilerp(GLint t, GLint a, GLint b) 2537117f1b4Smrg{ 2547117f1b4Smrg return a + ((t * (b - a)) >> FIXED_SHIFT); 2557117f1b4Smrg} 2567117f1b4Smrg 257af69d88dSmrgstatic inline GLint 2587117f1b4Smrgilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11) 2597117f1b4Smrg{ 2607117f1b4Smrg const GLint temp0 = ilerp(ia, v00, v10); 2617117f1b4Smrg const GLint temp1 = ilerp(ia, v01, v11); 2627117f1b4Smrg return ilerp(ib, temp0, temp1); 2637117f1b4Smrg} 2647117f1b4Smrg 2657117f1b4Smrg 2667117f1b4Smrg/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA 2677117f1b4Smrg * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD 2687117f1b4Smrg * texture env modes. 2697117f1b4Smrg */ 270af69d88dSmrgstatic inline void 2713464ebd5Sriastradhaffine_span(struct gl_context *ctx, SWspan *span, 2727117f1b4Smrg struct affine_info *info) 2737117f1b4Smrg{ 2747117f1b4Smrg GLchan sample[4]; /* the filtered texture sample */ 2754a49301eSmrg const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits; 2767117f1b4Smrg 2777117f1b4Smrg /* Instead of defining a function for each mode, a test is done 2787117f1b4Smrg * between the outer and inner loops. This is to reduce code size 2797117f1b4Smrg * and complexity. Observe that an optimizing compiler kills 2807117f1b4Smrg * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 2817117f1b4Smrg */ 2827117f1b4Smrg 2834a49301eSmrg#define NEAREST_RGB \ 2844a49301eSmrg sample[RCOMP] = tex00[2]; \ 2854a49301eSmrg sample[GCOMP] = tex00[1]; \ 2864a49301eSmrg sample[BCOMP] = tex00[0]; \ 2874a49301eSmrg sample[ACOMP] = CHAN_MAX; 2887117f1b4Smrg 2897117f1b4Smrg#define LINEAR_RGB \ 2904a49301eSmrg sample[RCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\ 2917117f1b4Smrg sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\ 2924a49301eSmrg sample[BCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\ 2937117f1b4Smrg sample[ACOMP] = CHAN_MAX; 2947117f1b4Smrg 2954a49301eSmrg#define NEAREST_RGBA \ 2964a49301eSmrg sample[RCOMP] = tex00[3]; \ 2974a49301eSmrg sample[GCOMP] = tex00[2]; \ 2984a49301eSmrg sample[BCOMP] = tex00[1]; \ 2994a49301eSmrg sample[ACOMP] = tex00[0]; 3007117f1b4Smrg 3017117f1b4Smrg#define LINEAR_RGBA \ 3024a49301eSmrg sample[RCOMP] = ilerp_2d(sf, tf, tex00[3], tex01[3], tex10[3], tex11[3]);\ 3034a49301eSmrg sample[GCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\ 3044a49301eSmrg sample[BCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\ 3054a49301eSmrg sample[ACOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]) 3067117f1b4Smrg 3077117f1b4Smrg#define MODULATE \ 3087117f1b4Smrg dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 3097117f1b4Smrg dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 3107117f1b4Smrg dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 3117117f1b4Smrg dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8) 3127117f1b4Smrg 3137117f1b4Smrg#define DECAL \ 3147117f1b4Smrg dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \ 3157117f1b4Smrg ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \ 3167117f1b4Smrg >> (FIXED_SHIFT + 8); \ 3177117f1b4Smrg dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \ 3187117f1b4Smrg ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \ 3197117f1b4Smrg >> (FIXED_SHIFT + 8); \ 3207117f1b4Smrg dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \ 3217117f1b4Smrg ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \ 3227117f1b4Smrg >> (FIXED_SHIFT + 8); \ 3237117f1b4Smrg dest[ACOMP] = FixedToInt(span->alpha) 3247117f1b4Smrg 3257117f1b4Smrg#define BLEND \ 3267117f1b4Smrg dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \ 3277117f1b4Smrg + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \ 3287117f1b4Smrg dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \ 3297117f1b4Smrg + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \ 3307117f1b4Smrg dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \ 3317117f1b4Smrg + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \ 3327117f1b4Smrg dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8) 3337117f1b4Smrg 3347117f1b4Smrg#define REPLACE COPY_CHAN4(dest, sample) 3357117f1b4Smrg 3367117f1b4Smrg#define ADD \ 3377117f1b4Smrg { \ 3387117f1b4Smrg GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \ 3397117f1b4Smrg GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \ 3407117f1b4Smrg GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \ 3417117f1b4Smrg dest[RCOMP] = MIN2(rSum, CHAN_MAX); \ 3427117f1b4Smrg dest[GCOMP] = MIN2(gSum, CHAN_MAX); \ 3437117f1b4Smrg dest[BCOMP] = MIN2(bSum, CHAN_MAX); \ 3447117f1b4Smrg dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \ 3457117f1b4Smrg } 3467117f1b4Smrg 3477117f1b4Smrg/* shortcuts */ 3487117f1b4Smrg 3497117f1b4Smrg#define NEAREST_RGB_REPLACE \ 3507117f1b4Smrg NEAREST_RGB; \ 3517117f1b4Smrg dest[0] = sample[0]; \ 3527117f1b4Smrg dest[1] = sample[1]; \ 3537117f1b4Smrg dest[2] = sample[2]; \ 3547117f1b4Smrg dest[3] = FixedToInt(span->alpha); 3557117f1b4Smrg 3564a49301eSmrg#define NEAREST_RGBA_REPLACE \ 3574a49301eSmrg dest[RCOMP] = tex00[3]; \ 3584a49301eSmrg dest[GCOMP] = tex00[2]; \ 3594a49301eSmrg dest[BCOMP] = tex00[1]; \ 3604a49301eSmrg dest[ACOMP] = tex00[0] 3617117f1b4Smrg 3627117f1b4Smrg#define SPAN_NEAREST(DO_TEX, COMPS) \ 3637117f1b4Smrg for (i = 0; i < span->end; i++) { \ 3647117f1b4Smrg /* Isn't it necessary to use FixedFloor below?? */ \ 3657117f1b4Smrg GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 3667117f1b4Smrg GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 3677117f1b4Smrg GLint pos = (t << info->twidth_log2) + s; \ 3687117f1b4Smrg const GLchan *tex00 = info->texture + COMPS * pos; \ 3697117f1b4Smrg DO_TEX; \ 3707117f1b4Smrg span->red += span->redStep; \ 3717117f1b4Smrg span->green += span->greenStep; \ 3727117f1b4Smrg span->blue += span->blueStep; \ 3737117f1b4Smrg span->alpha += span->alphaStep; \ 3747117f1b4Smrg span->intTex[0] += span->intTexStep[0]; \ 3757117f1b4Smrg span->intTex[1] += span->intTexStep[1]; \ 3767117f1b4Smrg dest += 4; \ 3777117f1b4Smrg } 3787117f1b4Smrg 3797117f1b4Smrg#define SPAN_LINEAR(DO_TEX, COMPS) \ 3807117f1b4Smrg for (i = 0; i < span->end; i++) { \ 3817117f1b4Smrg /* Isn't it necessary to use FixedFloor below?? */ \ 3827117f1b4Smrg const GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 3837117f1b4Smrg const GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 3847117f1b4Smrg const GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ 3857117f1b4Smrg const GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ 3867117f1b4Smrg const GLint pos = (t << info->twidth_log2) + s; \ 3877117f1b4Smrg const GLchan *tex00 = info->texture + COMPS * pos; \ 3887117f1b4Smrg const GLchan *tex10 = tex00 + info->tbytesline; \ 3897117f1b4Smrg const GLchan *tex01 = tex00 + COMPS; \ 3907117f1b4Smrg const GLchan *tex11 = tex10 + COMPS; \ 3917117f1b4Smrg if (t == info->tmask) { \ 3927117f1b4Smrg tex10 -= info->tsize; \ 3937117f1b4Smrg tex11 -= info->tsize; \ 3947117f1b4Smrg } \ 3957117f1b4Smrg if (s == info->smask) { \ 3967117f1b4Smrg tex01 -= info->tbytesline; \ 3977117f1b4Smrg tex11 -= info->tbytesline; \ 3987117f1b4Smrg } \ 3997117f1b4Smrg DO_TEX; \ 4007117f1b4Smrg span->red += span->redStep; \ 4017117f1b4Smrg span->green += span->greenStep; \ 4027117f1b4Smrg span->blue += span->blueStep; \ 4037117f1b4Smrg span->alpha += span->alphaStep; \ 4047117f1b4Smrg span->intTex[0] += span->intTexStep[0]; \ 4057117f1b4Smrg span->intTex[1] += span->intTexStep[1]; \ 4067117f1b4Smrg dest += 4; \ 4077117f1b4Smrg } 4087117f1b4Smrg 4097117f1b4Smrg 4107117f1b4Smrg GLuint i; 4117117f1b4Smrg GLchan *dest = span->array->rgba[0]; 4127117f1b4Smrg 413c1f859d4Smrg /* Disable tex units so they're not re-applied in swrast_write_rgba_span */ 4144a49301eSmrg ctx->Texture._EnabledCoordUnits = 0x0; 415c1f859d4Smrg 4167117f1b4Smrg span->intTex[0] -= FIXED_HALF; 4177117f1b4Smrg span->intTex[1] -= FIXED_HALF; 4187117f1b4Smrg switch (info->filter) { 4197117f1b4Smrg case GL_NEAREST: 4207117f1b4Smrg switch (info->format) { 421af69d88dSmrg case MESA_FORMAT_BGR_UNORM8: 4227117f1b4Smrg switch (info->envmode) { 4237117f1b4Smrg case GL_MODULATE: 4247117f1b4Smrg SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 4257117f1b4Smrg break; 4267117f1b4Smrg case GL_DECAL: 4277117f1b4Smrg case GL_REPLACE: 4287117f1b4Smrg SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 4297117f1b4Smrg break; 4307117f1b4Smrg case GL_BLEND: 4317117f1b4Smrg SPAN_NEAREST(NEAREST_RGB;BLEND,3); 4327117f1b4Smrg break; 4337117f1b4Smrg case GL_ADD: 4347117f1b4Smrg SPAN_NEAREST(NEAREST_RGB;ADD,3); 4357117f1b4Smrg break; 4367117f1b4Smrg default: 4377117f1b4Smrg _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR"); 4387117f1b4Smrg return; 4397117f1b4Smrg } 4407117f1b4Smrg break; 441af69d88dSmrg case MESA_FORMAT_A8B8G8R8_UNORM: 4427117f1b4Smrg switch(info->envmode) { 4437117f1b4Smrg case GL_MODULATE: 4447117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 4457117f1b4Smrg break; 4467117f1b4Smrg case GL_DECAL: 4477117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 4487117f1b4Smrg break; 4497117f1b4Smrg case GL_BLEND: 4507117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 4517117f1b4Smrg break; 4527117f1b4Smrg case GL_ADD: 4537117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;ADD,4); 4547117f1b4Smrg break; 4557117f1b4Smrg case GL_REPLACE: 4567117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 4577117f1b4Smrg break; 4587117f1b4Smrg default: 4597117f1b4Smrg _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR"); 4607117f1b4Smrg return; 4617117f1b4Smrg } 4627117f1b4Smrg break; 4637117f1b4Smrg } 4647117f1b4Smrg break; 4657117f1b4Smrg 4667117f1b4Smrg case GL_LINEAR: 4677117f1b4Smrg span->intTex[0] -= FIXED_HALF; 4687117f1b4Smrg span->intTex[1] -= FIXED_HALF; 4697117f1b4Smrg switch (info->format) { 470af69d88dSmrg case MESA_FORMAT_BGR_UNORM8: 4717117f1b4Smrg switch (info->envmode) { 4727117f1b4Smrg case GL_MODULATE: 4737117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 4747117f1b4Smrg break; 4757117f1b4Smrg case GL_DECAL: 4767117f1b4Smrg case GL_REPLACE: 4777117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 4787117f1b4Smrg break; 4797117f1b4Smrg case GL_BLEND: 4807117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;BLEND,3); 4817117f1b4Smrg break; 4827117f1b4Smrg case GL_ADD: 4837117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;ADD,3); 4847117f1b4Smrg break; 4857117f1b4Smrg default: 4867117f1b4Smrg _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR"); 4877117f1b4Smrg return; 4887117f1b4Smrg } 4897117f1b4Smrg break; 490af69d88dSmrg case MESA_FORMAT_A8B8G8R8_UNORM: 4917117f1b4Smrg switch (info->envmode) { 4927117f1b4Smrg case GL_MODULATE: 4937117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 4947117f1b4Smrg break; 4957117f1b4Smrg case GL_DECAL: 4967117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 4977117f1b4Smrg break; 4987117f1b4Smrg case GL_BLEND: 4997117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 5007117f1b4Smrg break; 5017117f1b4Smrg case GL_ADD: 5027117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;ADD,4); 5037117f1b4Smrg break; 5047117f1b4Smrg case GL_REPLACE: 5057117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 5067117f1b4Smrg break; 5077117f1b4Smrg default: 5087117f1b4Smrg _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR"); 5097117f1b4Smrg return; 5107117f1b4Smrg } 5117117f1b4Smrg break; 5127117f1b4Smrg } 5137117f1b4Smrg break; 5147117f1b4Smrg } 5157117f1b4Smrg span->interpMask &= ~SPAN_RGBA; 51601e04c3fSmrg assert(span->arrayMask & SPAN_RGBA); 517c1f859d4Smrg 5187117f1b4Smrg _swrast_write_rgba_span(ctx, span); 5197117f1b4Smrg 520c1f859d4Smrg /* re-enable texture units */ 5214a49301eSmrg ctx->Texture._EnabledCoordUnits = texEnableSave; 522c1f859d4Smrg 5237117f1b4Smrg#undef SPAN_NEAREST 5247117f1b4Smrg#undef SPAN_LINEAR 5257117f1b4Smrg} 5267117f1b4Smrg 5277117f1b4Smrg 5287117f1b4Smrg 5297117f1b4Smrg/* 5307117f1b4Smrg * Render an RGB/RGBA textured triangle without perspective correction. 5317117f1b4Smrg */ 5327117f1b4Smrg#define NAME affine_textured_triangle 5337117f1b4Smrg#define INTERP_Z 1 5347117f1b4Smrg#define INTERP_RGB 1 5357117f1b4Smrg#define INTERP_ALPHA 1 5367117f1b4Smrg#define INTERP_INT_TEX 1 5377117f1b4Smrg#define S_SCALE twidth 5387117f1b4Smrg#define T_SCALE theight 5397117f1b4Smrg 5407117f1b4Smrg#define SETUP_CODE \ 5417117f1b4Smrg struct affine_info info; \ 54201e04c3fSmrg struct gl_fixedfunc_texture_unit *unit = ctx->Texture.FixedFuncUnit+0; \ 5434a49301eSmrg const struct gl_texture_object *obj = \ 544c1f859d4Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 5454a49301eSmrg const struct gl_texture_image *texImg = \ 54601e04c3fSmrg _mesa_base_tex_image(obj); \ 547af69d88dSmrg const struct swrast_texture_image *swImg = \ 548af69d88dSmrg swrast_texture_image_const(texImg); \ 5494a49301eSmrg const GLfloat twidth = (GLfloat) texImg->Width; \ 5504a49301eSmrg const GLfloat theight = (GLfloat) texImg->Height; \ 551af69d88dSmrg info.texture = (const GLchan *) swImg->ImageSlices[0]; \ 5524a49301eSmrg info.twidth_log2 = texImg->WidthLog2; \ 5534a49301eSmrg info.smask = texImg->Width - 1; \ 5544a49301eSmrg info.tmask = texImg->Height - 1; \ 5554a49301eSmrg info.format = texImg->TexFormat; \ 5567ec681f3Smrg info.filter = obj->Sampler.Attrib.MinFilter; \ 5577117f1b4Smrg info.envmode = unit->EnvMode; \ 5584a49301eSmrg info.er = 0; \ 5594a49301eSmrg info.eg = 0; \ 5604a49301eSmrg info.eb = 0; \ 5617117f1b4Smrg span.arrayMask |= SPAN_RGBA; \ 5627117f1b4Smrg \ 5637117f1b4Smrg if (info.envmode == GL_BLEND) { \ 5647117f1b4Smrg /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 5657117f1b4Smrg info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ 5667117f1b4Smrg info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ 5677117f1b4Smrg info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ 5687117f1b4Smrg info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ 5697117f1b4Smrg } \ 5707117f1b4Smrg if (!info.texture) { \ 5717117f1b4Smrg /* this shouldn't happen */ \ 5727117f1b4Smrg return; \ 5737117f1b4Smrg } \ 5747117f1b4Smrg \ 5757117f1b4Smrg switch (info.format) { \ 576af69d88dSmrg case MESA_FORMAT_BGR_UNORM8: \ 5774a49301eSmrg info.tbytesline = texImg->Width * 3; \ 5787117f1b4Smrg break; \ 579af69d88dSmrg case MESA_FORMAT_A8B8G8R8_UNORM: \ 5804a49301eSmrg info.tbytesline = texImg->Width * 4; \ 5817117f1b4Smrg break; \ 5827117f1b4Smrg default: \ 5837117f1b4Smrg _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 5847117f1b4Smrg return; \ 5857117f1b4Smrg } \ 5864a49301eSmrg info.tsize = texImg->Height * info.tbytesline; 5877117f1b4Smrg 5887117f1b4Smrg#define RENDER_SPAN( span ) affine_span(ctx, &span, &info); 5897117f1b4Smrg 5907117f1b4Smrg#include "s_tritemp.h" 5917117f1b4Smrg 5927117f1b4Smrg 5937117f1b4Smrg 5947117f1b4Smrgstruct persp_info 5957117f1b4Smrg{ 5967117f1b4Smrg GLenum filter; 5977117f1b4Smrg GLenum format; 5987117f1b4Smrg GLenum envmode; 5997117f1b4Smrg GLint smask, tmask; 6007117f1b4Smrg GLint twidth_log2; 6017117f1b4Smrg const GLchan *texture; 6027117f1b4Smrg GLfixed er, eg, eb, ea; /* texture env color */ 6037117f1b4Smrg GLint tbytesline, tsize; 6047117f1b4Smrg}; 6057117f1b4Smrg 6067117f1b4Smrg 607af69d88dSmrgstatic inline void 6083464ebd5Sriastradhfast_persp_span(struct gl_context *ctx, SWspan *span, 6097117f1b4Smrg struct persp_info *info) 6107117f1b4Smrg{ 6117117f1b4Smrg GLchan sample[4]; /* the filtered texture sample */ 6127117f1b4Smrg 6137117f1b4Smrg /* Instead of defining a function for each mode, a test is done 6147117f1b4Smrg * between the outer and inner loops. This is to reduce code size 6157117f1b4Smrg * and complexity. Observe that an optimizing compiler kills 6167117f1b4Smrg * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 6177117f1b4Smrg */ 6187117f1b4Smrg#define SPAN_NEAREST(DO_TEX,COMP) \ 6197117f1b4Smrg for (i = 0; i < span->end; i++) { \ 6207117f1b4Smrg GLdouble invQ = tex_coord[2] ? \ 6217117f1b4Smrg (1.0 / tex_coord[2]) : 1.0; \ 6227117f1b4Smrg GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 6237117f1b4Smrg GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 6247ec681f3Smrg GLint s = util_ifloor(s_tmp) & info->smask; \ 6257ec681f3Smrg GLint t = util_ifloor(t_tmp) & info->tmask; \ 6267117f1b4Smrg GLint pos = (t << info->twidth_log2) + s; \ 6277117f1b4Smrg const GLchan *tex00 = info->texture + COMP * pos; \ 6287117f1b4Smrg DO_TEX; \ 6297117f1b4Smrg span->red += span->redStep; \ 6307117f1b4Smrg span->green += span->greenStep; \ 6317117f1b4Smrg span->blue += span->blueStep; \ 6327117f1b4Smrg span->alpha += span->alphaStep; \ 6337117f1b4Smrg tex_coord[0] += tex_step[0]; \ 6347117f1b4Smrg tex_coord[1] += tex_step[1]; \ 6357117f1b4Smrg tex_coord[2] += tex_step[2]; \ 6367117f1b4Smrg dest += 4; \ 6377117f1b4Smrg } 6387117f1b4Smrg 6397117f1b4Smrg#define SPAN_LINEAR(DO_TEX,COMP) \ 6407117f1b4Smrg for (i = 0; i < span->end; i++) { \ 6417117f1b4Smrg GLdouble invQ = tex_coord[2] ? \ 6427117f1b4Smrg (1.0 / tex_coord[2]) : 1.0; \ 6437117f1b4Smrg const GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 6447117f1b4Smrg const GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 6457117f1b4Smrg const GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \ 6467117f1b4Smrg const GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \ 6477117f1b4Smrg const GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ 6487117f1b4Smrg const GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ 6497117f1b4Smrg const GLfixed sf = s_fix & FIXED_FRAC_MASK; \ 6507117f1b4Smrg const GLfixed tf = t_fix & FIXED_FRAC_MASK; \ 6517117f1b4Smrg const GLint pos = (t << info->twidth_log2) + s; \ 6527117f1b4Smrg const GLchan *tex00 = info->texture + COMP * pos; \ 6537117f1b4Smrg const GLchan *tex10 = tex00 + info->tbytesline; \ 6547117f1b4Smrg const GLchan *tex01 = tex00 + COMP; \ 6557117f1b4Smrg const GLchan *tex11 = tex10 + COMP; \ 6567117f1b4Smrg if (t == info->tmask) { \ 6577117f1b4Smrg tex10 -= info->tsize; \ 6587117f1b4Smrg tex11 -= info->tsize; \ 6597117f1b4Smrg } \ 6607117f1b4Smrg if (s == info->smask) { \ 6617117f1b4Smrg tex01 -= info->tbytesline; \ 6627117f1b4Smrg tex11 -= info->tbytesline; \ 6637117f1b4Smrg } \ 6647117f1b4Smrg DO_TEX; \ 6657117f1b4Smrg span->red += span->redStep; \ 6667117f1b4Smrg span->green += span->greenStep; \ 6677117f1b4Smrg span->blue += span->blueStep; \ 6687117f1b4Smrg span->alpha += span->alphaStep; \ 6697117f1b4Smrg tex_coord[0] += tex_step[0]; \ 6707117f1b4Smrg tex_coord[1] += tex_step[1]; \ 6717117f1b4Smrg tex_coord[2] += tex_step[2]; \ 6727117f1b4Smrg dest += 4; \ 6737117f1b4Smrg } 6747117f1b4Smrg 6757117f1b4Smrg GLuint i; 6767117f1b4Smrg GLfloat tex_coord[3], tex_step[3]; 6777117f1b4Smrg GLchan *dest = span->array->rgba[0]; 6787117f1b4Smrg 6794a49301eSmrg const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits; 6804a49301eSmrg ctx->Texture._EnabledCoordUnits = 0; 6817117f1b4Smrg 682af69d88dSmrg tex_coord[0] = span->attrStart[VARYING_SLOT_TEX0][0] * (info->smask + 1); 683af69d88dSmrg tex_step[0] = span->attrStepX[VARYING_SLOT_TEX0][0] * (info->smask + 1); 684af69d88dSmrg tex_coord[1] = span->attrStart[VARYING_SLOT_TEX0][1] * (info->tmask + 1); 685af69d88dSmrg tex_step[1] = span->attrStepX[VARYING_SLOT_TEX0][1] * (info->tmask + 1); 686af69d88dSmrg /* span->attrStart[VARYING_SLOT_TEX0][2] only if 3D-texturing, here only 2D */ 687af69d88dSmrg tex_coord[2] = span->attrStart[VARYING_SLOT_TEX0][3]; 688af69d88dSmrg tex_step[2] = span->attrStepX[VARYING_SLOT_TEX0][3]; 6897117f1b4Smrg 6907117f1b4Smrg switch (info->filter) { 6917117f1b4Smrg case GL_NEAREST: 6927117f1b4Smrg switch (info->format) { 693af69d88dSmrg case MESA_FORMAT_BGR_UNORM8: 6947117f1b4Smrg switch (info->envmode) { 6957117f1b4Smrg case GL_MODULATE: 6967117f1b4Smrg SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 6977117f1b4Smrg break; 6987117f1b4Smrg case GL_DECAL: 6997117f1b4Smrg case GL_REPLACE: 7007117f1b4Smrg SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 7017117f1b4Smrg break; 7027117f1b4Smrg case GL_BLEND: 7037117f1b4Smrg SPAN_NEAREST(NEAREST_RGB;BLEND,3); 7047117f1b4Smrg break; 7057117f1b4Smrg case GL_ADD: 7067117f1b4Smrg SPAN_NEAREST(NEAREST_RGB;ADD,3); 7077117f1b4Smrg break; 7087117f1b4Smrg default: 7097117f1b4Smrg _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR"); 7107117f1b4Smrg return; 7117117f1b4Smrg } 7127117f1b4Smrg break; 713af69d88dSmrg case MESA_FORMAT_A8B8G8R8_UNORM: 7147117f1b4Smrg switch(info->envmode) { 7157117f1b4Smrg case GL_MODULATE: 7167117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 7177117f1b4Smrg break; 7187117f1b4Smrg case GL_DECAL: 7197117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 7207117f1b4Smrg break; 7217117f1b4Smrg case GL_BLEND: 7227117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 7237117f1b4Smrg break; 7247117f1b4Smrg case GL_ADD: 7257117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA;ADD,4); 7267117f1b4Smrg break; 7277117f1b4Smrg case GL_REPLACE: 7287117f1b4Smrg SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 7297117f1b4Smrg break; 7307117f1b4Smrg default: 7317117f1b4Smrg _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR"); 7327117f1b4Smrg return; 7337117f1b4Smrg } 7347117f1b4Smrg break; 7357117f1b4Smrg } 7367117f1b4Smrg break; 7377117f1b4Smrg 7387117f1b4Smrg case GL_LINEAR: 7397117f1b4Smrg switch (info->format) { 740af69d88dSmrg case MESA_FORMAT_BGR_UNORM8: 7417117f1b4Smrg switch (info->envmode) { 7427117f1b4Smrg case GL_MODULATE: 7437117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 7447117f1b4Smrg break; 7457117f1b4Smrg case GL_DECAL: 7467117f1b4Smrg case GL_REPLACE: 7477117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 7487117f1b4Smrg break; 7497117f1b4Smrg case GL_BLEND: 7507117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;BLEND,3); 7517117f1b4Smrg break; 7527117f1b4Smrg case GL_ADD: 7537117f1b4Smrg SPAN_LINEAR(LINEAR_RGB;ADD,3); 7547117f1b4Smrg break; 7557117f1b4Smrg default: 7567117f1b4Smrg _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR"); 7577117f1b4Smrg return; 7587117f1b4Smrg } 7597117f1b4Smrg break; 760af69d88dSmrg case MESA_FORMAT_A8B8G8R8_UNORM: 7617117f1b4Smrg switch (info->envmode) { 7627117f1b4Smrg case GL_MODULATE: 7637117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 7647117f1b4Smrg break; 7657117f1b4Smrg case GL_DECAL: 7667117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 7677117f1b4Smrg break; 7687117f1b4Smrg case GL_BLEND: 7697117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 7707117f1b4Smrg break; 7717117f1b4Smrg case GL_ADD: 7727117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;ADD,4); 7737117f1b4Smrg break; 7747117f1b4Smrg case GL_REPLACE: 7757117f1b4Smrg SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 7767117f1b4Smrg break; 7777117f1b4Smrg default: 7787117f1b4Smrg _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR"); 7797117f1b4Smrg return; 7807117f1b4Smrg } 7817117f1b4Smrg break; 7827117f1b4Smrg } 7837117f1b4Smrg break; 7847117f1b4Smrg } 7857ec681f3Smrg 78601e04c3fSmrg assert(span->arrayMask & SPAN_RGBA); 7877117f1b4Smrg _swrast_write_rgba_span(ctx, span); 7887117f1b4Smrg 7897117f1b4Smrg#undef SPAN_NEAREST 7907117f1b4Smrg#undef SPAN_LINEAR 7917117f1b4Smrg 7927117f1b4Smrg /* restore state */ 7934a49301eSmrg ctx->Texture._EnabledCoordUnits = texEnableSave; 7947117f1b4Smrg} 7957117f1b4Smrg 7967117f1b4Smrg 7977117f1b4Smrg/* 7987117f1b4Smrg * Render an perspective corrected RGB/RGBA textured triangle. 7997117f1b4Smrg * The Q (aka V in Mesa) coordinate must be zero such that the divide 8007117f1b4Smrg * by interpolated Q/W comes out right. 8017117f1b4Smrg * 8027117f1b4Smrg */ 8037117f1b4Smrg#define NAME persp_textured_triangle 8047117f1b4Smrg#define INTERP_Z 1 8057117f1b4Smrg#define INTERP_RGB 1 8067117f1b4Smrg#define INTERP_ALPHA 1 8077117f1b4Smrg#define INTERP_ATTRIBS 1 8087117f1b4Smrg 8097117f1b4Smrg#define SETUP_CODE \ 8107117f1b4Smrg struct persp_info info; \ 81101e04c3fSmrg const struct gl_fixedfunc_texture_unit *unit = ctx->Texture.FixedFuncUnit+0; \ 8124a49301eSmrg const struct gl_texture_object *obj = \ 813c1f859d4Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 8144a49301eSmrg const struct gl_texture_image *texImg = \ 81501e04c3fSmrg _mesa_base_tex_image(obj); \ 816af69d88dSmrg const struct swrast_texture_image *swImg = \ 817af69d88dSmrg swrast_texture_image_const(texImg); \ 818af69d88dSmrg info.texture = (const GLchan *) swImg->ImageSlices[0]; \ 8194a49301eSmrg info.twidth_log2 = texImg->WidthLog2; \ 8204a49301eSmrg info.smask = texImg->Width - 1; \ 8214a49301eSmrg info.tmask = texImg->Height - 1; \ 8224a49301eSmrg info.format = texImg->TexFormat; \ 8237ec681f3Smrg info.filter = obj->Sampler.Attrib.MinFilter; \ 8247117f1b4Smrg info.envmode = unit->EnvMode; \ 8254a49301eSmrg info.er = 0; \ 8264a49301eSmrg info.eg = 0; \ 8274a49301eSmrg info.eb = 0; \ 8287117f1b4Smrg \ 8297117f1b4Smrg if (info.envmode == GL_BLEND) { \ 8307117f1b4Smrg /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 8317117f1b4Smrg info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ 8327117f1b4Smrg info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ 8337117f1b4Smrg info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ 8347117f1b4Smrg info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ 8357117f1b4Smrg } \ 8367117f1b4Smrg if (!info.texture) { \ 8377117f1b4Smrg /* this shouldn't happen */ \ 8387117f1b4Smrg return; \ 8397117f1b4Smrg } \ 8407117f1b4Smrg \ 8417117f1b4Smrg switch (info.format) { \ 842af69d88dSmrg case MESA_FORMAT_BGR_UNORM8: \ 8434a49301eSmrg info.tbytesline = texImg->Width * 3; \ 8447117f1b4Smrg break; \ 845af69d88dSmrg case MESA_FORMAT_A8B8G8R8_UNORM: \ 8464a49301eSmrg info.tbytesline = texImg->Width * 4; \ 8477117f1b4Smrg break; \ 8487117f1b4Smrg default: \ 8497117f1b4Smrg _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\ 8507117f1b4Smrg return; \ 8517117f1b4Smrg } \ 8524a49301eSmrg info.tsize = texImg->Height * info.tbytesline; 8537117f1b4Smrg 8547117f1b4Smrg#define RENDER_SPAN( span ) \ 8557117f1b4Smrg span.interpMask &= ~SPAN_RGBA; \ 8567117f1b4Smrg span.arrayMask |= SPAN_RGBA; \ 8577117f1b4Smrg fast_persp_span(ctx, &span, &info); 8587117f1b4Smrg 8597117f1b4Smrg#include "s_tritemp.h" 8607117f1b4Smrg 861c1f859d4Smrg#endif /*CHAN_TYPE != GL_FLOAT*/ 8627117f1b4Smrg 8637117f1b4Smrg 8647117f1b4Smrg 8657117f1b4Smrg/* 8667117f1b4Smrg * Render an RGBA triangle with arbitrary attributes. 8677117f1b4Smrg */ 8687117f1b4Smrg#define NAME general_triangle 8697117f1b4Smrg#define INTERP_Z 1 8707117f1b4Smrg#define INTERP_RGB 1 8717117f1b4Smrg#define INTERP_ALPHA 1 8727117f1b4Smrg#define INTERP_ATTRIBS 1 8737117f1b4Smrg#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); 8747117f1b4Smrg#include "s_tritemp.h" 8757117f1b4Smrg 8767117f1b4Smrg 8777117f1b4Smrg 8787117f1b4Smrg 8797117f1b4Smrg/* 8807117f1b4Smrg * Special tri function for occlusion testing 8817117f1b4Smrg */ 882af69d88dSmrg#define NAME occlusion_zless_16_triangle 8837117f1b4Smrg#define INTERP_Z 1 8847117f1b4Smrg#define SETUP_CODE \ 885af69d88dSmrg struct gl_renderbuffer *rb = \ 886af69d88dSmrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; \ 8877117f1b4Smrg struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; \ 88801e04c3fSmrg assert(ctx->Depth.Test); \ 88901e04c3fSmrg assert(!ctx->Depth.Mask); \ 89001e04c3fSmrg assert(ctx->Depth.Func == GL_LESS); \ 891af69d88dSmrg assert(rb->Format == MESA_FORMAT_Z_UNORM16); \ 8927117f1b4Smrg if (!q) { \ 8937117f1b4Smrg return; \ 8947117f1b4Smrg } 8957117f1b4Smrg#define RENDER_SPAN( span ) \ 896af69d88dSmrg { \ 8977117f1b4Smrg GLuint i; \ 8987117f1b4Smrg const GLushort *zRow = (const GLushort *) \ 899af69d88dSmrg _swrast_pixel_address(rb, span.x, span.y); \ 9007117f1b4Smrg for (i = 0; i < span.end; i++) { \ 9017117f1b4Smrg GLuint z = FixedToDepth(span.z); \ 9027117f1b4Smrg if (z < zRow[i]) { \ 9037117f1b4Smrg q->Result++; \ 9047117f1b4Smrg } \ 9057117f1b4Smrg span.z += span.zStep; \ 9067117f1b4Smrg } \ 9077117f1b4Smrg } 9087117f1b4Smrg#include "s_tritemp.h" 9097117f1b4Smrg 9107117f1b4Smrg 9117117f1b4Smrg 9127117f1b4Smrgstatic void 9133464ebd5Sriastradhnodraw_triangle( struct gl_context *ctx, 9147117f1b4Smrg const SWvertex *v0, 9157117f1b4Smrg const SWvertex *v1, 9167117f1b4Smrg const SWvertex *v2 ) 9177117f1b4Smrg{ 9187117f1b4Smrg (void) (ctx && v0 && v1 && v2); 9197117f1b4Smrg} 9207117f1b4Smrg 9217117f1b4Smrg 9227117f1b4Smrg/* 9237117f1b4Smrg * This is used when separate specular color is enabled, but not 9247117f1b4Smrg * texturing. We add the specular color to the primary color, 9257117f1b4Smrg * draw the triangle, then restore the original primary color. 9267117f1b4Smrg * Inefficient, but seldom needed. 9277117f1b4Smrg */ 928c1f859d4Smrgvoid 9293464ebd5Sriastradh_swrast_add_spec_terms_triangle(struct gl_context *ctx, const SWvertex *v0, 930c1f859d4Smrg const SWvertex *v1, const SWvertex *v2) 9317117f1b4Smrg{ 9327117f1b4Smrg SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ 9337117f1b4Smrg SWvertex *ncv1 = (SWvertex *)v1; 9347117f1b4Smrg SWvertex *ncv2 = (SWvertex *)v2; 9357117f1b4Smrg GLfloat rSum, gSum, bSum; 936c1f859d4Smrg GLchan cSave[3][4]; 937c1f859d4Smrg 9387117f1b4Smrg /* save original colors */ 939c1f859d4Smrg COPY_CHAN4( cSave[0], ncv0->color ); 940c1f859d4Smrg COPY_CHAN4( cSave[1], ncv1->color ); 941c1f859d4Smrg COPY_CHAN4( cSave[2], ncv2->color ); 9427117f1b4Smrg /* sum v0 */ 943af69d88dSmrg rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0]; 944af69d88dSmrg gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1]; 945af69d88dSmrg bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2]; 946c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum); 947c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum); 948c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum); 9497117f1b4Smrg /* sum v1 */ 950af69d88dSmrg rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[VARYING_SLOT_COL1][0]; 951af69d88dSmrg gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[VARYING_SLOT_COL1][1]; 952af69d88dSmrg bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[VARYING_SLOT_COL1][2]; 953c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum); 954c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum); 955c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum); 9567117f1b4Smrg /* sum v2 */ 957af69d88dSmrg rSum = CHAN_TO_FLOAT(ncv2->color[0]) + ncv2->attrib[VARYING_SLOT_COL1][0]; 958af69d88dSmrg gSum = CHAN_TO_FLOAT(ncv2->color[1]) + ncv2->attrib[VARYING_SLOT_COL1][1]; 959af69d88dSmrg bSum = CHAN_TO_FLOAT(ncv2->color[2]) + ncv2->attrib[VARYING_SLOT_COL1][2]; 960c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[0], rSum); 961c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[1], gSum); 962c1f859d4Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[2], bSum); 9637117f1b4Smrg /* draw */ 9647117f1b4Smrg SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); 9657117f1b4Smrg /* restore original colors */ 966c1f859d4Smrg COPY_CHAN4( ncv0->color, cSave[0] ); 967c1f859d4Smrg COPY_CHAN4( ncv1->color, cSave[1] ); 968c1f859d4Smrg COPY_CHAN4( ncv2->color, cSave[2] ); 9697117f1b4Smrg} 9707117f1b4Smrg 9717117f1b4Smrg 9727117f1b4Smrg 9737117f1b4Smrg#ifdef DEBUG 9747117f1b4Smrg 9757117f1b4Smrg/* record the current triangle function name */ 9767117f1b4Smrgconst char *_mesa_triFuncName = NULL; 9777117f1b4Smrg 9787117f1b4Smrg#define USE(triFunc) \ 9797117f1b4Smrgdo { \ 9807117f1b4Smrg _mesa_triFuncName = #triFunc; \ 9817117f1b4Smrg /*printf("%s\n", _mesa_triFuncName);*/ \ 9827117f1b4Smrg swrast->Triangle = triFunc; \ 9837117f1b4Smrg} while (0) 9847117f1b4Smrg 9857117f1b4Smrg#else 9867117f1b4Smrg 9877117f1b4Smrg#define USE(triFunc) swrast->Triangle = triFunc; 9887117f1b4Smrg 9897117f1b4Smrg#endif 9907117f1b4Smrg 9917117f1b4Smrg 9927117f1b4Smrg 9937117f1b4Smrg 9947117f1b4Smrg/* 9957117f1b4Smrg * Determine which triangle rendering function to use given the current 9967117f1b4Smrg * rendering context. 9977117f1b4Smrg * 9987117f1b4Smrg * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 9997117f1b4Smrg * remove tests to this code. 10007117f1b4Smrg */ 10017117f1b4Smrgvoid 10023464ebd5Sriastradh_swrast_choose_triangle( struct gl_context *ctx ) 10037117f1b4Smrg{ 10047117f1b4Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 10057117f1b4Smrg 10067117f1b4Smrg if (ctx->Polygon.CullFlag && 10077117f1b4Smrg ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 10087117f1b4Smrg USE(nodraw_triangle); 10097117f1b4Smrg return; 10107117f1b4Smrg } 10117117f1b4Smrg 10127117f1b4Smrg if (ctx->RenderMode==GL_RENDER) { 1013af69d88dSmrg struct gl_renderbuffer *depthRb = 1014af69d88dSmrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 10157117f1b4Smrg 10167117f1b4Smrg if (ctx->Polygon.SmoothFlag) { 10177117f1b4Smrg _swrast_set_aa_triangle_function(ctx); 101801e04c3fSmrg assert(swrast->Triangle); 10197117f1b4Smrg return; 10207117f1b4Smrg } 10217117f1b4Smrg 10227117f1b4Smrg /* special case for occlusion testing */ 10237117f1b4Smrg if (ctx->Query.CurrentOcclusionObject && 10247117f1b4Smrg ctx->Depth.Test && 10257117f1b4Smrg ctx->Depth.Mask == GL_FALSE && 10267117f1b4Smrg ctx->Depth.Func == GL_LESS && 102701e04c3fSmrg !_mesa_stencil_is_enabled(ctx) && 1028af69d88dSmrg depthRb && 1029af69d88dSmrg depthRb->Format == MESA_FORMAT_Z_UNORM16) { 103001e04c3fSmrg if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0) == 0 && 103101e04c3fSmrg GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1) == 0 && 103201e04c3fSmrg GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2) == 0 && 103301e04c3fSmrg GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) == 0) { 1034af69d88dSmrg USE(occlusion_zless_16_triangle); 10357117f1b4Smrg return; 10367117f1b4Smrg } 10377117f1b4Smrg } 10387117f1b4Smrg 1039c1f859d4Smrg /* 1040c1f859d4Smrg * XXX should examine swrast->_ActiveAttribMask to determine what 1041c1f859d4Smrg * needs to be interpolated. 1042c1f859d4Smrg */ 10437117f1b4Smrg if (ctx->Texture._EnabledCoordUnits || 1044af69d88dSmrg _swrast_use_fragment_program(ctx) || 104501e04c3fSmrg _mesa_ati_fragment_shader_enabled(ctx) || 10463464ebd5Sriastradh _mesa_need_secondary_color(ctx) || 1047c1f859d4Smrg swrast->_FogEnabled) { 10487117f1b4Smrg /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 10497117f1b4Smrg const struct gl_texture_object *texObj2D; 1050af69d88dSmrg const struct gl_sampler_object *samp; 10517117f1b4Smrg const struct gl_texture_image *texImg; 1052af69d88dSmrg const struct swrast_texture_image *swImg; 10537117f1b4Smrg GLenum minFilter, magFilter, envMode; 1054af69d88dSmrg mesa_format format; 1055c1f859d4Smrg texObj2D = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; 1056af69d88dSmrg if (ctx->Texture.Unit[0].Sampler) 1057af69d88dSmrg samp = ctx->Texture.Unit[0].Sampler; 1058af69d88dSmrg else if (texObj2D) 1059af69d88dSmrg samp = &texObj2D->Sampler; 1060af69d88dSmrg else 1061af69d88dSmrg samp = NULL; 1062c1f859d4Smrg 106301e04c3fSmrg texImg = texObj2D ? _mesa_base_tex_image(texObj2D) : NULL; 1064af69d88dSmrg swImg = swrast_texture_image_const(texImg); 1065af69d88dSmrg 10664a49301eSmrg format = texImg ? texImg->TexFormat : MESA_FORMAT_NONE; 10677ec681f3Smrg minFilter = texObj2D ? samp->Attrib.MinFilter : GL_NONE; 10687ec681f3Smrg magFilter = texObj2D ? samp->Attrib.MagFilter : GL_NONE; 106901e04c3fSmrg envMode = ctx->Texture.FixedFuncUnit[0].EnvMode; 10707117f1b4Smrg 10717117f1b4Smrg /* First see if we can use an optimized 2-D texture function */ 10727117f1b4Smrg if (ctx->Texture._EnabledCoordUnits == 0x1 1073af69d88dSmrg && !_swrast_use_fragment_program(ctx) 107401e04c3fSmrg && !_mesa_ati_fragment_shader_enabled(ctx) 1075af69d88dSmrg && ctx->Texture._MaxEnabledTexImageUnit == 0 1076af69d88dSmrg && ctx->Texture.Unit[0]._Current->Target == GL_TEXTURE_2D 10777ec681f3Smrg && samp->Attrib.WrapS == GL_REPEAT 10787ec681f3Smrg && samp->Attrib.WrapT == GL_REPEAT 10797ec681f3Smrg && texObj2D->Attrib._Swizzle == SWIZZLE_NOOP 1080af69d88dSmrg && swImg->_IsPowerOfTwo 10817117f1b4Smrg && texImg->Border == 0 1082af69d88dSmrg && (_mesa_format_row_stride(format, texImg->Width) == 1083af69d88dSmrg swImg->RowStride) 1084af69d88dSmrg && (format == MESA_FORMAT_BGR_UNORM8 || format == MESA_FORMAT_A8B8G8R8_UNORM) 10857117f1b4Smrg && minFilter == magFilter 10867117f1b4Smrg && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR 1087c1f859d4Smrg && !swrast->_FogEnabled 108801e04c3fSmrg && ctx->Texture.FixedFuncUnit[0].EnvMode != GL_COMBINE_EXT 108901e04c3fSmrg && ctx->Texture.FixedFuncUnit[0].EnvMode != GL_COMBINE4_NV) { 10907117f1b4Smrg if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 10917117f1b4Smrg if (minFilter == GL_NEAREST 1092af69d88dSmrg && format == MESA_FORMAT_BGR_UNORM8 10937117f1b4Smrg && (envMode == GL_REPLACE || envMode == GL_DECAL) 10947117f1b4Smrg && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) 10957117f1b4Smrg && ctx->Depth.Func == GL_LESS 10967117f1b4Smrg && ctx->Depth.Mask == GL_TRUE) 10977117f1b4Smrg || swrast->_RasterMask == TEXTURE_BIT) 10987117f1b4Smrg && ctx->Polygon.StippleFlag == GL_FALSE 10997117f1b4Smrg && ctx->DrawBuffer->Visual.depthBits <= 16) { 11007117f1b4Smrg if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { 11017117f1b4Smrg USE(simple_z_textured_triangle); 11027117f1b4Smrg } 11037117f1b4Smrg else { 11047117f1b4Smrg USE(simple_textured_triangle); 11057117f1b4Smrg } 11067117f1b4Smrg } 11077117f1b4Smrg else { 1108c1f859d4Smrg#if CHAN_BITS != 8 11097117f1b4Smrg USE(general_triangle); 11107117f1b4Smrg#else 11117ec681f3Smrg if (format == MESA_FORMAT_A8B8G8R8_UNORM && !UTIL_ARCH_LITTLE_ENDIAN) { 11124a49301eSmrg /* We only handle RGBA8888 correctly on little endian 11134a49301eSmrg * in the optimized code above. 11144a49301eSmrg */ 11154a49301eSmrg USE(general_triangle); 11164a49301eSmrg } 11174a49301eSmrg else { 11184a49301eSmrg USE(affine_textured_triangle); 11194a49301eSmrg } 11207117f1b4Smrg#endif 11217117f1b4Smrg } 11227117f1b4Smrg } 11237117f1b4Smrg else { 1124c1f859d4Smrg#if CHAN_BITS != 8 11257117f1b4Smrg USE(general_triangle); 11267117f1b4Smrg#else 11277117f1b4Smrg USE(persp_textured_triangle); 11287117f1b4Smrg#endif 11297117f1b4Smrg } 11307117f1b4Smrg } 11317117f1b4Smrg else { 11327117f1b4Smrg /* general case textured triangles */ 11337117f1b4Smrg USE(general_triangle); 11347117f1b4Smrg } 11357117f1b4Smrg } 11367117f1b4Smrg else { 113701e04c3fSmrg assert(!swrast->_FogEnabled); 113801e04c3fSmrg assert(!_mesa_need_secondary_color(ctx)); 11397117f1b4Smrg if (ctx->Light.ShadeModel==GL_SMOOTH) { 11407117f1b4Smrg /* smooth shaded, no texturing, stippled or some raster ops */ 1141c1f859d4Smrg#if CHAN_BITS != 8 1142c1f859d4Smrg USE(general_triangle); 1143c1f859d4Smrg#else 1144c1f859d4Smrg USE(smooth_rgba_triangle); 1145c1f859d4Smrg#endif 11467117f1b4Smrg } 11477117f1b4Smrg else { 11487117f1b4Smrg /* flat shaded, no texturing, stippled or some raster ops */ 1149c1f859d4Smrg#if CHAN_BITS != 8 1150c1f859d4Smrg USE(general_triangle); 1151c1f859d4Smrg#else 11527117f1b4Smrg USE(flat_rgba_triangle); 1153c1f859d4Smrg#endif 11547117f1b4Smrg } 11557117f1b4Smrg } 11567117f1b4Smrg } 11577117f1b4Smrg else if (ctx->RenderMode==GL_FEEDBACK) { 11587117f1b4Smrg USE(_swrast_feedback_triangle); 11597117f1b4Smrg } 11607117f1b4Smrg else { 11617117f1b4Smrg /* GL_SELECT mode */ 11627117f1b4Smrg USE(_swrast_select_triangle); 11637117f1b4Smrg } 11647117f1b4Smrg} 1165