/*
* Mesa 3-D graphics library
- * Version: 5.1
+ * Version: 6.1
*
- * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2004 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"),
{
GLuint i;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- COPY_4V(span->tex[i], ctx->Current.RasterTexCoords[i]);
+ const GLfloat *tc = ctx->Current.RasterTexCoords[i];
+ if (tc[3] > 0.0F) {
+ /* use (s/q, t/q, r/q, 1) */
+ span->tex[i][0] = tc[0] / tc[3];
+ span->tex[i][1] = tc[1] / tc[3];
+ span->tex[i][2] = tc[2] / tc[3];
+ span->tex[i][3] = 1.0;
+ }
+ else {
+ ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F);
+ }
ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
}
return lambda;
}
-/*
+
+/**
* Fill in the span.texcoords array from the interpolation values.
- * XXX We could optimize here for the case when dq = 0. That would
- * usually be the case when using an orthographic projection.
+ * Note: in the places where we divide by Q (or mult by invQ) we're
+ * really doing two things: perspective correction and texcoord
+ * projection. Remember, for texcoord (s,t,r,q) we need to index
+ * texels with (s/q, t/q, r/q).
+ * If we're using a fragment program, we never do the division
+ * for texcoord projection. That's done by the TXP instruction
+ * or user-written code.
*/
static void
interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
if (obj) {
const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
needLambda = (obj->MinFilter != obj->MagFilter)
- || ctx->FragmentProgram.Enabled;
+ || ctx->FragmentProgram._Enabled;
texW = img->WidthScale;
texH = img->HeightScale;
}
else {
+ /* using a fragment program */
texW = 1.0;
texH = 1.0;
needLambda = GL_FALSE;
GLfloat r = span->tex[u][2];
GLfloat q = span->tex[u][3];
GLuint i;
- for (i = 0; i < span->end; i++) {
- const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
- texcoord[i][0] = s * invQ;
- texcoord[i][1] = t * invQ;
- texcoord[i][2] = r * invQ;
- texcoord[i][3] = q;
- lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
- dqdx, dqdy, texW, texH,
- s, t, q, invQ);
- s += dsdx;
- t += dtdx;
- r += drdx;
- q += dqdx;
+ if (ctx->FragmentProgram._Enabled) {
+ /* do perspective correction but don't divide s, t, r by q */
+ const GLfloat dwdx = span->dwdx;
+ GLfloat w = span->w;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invW = 1.0F / w;
+ texcoord[i][0] = s * invW;
+ texcoord[i][1] = t * invW;
+ texcoord[i][2] = r * invW;
+ texcoord[i][3] = q * invW;
+ lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+ dqdx, dqdy, texW, texH,
+ s, t, q, invW);
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ w += dwdx;
+ }
+
+ }
+ else {
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
+ texcoord[i][0] = s * invQ;
+ texcoord[i][1] = t * invQ;
+ texcoord[i][2] = r * invQ;
+ texcoord[i][3] = q;
+ lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+ dqdx, dqdy, texW, texH,
+ s, t, q, invQ);
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ }
}
span->arrayMask |= SPAN_LAMBDA;
}
GLfloat r = span->tex[u][2];
GLfloat q = span->tex[u][3];
GLuint i;
- if (dqdx == 0.0) {
+ if (ctx->FragmentProgram._Enabled) {
+ /* do perspective correction but don't divide s, t, r by q */
+ const GLfloat dwdx = span->dwdx;
+ GLfloat w = span->w;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invW = 1.0F / w;
+ texcoord[i][0] = s * invW;
+ texcoord[i][1] = t * invW;
+ texcoord[i][2] = r * invW;
+ texcoord[i][3] = q * invW;
+ lambda[i] = 0.0;
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ w += dwdx;
+ }
+ }
+ else if (dqdx == 0.0F) {
/* Ortho projection or polygon's parallel to window X axis */
const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
for (i = 0; i < span->end; i++) {
if (obj) {
const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
needLambda = (obj->MinFilter != obj->MagFilter)
- || ctx->FragmentProgram.Enabled;
+ || ctx->FragmentProgram._Enabled;
texW = (GLfloat) img->WidthScale;
texH = (GLfloat) img->HeightScale;
}
GLfloat r = span->tex[0][2];
GLfloat q = span->tex[0][3];
GLuint i;
- for (i = 0; i < span->end; i++) {
- const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
- lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
- dqdx, dqdy, texW, texH,
- s, t, q, invQ);
- texcoord[i][0] = s * invQ;
- texcoord[i][1] = t * invQ;
- texcoord[i][2] = r * invQ;
- texcoord[i][3] = q;
- s += dsdx;
- t += dtdx;
- r += drdx;
- q += dqdx;
+ if (ctx->FragmentProgram._Enabled) {
+ /* do perspective correction but don't divide s, t, r by q */
+ const GLfloat dwdx = span->dwdx;
+ GLfloat w = span->w;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invW = 1.0F / w;
+ texcoord[i][0] = s * invW;
+ texcoord[i][1] = t * invW;
+ texcoord[i][2] = r * invW;
+ texcoord[i][3] = q * invW;
+ lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+ dqdx, dqdy, texW, texH,
+ s, t, q, invW);
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ w += dwdx;
+ }
+ }
+ else {
+ /* tex.c */
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
+ lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+ dqdx, dqdy, texW, texH,
+ s, t, q, invQ);
+ texcoord[i][0] = s * invQ;
+ texcoord[i][1] = t * invQ;
+ texcoord[i][2] = r * invQ;
+ texcoord[i][3] = q;
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ }
}
span->arrayMask |= SPAN_LAMBDA;
}
GLfloat r = span->tex[0][2];
GLfloat q = span->tex[0][3];
GLuint i;
- if (dqdx == 0.0) {
+ if (ctx->FragmentProgram._Enabled) {
+ /* do perspective correction but don't divide s, t, r by q */
+ const GLfloat dwdx = span->dwdx;
+ GLfloat w = span->w;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invW = 1.0F / w;
+ texcoord[i][0] = s * invW;
+ texcoord[i][1] = t * invW;
+ texcoord[i][2] = r * invW;
+ texcoord[i][3] = q * invW;
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ w += dwdx;
+ }
+ }
+ else if (dqdx == 0.0F) {
/* Ortho projection or polygon's parallel to window X axis */
const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
for (i = 0; i < span->end; i++) {
}
/* Fragment program */
- if (ctx->FragmentProgram.Enabled) {
- /* Now we may need to interpolate the colors */
+ if (ctx->FragmentProgram._Enabled) {
+ /* Now we may need to interpolate the colors and texcoords */
if ((span->interpMask & SPAN_RGBA) &&
(span->arrayMask & SPAN_RGBA) == 0) {
interpolate_colors(ctx, span);
if (span->interpMask & SPAN_SPEC) {
interpolate_specular(ctx, span);
}
+ if ((span->interpMask & SPAN_TEXTURE)
+ && (span->arrayMask & SPAN_TEXTURE) == 0)
+ interpolate_texcoords(ctx, span);
_swrast_exec_fragment_program(ctx, span);
monoColor = GL_FALSE;
}
/* write pixels */
if (span->arrayMask & SPAN_XY) {
/* array of pixel coords */
- /* XXX test for mono color */
- (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
- span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
- if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
- _swrast_write_alpha_pixels(ctx, span->end,
- span->array->x, span->array->y,
- (const GLchan (*)[4]) span->array->rgba,
- span->array->mask);
+ if (monoColor) {
+ /* all pixels have same color */
+ GLchan color[4];
+ color[RCOMP] = FixedToChan(span->red);
+ color[GCOMP] = FixedToChan(span->green);
+ color[BCOMP] = FixedToChan(span->blue);
+ color[ACOMP] = FixedToChan(span->alpha);
+ (*swrast->Driver.WriteMonoRGBAPixels)(ctx, span->end,
+ span->array->x, span->array->y, color, span->array->mask);
+ if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
+ _swrast_write_mono_alpha_pixels(ctx, span->end,
+ span->array->x, span->array->y,
+ color[ACOMP], span->array->mask);
+ }
+ }
+ else {
+ (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
+ span->array->x, span->array->y,
+ (const GLchan (*)[4]) span->array->rgba,
+ span->array->mask);
+ if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
+ _swrast_write_alpha_pixels(ctx, span->end,
+ span->array->x, span->array->y,
+ (const GLchan (*)[4]) span->array->rgba,
+ span->array->mask);
+ }
}
}
else {
color[BCOMP] = FixedToChan(span->blue);
color[ACOMP] = FixedToChan(span->alpha);
(*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
- span->y, color, span->array->mask);
+ span->y, color, span->array->mask);
if (swrast->_RasterMask & ALPHABUF_BIT) {
_swrast_write_mono_alpha_span(ctx, span->end, span->x, span->y,
color[ACOMP],
span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
ASSERT(span->end <= MAX_WIDTH);
ASSERT((span->interpMask & span->arrayMask) == 0);
- ASSERT(ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram.Enabled);
+ ASSERT(ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Enabled);
/*
printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
/* Texturing without alpha is done after depth-testing which
* gives a potential speed-up.
*/
- if (ctx->FragmentProgram.Enabled)
+ if (ctx->FragmentProgram._Enabled)
_swrast_exec_fragment_program( ctx, span );
else
_swrast_texture_span( ctx, span );
interpolate_specular(ctx, span);
}
- if (ctx->FragmentProgram.Enabled)
+ if (ctx->FragmentProgram._Enabled)
_swrast_exec_fragment_program( ctx, span );
else
_swrast_texture_span( ctx, span );