X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_span.c;h=41db42e2b80726689fe1b1fdf39acdb224fab2f3;hb=1a544b0500ebacb52a7412ad17c4a2002a00ff94;hp=801595d970c008cd03c5a1e7312e2470f7e22497;hpb=e22540c2765e034fed558ea1d44488a03fbba170;p=mesa.git diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index 801595d970c..41db42e2b80 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -1,8 +1,8 @@ /* * 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"), @@ -126,7 +126,17 @@ _swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span ) { 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); } @@ -340,10 +350,16 @@ _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 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) @@ -363,11 +379,12 @@ 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; @@ -387,19 +404,42 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) 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; } @@ -415,7 +455,25 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) 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++) { @@ -455,7 +513,7 @@ 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 = (GLfloat) img->WidthScale; texH = (GLfloat) img->HeightScale; } @@ -480,19 +538,42 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) 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; } @@ -508,7 +589,24 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) 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++) { @@ -653,7 +751,7 @@ multi_write_index_span( GLcontext *ctx, struct sw_span *span ) ASSERT(span->end < MAX_WIDTH); /* Set the current read/draw buffer */ - swrast->CurrentBuffer = bufferBit; + swrast->CurrentBufferBit = bufferBit; (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); /* make copy of incoming indexes */ @@ -710,7 +808,7 @@ multi_write_rgba_span( GLcontext *ctx, struct sw_span *span ) ASSERT(span->end < MAX_WIDTH); /* Set the current read/draw buffer */ - swrast->CurrentBuffer = bufferBit; + swrast->CurrentBufferBit = bufferBit; (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); /* make copy of incoming colors */ @@ -1006,8 +1104,8 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) } /* 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); @@ -1016,6 +1114,9 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *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; } @@ -1118,14 +1219,32 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) /* 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 { @@ -1138,7 +1257,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) 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], @@ -1207,7 +1326,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span) 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); @@ -1267,7 +1386,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span) /* 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 ); @@ -1334,7 +1453,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *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 );