More span rendering optimizations from Klaus Niederkrueger

This commit is contained in:
Brian Paul
2001-11-19 01:18:28 +00:00
parent 71515b9175
commit 71340e861e
4 changed files with 707 additions and 353 deletions

View File

@@ -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 * Mesa 3-D graphics library
@@ -33,6 +33,7 @@
#include "glheader.h" #include "glheader.h"
#include "colormac.h" #include "colormac.h"
#include "context.h"
#include "macros.h" #include "macros.h"
#include "mem.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; GLboolean write_all = GL_TRUE;
GLchan rgbaBackup[MAX_WIDTH][4]; GLchan rgbaBackup[MAX_WIDTH][4];
GLchan (*rgba)[4]; GLchan (*rgba)[4];
const GLubyte *Null = 0;
SWcontext *swrast = SWRAST_CONTEXT(ctx); SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* init mask to 1's (all pixels are to be written) */ /* 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 */ /* write pixels */
(*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
(const GLchan (*)[4]) rgba, (const GLchan (*)[4]) rgba,
write_all ? Null : mask ); write_all ? ((const GLubyte *) NULL) : mask );
if (swrast->_RasterMask & ALPHABUF_BIT) { if (swrast->_RasterMask & ALPHABUF_BIT) {
_mesa_write_alpha_span( ctx, n, x, y, _mesa_write_alpha_span( ctx, n, x, y,
(const GLchan (*)[4]) rgba, (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]; GLubyte mask[MAX_WIDTH];
GLboolean write_all = GL_TRUE; GLboolean write_all = GL_TRUE;
GLchan rgba[MAX_WIDTH][4]; GLchan rgba[MAX_WIDTH][4];
const GLubyte *Null = 0;
SWcontext *swrast = SWRAST_CONTEXT(ctx); SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* init mask to 1's (all pixels are to be written) */ /* 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 */ /* write pixels */
(*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y,
(const GLchan (*)[4]) rgba, (const GLchan (*)[4]) rgba,
write_all ? Null : mask ); write_all ? ((const GLubyte *) NULL) : mask );
if (swrast->_RasterMask & ALPHABUF_BIT) { if (swrast->_RasterMask & ALPHABUF_BIT) {
_mesa_write_alpha_span( ctx, n, x, y, _mesa_write_alpha_span( ctx, n, x, y,
(const GLchan (*)[4]) rgba, (const GLchan (*)[4]) rgba,
write_all ? Null : mask ); 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 ); (*swrast->Driver.WriteMonoRGBASpan)( ctx, n, x, y, color, mask );
if (swrast->_RasterMask & ALPHABUF_BIT) { if (swrast->_RasterMask & ALPHABUF_BIT) {
_mesa_write_mono_alpha_span( ctx, n, x, y, (GLchan) color[ACOMP], _mesa_write_mono_alpha_span( ctx, n, x, y, (GLchan) color[ACOMP],
write_all ? Null : mask ); write_all ? ((const GLubyte *) NULL) : mask );
} }
} }
} }
@@ -801,6 +800,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. * Write a horizontal span of textured pixels to the frame buffer.
* The color of each pixel is different. * The color of each pixel is different.
@@ -828,7 +1482,6 @@ _mesa_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
GLboolean write_all = GL_TRUE; GLboolean write_all = GL_TRUE;
GLchan rgbaBackup[MAX_WIDTH][4]; GLchan rgbaBackup[MAX_WIDTH][4];
GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */ GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */
const GLubyte *Null = 0;
SWcontext *swrast = SWRAST_CONTEXT(ctx); SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* init mask to 1's (all pixels are to be written) */ /* 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, (*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) { if (swrast->_RasterMask & ALPHABUF_BIT) {
_mesa_write_alpha_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, _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 * Read RGBA pixels from frame buffer. Clipping will be done to prevent
* reading ouside the buffer's boundaries. * reading ouside the buffer's boundaries.

View File

@@ -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 * Mesa 3-D graphics library
@@ -31,6 +31,7 @@
#include "mtypes.h" #include "mtypes.h"
#include "swrast.h" #include "swrast.h"
#include "s_trispan.h"
extern void extern void
@@ -61,6 +62,10 @@ _mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
GLenum primitive ); GLenum primitive );
extern void
_mesa_rasterize_span(GLcontext *ctx, struct triangle_span *span);
extern void extern void
_mesa_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y, _mesa_write_texture_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
const GLdepth z[], const GLfloat fog[], const GLdepth z[], const GLfloat fog[],

View File

@@ -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 * 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) * 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; GLuint i;
(void) u; (void) u;
#ifdef DEBUG
ASSERT (span_is_monotonous(n, lambda) == GL_TRUE);
#endif /* DEBUG */
/* since lambda is monotonous-array use this check first */ /* since lambda is monotonous-array use this check first */
if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) { if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
/* magnification for whole span */ /* magnification for whole span */

View File

@@ -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 * 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 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
* texture env modes. * texture env modes.
*/ */
static void static INLINE void
affine_span(GLcontext *ctx, struct triangle_span *span, affine_span(GLcontext *ctx, struct triangle_span *span,
struct affine_info *info) 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, fast_persp_span(GLcontext *ctx, struct triangle_span *span,
struct persp_info *info) struct persp_info *info)
{ {
@@ -973,335 +973,6 @@ static void persp_textured_triangle( GLcontext *ctx,
#endif /* CHAN_BITS != GL_FLOAT */ #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; \ span.texHeight[0] = (GLfloat) texImage->Height; \
(void) fixedToDepthShift; (void) fixedToDepthShift;
#define RENDER_SPAN( span ) rasterize_span(ctx, &span); #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
#include "s_tritemp.h" #include "s_tritemp.h"
} }
@@ -1433,7 +1104,7 @@ static void lambda_textured_triangle( GLcontext *ctx,
span.texHeight[0] = (GLfloat) texImage->Height; \ span.texHeight[0] = (GLfloat) texImage->Height; \
(void) fixedToDepthShift; (void) fixedToDepthShift;
#define RENDER_SPAN( span ) rasterize_span(ctx, &span); #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
#include "s_tritemp.h" #include "s_tritemp.h"
} }
@@ -1468,7 +1139,7 @@ static void lambda_textured_spec_triangle( GLcontext *ctx,
span.texHeight[0] = (GLfloat) texImage->Height; \ span.texHeight[0] = (GLfloat) texImage->Height; \
(void) fixedToDepthShift; (void) fixedToDepthShift;
#define RENDER_SPAN( span ) rasterize_span(ctx, &span); #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
#include "s_tritemp.h" #include "s_tritemp.h"
} }
@@ -1510,7 +1181,7 @@ lambda_multitextured_triangle( GLcontext *ctx,
} \ } \
(void) fixedToDepthShift; (void) fixedToDepthShift;
#define RENDER_SPAN( span ) rasterize_span(ctx, &span); #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
#include "s_tritemp.h" #include "s_tritemp.h"