diff options
author | Brian Paul <[email protected]> | 2001-11-19 01:18:28 +0000 |
---|---|---|
committer | Brian Paul <[email protected]> | 2001-11-19 01:18:28 +0000 |
commit | 71340e861edf35bfdeb536718cd230fc33c41ee2 (patch) | |
tree | 1dcf9d944afe55103cfd24bb4123e04fc2270bc1 | |
parent | 71515b9175df29e0b230c1930a1786779325e70d (diff) |
More span rendering optimizations from Klaus Niederkrueger
-rw-r--r-- | src/mesa/swrast/s_span.c | 682 | ||||
-rw-r--r-- | src/mesa/swrast/s_span.h | 7 | ||||
-rw-r--r-- | src/mesa/swrast/s_texture.c | 28 | ||||
-rw-r--r-- | src/mesa/swrast/s_triangle.c | 343 |
4 files changed, 707 insertions, 353 deletions
diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index 2c02e0368e8..e475da3d042 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -1,4 +1,4 @@ -/* $Id: s_span.c,v 1.18 2001/10/17 23:03:56 brianp Exp $ */ +/* $Id: s_span.c,v 1.19 2001/11/19 01:18:28 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -33,6 +33,7 @@ #include "glheader.h" #include "colormac.h" +#include "context.h" #include "macros.h" #include "mem.h" @@ -482,7 +483,6 @@ _mesa_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y, GLboolean write_all = GL_TRUE; GLchan rgbaBackup[MAX_WIDTH][4]; GLchan (*rgba)[4]; - const GLubyte *Null = 0; SWcontext *swrast = SWRAST_CONTEXT(ctx); /* init mask to 1's (all pixels are to be written) */ @@ -591,13 +591,13 @@ _mesa_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y, /* write pixels */ (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, - (const GLchan (*)[4]) rgba, - write_all ? Null : mask ); + (const GLchan (*)[4]) rgba, + write_all ? ((const GLubyte *) NULL) : mask ); if (swrast->_RasterMask & ALPHABUF_BIT) { _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, - write_all ? Null : mask ); + write_all ? ((const GLubyte *) NULL) : mask ); } } } @@ -626,7 +626,6 @@ _mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte mask[MAX_WIDTH]; GLboolean write_all = GL_TRUE; GLchan rgba[MAX_WIDTH][4]; - const GLubyte *Null = 0; SWcontext *swrast = SWRAST_CONTEXT(ctx); /* init mask to 1's (all pixels are to be written) */ @@ -740,12 +739,12 @@ _mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y, /* write pixels */ (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, - (const GLchan (*)[4]) rgba, - write_all ? Null : mask ); + (const GLchan (*)[4]) rgba, + write_all ? ((const GLubyte *) NULL) : mask ); if (swrast->_RasterMask & ALPHABUF_BIT) { _mesa_write_alpha_span( ctx, n, x, y, - (const GLchan (*)[4]) rgba, - write_all ? Null : mask ); + (const GLchan (*)[4]) rgba, + write_all ? ((const GLubyte *) NULL) : mask ); } } } @@ -767,7 +766,7 @@ _mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y, (*swrast->Driver.WriteMonoRGBASpan)( ctx, n, x, y, color, mask ); if (swrast->_RasterMask & ALPHABUF_BIT) { _mesa_write_mono_alpha_span( ctx, n, x, y, (GLchan) color[ACOMP], - write_all ? Null : mask ); + write_all ? ((const GLubyte *) NULL) : mask ); } } } @@ -804,6 +803,661 @@ add_colors(GLuint n, GLchan rgba[][4], CONST GLchan specular[][4] ) /* * Write a horizontal span of textured pixels to the frame buffer. * The color of each pixel is different. + * Depth-testing, stenciling, scissor-testing etc. should already + * have been done, + * only if alpha-testing is used, depth-testing is still done in this + * function. + * Input: n - number of pixels in the span + * x, y - location of leftmost pixel in the span + * z - array of [n] z-values + * s, t - array of (s,t) texture coordinates for each pixel + * lambda - array of texture lambda values + * rgba - array of [n] color components + * mask - masked pixels + * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP. + * Contributed by Klaus Niederkrueger. + */ +static void +masked_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLdepth z[], const GLfloat fog[], + const GLfloat s[], const GLfloat t[], + const GLfloat u[], GLfloat lambda[], + GLchan rgbaIn[][4], CONST GLchan spec[][4], + const GLfloat coverage[], GLubyte mask[], + GLboolean write_all ) +{ + const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); + GLchan rgbaBackup[MAX_WIDTH][4]; + GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + + if (swrast->_RasterMask & MULTI_DRAW_BIT) { + /* must make a copy of the colors since they may be modified */ + MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan)); + rgba = rgbaBackup; + } + else { + rgba = rgbaIn; + } + + + ASSERT(ctx->Texture._ReallyEnabled); + _swrast_texture_fragments( ctx, 0, n, s, t, u, lambda, + (CONST GLchan (*)[4]) rgba, rgba ); + + + /* Texture with alpha test */ + if (ctx->Color.AlphaEnabled) { + /* Do the alpha test */ + if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) { + return; + } + write_all = GL_FALSE; + + /* Depth test usually in 'rasterize_span' but if alpha test + needed, we have to wait for that test before depth test can + be done. */ + if (ctx->Stencil.Enabled) { + /* first stencil test */ + if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) { + return; + } + write_all = GL_FALSE; + } + else if (ctx->Depth.Test) { + /* regular depth testing */ + GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask ); + if (m == 0) { + return; + } + if (m < n) { + write_all = GL_FALSE; + } + } + } + + /* if we get here, something passed the depth test */ + ctx->OcclusionResult = GL_TRUE; + + + /* Add base and specular colors */ + if (spec && + (ctx->Fog.ColorSumEnabled || + (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))) + add_colors( n, rgba, spec ); /* rgba = rgba + spec */ + + /* Per-pixel fog */ + if (ctx->Fog.Enabled) { + if (fog && !swrast->_PreferPixelFog) + _mesa_fog_rgba_pixels( ctx, n, fog, rgba ); + else + _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba ); + } + + /* Antialias coverage application */ + if (coverage) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); + } + } + + if (swrast->_RasterMask & MULTI_DRAW_BIT) { + multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask ); + } + else { + /* normal: write to exactly one buffer */ + if (ctx->Color.ColorLogicOpEnabled) { + _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask ); + } + else if (ctx->Color.BlendEnabled) { + _mesa_blend_span( ctx, n, x, y, rgba, mask ); + } + if (colorMask == 0x0) { + return; + } + else if (colorMask != 0xffffffff) { + _mesa_mask_rgba_span( ctx, n, x, y, rgba ); + } + + (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba, + write_all ? NULL : mask ); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, + write_all ? NULL : mask ); + } + } +} + + +/* + * As above but perform multiple stages of texture application. + * Contributed by Klaus Niederkrueger. + */ +static void +masked_multitexture_span( GLcontext *ctx, GLuint n, GLint x, GLint y, + const GLdepth z[], const GLfloat fog[], + CONST GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH], + CONST GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH], + CONST GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH], + GLfloat lambda[][MAX_WIDTH], + GLchan rgbaIn[MAX_TEXTURE_UNITS][4], + CONST GLchan spec[MAX_TEXTURE_UNITS][4], + const GLfloat coverage[], GLubyte mask[], + GLboolean write_all ) +{ + GLchan rgbaBackup[MAX_WIDTH][4]; + GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */ + GLuint i; + const GLuint texUnits = ctx->Const.MaxTextureUnits; + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + + if ( (swrast->_RasterMask & MULTI_DRAW_BIT) || texUnits > 1) { + /* must make a copy of the colors since they may be modified */ + MEMCPY(rgbaBackup, rgbaIn, 4 * n * sizeof(GLchan)); + rgba = rgbaBackup; + } + else { + rgba = rgbaIn; + } + + + ASSERT(ctx->Texture._ReallyEnabled); + for (i = 0; i < texUnits; i++) + _swrast_texture_fragments( ctx, i, n, s[i], t[i], u[i], lambda[i], + (CONST GLchan (*)[4]) rgbaIn, rgba ); + + /* Texture with alpha test */ + if (ctx->Color.AlphaEnabled) { + /* Do the alpha test */ + if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) { + return; + } + write_all = GL_FALSE; + /* Depth test usually in 'rasterize_span' but if alpha test + needed, we have to wait for that test before depth test can + be done. */ + if (ctx->Stencil.Enabled) { + /* first stencil test */ + if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) { + return; + } + write_all = GL_FALSE; + } + else if (ctx->Depth.Test) { + /* regular depth testing */ + GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask ); + if (m == 0) { + return; + } + if (m < n) { + write_all = GL_FALSE; + } + } + } + + /* if we get here, something passed the depth test */ + ctx->OcclusionResult = GL_TRUE; + + + /* Add base and specular colors */ + if (spec && + (ctx->Fog.ColorSumEnabled || + (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))) + add_colors( n, rgba, spec ); /* rgba = rgba + spec */ + + /* Per-pixel fog */ + if (ctx->Fog.Enabled) { + if (fog && !swrast->_PreferPixelFog) + _mesa_fog_rgba_pixels( ctx, n, fog, rgba ); + else + _mesa_depth_fog_rgba_pixels( ctx, n, z, rgba ); + } + + /* Antialias coverage application */ + if (coverage) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); + } + } + + if (swrast->_RasterMask & MULTI_DRAW_BIT) { + multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask ); + } + else { + /* normal: write to exactly one buffer */ + const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); + + if (ctx->Color.ColorLogicOpEnabled) { + _mesa_logicop_rgba_span( ctx, n, x, y, rgba, mask ); + } + else if (ctx->Color.BlendEnabled) { + _mesa_blend_span( ctx, n, x, y, rgba, mask ); + } + + if (colorMask == 0x0) { + return; + } + else if (colorMask != 0xffffffff) { + _mesa_mask_rgba_span( ctx, n, x, y, rgba ); + } + + (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba, + write_all ? NULL : mask ); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4])rgba, + write_all ? NULL : mask ); + } + } +} + + +/* + * Generate arrays of fragment colors, z, fog, texcoords, etc from a + * triangle span object. Then call the span/fragment processsing + * functions in s_span.[ch]. This is used by a bunch of the textured + * triangle functions. + * Contributed by Klaus Niederkrueger. + */ +void +_mesa_rasterize_span(GLcontext *ctx, struct triangle_span *span) +{ + DEFARRAY(GLubyte, mask, MAX_WIDTH); + DEFMARRAY(GLchan, rgba, MAX_WIDTH, 4); + DEFMARRAY(GLchan, spec, MAX_WIDTH, 4); + DEFARRAY(GLuint, index, MAX_WIDTH); + DEFARRAY(GLuint, z, MAX_WIDTH); + DEFARRAY(GLfloat, fog, MAX_WIDTH); + DEFARRAY(GLfloat, sTex, MAX_WIDTH); + DEFARRAY(GLfloat, tTex, MAX_WIDTH); + DEFARRAY(GLfloat, rTex, MAX_WIDTH); + DEFARRAY(GLfloat, lambda, MAX_WIDTH); + DEFMARRAY(GLfloat, msTex, MAX_TEXTURE_UNITS, MAX_WIDTH); + DEFMARRAY(GLfloat, mtTex, MAX_TEXTURE_UNITS, MAX_WIDTH); + DEFMARRAY(GLfloat, mrTex, MAX_TEXTURE_UNITS, MAX_WIDTH); + DEFMARRAY(GLfloat, mLambda, MAX_TEXTURE_UNITS, MAX_WIDTH); + + GLboolean write_all = GL_TRUE; + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + CHECKARRAY(mask, return); + CHECKARRAY(rgba, return); + CHECKARRAY(spec, return); + CHECKARRAY(index, return); + CHECKARRAY(z, return); + CHECKARRAY(fog, return); + CHECKARRAY(sTex, return); + CHECKARRAY(tTex, return); + CHECKARRAY(rTex, return); + CHECKARRAY(lambda, return); + CHECKARRAY(msTex, return); + CHECKARRAY(mtTex, return); + CHECKARRAY(mrTex, return); + CHECKARRAY(mLambda, return); + + /* init mask to 1's (all pixels are to be written) */ + MEMSET(mask, 1, span->count); + + if (swrast->_RasterMask & WINCLIP_BIT) { + if ((span->count = clip_span(ctx, span->count, span->x, span->y, mask)) + == 0) { + return; + } + if (mask[0] == 0) + write_all = GL_FALSE; + } + + /* Do the scissor test */ + if (ctx->Scissor.Enabled) { + if ((span->count = _mesa_scissor_span(ctx, span->count, span->x, span->y, mask )) == 0) { + return; + } + if (mask[0] == 0) + write_all = GL_FALSE; + } + + /* Polygon Stippling */ + if (ctx->Polygon.StippleFlag) { + stipple_polygon_span( ctx, span->count, span->x, span->y, mask ); + write_all = GL_FALSE; + } + + + + if (span->activeMask & SPAN_Z) { + if (ctx->Visual.depthBits <= 16) { + GLuint i; + GLfixed zval = span->z; + for (i = 0; i < span->count; i++) { + z[i] = FixedToInt(zval); + zval += span->zStep; + } + } + else { + /* Deep Z buffer, no fixed->int shift */ + GLuint i; + GLfixed zval = span->z; + for (i = 0; i < span->count; i++) { + z[i] = zval; + zval += span->zStep; + } + } + } + + /* Correct order: texturing --> alpha test --> depth test. But if + no alpha test needed, we can do here the depth test and + potentially avoid some of the texturing (otherwise alpha test, + depth test etc. happens in masked_texture_span(). */ + if (!ctx->Color.AlphaEnabled) { + if (ctx->Stencil.Enabled) { + /* first stencil test */ + if (_mesa_stencil_and_ztest_span(ctx, span->count, span->x, + span->y, z, mask) == GL_FALSE) { + return; + } + write_all = GL_FALSE; + } + else if (ctx->Depth.Test) { + /* regular depth testing */ + GLuint m = _mesa_depth_test_span( ctx, span->count, span->x, + span->y, z, mask ); + if (m == 0) { + return; + } + if (m < span->count) { + write_all = GL_FALSE; + } + } + } + + if (span->activeMask & SPAN_RGBA) { + if (span->activeMask & SPAN_FLAT) { + GLuint i; + GLchan color[4]; + color[RCOMP] = FixedToChan(span->red); + color[GCOMP] = FixedToChan(span->green); + color[BCOMP] = FixedToChan(span->blue); + color[ACOMP] = FixedToChan(span->alpha); + for (i = 0; i < span->count; i++) { + COPY_CHAN4(rgba[i], color); + } + } + else { + /* smooth interpolation */ +#if CHAN_TYPE == GL_FLOAT + GLfloat r = span->red; + GLfloat g = span->green; + GLfloat b = span->blue; + GLfloat a = span->alpha; +#else + GLfixed r = span->red; + GLfixed g = span->green; + GLfixed b = span->blue; + GLfixed a = span->alpha; +#endif + GLuint i; + for (i = 0; i < span->count; i++) { + rgba[i][RCOMP] = FixedToChan(r); + rgba[i][GCOMP] = FixedToChan(g); + rgba[i][BCOMP] = FixedToChan(b); + rgba[i][ACOMP] = FixedToChan(a); + r += span->redStep; + g += span->greenStep; + b += span->blueStep; + a += span->alphaStep; + } + } + } + + if (span->activeMask & SPAN_SPEC) { + if (span->activeMask & SPAN_FLAT) { + const GLchan r = FixedToChan(span->specRed); + const GLchan g = FixedToChan(span->specGreen); + const GLchan b = FixedToChan(span->specBlue); + GLuint i; + for (i = 0; i < span->count; i++) { + spec[i][RCOMP] = r; + spec[i][GCOMP] = g; + spec[i][BCOMP] = b; + } + } + else { + /* smooth interpolation */ +#if CHAN_TYPE == GL_FLOAT + GLfloat r = span->specRed; + GLfloat g = span->specGreen; + GLfloat b = span->specBlue; +#else + GLfixed r = span->specRed; + GLfixed g = span->specGreen; + GLfixed b = span->specBlue; +#endif + GLuint i; + for (i = 0; i < span->count; i++) { + spec[i][RCOMP] = FixedToChan(r); + spec[i][GCOMP] = FixedToChan(g); + spec[i][BCOMP] = FixedToChan(b); + r += span->specRedStep; + g += span->specGreenStep; + b += span->specBlueStep; + } + } + } + + if (span->activeMask & SPAN_INDEX) { + if (span->activeMask & SPAN_FLAT) { + GLuint i; + const GLint indx = FixedToInt(span->index); + for (i = 0; i < span->count; i++) { + index[i] = indx; + } + } + else { + /* smooth interpolation */ + GLuint i; + GLfixed ind = span->index; + for (i = 0; i < span->count; i++) { + index[i] = FixedToInt(ind); + ind += span->indexStep; + } + } + } + + if (span->activeMask & SPAN_FOG) { + GLuint i; + GLfloat f = span->fog; + for (i = 0; i < span->count; i++) { + fog[i] = f; + f += span->fogStep; + } + } + if (span->activeMask & SPAN_TEXTURE) { + if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { + /* multitexture */ + if (span->activeMask & SPAN_LAMBDA) { + /* with lambda */ + GLuint u; + /* multitexture, lambda */ + for (u = 0; u < MAX_TEXTURE_UNITS; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + GLfloat s = span->tex[u][0]; + GLfloat t = span->tex[u][1]; + GLfloat r = span->tex[u][2]; + GLfloat q = span->tex[u][3]; + GLuint i; + for (i = 0; i < span->count; i++) { + const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); + msTex[u][i] = s * invQ; + mtTex[u][i] = t * invQ; + mrTex[u][i] = r * invQ; + mLambda[u][i] = (GLfloat) + (log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F); + s += span->texStep[u][0]; + t += span->texStep[u][1]; + r += span->texStep[u][2]; + q += span->texStep[u][3]; + } + } + } + } + else { + /* without lambda */ + GLuint u; + /* multitexture, no lambda */ + for (u = 0; u < MAX_TEXTURE_UNITS; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + GLfloat s = span->tex[u][0]; + GLfloat t = span->tex[u][1]; + GLfloat r = span->tex[u][2]; + GLfloat q = span->tex[u][3]; + GLuint i; + for (i = 0; i < span->count; i++) { + const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); + msTex[u][i] = s * invQ; + mtTex[u][i] = t * invQ; + mrTex[u][i] = r * invQ; + s += span->texStep[u][0]; + t += span->texStep[u][1]; + r += span->texStep[u][2]; + q += span->texStep[u][3]; + } + } + } + } + } + else { + /* just texture unit 0 */ + if (span->activeMask & SPAN_LAMBDA) { + /* with lambda */ + GLfloat s = span->tex[0][0]; + GLfloat t = span->tex[0][1]; + GLfloat r = span->tex[0][2]; + GLfloat q = span->tex[0][3]; + GLuint i; + /* single texture, lambda */ + for (i = 0; i < span->count; i++) { + const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); + sTex[i] = s * invQ; + tTex[i] = t * invQ; + rTex[i] = r * invQ; + lambda[i] = (GLfloat) + (log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F); + s += span->texStep[0][0]; + t += span->texStep[0][1]; + r += span->texStep[0][2]; + q += span->texStep[0][3]; + } + } + else { + /* without lambda */ + GLfloat s = span->tex[0][0]; + GLfloat t = span->tex[0][1]; + GLfloat r = span->tex[0][2]; + GLfloat q = span->tex[0][3]; + GLuint i; + /* single texture, no lambda */ + for (i = 0; i < span->count; i++) { + const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); + sTex[i] = s * invQ; + tTex[i] = t * invQ; + rTex[i] = r * invQ; + s += span->texStep[0][0]; + t += span->texStep[0][1]; + r += span->texStep[0][2]; + q += span->texStep[0][3]; + } + } + } + } + /* XXX keep this? */ + if (span->activeMask & SPAN_INT_TEXTURE) { + GLint intTexcoord[MAX_WIDTH][2]; + GLfixed s = span->intTex[0]; + GLfixed t = span->intTex[1]; + GLuint i; + for (i = 0; i < span->count; i++) { + intTexcoord[i][0] = FixedToInt(s); + intTexcoord[i][1] = FixedToInt(t); + s += span->intTexStep[0]; + t += span->intTexStep[1]; + } + } + + /* examine activeMask and call a s_span.c function */ + if (span->activeMask & SPAN_TEXTURE) { + const GLfloat *fogPtr; + if (span->activeMask & SPAN_FOG) + fogPtr = fog; + else + fogPtr = NULL; + + if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { + if (span->activeMask & SPAN_SPEC) { + masked_multitexture_span(ctx, span->count, span->x, span->y, + z, fogPtr, + (const GLfloat (*)[MAX_WIDTH]) msTex, + (const GLfloat (*)[MAX_WIDTH]) mtTex, + (const GLfloat (*)[MAX_WIDTH]) mrTex, + (GLfloat (*)[MAX_WIDTH]) mLambda, + rgba, (CONST GLchan (*)[4]) spec, + NULL, mask, write_all ); + } + else { + masked_multitexture_span(ctx, span->count, span->x, span->y, + z, fogPtr, + (const GLfloat (*)[MAX_WIDTH]) msTex, + (const GLfloat (*)[MAX_WIDTH]) mtTex, + (const GLfloat (*)[MAX_WIDTH]) mrTex, + (GLfloat (*)[MAX_WIDTH]) mLambda, + rgba, NULL, NULL, mask, write_all ); + } + } + else { + /* single texture */ + if (span->activeMask & SPAN_SPEC) { + masked_texture_span(ctx, span->count, span->x, span->y, + z, fogPtr, sTex, tTex, rTex, + lambda, rgba, + (CONST GLchan (*)[4]) spec, + NULL, mask, write_all); + } + else { + masked_texture_span(ctx, span->count, span->x, span->y, + z, fogPtr, sTex, tTex, rTex, + lambda, rgba, NULL, NULL, + mask, write_all); + } + } + } + else { + _mesa_problem(ctx, "rasterize_span() should only be used for texturing"); + } + + UNDEFARRAY(mask); + UNDEFARRAY(rgba); + UNDEFARRAY(spec); + UNDEFARRAY(index); + UNDEFARRAY(z); + UNDEFARRAY(fog); + UNDEFARRAY(sTex); + UNDEFARRAY(tTex); + UNDEFARRAY(rTex); + UNDEFARRAY(lambda); + UNDEFARRAY(msTex); + UNDEFARRAY(mtTex); + UNDEFARRAY(mrTex); + UNDEFARRAY(mLambda); +} + + +/* + * Write a horizontal span of textured pixels to the frame buffer. + * The color of each pixel is different. * Alpha-testing, stenciling, depth-testing, and blending are done * as needed. * Input: n - number of pixels in the span @@ -828,7 +1482,6 @@ _mesa_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y, GLboolean write_all = GL_TRUE; GLchan rgbaBackup[MAX_WIDTH][4]; GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */ - const GLubyte *Null = 0; SWcontext *swrast = SWRAST_CONTEXT(ctx); /* init mask to 1's (all pixels are to be written) */ @@ -952,10 +1605,10 @@ _mesa_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y, } (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLchan (*)[4])rgba, - write_all ? Null : mask ); + write_all ? ((const GLubyte *) NULL) : mask ); if (swrast->_RasterMask & ALPHABUF_BIT) { _mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, - write_all ? Null : mask ); + write_all ? ((const GLubyte *) NULL) : mask ); } } } @@ -1123,7 +1776,6 @@ _mesa_write_multitexture_span( GLcontext *ctx, GLuint n, GLint x, GLint y, } - /* * Read RGBA pixels from frame buffer. Clipping will be done to prevent * reading ouside the buffer's boundaries. diff --git a/src/mesa/swrast/s_span.h b/src/mesa/swrast/s_span.h index 5c5e49c12d0..522ec93329c 100644 --- a/src/mesa/swrast/s_span.h +++ b/src/mesa/swrast/s_span.h @@ -1,4 +1,4 @@ -/* $Id: s_span.h,v 1.6 2001/05/15 21:30:27 brianp Exp $ */ +/* $Id: s_span.h,v 1.7 2001/11/19 01:18:28 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -31,6 +31,7 @@ #include "mtypes.h" #include "swrast.h" +#include "s_trispan.h" extern void @@ -62,6 +63,10 @@ _mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y, extern void +_mesa_rasterize_span(GLcontext *ctx, struct triangle_span *span); + + +extern void _mesa_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y, const GLdepth z[], const GLfloat fog[], const GLfloat s[], const GLfloat t[], diff --git a/src/mesa/swrast/s_texture.c b/src/mesa/swrast/s_texture.c index 24402259233..e1e1d0f0ceb 100644 --- a/src/mesa/swrast/s_texture.c +++ b/src/mesa/swrast/s_texture.c @@ -1,4 +1,4 @@ -/* $Id: s_texture.c,v 1.41 2001/10/17 23:03:34 brianp Exp $ */ +/* $Id: s_texture.c,v 1.42 2001/11/19 01:18:28 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -956,6 +956,28 @@ opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit, } } +#ifdef DEBUG +static int +span_is_monotonous (GLuint n, const GLfloat lambda[]) +{ + GLuint i; + + if (n <= 1) /* array too short */ + return GL_TRUE; + else if (lambda[0] >= lambda[n-1]) { /* decreasing */ + for (i=0; i<n-1; i++) + if (lambda[i] < lambda[i+1]) + return GL_FALSE; + } + else { /* increasing */ + for (i=0; i<n-1; i++) + if (lambda[i] > lambda[i+1]) + return GL_FALSE; + } + + return GL_TRUE; +} +#endif /* DEBUG */ /* * Given an array of (s,t) texture coordinate and lambda (level of detail) @@ -973,6 +995,10 @@ sample_lambda_2d( GLcontext *ctx, GLuint texUnit, GLuint i; (void) u; +#ifdef DEBUG + ASSERT (span_is_monotonous(n, lambda) == GL_TRUE); +#endif /* DEBUG */ + /* since lambda is monotonous-array use this check first */ if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) { /* magnification for whole span */ diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index 02c27d52968..7d6a87ddfac 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -1,4 +1,4 @@ -/* $Id: s_triangle.c,v 1.39 2001/09/19 22:21:13 brianp Exp $ */ +/* $Id: s_triangle.c,v 1.40 2001/11/19 01:18:28 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -349,7 +349,7 @@ struct affine_info * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD * texture env modes. */ -static void +static INLINE void affine_span(GLcontext *ctx, struct triangle_span *span, struct affine_info *info) { @@ -694,7 +694,7 @@ struct persp_info }; -static void +static INLINE void fast_persp_span(GLcontext *ctx, struct triangle_span *span, struct persp_info *info) { @@ -973,335 +973,6 @@ static void persp_textured_triangle( GLcontext *ctx, #endif /* CHAN_BITS != GL_FLOAT */ - -/* - * Generate arrays of fragment colors, z, fog, texcoords, etc from a - * triangle span object. Then call the span/fragment processsing - * functions in s_span.[ch]. This is used by a bunch of the textured - * triangle functions. - */ -static void -rasterize_span(GLcontext *ctx, const struct triangle_span *span) -{ - DEFMARRAY(GLchan, rgba, MAX_WIDTH, 4); - DEFMARRAY(GLchan, spec, MAX_WIDTH, 4); - DEFARRAY(GLuint, index, MAX_WIDTH); - DEFARRAY(GLuint, z, MAX_WIDTH); - DEFARRAY(GLfloat, fog, MAX_WIDTH); - DEFARRAY(GLfloat, sTex, MAX_WIDTH); - DEFARRAY(GLfloat, tTex, MAX_WIDTH); - DEFARRAY(GLfloat, rTex, MAX_WIDTH); - DEFARRAY(GLfloat, lambda, MAX_WIDTH); - DEFMARRAY(GLfloat, msTex, MAX_TEXTURE_UNITS, MAX_WIDTH); - DEFMARRAY(GLfloat, mtTex, MAX_TEXTURE_UNITS, MAX_WIDTH); - DEFMARRAY(GLfloat, mrTex, MAX_TEXTURE_UNITS, MAX_WIDTH); - DEFMARRAY(GLfloat, mLambda, MAX_TEXTURE_UNITS, MAX_WIDTH); - - CHECKARRAY(rgba, return); - CHECKARRAY(spec, return); - CHECKARRAY(index, return); - CHECKARRAY(z, return); - CHECKARRAY(fog, return); - CHECKARRAY(sTex, return); - CHECKARRAY(tTex, return); - CHECKARRAY(rTex, return); - CHECKARRAY(lambda, return); - CHECKARRAY(msTex, return); - CHECKARRAY(mtTex, return); - CHECKARRAY(mrTex, return); - CHECKARRAY(mLambda, return); - - if (span->activeMask & SPAN_RGBA) { - if (span->activeMask & SPAN_FLAT) { - GLuint i; - GLchan color[4]; - color[RCOMP] = FixedToChan(span->red); - color[GCOMP] = FixedToChan(span->green); - color[BCOMP] = FixedToChan(span->blue); - color[ACOMP] = FixedToChan(span->alpha); - for (i = 0; i < span->count; i++) { - COPY_CHAN4(rgba[i], color); - } - } - else { - /* smooth interpolation */ -#if CHAN_TYPE == GL_FLOAT - GLfloat r = span->red; - GLfloat g = span->green; - GLfloat b = span->blue; - GLfloat a = span->alpha; -#else - GLfixed r = span->red; - GLfixed g = span->green; - GLfixed b = span->blue; - GLfixed a = span->alpha; -#endif - GLuint i; - for (i = 0; i < span->count; i++) { - rgba[i][RCOMP] = FixedToChan(r); - rgba[i][GCOMP] = FixedToChan(g); - rgba[i][BCOMP] = FixedToChan(b); - rgba[i][ACOMP] = FixedToChan(a); - r += span->redStep; - g += span->greenStep; - b += span->blueStep; - a += span->alphaStep; - } - } - } - - if (span->activeMask & SPAN_SPEC) { - if (span->activeMask & SPAN_FLAT) { - const GLchan r = FixedToChan(span->specRed); - const GLchan g = FixedToChan(span->specGreen); - const GLchan b = FixedToChan(span->specBlue); - GLuint i; - for (i = 0; i < span->count; i++) { - spec[i][RCOMP] = r; - spec[i][GCOMP] = g; - spec[i][BCOMP] = b; - } - } - else { - /* smooth interpolation */ -#if CHAN_TYPE == GL_FLOAT - GLfloat r = span->specRed; - GLfloat g = span->specGreen; - GLfloat b = span->specBlue; -#else - GLfixed r = span->specRed; - GLfixed g = span->specGreen; - GLfixed b = span->specBlue; -#endif - GLuint i; - for (i = 0; i < span->count; i++) { - spec[i][RCOMP] = FixedToChan(r); - spec[i][GCOMP] = FixedToChan(g); - spec[i][BCOMP] = FixedToChan(b); - r += span->specRedStep; - g += span->specGreenStep; - b += span->specBlueStep; - } - } - } - - if (span->activeMask & SPAN_INDEX) { - if (span->activeMask & SPAN_FLAT) { - GLuint i; - const GLint indx = FixedToInt(span->index); - for (i = 0; i < span->count; i++) { - index[i] = indx; - } - } - else { - /* smooth interpolation */ - GLuint i; - GLfixed ind = span->index; - for (i = 0; i < span->count; i++) { - index[i] = FixedToInt(ind); - ind += span->indexStep; - } - } - } - - if (span->activeMask & SPAN_Z) { - if (ctx->Visual.depthBits <= 16) { - GLuint i; - GLfixed zval = span->z; - for (i = 0; i < span->count; i++) { - z[i] = FixedToInt(zval); - zval += span->zStep; - } - } - else { - /* Deep Z buffer, no fixed->int shift */ - GLuint i; - GLfixed zval = span->z; - for (i = 0; i < span->count; i++) { - z[i] = zval; - zval += span->zStep; - } - } - } - if (span->activeMask & SPAN_FOG) { - GLuint i; - GLfloat f = span->fog; - for (i = 0; i < span->count; i++) { - fog[i] = f; - f += span->fogStep; - } - } - if (span->activeMask & SPAN_TEXTURE) { - if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { - /* multitexture */ - if (span->activeMask & SPAN_LAMBDA) { - /* with lambda */ - GLuint u; - for (u = 0; u < MAX_TEXTURE_UNITS; u++) { - if (ctx->Texture.Unit[u]._ReallyEnabled) { - GLfloat s = span->tex[u][0]; - GLfloat t = span->tex[u][1]; - GLfloat r = span->tex[u][2]; - GLfloat q = span->tex[u][3]; - GLuint i; - for (i = 0; i < span->count; i++) { - const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); - msTex[u][i] = s * invQ; - mtTex[u][i] = t * invQ; - mrTex[u][i] = r * invQ; - mLambda[u][i] = (GLfloat) - (log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F); - s += span->texStep[u][0]; - t += span->texStep[u][1]; - r += span->texStep[u][2]; - q += span->texStep[u][3]; - } - } - } - } - else { - /* without lambda */ - GLuint u; - for (u = 0; u < MAX_TEXTURE_UNITS; u++) { - if (ctx->Texture.Unit[u]._ReallyEnabled) { - GLfloat s = span->tex[u][0]; - GLfloat t = span->tex[u][1]; - GLfloat r = span->tex[u][2]; - GLfloat q = span->tex[u][3]; - GLuint i; - for (i = 0; i < span->count; i++) { - const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); - msTex[u][i] = s * invQ; - mtTex[u][i] = t * invQ; - mrTex[u][i] = r * invQ; - s += span->texStep[u][0]; - t += span->texStep[u][1]; - r += span->texStep[u][2]; - q += span->texStep[u][3]; - } - } - } - } - } - else { - /* just texture unit 0 */ - if (span->activeMask & SPAN_LAMBDA) { - /* with lambda */ - GLfloat s = span->tex[0][0]; - GLfloat t = span->tex[0][1]; - GLfloat r = span->tex[0][2]; - GLfloat q = span->tex[0][3]; - GLuint i; - for (i = 0; i < span->count; i++) { - const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); - sTex[i] = s * invQ; - tTex[i] = t * invQ; - rTex[i] = r * invQ; - lambda[i] = (GLfloat) - (log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F); - s += span->texStep[0][0]; - t += span->texStep[0][1]; - r += span->texStep[0][2]; - q += span->texStep[0][3]; - } - } - else { - /* without lambda */ - GLfloat s = span->tex[0][0]; - GLfloat t = span->tex[0][1]; - GLfloat r = span->tex[0][2]; - GLfloat q = span->tex[0][3]; - GLuint i; - for (i = 0; i < span->count; i++) { - const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); - sTex[i] = s * invQ; - tTex[i] = t * invQ; - rTex[i] = r * invQ; - s += span->texStep[0][0]; - t += span->texStep[0][1]; - r += span->texStep[0][2]; - q += span->texStep[0][3]; - } - } - } - } - /* XXX keep this? */ - if (span->activeMask & SPAN_INT_TEXTURE) { - GLint intTexcoord[MAX_WIDTH][2]; - GLfixed s = span->intTex[0]; - GLfixed t = span->intTex[1]; - GLuint i; - for (i = 0; i < span->count; i++) { - intTexcoord[i][0] = FixedToInt(s); - intTexcoord[i][1] = FixedToInt(t); - s += span->intTexStep[0]; - t += span->intTexStep[1]; - } - } - - /* examine activeMask and call a s_span.c function */ - if (span->activeMask & SPAN_TEXTURE) { - const GLfloat *fogPtr; - if (span->activeMask & SPAN_FOG) - fogPtr = fog; - else - fogPtr = NULL; - - if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { - if (span->activeMask & SPAN_SPEC) { - _mesa_write_multitexture_span(ctx, span->count, span->x, span->y, - z, fogPtr, - (const GLfloat (*)[MAX_WIDTH]) msTex, - (const GLfloat (*)[MAX_WIDTH]) mtTex, - (const GLfloat (*)[MAX_WIDTH]) mrTex, - (GLfloat (*)[MAX_WIDTH]) mLambda, - rgba, (CONST GLchan (*)[4]) spec, - NULL, GL_POLYGON ); - } - else { - _mesa_write_multitexture_span(ctx, span->count, span->x, span->y, - z, fogPtr, - (const GLfloat (*)[MAX_WIDTH]) msTex, - (const GLfloat (*)[MAX_WIDTH]) mtTex, - (const GLfloat (*)[MAX_WIDTH]) mrTex, - (GLfloat (*)[MAX_WIDTH]) mLambda, - rgba, NULL, NULL, GL_POLYGON); - } - } - else { - /* single texture */ - if (span->activeMask & SPAN_SPEC) { - _mesa_write_texture_span(ctx, span->count, span->x, span->y, - z, fogPtr, sTex, tTex, rTex, lambda, - rgba, (CONST GLchan (*)[4]) spec, - NULL, GL_POLYGON); - } - else { - _mesa_write_texture_span(ctx, span->count, span->x, span->y, - z, fogPtr, sTex, tTex, rTex, lambda, - rgba, NULL, NULL, GL_POLYGON); - } - } - } - else { - _mesa_problem(ctx, "rasterize_span() should only be used for texturing"); - } - - UNDEFARRAY(rgba); - UNDEFARRAY(spec); - UNDEFARRAY(index); - UNDEFARRAY(z); - UNDEFARRAY(fog); - UNDEFARRAY(sTex); - UNDEFARRAY(tTex); - UNDEFARRAY(rTex); - UNDEFARRAY(lambda); - UNDEFARRAY(msTex); - UNDEFARRAY(mtTex); - UNDEFARRAY(mrTex); - UNDEFARRAY(mLambda); -} - @@ -1400,7 +1071,7 @@ static void general_textured_spec_triangle( GLcontext *ctx, span.texHeight[0] = (GLfloat) texImage->Height; \ (void) fixedToDepthShift; -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); +#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); #include "s_tritemp.h" } @@ -1433,7 +1104,7 @@ static void lambda_textured_triangle( GLcontext *ctx, span.texHeight[0] = (GLfloat) texImage->Height; \ (void) fixedToDepthShift; -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); +#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); #include "s_tritemp.h" } @@ -1468,7 +1139,7 @@ static void lambda_textured_spec_triangle( GLcontext *ctx, span.texHeight[0] = (GLfloat) texImage->Height; \ (void) fixedToDepthShift; -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); +#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); #include "s_tritemp.h" } @@ -1510,7 +1181,7 @@ lambda_multitextured_triangle( GLcontext *ctx, } \ (void) fixedToDepthShift; -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); +#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); #include "s_tritemp.h" |