| /* |
| * Mesa 3-D graphics library |
| * |
| * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| |
| /* |
| * When the device driver doesn't implement triangle rasterization it |
| * can hook in _swrast_Triangle, which eventually calls one of these |
| * functions to draw triangles. |
| */ |
| |
| #include "main/glheader.h" |
| #include "main/context.h" |
| #include "main/imports.h" |
| #include "main/macros.h" |
| #include "main/mtypes.h" |
| #include "main/state.h" |
| #include "main/samplerobj.h" |
| #include "main/teximage.h" |
| #include "program/prog_instruction.h" |
| |
| #include "s_aatriangle.h" |
| #include "s_context.h" |
| #include "s_feedback.h" |
| #include "s_span.h" |
| #include "s_triangle.h" |
| |
| |
| /** |
| * Test if a triangle should be culled. Used for feedback and selection mode. |
| * \return GL_TRUE if the triangle is to be culled, GL_FALSE otherwise. |
| */ |
| GLboolean |
| _swrast_culltriangle( struct gl_context *ctx, |
| const SWvertex *v0, |
| const SWvertex *v1, |
| const SWvertex *v2 ) |
| { |
| SWcontext *swrast = SWRAST_CONTEXT(ctx); |
| GLfloat ex = v1->attrib[VARYING_SLOT_POS][0] - v0->attrib[VARYING_SLOT_POS][0]; |
| GLfloat ey = v1->attrib[VARYING_SLOT_POS][1] - v0->attrib[VARYING_SLOT_POS][1]; |
| GLfloat fx = v2->attrib[VARYING_SLOT_POS][0] - v0->attrib[VARYING_SLOT_POS][0]; |
| GLfloat fy = v2->attrib[VARYING_SLOT_POS][1] - v0->attrib[VARYING_SLOT_POS][1]; |
| GLfloat c = ex*fy-ey*fx; |
| |
| if (c * swrast->_BackfaceSign * swrast->_BackfaceCullSign <= 0.0F) |
| return GL_FALSE; |
| |
| return GL_TRUE; |
| } |
| |
| |
| |
| /* |
| * Render a flat-shaded RGBA triangle. |
| */ |
| #define NAME flat_rgba_triangle |
| #define INTERP_Z 1 |
| #define SETUP_CODE \ |
| assert(ctx->Texture._EnabledCoordUnits == 0);\ |
| assert(ctx->Light.ShadeModel==GL_FLAT); \ |
| span.interpMask |= SPAN_RGBA; \ |
| span.red = ChanToFixed(v2->color[0]); \ |
| span.green = ChanToFixed(v2->color[1]); \ |
| span.blue = ChanToFixed(v2->color[2]); \ |
| span.alpha = ChanToFixed(v2->color[3]); \ |
| span.redStep = 0; \ |
| span.greenStep = 0; \ |
| span.blueStep = 0; \ |
| span.alphaStep = 0; |
| #define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); |
| #include "s_tritemp.h" |
| |
| |
| |
| /* |
| * Render a smooth-shaded RGBA triangle. |
| */ |
| #define NAME smooth_rgba_triangle |
| #define INTERP_Z 1 |
| #define INTERP_RGB 1 |
| #define INTERP_ALPHA 1 |
| #define SETUP_CODE \ |
| { \ |
| /* texturing must be off */ \ |
| assert(ctx->Texture._EnabledCoordUnits == 0); \ |
| assert(ctx->Light.ShadeModel==GL_SMOOTH); \ |
| } |
| #define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); |
| #include "s_tritemp.h" |
| |
| |
| |
| /* |
| * Render an RGB, GL_DECAL, textured triangle. |
| * Interpolate S,T only w/out mipmapping or perspective correction. |
| * |
| * No fog. No depth testing. |
| */ |
| #define NAME simple_textured_triangle |
| #define INTERP_INT_TEX 1 |
| #define S_SCALE twidth |
| #define T_SCALE theight |
| |
| #define SETUP_CODE \ |
| struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \ |
| const struct gl_texture_object *obj = \ |
| ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ |
| const struct gl_texture_image *texImg = \ |
| _mesa_base_tex_image(obj); \ |
| const struct swrast_texture_image *swImg = \ |
| swrast_texture_image_const(texImg); \ |
| const GLfloat twidth = (GLfloat) texImg->Width; \ |
| const GLfloat theight = (GLfloat) texImg->Height; \ |
| const GLint twidth_log2 = texImg->WidthLog2; \ |
| const GLubyte *texture = (const GLubyte *) swImg->ImageSlices[0]; \ |
| const GLint smask = texImg->Width - 1; \ |
| const GLint tmask = texImg->Height - 1; \ |
| assert(texImg->TexFormat == MESA_FORMAT_BGR_UNORM8); \ |
| if (!rb || !texture) { \ |
| return; \ |
| } |
| |
| #define RENDER_SPAN( span ) \ |
| GLuint i; \ |
| GLubyte (*rgba)[4] = swrast->SpanArrays->rgba8; \ |
| span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ |
| span.intTex[1] -= FIXED_HALF; \ |
| for (i = 0; i < span.end; i++) { \ |
| GLint s = FixedToInt(span.intTex[0]) & smask; \ |
| GLint t = FixedToInt(span.intTex[1]) & tmask; \ |
| GLint pos = (t << twidth_log2) + s; \ |
| pos = pos + pos + pos; /* multiply by 3 */ \ |
| rgba[i][RCOMP] = texture[pos+2]; \ |
| rgba[i][GCOMP] = texture[pos+1]; \ |
| rgba[i][BCOMP] = texture[pos+0]; \ |
| rgba[i][ACOMP] = 0xff; \ |
| span.intTex[0] += span.intTexStep[0]; \ |
| span.intTex[1] += span.intTexStep[1]; \ |
| } \ |
| _swrast_put_row(ctx, rb, GL_UNSIGNED_BYTE, span.end, \ |
| span.x, span.y, rgba, NULL); |
| |
| #include "s_tritemp.h" |
| |
| |
| |
| /* |
| * Render an RGB, GL_DECAL, textured triangle. |
| * Interpolate S,T, GL_LESS depth test, w/out mipmapping or |
| * perspective correction. |
| * Depth buffer bits must be <= sizeof(DEFAULT_SOFTWARE_DEPTH_TYPE) |
| * |
| * No fog. |
| */ |
| #define NAME simple_z_textured_triangle |
| #define INTERP_Z 1 |
| #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
| #define INTERP_INT_TEX 1 |
| #define S_SCALE twidth |
| #define T_SCALE theight |
| |
| #define SETUP_CODE \ |
| struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \ |
| const struct gl_texture_object *obj = \ |
| ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ |
| const struct gl_texture_image *texImg = \ |
| _mesa_base_tex_image(obj); \ |
| const struct swrast_texture_image *swImg = \ |
| swrast_texture_image_const(texImg); \ |
| const GLfloat twidth = (GLfloat) texImg->Width; \ |
| const GLfloat theight = (GLfloat) texImg->Height; \ |
| const GLint twidth_log2 = texImg->WidthLog2; \ |
| const GLubyte *texture = (const GLubyte *) swImg->ImageSlices[0]; \ |
| const GLint smask = texImg->Width - 1; \ |
| const GLint tmask = texImg->Height - 1; \ |
| assert(texImg->TexFormat == MESA_FORMAT_BGR_UNORM8); \ |
| if (!rb || !texture) { \ |
| return; \ |
| } |
| |
| #define RENDER_SPAN( span ) \ |
| GLuint i; \ |
| GLubyte (*rgba)[4] = swrast->SpanArrays->rgba8; \ |
| GLubyte *mask = swrast->SpanArrays->mask; \ |
| span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ |
| span.intTex[1] -= FIXED_HALF; \ |
| for (i = 0; i < span.end; i++) { \ |
| const GLuint z = FixedToDepth(span.z); \ |
| if (z < zRow[i]) { \ |
| GLint s = FixedToInt(span.intTex[0]) & smask; \ |
| GLint t = FixedToInt(span.intTex[1]) & tmask; \ |
| GLint pos = (t << twidth_log2) + s; \ |
| pos = pos + pos + pos; /* multiply by 3 */ \ |
| rgba[i][RCOMP] = texture[pos+2]; \ |
| rgba[i][GCOMP] = texture[pos+1]; \ |
| rgba[i][BCOMP] = texture[pos+0]; \ |
| rgba[i][ACOMP] = 0xff; \ |
| zRow[i] = z; \ |
| mask[i] = 1; \ |
| } \ |
| else { \ |
| mask[i] = 0; \ |
| } \ |
| span.intTex[0] += span.intTexStep[0]; \ |
| span.intTex[1] += span.intTexStep[1]; \ |
| span.z += span.zStep; \ |
| } \ |
| _swrast_put_row(ctx, rb, GL_UNSIGNED_BYTE, \ |
| span.end, span.x, span.y, rgba, mask); |
| |
| #include "s_tritemp.h" |
| |
| |
| #if CHAN_TYPE != GL_FLOAT |
| |
| struct affine_info |
| { |
| GLenum filter; |
| GLenum format; |
| GLenum envmode; |
| GLint smask, tmask; |
| GLint twidth_log2; |
| const GLchan *texture; |
| GLfixed er, eg, eb, ea; |
| GLint tbytesline, tsize; |
| }; |
| |
| |
| static inline GLint |
| ilerp(GLint t, GLint a, GLint b) |
| { |
| return a + ((t * (b - a)) >> FIXED_SHIFT); |
| } |
| |
| static inline GLint |
| ilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11) |
| { |
| const GLint temp0 = ilerp(ia, v00, v10); |
| const GLint temp1 = ilerp(ia, v01, v11); |
| return ilerp(ib, temp0, temp1); |
| } |
| |
| |
| /* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA |
| * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD |
| * texture env modes. |
| */ |
| static inline void |
| affine_span(struct gl_context *ctx, SWspan *span, |
| struct affine_info *info) |
| { |
| GLchan sample[4]; /* the filtered texture sample */ |
| const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits; |
| |
| /* Instead of defining a function for each mode, a test is done |
| * between the outer and inner loops. This is to reduce code size |
| * and complexity. Observe that an optimizing compiler kills |
| * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). |
| */ |
| |
| #define NEAREST_RGB \ |
| sample[RCOMP] = tex00[2]; \ |
| sample[GCOMP] = tex00[1]; \ |
| sample[BCOMP] = tex00[0]; \ |
| sample[ACOMP] = CHAN_MAX; |
| |
| #define LINEAR_RGB \ |
| sample[RCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\ |
| sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\ |
| sample[BCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\ |
| sample[ACOMP] = CHAN_MAX; |
| |
| #define NEAREST_RGBA \ |
| sample[RCOMP] = tex00[3]; \ |
| sample[GCOMP] = tex00[2]; \ |
| sample[BCOMP] = tex00[1]; \ |
| sample[ACOMP] = tex00[0]; |
| |
| #define LINEAR_RGBA \ |
| sample[RCOMP] = ilerp_2d(sf, tf, tex00[3], tex01[3], tex10[3], tex11[3]);\ |
| sample[GCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\ |
| sample[BCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\ |
| sample[ACOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]) |
| |
| #define MODULATE \ |
| dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \ |
| dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \ |
| dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \ |
| dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8) |
| |
| #define DECAL \ |
| dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \ |
| ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \ |
| >> (FIXED_SHIFT + 8); \ |
| dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \ |
| ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \ |
| >> (FIXED_SHIFT + 8); \ |
| dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \ |
| ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \ |
| >> (FIXED_SHIFT + 8); \ |
| dest[ACOMP] = FixedToInt(span->alpha) |
| |
| #define BLEND \ |
| dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \ |
| + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \ |
| dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \ |
| + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \ |
| dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \ |
| + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \ |
| dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8) |
| |
| #define REPLACE COPY_CHAN4(dest, sample) |
| |
| #define ADD \ |
| { \ |
| GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \ |
| GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \ |
| GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \ |
| dest[RCOMP] = MIN2(rSum, CHAN_MAX); \ |
| dest[GCOMP] = MIN2(gSum, CHAN_MAX); \ |
| dest[BCOMP] = MIN2(bSum, CHAN_MAX); \ |
| dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \ |
| } |
| |
| /* shortcuts */ |
| |
| #define NEAREST_RGB_REPLACE \ |
| NEAREST_RGB; \ |
| dest[0] = sample[0]; \ |
| dest[1] = sample[1]; \ |
| dest[2] = sample[2]; \ |
| dest[3] = FixedToInt(span->alpha); |
| |
| #define NEAREST_RGBA_REPLACE \ |
| dest[RCOMP] = tex00[3]; \ |
| dest[GCOMP] = tex00[2]; \ |
| dest[BCOMP] = tex00[1]; \ |
| dest[ACOMP] = tex00[0] |
| |
| #define SPAN_NEAREST(DO_TEX, COMPS) \ |
| for (i = 0; i < span->end; i++) { \ |
| /* Isn't it necessary to use FixedFloor below?? */ \ |
| GLint s = FixedToInt(span->intTex[0]) & info->smask; \ |
| GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ |
| GLint pos = (t << info->twidth_log2) + s; \ |
| const GLchan *tex00 = info->texture + COMPS * pos; \ |
| DO_TEX; \ |
| span->red += span->redStep; \ |
| span->green += span->greenStep; \ |
| span->blue += span->blueStep; \ |
| span->alpha += span->alphaStep; \ |
| span->intTex[0] += span->intTexStep[0]; \ |
| span->intTex[1] += span->intTexStep[1]; \ |
| dest += 4; \ |
| } |
| |
| #define SPAN_LINEAR(DO_TEX, COMPS) \ |
| for (i = 0; i < span->end; i++) { \ |
| /* Isn't it necessary to use FixedFloor below?? */ \ |
| const GLint s = FixedToInt(span->intTex[0]) & info->smask; \ |
| const GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ |
| const GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ |
| const GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ |
| const GLint pos = (t << info->twidth_log2) + s; \ |
| const GLchan *tex00 = info->texture + COMPS * pos; \ |
| const GLchan *tex10 = tex00 + info->tbytesline; \ |
| const GLchan *tex01 = tex00 + COMPS; \ |
| const GLchan *tex11 = tex10 + COMPS; \ |
| if (t == info->tmask) { \ |
| tex10 -= info->tsize; \ |
| tex11 -= info->tsize; \ |
| } \ |
| if (s == info->smask) { \ |
| tex01 -= info->tbytesline; \ |
| tex11 -= info->tbytesline; \ |
| } \ |
| DO_TEX; \ |
| span->red += span->redStep; \ |
| span->green += span->greenStep; \ |
| span->blue += span->blueStep; \ |
| span->alpha += span->alphaStep; \ |
| span->intTex[0] += span->intTexStep[0]; \ |
| span->intTex[1] += span->intTexStep[1]; \ |
| dest += 4; \ |
| } |
| |
| |
| GLuint i; |
| GLchan *dest = span->array->rgba[0]; |
| |
| /* Disable tex units so they're not re-applied in swrast_write_rgba_span */ |
| ctx->Texture._EnabledCoordUnits = 0x0; |
| |
| span->intTex[0] -= FIXED_HALF; |
| span->intTex[1] -= FIXED_HALF; |
| switch (info->filter) { |
| case GL_NEAREST: |
| switch (info->format) { |
| case MESA_FORMAT_BGR_UNORM8: |
| switch (info->envmode) { |
| case GL_MODULATE: |
| SPAN_NEAREST(NEAREST_RGB;MODULATE,3); |
| break; |
| case GL_DECAL: |
| case GL_REPLACE: |
| SPAN_NEAREST(NEAREST_RGB_REPLACE,3); |
| break; |
| case GL_BLEND: |
| SPAN_NEAREST(NEAREST_RGB;BLEND,3); |
| break; |
| case GL_ADD: |
| SPAN_NEAREST(NEAREST_RGB;ADD,3); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| case MESA_FORMAT_A8B8G8R8_UNORM: |
| switch(info->envmode) { |
| case GL_MODULATE: |
| SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); |
| break; |
| case GL_DECAL: |
| SPAN_NEAREST(NEAREST_RGBA;DECAL,4); |
| break; |
| case GL_BLEND: |
| SPAN_NEAREST(NEAREST_RGBA;BLEND,4); |
| break; |
| case GL_ADD: |
| SPAN_NEAREST(NEAREST_RGBA;ADD,4); |
| break; |
| case GL_REPLACE: |
| SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| } |
| break; |
| |
| case GL_LINEAR: |
| span->intTex[0] -= FIXED_HALF; |
| span->intTex[1] -= FIXED_HALF; |
| switch (info->format) { |
| case MESA_FORMAT_BGR_UNORM8: |
| switch (info->envmode) { |
| case GL_MODULATE: |
| SPAN_LINEAR(LINEAR_RGB;MODULATE,3); |
| break; |
| case GL_DECAL: |
| case GL_REPLACE: |
| SPAN_LINEAR(LINEAR_RGB;REPLACE,3); |
| break; |
| case GL_BLEND: |
| SPAN_LINEAR(LINEAR_RGB;BLEND,3); |
| break; |
| case GL_ADD: |
| SPAN_LINEAR(LINEAR_RGB;ADD,3); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| case MESA_FORMAT_A8B8G8R8_UNORM: |
| switch (info->envmode) { |
| case GL_MODULATE: |
| SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); |
| break; |
| case GL_DECAL: |
| SPAN_LINEAR(LINEAR_RGBA;DECAL,4); |
| break; |
| case GL_BLEND: |
| SPAN_LINEAR(LINEAR_RGBA;BLEND,4); |
| break; |
| case GL_ADD: |
| SPAN_LINEAR(LINEAR_RGBA;ADD,4); |
| break; |
| case GL_REPLACE: |
| SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| } |
| break; |
| } |
| span->interpMask &= ~SPAN_RGBA; |
| assert(span->arrayMask & SPAN_RGBA); |
| |
| _swrast_write_rgba_span(ctx, span); |
| |
| /* re-enable texture units */ |
| ctx->Texture._EnabledCoordUnits = texEnableSave; |
| |
| #undef SPAN_NEAREST |
| #undef SPAN_LINEAR |
| } |
| |
| |
| |
| /* |
| * Render an RGB/RGBA textured triangle without perspective correction. |
| */ |
| #define NAME affine_textured_triangle |
| #define INTERP_Z 1 |
| #define INTERP_RGB 1 |
| #define INTERP_ALPHA 1 |
| #define INTERP_INT_TEX 1 |
| #define S_SCALE twidth |
| #define T_SCALE theight |
| |
| #define SETUP_CODE \ |
| struct affine_info info; \ |
| struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ |
| const struct gl_texture_object *obj = \ |
| ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ |
| const struct gl_texture_image *texImg = \ |
| _mesa_base_tex_image(obj); \ |
| const struct swrast_texture_image *swImg = \ |
| swrast_texture_image_const(texImg); \ |
| const GLfloat twidth = (GLfloat) texImg->Width; \ |
| const GLfloat theight = (GLfloat) texImg->Height; \ |
| info.texture = (const GLchan *) swImg->ImageSlices[0]; \ |
| info.twidth_log2 = texImg->WidthLog2; \ |
| info.smask = texImg->Width - 1; \ |
| info.tmask = texImg->Height - 1; \ |
| info.format = texImg->TexFormat; \ |
| info.filter = obj->Sampler.MinFilter; \ |
| info.envmode = unit->EnvMode; \ |
| info.er = 0; \ |
| info.eg = 0; \ |
| info.eb = 0; \ |
| span.arrayMask |= SPAN_RGBA; \ |
| \ |
| if (info.envmode == GL_BLEND) { \ |
| /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ |
| info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ |
| info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ |
| info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ |
| info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ |
| } \ |
| if (!info.texture) { \ |
| /* this shouldn't happen */ \ |
| return; \ |
| } \ |
| \ |
| switch (info.format) { \ |
| case MESA_FORMAT_BGR_UNORM8: \ |
| info.tbytesline = texImg->Width * 3; \ |
| break; \ |
| case MESA_FORMAT_A8B8G8R8_UNORM: \ |
| info.tbytesline = texImg->Width * 4; \ |
| break; \ |
| default: \ |
| _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ |
| return; \ |
| } \ |
| info.tsize = texImg->Height * info.tbytesline; |
| |
| #define RENDER_SPAN( span ) affine_span(ctx, &span, &info); |
| |
| #include "s_tritemp.h" |
| |
| |
| |
| struct persp_info |
| { |
| GLenum filter; |
| GLenum format; |
| GLenum envmode; |
| GLint smask, tmask; |
| GLint twidth_log2; |
| const GLchan *texture; |
| GLfixed er, eg, eb, ea; /* texture env color */ |
| GLint tbytesline, tsize; |
| }; |
| |
| |
| static inline void |
| fast_persp_span(struct gl_context *ctx, SWspan *span, |
| struct persp_info *info) |
| { |
| GLchan sample[4]; /* the filtered texture sample */ |
| |
| /* Instead of defining a function for each mode, a test is done |
| * between the outer and inner loops. This is to reduce code size |
| * and complexity. Observe that an optimizing compiler kills |
| * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). |
| */ |
| #define SPAN_NEAREST(DO_TEX,COMP) \ |
| for (i = 0; i < span->end; i++) { \ |
| GLdouble invQ = tex_coord[2] ? \ |
| (1.0 / tex_coord[2]) : 1.0; \ |
| GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ |
| GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ |
| GLint s = IFLOOR(s_tmp) & info->smask; \ |
| GLint t = IFLOOR(t_tmp) & info->tmask; \ |
| GLint pos = (t << info->twidth_log2) + s; \ |
| const GLchan *tex00 = info->texture + COMP * pos; \ |
| DO_TEX; \ |
| span->red += span->redStep; \ |
| span->green += span->greenStep; \ |
| span->blue += span->blueStep; \ |
| span->alpha += span->alphaStep; \ |
| tex_coord[0] += tex_step[0]; \ |
| tex_coord[1] += tex_step[1]; \ |
| tex_coord[2] += tex_step[2]; \ |
| dest += 4; \ |
| } |
| |
| #define SPAN_LINEAR(DO_TEX,COMP) \ |
| for (i = 0; i < span->end; i++) { \ |
| GLdouble invQ = tex_coord[2] ? \ |
| (1.0 / tex_coord[2]) : 1.0; \ |
| const GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ |
| const GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ |
| const GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \ |
| const GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \ |
| const GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ |
| const GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ |
| const GLfixed sf = s_fix & FIXED_FRAC_MASK; \ |
| const GLfixed tf = t_fix & FIXED_FRAC_MASK; \ |
| const GLint pos = (t << info->twidth_log2) + s; \ |
| const GLchan *tex00 = info->texture + COMP * pos; \ |
| const GLchan *tex10 = tex00 + info->tbytesline; \ |
| const GLchan *tex01 = tex00 + COMP; \ |
| const GLchan *tex11 = tex10 + COMP; \ |
| if (t == info->tmask) { \ |
| tex10 -= info->tsize; \ |
| tex11 -= info->tsize; \ |
| } \ |
| if (s == info->smask) { \ |
| tex01 -= info->tbytesline; \ |
| tex11 -= info->tbytesline; \ |
| } \ |
| DO_TEX; \ |
| span->red += span->redStep; \ |
| span->green += span->greenStep; \ |
| span->blue += span->blueStep; \ |
| span->alpha += span->alphaStep; \ |
| tex_coord[0] += tex_step[0]; \ |
| tex_coord[1] += tex_step[1]; \ |
| tex_coord[2] += tex_step[2]; \ |
| dest += 4; \ |
| } |
| |
| GLuint i; |
| GLfloat tex_coord[3], tex_step[3]; |
| GLchan *dest = span->array->rgba[0]; |
| |
| const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits; |
| ctx->Texture._EnabledCoordUnits = 0; |
| |
| tex_coord[0] = span->attrStart[VARYING_SLOT_TEX0][0] * (info->smask + 1); |
| tex_step[0] = span->attrStepX[VARYING_SLOT_TEX0][0] * (info->smask + 1); |
| tex_coord[1] = span->attrStart[VARYING_SLOT_TEX0][1] * (info->tmask + 1); |
| tex_step[1] = span->attrStepX[VARYING_SLOT_TEX0][1] * (info->tmask + 1); |
| /* span->attrStart[VARYING_SLOT_TEX0][2] only if 3D-texturing, here only 2D */ |
| tex_coord[2] = span->attrStart[VARYING_SLOT_TEX0][3]; |
| tex_step[2] = span->attrStepX[VARYING_SLOT_TEX0][3]; |
| |
| switch (info->filter) { |
| case GL_NEAREST: |
| switch (info->format) { |
| case MESA_FORMAT_BGR_UNORM8: |
| switch (info->envmode) { |
| case GL_MODULATE: |
| SPAN_NEAREST(NEAREST_RGB;MODULATE,3); |
| break; |
| case GL_DECAL: |
| case GL_REPLACE: |
| SPAN_NEAREST(NEAREST_RGB_REPLACE,3); |
| break; |
| case GL_BLEND: |
| SPAN_NEAREST(NEAREST_RGB;BLEND,3); |
| break; |
| case GL_ADD: |
| SPAN_NEAREST(NEAREST_RGB;ADD,3); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| case MESA_FORMAT_A8B8G8R8_UNORM: |
| switch(info->envmode) { |
| case GL_MODULATE: |
| SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); |
| break; |
| case GL_DECAL: |
| SPAN_NEAREST(NEAREST_RGBA;DECAL,4); |
| break; |
| case GL_BLEND: |
| SPAN_NEAREST(NEAREST_RGBA;BLEND,4); |
| break; |
| case GL_ADD: |
| SPAN_NEAREST(NEAREST_RGBA;ADD,4); |
| break; |
| case GL_REPLACE: |
| SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| } |
| break; |
| |
| case GL_LINEAR: |
| switch (info->format) { |
| case MESA_FORMAT_BGR_UNORM8: |
| switch (info->envmode) { |
| case GL_MODULATE: |
| SPAN_LINEAR(LINEAR_RGB;MODULATE,3); |
| break; |
| case GL_DECAL: |
| case GL_REPLACE: |
| SPAN_LINEAR(LINEAR_RGB;REPLACE,3); |
| break; |
| case GL_BLEND: |
| SPAN_LINEAR(LINEAR_RGB;BLEND,3); |
| break; |
| case GL_ADD: |
| SPAN_LINEAR(LINEAR_RGB;ADD,3); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| case MESA_FORMAT_A8B8G8R8_UNORM: |
| switch (info->envmode) { |
| case GL_MODULATE: |
| SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); |
| break; |
| case GL_DECAL: |
| SPAN_LINEAR(LINEAR_RGBA;DECAL,4); |
| break; |
| case GL_BLEND: |
| SPAN_LINEAR(LINEAR_RGBA;BLEND,4); |
| break; |
| case GL_ADD: |
| SPAN_LINEAR(LINEAR_RGBA;ADD,4); |
| break; |
| case GL_REPLACE: |
| SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); |
| break; |
| default: |
| _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR"); |
| return; |
| } |
| break; |
| } |
| break; |
| } |
| |
| assert(span->arrayMask & SPAN_RGBA); |
| _swrast_write_rgba_span(ctx, span); |
| |
| #undef SPAN_NEAREST |
| #undef SPAN_LINEAR |
| |
| /* restore state */ |
| ctx->Texture._EnabledCoordUnits = texEnableSave; |
| } |
| |
| |
| /* |
| * Render an perspective corrected RGB/RGBA textured triangle. |
| * The Q (aka V in Mesa) coordinate must be zero such that the divide |
| * by interpolated Q/W comes out right. |
| * |
| */ |
| #define NAME persp_textured_triangle |
| #define INTERP_Z 1 |
| #define INTERP_RGB 1 |
| #define INTERP_ALPHA 1 |
| #define INTERP_ATTRIBS 1 |
| |
| #define SETUP_CODE \ |
| struct persp_info info; \ |
| const struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ |
| const struct gl_texture_object *obj = \ |
| ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ |
| const struct gl_texture_image *texImg = \ |
| _mesa_base_tex_image(obj); \ |
| const struct swrast_texture_image *swImg = \ |
| swrast_texture_image_const(texImg); \ |
| info.texture = (const GLchan *) swImg->ImageSlices[0]; \ |
| info.twidth_log2 = texImg->WidthLog2; \ |
| info.smask = texImg->Width - 1; \ |
| info.tmask = texImg->Height - 1; \ |
| info.format = texImg->TexFormat; \ |
| info.filter = obj->Sampler.MinFilter; \ |
| info.envmode = unit->EnvMode; \ |
| info.er = 0; \ |
| info.eg = 0; \ |
| info.eb = 0; \ |
| \ |
| if (info.envmode == GL_BLEND) { \ |
| /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ |
| info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ |
| info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ |
| info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ |
| info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ |
| } \ |
| if (!info.texture) { \ |
| /* this shouldn't happen */ \ |
| return; \ |
| } \ |
| \ |
| switch (info.format) { \ |
| case MESA_FORMAT_BGR_UNORM8: \ |
| info.tbytesline = texImg->Width * 3; \ |
| break; \ |
| case MESA_FORMAT_A8B8G8R8_UNORM: \ |
| info.tbytesline = texImg->Width * 4; \ |
| break; \ |
| default: \ |
| _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\ |
| return; \ |
| } \ |
| info.tsize = texImg->Height * info.tbytesline; |
| |
| #define RENDER_SPAN( span ) \ |
| span.interpMask &= ~SPAN_RGBA; \ |
| span.arrayMask |= SPAN_RGBA; \ |
| fast_persp_span(ctx, &span, &info); |
| |
| #include "s_tritemp.h" |
| |
| #endif /*CHAN_TYPE != GL_FLOAT*/ |
| |
| |
| |
| /* |
| * Render an RGBA triangle with arbitrary attributes. |
| */ |
| #define NAME general_triangle |
| #define INTERP_Z 1 |
| #define INTERP_RGB 1 |
| #define INTERP_ALPHA 1 |
| #define INTERP_ATTRIBS 1 |
| #define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); |
| #include "s_tritemp.h" |
| |
| |
| |
| |
| /* |
| * Special tri function for occlusion testing |
| */ |
| #define NAME occlusion_zless_16_triangle |
| #define INTERP_Z 1 |
| #define SETUP_CODE \ |
| struct gl_renderbuffer *rb = \ |
| ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; \ |
| struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; \ |
| assert(ctx->Depth.Test); \ |
| assert(!ctx->Depth.Mask); \ |
| assert(ctx->Depth.Func == GL_LESS); \ |
| assert(rb->Format == MESA_FORMAT_Z_UNORM16); \ |
| if (!q) { \ |
| return; \ |
| } |
| #define RENDER_SPAN( span ) \ |
| { \ |
| GLuint i; \ |
| const GLushort *zRow = (const GLushort *) \ |
| _swrast_pixel_address(rb, span.x, span.y); \ |
| for (i = 0; i < span.end; i++) { \ |
| GLuint z = FixedToDepth(span.z); \ |
| if (z < zRow[i]) { \ |
| q->Result++; \ |
| } \ |
| span.z += span.zStep; \ |
| } \ |
| } |
| #include "s_tritemp.h" |
| |
| |
| |
| static void |
| nodraw_triangle( struct gl_context *ctx, |
| const SWvertex *v0, |
| const SWvertex *v1, |
| const SWvertex *v2 ) |
| { |
| (void) (ctx && v0 && v1 && v2); |
| } |
| |
| |
| /* |
| * This is used when separate specular color is enabled, but not |
| * texturing. We add the specular color to the primary color, |
| * draw the triangle, then restore the original primary color. |
| * Inefficient, but seldom needed. |
| */ |
| void |
| _swrast_add_spec_terms_triangle(struct gl_context *ctx, const SWvertex *v0, |
| const SWvertex *v1, const SWvertex *v2) |
| { |
| SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ |
| SWvertex *ncv1 = (SWvertex *)v1; |
| SWvertex *ncv2 = (SWvertex *)v2; |
| GLfloat rSum, gSum, bSum; |
| GLchan cSave[3][4]; |
| |
| /* save original colors */ |
| COPY_CHAN4( cSave[0], ncv0->color ); |
| COPY_CHAN4( cSave[1], ncv1->color ); |
| COPY_CHAN4( cSave[2], ncv2->color ); |
| /* sum v0 */ |
| rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0]; |
| gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1]; |
| bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2]; |
| UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum); |
| UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum); |
| UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum); |
| /* sum v1 */ |
| rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[VARYING_SLOT_COL1][0]; |
| gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[VARYING_SLOT_COL1][1]; |
| bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[VARYING_SLOT_COL1][2]; |
| UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum); |
| UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum); |
| UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum); |
| /* sum v2 */ |
| rSum = CHAN_TO_FLOAT(ncv2->color[0]) + ncv2->attrib[VARYING_SLOT_COL1][0]; |
| gSum = CHAN_TO_FLOAT(ncv2->color[1]) + ncv2->attrib[VARYING_SLOT_COL1][1]; |
| bSum = CHAN_TO_FLOAT(ncv2->color[2]) + ncv2->attrib[VARYING_SLOT_COL1][2]; |
| UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[0], rSum); |
| UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[1], gSum); |
| UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[2], bSum); |
| /* draw */ |
| SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); |
| /* restore original colors */ |
| COPY_CHAN4( ncv0->color, cSave[0] ); |
| COPY_CHAN4( ncv1->color, cSave[1] ); |
| COPY_CHAN4( ncv2->color, cSave[2] ); |
| } |
| |
| |
| |
| #ifdef DEBUG |
| |
| /* record the current triangle function name */ |
| const char *_mesa_triFuncName = NULL; |
| |
| #define USE(triFunc) \ |
| do { \ |
| _mesa_triFuncName = #triFunc; \ |
| /*printf("%s\n", _mesa_triFuncName);*/ \ |
| swrast->Triangle = triFunc; \ |
| } while (0) |
| |
| #else |
| |
| #define USE(triFunc) swrast->Triangle = triFunc; |
| |
| #endif |
| |
| |
| |
| |
| /* |
| * Determine which triangle rendering function to use given the current |
| * rendering context. |
| * |
| * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or |
| * remove tests to this code. |
| */ |
| void |
| _swrast_choose_triangle( struct gl_context *ctx ) |
| { |
| SWcontext *swrast = SWRAST_CONTEXT(ctx); |
| |
| if (ctx->Polygon.CullFlag && |
| ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { |
| USE(nodraw_triangle); |
| return; |
| } |
| |
| if (ctx->RenderMode==GL_RENDER) { |
| struct gl_renderbuffer *depthRb = |
| ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; |
| |
| if (ctx->Polygon.SmoothFlag) { |
| _swrast_set_aa_triangle_function(ctx); |
| assert(swrast->Triangle); |
| return; |
| } |
| |
| /* special case for occlusion testing */ |
| if (ctx->Query.CurrentOcclusionObject && |
| ctx->Depth.Test && |
| ctx->Depth.Mask == GL_FALSE && |
| ctx->Depth.Func == GL_LESS && |
| !ctx->Stencil._Enabled && |
| depthRb && |
| depthRb->Format == MESA_FORMAT_Z_UNORM16) { |
| if (ctx->Color.ColorMask[0][0] == 0 && |
| ctx->Color.ColorMask[0][1] == 0 && |
| ctx->Color.ColorMask[0][2] == 0 && |
| ctx->Color.ColorMask[0][3] == 0) { |
| USE(occlusion_zless_16_triangle); |
| return; |
| } |
| } |
| |
| /* |
| * XXX should examine swrast->_ActiveAttribMask to determine what |
| * needs to be interpolated. |
| */ |
| if (ctx->Texture._EnabledCoordUnits || |
| _swrast_use_fragment_program(ctx) || |
| ctx->ATIFragmentShader._Enabled || |
| _mesa_need_secondary_color(ctx) || |
| swrast->_FogEnabled) { |
| /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ |
| const struct gl_texture_object *texObj2D; |
| const struct gl_sampler_object *samp; |
| const struct gl_texture_image *texImg; |
| const struct swrast_texture_image *swImg; |
| GLenum minFilter, magFilter, envMode; |
| mesa_format format; |
| texObj2D = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; |
| if (ctx->Texture.Unit[0].Sampler) |
| samp = ctx->Texture.Unit[0].Sampler; |
| else if (texObj2D) |
| samp = &texObj2D->Sampler; |
| else |
| samp = NULL; |
| |
| texImg = texObj2D ? _mesa_base_tex_image(texObj2D) : NULL; |
| swImg = swrast_texture_image_const(texImg); |
| |
| format = texImg ? texImg->TexFormat : MESA_FORMAT_NONE; |
| minFilter = texObj2D ? samp->MinFilter : GL_NONE; |
| magFilter = texObj2D ? samp->MagFilter : GL_NONE; |
| envMode = ctx->Texture.Unit[0].EnvMode; |
| |
| /* First see if we can use an optimized 2-D texture function */ |
| if (ctx->Texture._EnabledCoordUnits == 0x1 |
| && !_swrast_use_fragment_program(ctx) |
| && !ctx->ATIFragmentShader._Enabled |
| && ctx->Texture._MaxEnabledTexImageUnit == 0 |
| && ctx->Texture.Unit[0]._Current->Target == GL_TEXTURE_2D |
| && samp->WrapS == GL_REPEAT |
| && samp->WrapT == GL_REPEAT |
| && texObj2D->_Swizzle == SWIZZLE_NOOP |
| && swImg->_IsPowerOfTwo |
| && texImg->Border == 0 |
| && (_mesa_format_row_stride(format, texImg->Width) == |
| swImg->RowStride) |
| && (format == MESA_FORMAT_BGR_UNORM8 || format == MESA_FORMAT_A8B8G8R8_UNORM) |
| && minFilter == magFilter |
| && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR |
| && !swrast->_FogEnabled |
| && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT |
| && ctx->Texture.Unit[0].EnvMode != GL_COMBINE4_NV) { |
| if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { |
| if (minFilter == GL_NEAREST |
| && format == MESA_FORMAT_BGR_UNORM8 |
| && (envMode == GL_REPLACE || envMode == GL_DECAL) |
| && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) |
| && ctx->Depth.Func == GL_LESS |
| && ctx->Depth.Mask == GL_TRUE) |
| || swrast->_RasterMask == TEXTURE_BIT) |
| && ctx->Polygon.StippleFlag == GL_FALSE |
| && ctx->DrawBuffer->Visual.depthBits <= 16) { |
| if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { |
| USE(simple_z_textured_triangle); |
| } |
| else { |
| USE(simple_textured_triangle); |
| } |
| } |
| else { |
| #if CHAN_BITS != 8 |
| USE(general_triangle); |
| #else |
| if (format == MESA_FORMAT_A8B8G8R8_UNORM && !_mesa_little_endian()) { |
| /* We only handle RGBA8888 correctly on little endian |
| * in the optimized code above. |
| */ |
| USE(general_triangle); |
| } |
| else { |
| USE(affine_textured_triangle); |
| } |
| #endif |
| } |
| } |
| else { |
| #if CHAN_BITS != 8 |
| USE(general_triangle); |
| #else |
| USE(persp_textured_triangle); |
| #endif |
| } |
| } |
| else { |
| /* general case textured triangles */ |
| USE(general_triangle); |
| } |
| } |
| else { |
| assert(!swrast->_FogEnabled); |
| assert(!_mesa_need_secondary_color(ctx)); |
| if (ctx->Light.ShadeModel==GL_SMOOTH) { |
| /* smooth shaded, no texturing, stippled or some raster ops */ |
| #if CHAN_BITS != 8 |
| USE(general_triangle); |
| #else |
| USE(smooth_rgba_triangle); |
| #endif |
| } |
| else { |
| /* flat shaded, no texturing, stippled or some raster ops */ |
| #if CHAN_BITS != 8 |
| USE(general_triangle); |
| #else |
| USE(flat_rgba_triangle); |
| #endif |
| } |
| } |
| } |
| else if (ctx->RenderMode==GL_FEEDBACK) { |
| USE(_swrast_feedback_triangle); |
| } |
| else { |
| /* GL_SELECT mode */ |
| USE(_swrast_select_triangle); |
| } |
| } |