X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_triangle.c;h=9bdc2035242d7727db103db1b3006e72b38c519d;hb=612fc012934d9ec61972c3cfd914923937339611;hp=b71da4f648bc9eef073a8183b8e4f8ece6007164;hpb=c19d783e0715ac01ad4d3fd0705500d2bf6f7039;p=mesa.git diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index b71da4f648b..9bdc2035242 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -1,21 +1,21 @@ -/* $Id: s_triangle.c,v 1.4 2000/11/14 17:40:16 brianp Exp $ */ +/* $Id: s_triangle.c,v 1.54 2002/02/02 17:24:11 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * Version: 4.1 + * + * Copyright (C) 1999-2002 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 @@ -26,17 +26,18 @@ /* - * Triangle rasterizers - * When the device driver doesn't implement triangle rasterization Mesa - * will use these functions to draw triangles. + * 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 "glheader.h" #include "context.h" +#include "colormac.h" #include "macros.h" #include "mem.h" #include "mmath.h" +#include "texformat.h" #include "teximage.h" #include "texstate.h" @@ -46,11 +47,13 @@ #include "s_feedback.h" #include "s_span.h" #include "s_triangle.h" - -GLboolean gl_cull_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) + + + +GLboolean _mesa_cull_triangle( GLcontext *ctx, + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { GLfloat ex = v1->win[0] - v0->win[0]; GLfloat ey = v1->win[1] - v0->win[1]; @@ -60,41 +63,31 @@ GLboolean gl_cull_triangle( GLcontext *ctx, if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0) return 0; - + return 1; } + /* * Render a flat-shaded color index triangle. */ static void flat_ci_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { #define INTERP_Z 1 -#define SETUP_CODE - -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - const GLint n = RIGHT-LEFT; \ - GLint i; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - if (n>0) { \ - for (i=0;iindex, GL_POLYGON ); \ - } \ - } +#define INTERP_FOG 1 -#include "s_tritemp.h" +#define SETUP_CODE \ + span.interpMask |= SPAN_INDEX; \ + span.index = IntToFixed(v2->index); \ + span.indexStep = 0; + +#define RENDER_SPAN( span ) _mesa_write_index_span(ctx, &span, GL_POLYGON ) + +#include "s_tritemp.h" } @@ -103,33 +96,15 @@ static void flat_ci_triangle( GLcontext *ctx, * Render a smooth-shaded color index triangle. */ static void smooth_ci_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { #define INTERP_Z 1 +#define INTERP_FOG 1 #define INTERP_INDEX 1 -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - const GLint n = RIGHT-LEFT; \ - GLint i; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - GLuint index[MAX_WIDTH]; \ - if (n>0) { \ - for (i=0;i0) { \ - for (i=0;icolor, \ - GL_POLYGON ); \ - } \ - } +#define SETUP_CODE \ + ASSERT(!ctx->Texture._ReallyEnabled); \ + 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 ) _mesa_write_rgba_span(ctx, &span, GL_POLYGON ) #include "s_tritemp.h" - - ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ - ASSERT(ctx->Light.ShadeModel==GL_FLAT); } @@ -180,49 +147,28 @@ static void flat_rgba_triangle( GLcontext *ctx, * Render a smooth-shaded RGBA triangle. */ static void smooth_rgba_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { #define INTERP_Z 1 +#define INTERP_FOG 1 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE #define INTERP_RGB 1 #define INTERP_ALPHA 1 -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - const GLint n = RIGHT-LEFT; \ - GLint i; \ - GLdepth zspan[MAX_WIDTH]; \ - GLchan rgba[MAX_WIDTH][4]; \ - GLfixed fogspan[MAX_WIDTH]; \ - if (n>0) { \ - for (i=0;iTexture._ReallyEnabled); \ + ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); \ + } + +#define RENDER_SPAN( span ) _mesa_write_rgba_span(ctx, &span, GL_POLYGON) #include "s_tritemp.h" - ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ - ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); } @@ -233,52 +179,47 @@ static void smooth_rgba_triangle( GLcontext *ctx, * No fog. */ static void simple_textured_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { #define INTERP_INT_TEX 1 #define S_SCALE twidth #define T_SCALE theight + #define SETUP_CODE \ - struct gl_texture_object *obj = ctx->Texture.Unit[0].CurrentD[2]; \ - GLint b = obj->BaseLevel; \ - GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ - GLfloat theight = (GLfloat) obj->Image[b]->Height; \ - GLint twidth_log2 = obj->Image[b]->WidthLog2; \ - GLchan *texture = obj->Image[b]->Data; \ - GLint smask = obj->Image[b]->Width - 1; \ - GLint tmask = obj->Image[b]->Height - 1; \ + SWcontext *swrast = SWRAST_CONTEXT(ctx); \ + struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ + const GLint b = obj->BaseLevel; \ + const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ + const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ + const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ + const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ + const GLint smask = obj->Image[b]->Width - 1; \ + const GLint tmask = obj->Image[b]->Height - 1; \ if (!texture) { \ - if (!_mesa_get_teximages_from_driver(ctx, obj)) \ - return; \ - texture = obj->Image[b]->Data; \ - ASSERT(texture); \ + /* this shouldn't happen */ \ + return; \ } -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - CONST GLint n = RIGHT-LEFT; \ - GLint i; \ - GLchan rgb[MAX_WIDTH][3]; \ - if (n>0) { \ - ffs -= FIXED_HALF; /* off-by-one error? */ \ - fft -= FIXED_HALF; \ - for (i=0;iDriver.WriteRGBSpan)( ctx, n, LEFT, Y, \ - (CONST GLchan (*)[3]) rgb, NULL ); \ - } \ - } +#define RENDER_SPAN( span ) \ + GLuint i; \ + 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 */ \ + span.color.rgb[i][RCOMP] = texture[pos]; \ + span.color.rgb[i][GCOMP] = texture[pos+1]; \ + span.color.rgb[i][BCOMP] = texture[pos+2]; \ + span.intTex[0] += span.intTexStep[0]; \ + span.intTex[1] += span.intTexStep[1]; \ + } \ + (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ + (CONST GLchan (*)[3]) span.color.rgb, \ + NULL ); #include "s_tritemp.h" } @@ -288,1744 +229,733 @@ static void simple_textured_triangle( GLcontext *ctx, * Render an RGB, GL_DECAL, textured triangle. * Interpolate S,T, GL_LESS depth test, w/out mipmapping or * perspective correction. - * + * * No fog. */ static void simple_z_textured_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { #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_texture_object *obj = ctx->Texture.Unit[0].CurrentD[2]; \ - GLint b = obj->BaseLevel; \ - GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ - GLfloat theight = (GLfloat) obj->Image[b]->Height; \ - GLint twidth_log2 = obj->Image[b]->WidthLog2; \ - GLchan *texture = obj->Image[b]->Data; \ - GLint smask = obj->Image[b]->Width - 1; \ - GLint tmask = obj->Image[b]->Height - 1; \ + SWcontext *swrast = SWRAST_CONTEXT(ctx); \ + struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ + const GLint b = obj->BaseLevel; \ + const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ + const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ + const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ + const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ + const GLint smask = obj->Image[b]->Width - 1; \ + const GLint tmask = obj->Image[b]->Height - 1; \ if (!texture) { \ - if (!_mesa_get_teximages_from_driver(ctx, obj)) \ - return; \ - texture = obj->Image[b]->Data; \ - ASSERT(texture); \ + /* this shouldn't happen */ \ + return; \ } -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - CONST GLint n = RIGHT-LEFT; \ - GLint i; \ - GLchan rgb[MAX_WIDTH][3]; \ - GLubyte mask[MAX_WIDTH]; \ - (void) fffog; \ - if (n>0) { \ - ffs -= FIXED_HALF; /* off-by-one error? */ \ - fft -= FIXED_HALF; \ - for (i=0;iDriver.WriteRGBSpan)( ctx, n, LEFT, Y, \ - (CONST GLchan (*)[3]) rgb, mask ); \ - } \ - } +#define RENDER_SPAN( span ) \ + GLuint i; \ + span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ + span.intTex[1] -= FIXED_HALF; \ + for (i = 0; i < span.end; i++) { \ + const GLdepth 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 */ \ + span.color.rgb[i][RCOMP] = texture[pos]; \ + span.color.rgb[i][GCOMP] = texture[pos+1]; \ + span.color.rgb[i][BCOMP] = texture[pos+2]; \ + zRow[i] = z; \ + span.mask[i] = 1; \ + } \ + else { \ + span.mask[i] = 0; \ + } \ + span.intTex[0] += span.intTexStep[0]; \ + span.intTex[1] += span.intTexStep[1]; \ + span.z += span.zStep; \ + } \ + (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ + (CONST GLchan (*)[3]) span.color.rgb, \ + span.mask ); #include "s_tritemp.h" } +#if CHAN_TYPE != GL_FLOAT -/* - * Render an RGB/RGBA textured triangle without perspective correction. +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; +}; + + +/* 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 void affine_textured_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) +static INLINE void +affine_span(GLcontext *ctx, struct sw_span *span, + struct affine_info *info) { -#define INTERP_Z 1 -#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#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 gl_texture_unit *unit = ctx->Texture.Unit+0; \ - struct gl_texture_object *obj = unit->CurrentD[2]; \ - GLint b = obj->BaseLevel; \ - GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ - GLfloat theight = (GLfloat) obj->Image[b]->Height; \ - GLint twidth_log2 = obj->Image[b]->WidthLog2; \ - GLchan *texture = obj->Image[b]->Data; \ - GLint smask = obj->Image[b]->Width - 1; \ - GLint tmask = obj->Image[b]->Height - 1; \ - GLint format = obj->Image[b]->Format; \ - GLint filter = obj->MinFilter; \ - GLint envmode = unit->EnvMode; \ - GLint comp, tbytesline, tsize; \ - GLfixed er, eg, eb, ea; \ - GLint tr, tg, tb, ta; \ - if (!texture) { \ - if (!_mesa_get_teximages_from_driver(ctx, obj)) \ - return; \ - texture = obj->Image[b]->Data; \ - ASSERT(texture); \ - } \ - if (envmode == GL_BLEND || envmode == GL_ADD) { \ - /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ - er = FloatToFixed(unit->EnvColor[0]); \ - eg = FloatToFixed(unit->EnvColor[1]); \ - eb = FloatToFixed(unit->EnvColor[2]); \ - ea = FloatToFixed(unit->EnvColor[3]); \ - } \ - switch (format) { \ - case GL_ALPHA: \ - case GL_LUMINANCE: \ - case GL_INTENSITY: \ - comp = 1; \ - break; \ - case GL_LUMINANCE_ALPHA: \ - comp = 2; \ - break; \ - case GL_RGB: \ - comp = 3; \ - break; \ - case GL_RGBA: \ - comp = 4; \ - break; \ - default: \ - gl_problem(NULL, "Bad texture format in affine_texture_triangle");\ - return; \ - } \ - tbytesline = obj->Image[b]->Width * comp; \ - tsize = theight * tbytesline; - - - /* 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 \ - tr = tex00[0]; \ - tg = tex00[1]; \ - tb = tex00[2]; \ - ta = 0xff - -#define LINEAR_RGB \ - tr = (ti * (si * tex00[0] + sf * tex01[0]) + \ - tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ - tg = (ti * (si * tex00[1] + sf * tex01[1]) + \ - tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ - tb = (ti * (si * tex00[2] + sf * tex01[2]) + \ - tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ - ta = 0xff - -#define NEAREST_RGBA \ - tr = tex00[0]; \ - tg = tex00[1]; \ - tb = tex00[2]; \ - ta = tex00[3] - -#define LINEAR_RGBA \ - tr = (ti * (si * tex00[0] + sf * tex01[0]) + \ - tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ - tg = (ti * (si * tex00[1] + sf * tex01[1]) + \ - tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ - tb = (ti * (si * tex00[2] + sf * tex01[2]) + \ - tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ - ta = (ti * (si * tex00[3] + sf * tex01[3]) + \ - tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT - -#define MODULATE \ - dest[0] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \ - dest[1] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \ - dest[2] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \ - dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) - -#define DECAL \ - dest[0] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ - dest[1] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ - dest[2] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ - dest[3] = FixedToInt(ffa) - -#define BLEND \ - dest[0] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \ - dest[1] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \ - dest[2] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \ - dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) - -#define REPLACE \ - dest[0] = tr; \ - dest[1] = tg; \ - dest[2] = tb; \ - dest[3] = ta - -#define ADD \ - dest[0] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \ - dest[1] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \ - dest[2] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \ - dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) + 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 NEAREST_RGB \ + sample[RCOMP] = tex00[RCOMP]; \ + sample[GCOMP] = tex00[GCOMP]; \ + sample[BCOMP] = tex00[BCOMP]; \ + sample[ACOMP] = CHAN_MAX + +#define LINEAR_RGB \ + sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ + tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ + sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ + tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ + sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ + tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ + sample[ACOMP] = CHAN_MAX + +#define NEAREST_RGBA COPY_CHAN4(sample, tex00) + +#define LINEAR_RGBA \ + sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ + tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\ + sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ + tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\ + sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ + tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\ + sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) + \ + tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT + +#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;REPLACE - -#define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00 - -#define SPAN1(DO_TEX,COMP) \ - for (i=0;ialpha); + +#define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00) + +#define SPAN_NEAREST(DO_TEX,COMP) \ + 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 + COMP * 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 SPAN2(DO_TEX,COMP) \ - for (i=0;iend; 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; \ + GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ + GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ + GLfixed si = FIXED_FRAC_MASK - sf; \ + GLfixed ti = FIXED_FRAC_MASK - tf; \ + 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; \ + (void) ti; \ + (void) si; \ + 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; \ } -/* here comes the heavy part.. (something for the compiler to chew on) */ -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - CONST GLint n = RIGHT-LEFT; \ - GLint i; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - GLchan rgba[MAX_WIDTH][4]; \ - if (n>0) { \ - GLchan *dest = rgba[0]; \ - ffs -= FIXED_HALF; /* off-by-one error? */ \ - fft -= FIXED_HALF; \ - switch (filter) { \ - case GL_NEAREST: \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN1(NEAREST_RGB;MODULATE,3); \ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN1(NEAREST_RGB_REPLACE,3); \ - break; \ - case GL_BLEND: \ - SPAN1(NEAREST_RGB;BLEND,3); \ - break; \ - case GL_ADD: \ - SPAN1(NEAREST_RGB;ADD,3); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN1(NEAREST_RGBA;MODULATE,4); \ - break; \ - case GL_DECAL: \ - SPAN1(NEAREST_RGBA;DECAL,4); \ - break; \ - case GL_BLEND: \ - SPAN1(NEAREST_RGBA;BLEND,4); \ - break; \ - case GL_ADD: \ - SPAN1(NEAREST_RGBA;ADD,4); \ - break; \ - case GL_REPLACE: \ - SPAN1(NEAREST_RGBA_REPLACE,4); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - } \ - break; \ - case GL_LINEAR: \ - ffs -= FIXED_HALF; \ - fft -= FIXED_HALF; \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN2(LINEAR_RGB;MODULATE,3); \ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN2(LINEAR_RGB;REPLACE,3); \ - break; \ - case GL_BLEND: \ - SPAN2(LINEAR_RGB;BLEND,3); \ - break; \ - case GL_ADD: \ - SPAN2(LINEAR_RGB;ADD,3); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN2(LINEAR_RGBA;MODULATE,4); \ - break; \ - case GL_DECAL: \ - SPAN2(LINEAR_RGBA;DECAL,4); \ - break; \ - case GL_BLEND: \ - SPAN2(LINEAR_RGBA;BLEND,4); \ - break; \ - case GL_ADD: \ - SPAN2(LINEAR_RGBA;ADD,4); \ - break; \ - case GL_REPLACE: \ - SPAN2(LINEAR_RGBA;REPLACE,4); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - } \ - break; \ - } \ - gl_write_rgba_span(ctx, n, LEFT, Y, zspan, \ - fogspan, \ - rgba, GL_POLYGON); \ - /* explicit kill of variables: */ \ - ffr = ffg = ffb = ffa = 0; \ - } \ - } -#include "s_tritemp.h" -#undef SPAN1 -#undef SPAN2 + GLuint i; + GLchan *dest = span->color.rgba[0]; + + span->intTex[0] -= FIXED_HALF; + span->intTex[1] -= FIXED_HALF; + switch (info->filter) { + case GL_NEAREST: + switch (info->format) { + case GL_RGB: + 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: + abort(); + } + break; + case GL_RGBA: + 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: + abort(); + } + break; + } + break; + + case GL_LINEAR: + span->intTex[0] -= FIXED_HALF; + span->intTex[1] -= FIXED_HALF; + switch (info->format) { + case GL_RGB: + 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: + abort(); + } + break; + case GL_RGBA: + 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: + abort(); + } break; + } + break; + } + ASSERT(span->interpMask & SPAN_RGBA); /* XXXX unset */ + span->interpMask &= ~SPAN_RGBA; + ASSERT(span->arrayMask & SPAN_RGBA); + _mesa_write_rgba_span(ctx, span, GL_POLYGON); + +#undef SPAN_NEAREST +#undef SPAN_LINEAR } /* - * 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. - * - * This function only renders textured triangles that use GL_NEAREST. - * Perspective correction works right. - * - * This function written by Klaus Niederkrueger - * Send all questions and bug reports to him. + * Render an RGB/RGBA textured triangle without perspective correction. */ -static void near_persp_textured_triangle(GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) +static void affine_textured_triangle( GLcontext *ctx, + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { -/* The BIAS value is used to shift negative values into positive values. - * Without this, negative texture values don't GL_REPEAT correctly at just - * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry - * about texture coords less than -BIAS. This could be fixed by using - * FLOORF etc. instead, but this is slower... - */ -#define BIAS 4096.0F - #define INTERP_Z 1 +#define INTERP_FOG 1 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE #define INTERP_RGB 1 #define INTERP_ALPHA 1 -#define INTERP_TEX 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; \ - struct gl_texture_object *obj = unit->CurrentD[2]; \ + struct gl_texture_object *obj = unit->Current2D; \ const GLint b = obj->BaseLevel; \ - const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ + const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ - const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ - GLchan *texture = obj->Image[b]->Data; \ - const GLint smask = (obj->Image[b]->Width - 1); \ - const GLint tmask = (obj->Image[b]->Height - 1); \ - const GLint format = obj->Image[b]->Format; \ - const GLint envmode = unit->EnvMode; \ - GLfloat sscale, tscale; \ - GLfixed er, eg, eb, ea; \ - GLint tr, tg, tb, ta; \ - if (!texture) { \ - if (!_mesa_get_teximages_from_driver(ctx, obj)) \ - return; \ - texture = obj->Image[b]->Data; \ - ASSERT(texture); \ - } \ - if (envmode == GL_BLEND || envmode == GL_ADD) { \ - er = FloatToFixed(unit->EnvColor[0]); \ - eg = FloatToFixed(unit->EnvColor[1]); \ - eb = FloatToFixed(unit->EnvColor[2]); \ - ea = FloatToFixed(unit->EnvColor[3]); \ - } \ - sscale = twidth; \ - tscale = theight; \ - - -#define OLD_SPAN(DO_TEX,COMP) \ - for (i=0;iImage[b]->Data; \ + info.twidth_log2 = obj->Image[b]->WidthLog2; \ + info.smask = obj->Image[b]->Width - 1; \ + info.tmask = obj->Image[b]->Height - 1; \ + info.format = obj->Image[b]->Format; \ + info.filter = obj->MinFilter; \ + info.envmode = unit->EnvMode; \ + 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); \ } \ - nominator += vv*x_min; \ - denominator -= dvdx*x_min; \ - j = nominator / denominator; \ - pos = COMP * TEX_COORD(x_m, y_tex); \ - DRAW_LINE (DO_TEX); \ - while (iImage[b]->Width; \ + break; \ + case GL_LUMINANCE_ALPHA: \ + info.tbytesline = obj->Image[b]->Width * 2; \ + break; \ + case GL_RGB: \ + info.tbytesline = obj->Image[b]->Width * 3; \ + break; \ + case GL_RGBA: \ + info.tbytesline = obj->Image[b]->Width * 4; \ + break; \ + default: \ + _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ + return; \ } \ + info.tsize = obj->Image[b]->Height * info.tbytesline; + +#define RENDER_SPAN( span ) affine_span(ctx, &span, &info); + +#include "s_tritemp.h" + } -#define DRAW_LINE(DO_TEX) \ - { \ - GLchan *tex00 = texture + pos; \ - if (j>n || j<-100000) \ - j = n; \ - while (iend; 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; \ + GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ + GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ + GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \ + GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \ + GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ + GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ + GLfixed sf = s_fix & FIXED_FRAC_MASK; \ + GLfixed tf = t_fix & FIXED_FRAC_MASK; \ + GLfixed si = FIXED_FRAC_MASK - sf; \ + GLfixed ti = FIXED_FRAC_MASK - tf; \ + 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; \ + (void) ti; \ + (void) si; \ + 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->color.rgba[0]; + + tex_coord[0] = span->tex[0][0] * (info->smask + 1), + tex_step[0] = span->texStep[0][0] * (info->smask + 1); + tex_coord[1] = span->tex[0][1] * (info->tmask + 1), + tex_step[1] = span->texStep[0][1] * (info->tmask + 1); + /* span->tex[0][2] only if 3D-texturing, here only 2D */ + tex_coord[2] = span->tex[0][3], + tex_step[2] = span->texStep[0][3]; + + switch (info->filter) { + case GL_NEAREST: + switch (info->format) { + case GL_RGB: + 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: + abort(); + } + break; + case GL_RGBA: + 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: + abort(); + } + break; + } + break; + + case GL_LINEAR: + switch (info->format) { + case GL_RGB: + 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: + abort(); + } + break; + case GL_RGBA: + 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: + abort(); + } + break; + } + break; } + + ASSERT(span->arrayMask & SPAN_RGBA); + _mesa_write_rgba_span(ctx, span, GL_POLYGON); -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - GLint i = 0; \ - const GLint n = RIGHT-LEFT; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - GLchan rgba[MAX_WIDTH][4]; \ - (void)uu; /* please GCC */ \ - if (n > 0) { \ - GLchan *dest = rgba[0]; \ - GLfloat SS = ss * sscale; \ - GLfloat TT = tt * tscale; \ - GLfloat dSdx = dsdx * sscale; \ - GLfloat dTdx = dtdx * tscale; \ - GLfloat x_tex; \ - GLfloat y_tex; \ - GLfloat dx_tex; \ - GLfloat dy_tex; \ - if (n<5) /* When line very short, setup-time > speed-gain. */ \ - goto old_span; /* So: take old method */ \ - x_tex = SS / vv, \ - y_tex = TT / vv; \ - dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \ - dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \ - /* Choose between walking over texture or over pixelline: */ \ - /* If there are few texels, walk over texture otherwise */ \ - /* walk over pixelarray. The quotient on the right side */ \ - /* should give the timeratio needed to draw one texel in */ \ - /* comparison to one pixel. Depends on CPU. */ \ - if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \ - x_tex += BIAS; \ - y_tex += BIAS; \ - if (dx_tex*dx_tex > dy_tex*dy_tex) { \ - /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \ - GLfloat nominator = - SS - vv * BIAS; \ - GLfloat denominator = dvdx * BIAS + dSdx; \ - GLfloat dy_dx; \ - GLfloat dx_dy; \ - if (dy_tex != 0.0f) { \ - dy_dx = dy_tex / dx_tex; \ - dx_dy = 1.0f/dy_dx; \ - } \ - else \ - dy_dx = 0.0f; \ - if (dx_tex > 0.0f) { \ - if (dy_tex > 0.0f) { \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - } \ - } \ - else { /* dy_tex <= 0.0f */ \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - } \ - } \ - } \ - else { /* dx_tex < 0.0f */ \ - if (dy_tex > 0.0f) { \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - } \ - } \ - else { /* dy_tex <= 0.0f */ \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ - break; \ - default: \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - } \ - } \ - } \ - } \ - else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \ - GLfloat swap; \ - GLfloat dy_dx; \ - GLfloat dx_dy; \ - GLfloat nominator, denominator; \ - if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \ - goto old_span; /* case so special, that use old */ \ - /* swap some x-values and y-values */ \ - SS = TT; \ - dSdx = dTdx; \ - swap = x_tex, x_tex = y_tex, y_tex = swap; \ - swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \ - nominator = - SS - vv * BIAS; \ - denominator = dvdx * BIAS + dSdx; \ - if (dy_tex != 0.0f) { \ - dy_dx = dy_tex / dx_tex; \ - dx_dy = 1.0f/dy_dx; \ - } \ - else \ - dy_dx = 0.0f; \ - if (dx_tex > 0.0f) { \ - if (dy_tex > 0.0f) { \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ - break; \ - default: \ - abort(); \ - } \ - break; \ - } \ - } \ - else { /* dy_tex <= 0.0f */ \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ - break; \ - default: \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ - break; \ - default: \ - abort(); \ - } \ - break; \ - } \ - } \ - } \ - else { /* dx_tex < 0.0f */ \ - if (dy_tex > 0.0f) { \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ - break; \ - default: \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ - break; \ - default: \ - abort(); \ - } \ - break; \ - } \ - } \ - else { /* dy_tex <= 0.0f */ \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ - break; \ - default: \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ - break; \ - case GL_DECAL: \ - SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ - break; \ - case GL_BLEND: \ - SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ - break; \ - case GL_ADD: \ - SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ - break; \ - case GL_REPLACE: \ - SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ - break; \ - default: \ - abort(); \ - } \ - break; \ - } \ - } \ - } \ - } \ - } \ - else { \ - old_span: \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - OLD_SPAN(NEAREST_RGB;MODULATE,3); \ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - OLD_SPAN(NEAREST_RGB_REPLACE,3); \ - break; \ - case GL_BLEND: \ - OLD_SPAN(NEAREST_RGB;BLEND,3); \ - break; \ - case GL_ADD: \ - OLD_SPAN(NEAREST_RGB;ADD,3); \ - break; \ - default: \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch(envmode) { \ - case GL_MODULATE: \ - OLD_SPAN(NEAREST_RGBA;MODULATE,4); \ - break; \ - case GL_DECAL: \ - OLD_SPAN(NEAREST_RGBA;DECAL,4); \ - break; \ - case GL_BLEND: \ - OLD_SPAN(NEAREST_RGBA;BLEND,4); \ - break; \ - case GL_ADD: \ - OLD_SPAN(NEAREST_RGBA;ADD,4); \ - break; \ - case GL_REPLACE: \ - OLD_SPAN(NEAREST_RGBA_REPLACE,4); \ - break; \ - default: \ - abort(); \ - } \ - break; \ - } \ - } \ - gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \ - fogspan, rgba, GL_POLYGON); \ - ffr = ffg = ffb = ffa = 0; \ - } \ - } \ -#include "s_tritemp.h" -#undef OLD_SPAN -#undef SPAN1 -#undef SPAN2 -#undef SPAN3 -#undef SPAN4 -#undef X_Y_TEX_COORD -#undef Y_X_TEX_COORD -#undef DRAW_LINE -#undef BIAS +#undef SPAN_NEAREST +#undef SPAN_LINEAR } - /* * 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. * - * This function written by Klaus Niederkrueger - * Send all questions and bug reports to him. */ -static void lin_persp_textured_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) +static void persp_textured_triangle( GLcontext *ctx, + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { #define INTERP_Z 1 +#define INTERP_FOG 1 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE #define INTERP_RGB 1 #define INTERP_ALPHA 1 #define INTERP_TEX 1 + #define SETUP_CODE \ - struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ - struct gl_texture_object *obj = unit->CurrentD[2]; \ + struct persp_info info; \ + const struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ + const struct gl_texture_object *obj = unit->Current2D; \ const GLint b = obj->BaseLevel; \ - const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ - const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ - const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ - GLchan *texture = obj->Image[b]->Data; \ - const GLint smask = (obj->Image[b]->Width - 1); \ - const GLint tmask = (obj->Image[b]->Height - 1); \ - const GLint format = obj->Image[b]->Format; \ - const GLint envmode = unit->EnvMode; \ - GLfloat sscale, tscale; \ - GLint comp, tbytesline, tsize; \ - GLfixed er, eg, eb, ea; \ - GLint tr, tg, tb, ta; \ - if (!texture) { \ - if (!_mesa_get_teximages_from_driver(ctx, obj)) \ - return; \ - texture = obj->Image[b]->Data; \ - ASSERT(texture); \ + info.texture = (const GLchan *) obj->Image[b]->Data; \ + info.twidth_log2 = obj->Image[b]->WidthLog2; \ + info.smask = obj->Image[b]->Width - 1; \ + info.tmask = obj->Image[b]->Height - 1; \ + info.format = obj->Image[b]->Format; \ + info.filter = obj->MinFilter; \ + info.envmode = unit->EnvMode; \ + \ + 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; \ } \ - if (envmode == GL_BLEND || envmode == GL_ADD) { \ - er = FloatToFixed(unit->EnvColor[0]); \ - eg = FloatToFixed(unit->EnvColor[1]); \ - eb = FloatToFixed(unit->EnvColor[2]); \ - ea = FloatToFixed(unit->EnvColor[3]); \ - } \ - switch (format) { \ + \ + switch (info.format) { \ case GL_ALPHA: \ case GL_LUMINANCE: \ case GL_INTENSITY: \ - comp = 1; \ - break; \ + info.tbytesline = obj->Image[b]->Width; \ + break; \ case GL_LUMINANCE_ALPHA: \ - comp = 2; \ - break; \ + info.tbytesline = obj->Image[b]->Width * 2; \ + break; \ case GL_RGB: \ - comp = 3; \ - break; \ + info.tbytesline = obj->Image[b]->Width * 3; \ + break; \ case GL_RGBA: \ - comp = 4; \ - break; \ + info.tbytesline = obj->Image[b]->Width * 4; \ + break; \ default: \ - gl_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \ - return; \ - } \ - sscale = FIXED_SCALE * twidth; \ - tscale = FIXED_SCALE * theight; \ - tbytesline = obj->Image[b]->Width * comp; \ - tsize = theight * tbytesline; - - -#define SPAN(DO_TEX,COMP) \ - for (i=0;i 0) { \ - GLfloat SS = ss * sscale; \ - GLfloat TT = tt * tscale; \ - GLfloat dSdx = dsdx * sscale; \ - GLfloat dTdx = dtdx * tscale; \ - GLchan *dest = rgba[0]; \ - SS -= 0.5f * FIXED_SCALE * vv; \ - TT -= 0.5f * FIXED_SCALE * vv; \ - switch (format) { \ - case GL_RGB: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN(LINEAR_RGB;MODULATE,3); \ - break; \ - case GL_DECAL: \ - case GL_REPLACE: \ - SPAN(LINEAR_RGB;REPLACE,3); \ - break; \ - case GL_BLEND: \ - SPAN(LINEAR_RGB;BLEND,3); \ - break; \ - case GL_ADD: \ - SPAN(LINEAR_RGB;ADD,3); \ - break; \ - default: \ - abort(); \ - } \ - break; \ - case GL_RGBA: \ - switch (envmode) { \ - case GL_MODULATE: \ - SPAN(LINEAR_RGBA;MODULATE,4); \ - break; \ - case GL_DECAL: \ - SPAN(LINEAR_RGBA;DECAL,4); \ - break; \ - case GL_BLEND: \ - SPAN(LINEAR_RGBA;BLEND,4); \ - break; \ - case GL_REPLACE: \ - SPAN(LINEAR_RGBA;REPLACE,4); \ - break; \ - case GL_ADD: \ - SPAN(LINEAR_RGBA;ADD,4); \ - break; \ - default: /* unexpected env mode */ \ - abort(); \ - } \ - } \ - gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \ - fogspan, \ - rgba, GL_POLYGON ); \ - ffr = ffg = ffb = ffa = 0; \ - } \ - } + _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\ + return; \ + } \ + info.tsize = obj->Image[b]->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" -#undef SPAN -} - - - -/* - * Render a smooth-shaded, textured, RGBA triangle. - * Interpolate S,T,U with perspective correction, w/out mipmapping. - * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because - * R is already used for red. - */ -static void general_textured_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) -{ -#define INTERP_Z 1 -#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define INTERP_RGB 1 -#define INTERP_ALPHA 1 -#define INTERP_TEX 1 -#define SETUP_CODE \ - GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ - GLint r, g, b, a; \ - if (flat_shade) { \ - r = v0->color[0]; \ - g = v0->color[1]; \ - b = v0->color[2]; \ - a = v0->color[3]; \ - } -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - GLint i; \ - const GLint n = RIGHT-LEFT; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - GLchan rgba[MAX_WIDTH][4]; \ - GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \ - if (n>0) { \ - if (flat_shade) { \ - for (i=0;iLight.ShadeModel==GL_FLAT); \ - GLint r, g, b, a, sr, sg, sb; \ - if (flat_shade) { \ - r = v0->color[0]; \ - g = v0->color[1]; \ - b = v0->color[2]; \ - a = v0->color[3]; \ - sr = v0->specular[0]; \ - sg = v0->specular[1]; \ - sb = v0->specular[2]; \ - } -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - GLint i; \ - const GLint n = RIGHT-LEFT; \ - GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \ - if (n>0) { \ - if (flat_shade) { \ - for (i=0;iTexture.Unit[0]._Current; \ - const GLint baseLevel = obj->BaseLevel; \ - const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ - const GLfloat twidth = (GLfloat) texImage->Width; \ - const GLfloat theight = (GLfloat) texImage->Height; \ - const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ - GLint r, g, b, a; \ - if (flat_shade) { \ - r = v0->color[0]; \ - g = v0->color[1]; \ - b = v0->color[2]; \ - a = v0->color[3]; \ - } - -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - GLint i; \ - const GLint n = RIGHT-LEFT; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - GLchan rgba[MAX_WIDTH][4]; \ - GLfloat lambda[MAX_WIDTH]; \ - if (n>0) { \ - if (flat_shade) { \ - for (i=0;iTexture.Unit[0]._Current; \ - const GLint baseLevel = obj->BaseLevel; \ - const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ - const GLfloat twidth = (GLfloat) texImage->Width; \ - const GLfloat theight = (GLfloat) texImage->Height; \ - const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ - GLint r, g, b, a, sr, sg, sb; \ - if (flat_shade) { \ - r = v0->color[0]; \ - g = v0->color[1]; \ - b = v0->color[2]; \ - a = v0->color[3]; \ - sr = v0->specular[0]; \ - sg = v0->specular[1]; \ - sb = v0->specular[2]; \ - } - -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - GLint i; \ - const GLint n = RIGHT-LEFT; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - GLchan spec[MAX_WIDTH][4]; \ - GLchan rgba[MAX_WIDTH][4]; \ - GLfloat lambda[MAX_WIDTH]; \ - if (n>0) { \ - if (flat_shade) { \ - for (i=0;iLight.ShadeModel==GL_FLAT); \ - GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \ - GLint r, g, b, a; \ - if (flat_shade) { \ - r = v0->color[0]; \ - g = v0->color[1]; \ - b = v0->color[2]; \ - a = v0->color[3]; \ - } \ - { \ - GLuint unit; \ - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \ - if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ - const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \ - const GLint baseLevel = obj->BaseLevel; \ - const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ - twidth[unit] = (GLfloat) texImage->Width; \ - theight[unit] = (GLfloat) texImage->Height; \ - } \ - } \ - } - - +#define RENDER_SPAN( span ) _mesa_write_texture_span(ctx, &span, GL_POLYGON); -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - GLint i; \ - const GLint n = RIGHT-LEFT; \ - GLdepth zspan[MAX_WIDTH]; \ - GLfixed fogspan[MAX_WIDTH]; \ - GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \ - if (n > 0) { \ - if (flat_shade) { \ - for (i=0;iConst.MaxTextureUnits; unit++) { \ - if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ - GLdouble invQ = 1.0 / vv[unit]; \ - s[unit][i] = ss[unit] * invQ; \ - t[unit][i] = tt[unit] * invQ; \ - u[unit][i] = uu[unit] * invQ; \ - lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\ - dtdx[unit], dtdy[unit], invQ, \ - twidth[unit], theight[unit] ); \ - ss[unit] += dsdx[unit]; \ - tt[unit] += dtdx[unit]; \ - uu[unit] += dudx[unit]; \ - vv[unit] += dvdx[unit]; \ - } \ - } \ - } \ - } \ - } \ - else { /* smooth shade */ \ - for (i=0;iConst.MaxTextureUnits; unit++) { \ - if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ - GLdouble invQ = 1.0 / vv[unit]; \ - s[unit][i] = ss[unit] * invQ; \ - t[unit][i] = tt[unit] * invQ; \ - u[unit][i] = uu[unit] * invQ; \ - lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\ - dtdx[unit], dtdy[unit], invQ, \ - twidth[unit], theight[unit] ); \ - ss[unit] += dsdx[unit]; \ - tt[unit] += dtdx[unit]; \ - uu[unit] += dudx[unit]; \ - vv[unit] += dvdx[unit]; \ - } \ - } \ - } \ - } \ - } \ - gl_write_multitexture_span( ctx, n, LEFT, Y, zspan, fogspan, \ - (const GLfloat (*)[MAX_WIDTH]) s, \ - (const GLfloat (*)[MAX_WIDTH]) t, \ - (const GLfloat (*)[MAX_WIDTH]) u, \ - (GLfloat (*)[MAX_WIDTH]) lambda, \ - rgba, NULL, GL_POLYGON ); \ - } \ - } #include "s_tritemp.h" -} - - -/* - * These wrappers are needed to deal with the 32KB / stack frame limit - * on Mac / PowerPC systems. - */ -static void general_textured_spec_triangle(GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) -{ - GLdepth zspan[MAX_WIDTH]; - GLfixed fogspan[MAX_WIDTH]; - GLchan rgba[MAX_WIDTH][4], spec[MAX_WIDTH][4]; - general_textured_spec_triangle1(ctx,v0,v1,v2,zspan,fogspan,rgba,spec); } -static void lambda_textured_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) -{ - GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; - lambda_textured_triangle1(ctx,v0,v1,v2,s,t,u); -} - -static void lambda_textured_spec_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) -{ - GLfloat s[MAX_WIDTH]; - GLfloat t[MAX_WIDTH]; - GLfloat u[MAX_WIDTH]; - lambda_textured_spec_triangle1(ctx,v0,v1,v2,s,t,u); -} - - -static void lambda_multitextured_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) -{ - - GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH]; - GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH]; - DEFMARRAY(GLfloat,u,MAX_TEXTURE_UNITS,MAX_WIDTH); - CHECKARRAY(u,return); - - lambda_multitextured_triangle1(ctx,v0,v1,v2,s,t,u); - - UNDEFARRAY(u); -} - - static void occlusion_zless_triangle( GLcontext *ctx, - SWvertex *v0, - SWvertex *v1, - SWvertex *v2 ) + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { if (ctx->OcclusionResult) { return; @@ -2228,35 +1002,106 @@ static void occlusion_zless_triangle( GLcontext *ctx, #define DO_OCCLUSION_TEST #define INTERP_Z 1 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define INNER_LOOP( LEFT, RIGHT, Y ) \ - { \ - GLint i; \ - const GLint len = RIGHT-LEFT; \ - for (i=0;iOcclusionResult = GL_TRUE; \ - return; \ - } \ - ffz += fdzdx; \ - } \ + +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + GLdepth z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + ctx->OcclusionResult = GL_TRUE; \ + return; \ + } \ + span.z += span.zStep; \ } + #include "s_tritemp.h" } +static void nodraw_triangle( GLcontext *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( GLcontext *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; +#if CHAN_TYPE == GL_FLOAT + GLfloat rSum, gSum, bSum; +#else + GLint rSum, gSum, bSum; +#endif + GLchan c[3][4]; + /* save original colors */ + COPY_CHAN4( c[0], ncv0->color ); + COPY_CHAN4( c[1], ncv1->color ); + COPY_CHAN4( c[2], ncv2->color ); + /* sum v0 */ + rSum = ncv0->color[0] + ncv0->specular[0]; + gSum = ncv0->color[1] + ncv0->specular[1]; + bSum = ncv0->color[2] + ncv0->specular[2]; + ncv0->color[0] = MIN2(rSum, CHAN_MAX); + ncv0->color[1] = MIN2(gSum, CHAN_MAX); + ncv0->color[2] = MIN2(bSum, CHAN_MAX); + /* sum v1 */ + rSum = ncv1->color[0] + ncv1->specular[0]; + gSum = ncv1->color[1] + ncv1->specular[1]; + bSum = ncv1->color[2] + ncv1->specular[2]; + ncv1->color[0] = MIN2(rSum, CHAN_MAX); + ncv1->color[1] = MIN2(gSum, CHAN_MAX); + ncv1->color[2] = MIN2(bSum, CHAN_MAX); + /* sum v2 */ + rSum = ncv2->color[0] + ncv2->specular[0]; + gSum = ncv2->color[1] + ncv2->specular[1]; + bSum = ncv2->color[2] + ncv2->specular[2]; + ncv2->color[0] = MIN2(rSum, CHAN_MAX); + ncv2->color[1] = MIN2(gSum, CHAN_MAX); + ncv2->color[2] = MIN2(bSum, CHAN_MAX); + /* draw */ + SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); + /* restore original colors */ + COPY_CHAN4( ncv0->color, c[0] ); + COPY_CHAN4( ncv1->color, c[1] ); + COPY_CHAN4( ncv2->color, c[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) -#if 0 -# define dputs(s) puts(s) #else -# define dputs(s) + +#define USE(triFunc) swrast->Triangle = triFunc; + #endif + /* * Determine which triangle rendering function to use given the current * rendering context. @@ -2264,11 +1109,17 @@ static void occlusion_zless_triangle( GLcontext *ctx, * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or * remove tests to this code. */ -void +void _swrast_choose_triangle( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - const GLboolean rgbmode = ctx->Visual.RGBAflag; + const GLboolean rgbmode = ctx->Visual.rgbMode; + + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { + USE(nodraw_triangle); + return; + } if (ctx->RenderMode==GL_RENDER) { @@ -2284,75 +1135,69 @@ _swrast_choose_triangle( GLcontext *ctx ) ctx->Depth.Func == GL_LESS && !ctx->Stencil.Enabled) { if ((rgbmode && - ctx->Color.ColorMask[0] == 0 && - ctx->Color.ColorMask[1] == 0 && + ctx->Color.ColorMask[0] == 0 && + ctx->Color.ColorMask[1] == 0 && ctx->Color.ColorMask[2] == 0 && ctx->Color.ColorMask[3] == 0) || (!rgbmode && ctx->Color.IndexMask == 0)) { - dputs("occlusion_test_triangle"); - swrast->Triangle = occlusion_zless_triangle; + USE(occlusion_zless_triangle); return; } } if (ctx->Texture._ReallyEnabled) { /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ - GLint format, filter; - const struct gl_texture_object *current2Dtex = ctx->Texture.Unit[0].CurrentD[2]; - const struct gl_texture_image *image; + const struct gl_texture_object *texObj2D; + const struct gl_texture_image *texImg; + GLenum minFilter, magFilter, envMode; + GLint format; + texObj2D = ctx->Texture.Unit[0].Current2D; + texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL; + format = texImg ? texImg->TexFormat->MesaFormat : -1; + minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0; + magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0; + envMode = ctx->Texture.Unit[0].EnvMode; + /* First see if we can used an optimized 2-D texture function */ if (ctx->Texture._ReallyEnabled==TEXTURE0_2D - && current2Dtex->WrapS==GL_REPEAT - && current2Dtex->WrapT==GL_REPEAT - && ((image = current2Dtex->Image[current2Dtex->BaseLevel]) != 0) /* correct! */ - && image->Border==0 - && ((format = image->Format)==GL_RGB || format==GL_RGBA) - && (filter = current2Dtex->MinFilter)==current2Dtex->MagFilter - && ctx->Light.Model.ColorControl==GL_SINGLE_COLOR - && ctx->Texture.Unit[0].EnvMode!=GL_COMBINE_EXT) { - + && texObj2D->WrapS==GL_REPEAT + && texObj2D->WrapT==GL_REPEAT + && texImg->Border==0 + && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) + && minFilter == magFilter + && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR + && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) { if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { - - if (filter==GL_NEAREST - && format==GL_RGB - && (ctx->Texture.Unit[0].EnvMode==GL_REPLACE - || ctx->Texture.Unit[0].EnvMode==GL_DECAL) - && ((swrast->_RasterMask==DEPTH_BIT - && ctx->Depth.Func==GL_LESS - && ctx->Depth.Mask==GL_TRUE) - || swrast->_RasterMask==0) - && ctx->Polygon.StippleFlag==GL_FALSE) { - - if (swrast->_RasterMask==DEPTH_BIT) { - swrast->Triangle = simple_z_textured_triangle; - dputs("simple_z_textured_triangle"); + if (minFilter == GL_NEAREST + && format == MESA_FORMAT_RGB + && (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) { + if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { + USE(simple_z_textured_triangle); } else { - swrast->Triangle = simple_textured_triangle; - dputs("simple_textured_triangle"); + USE(simple_textured_triangle); } } else { - if (ctx->Texture.Unit[0].EnvMode==GL_ADD) { - swrast->Triangle = general_textured_triangle; - dputs("general_textured_triangle"); - } - else { - swrast->Triangle = affine_textured_triangle; - dputs("affine_textured_triangle"); - } +#if (CHAN_BITS == 16 || CHAN_BITS == 32) + USE(general_textured_triangle); +#else + USE(affine_textured_triangle); +#endif } } else { - if (filter==GL_NEAREST) { - swrast->Triangle = near_persp_textured_triangle; - dputs("near_persp_textured_triangle"); - } - else { - swrast->Triangle = lin_persp_textured_triangle; - dputs("lin_persp_textured_triangle"); - } +#if (CHAN_BITS == 16 || CHAN_BITS == 32) + USE(general_textured_triangle); +#else + USE(persp_textured_triangle); +#endif } } else { @@ -2364,65 +1209,46 @@ _swrast_choose_triangle( GLcontext *ctx ) needLambda = GL_TRUE; else needLambda = GL_FALSE; - if (swrast->_MultiTextureEnabled) { - swrast->Triangle = lambda_multitextured_triangle; - dputs("lambda_multitextured_triangle"); - } - else if ((ctx->Light.Enabled && - ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) - || ctx->Fog.ColorSumEnabled) { - /* separate specular color interpolation */ - if (needLambda) { - swrast->Triangle = lambda_textured_spec_triangle; - dputs("lambda_textured_spec_triangle"); - } - else { - swrast->Triangle = general_textured_spec_triangle; - dputs("general_textured_spec_triangle"); - } + if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { + USE(lambda_multitextured_triangle); } else { if (needLambda) { - swrast->Triangle = lambda_textured_triangle; - dputs("lambda_textured_triangle"); + USE(lambda_textured_triangle); } else { - swrast->Triangle = general_textured_triangle; - dputs("general_textured_triangle"); + USE(general_textured_triangle); } } } } else { + ASSERT(!ctx->Texture._ReallyEnabled); if (ctx->Light.ShadeModel==GL_SMOOTH) { /* smooth shaded, no texturing, stippled or some raster ops */ if (rgbmode) { - dputs("smooth_rgba_triangle"); - swrast->Triangle = smooth_rgba_triangle; + USE(smooth_rgba_triangle); } else { - dputs("smooth_ci_triangle"); - swrast->Triangle = smooth_ci_triangle; + USE(smooth_ci_triangle); } } else { /* flat shaded, no texturing, stippled or some raster ops */ if (rgbmode) { - dputs("flat_rgba_triangle"); - swrast->Triangle = flat_rgba_triangle; + USE(flat_rgba_triangle); } else { - dputs("flat_ci_triangle"); - swrast->Triangle = flat_ci_triangle; + USE(flat_ci_triangle); } } } } else if (ctx->RenderMode==GL_FEEDBACK) { - swrast->Triangle = gl_feedback_triangle; + USE(_mesa_feedback_triangle); } else { /* GL_SELECT mode */ - swrast->Triangle = gl_select_triangle; + USE(_mesa_select_triangle); } }