diff options
Diffstat (limited to 'xc/extras/Mesa/src/swrast')
50 files changed, 6267 insertions, 6813 deletions
diff --git a/xc/extras/Mesa/src/swrast/s_aaline.c b/xc/extras/Mesa/src/swrast/s_aaline.c index 08bcaac63..cef87b2c1 100644 --- a/xc/extras/Mesa/src/swrast/s_aaline.c +++ b/xc/extras/Mesa/src/swrast/s_aaline.c @@ -1,10 +1,9 @@ -/* $Id: s_aaline.c,v 1.1.1.1 2002/10/22 13:06:56 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -27,8 +26,8 @@ #include "glheader.h" #include "swrast/s_aaline.h" -#include "swrast/s_pb.h" #include "swrast/s_context.h" +#include "swrast/s_span.h" #include "swrast/swrast.h" #include "mtypes.h" #include "mmath.h" @@ -75,6 +74,8 @@ struct LineInfo GLfloat vPlane[MAX_TEXTURE_UNITS][4]; GLfloat lambda[MAX_TEXTURE_UNITS]; GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS]; + + struct sw_span span; }; @@ -326,8 +327,9 @@ compute_coveragef(const struct LineInfo *info, -typedef void (*plot_func)(GLcontext *ctx, const struct LineInfo *line, - struct pixel_buffer *pb, int ix, int iy); +typedef void (*plot_func)(GLcontext *ctx, struct LineInfo *line, + int ix, int iy); + /* @@ -337,7 +339,6 @@ static void segment(GLcontext *ctx, struct LineInfo *line, plot_func plot, - struct pixel_buffer *pb, GLfloat t0, GLfloat t1) { const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx; @@ -407,7 +408,7 @@ segment(GLcontext *ctx, GLint iy; /* scan across the line, bottom-to-top */ for (iy = iyBot; iy < iyTop; iy++) { - (*plot)(ctx, line, pb, ix, iy); + (*plot)(ctx, line, ix, iy); } yBot += dydx; yTop += dydx; @@ -453,7 +454,7 @@ segment(GLcontext *ctx, GLint ix; /* scan across the line, left-to-right */ for (ix = ixLeft; ix < ixRight; ix++) { - (*plot)(ctx, line, pb, ix, iy); + (*plot)(ctx, line, ix, iy); } xLeft += dxdy; xRight += dxdy; @@ -486,6 +487,7 @@ segment(GLcontext *ctx, #define NAME(x) aa_multitex_rgba_##x #define DO_Z +#define DO_FOG #define DO_RGBA #define DO_MULTITEX #include "s_aalinetemp.h" @@ -493,6 +495,7 @@ segment(GLcontext *ctx, #define NAME(x) aa_multitex_spec_##x #define DO_Z +#define DO_FOG #define DO_RGBA #define DO_MULTITEX #define DO_SPEC @@ -509,8 +512,8 @@ _swrast_choose_aa_line_function(GLcontext *ctx) if (ctx->Visual.rgbMode) { /* RGBA */ - if (ctx->Texture._ReallyEnabled) { - if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { + if (ctx->Texture._EnabledUnits != 0) { + if (ctx->Texture._EnabledUnits > 1) { /* Multitextured! */ if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR || ctx->Fog.ColorSumEnabled) diff --git a/xc/extras/Mesa/src/swrast/s_aalinetemp.h b/xc/extras/Mesa/src/swrast/s_aalinetemp.h index bd675f365..4dc2691a1 100644 --- a/xc/extras/Mesa/src/swrast/s_aalinetemp.h +++ b/xc/extras/Mesa/src/swrast/s_aalinetemp.h @@ -1,10 +1,9 @@ -/* $Id: s_aalinetemp.h,v 1.1.1.1 2002/10/22 13:06:52 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -34,107 +33,81 @@ * Function to render each fragment in the AA line. */ static void -NAME(plot)(GLcontext *ctx, const struct LineInfo *line, - struct pixel_buffer *pb, int ix, int iy) +NAME(plot)(GLcontext *ctx, struct LineInfo *line, int ix, int iy) { const GLfloat fx = (GLfloat) ix; const GLfloat fy = (GLfloat) iy; const GLfloat coverage = compute_coveragef(line, ix, iy); - GLdepth z; - GLfloat fog; -#ifdef DO_RGBA - GLchan red, green, blue, alpha; -#else - GLint index; -#endif - GLchan specRed, specGreen, specBlue; - GLfloat tex[MAX_TEXTURE_UNITS][4], lambda[MAX_TEXTURE_UNITS]; + const GLuint i = line->span.end; if (coverage == 0.0) return; + line->span.end++; + line->span.array->coverage[i] = coverage; + line->span.array->x[i] = ix; + line->span.array->y[i] = iy; + /* * Compute Z, color, texture coords, fog for the fragment by * solving the plane equations at (ix,iy). */ #ifdef DO_Z - z = (GLdepth) solve_plane(fx, fy, line->zPlane); -#else - z = 0.0; + line->span.array->z[i] = (GLdepth) solve_plane(fx, fy, line->zPlane); #endif #ifdef DO_FOG - fog = solve_plane(fx, fy, line->fPlane); -#else - fog = 0.0; + line->span.array->fog[i] = solve_plane(fx, fy, line->fPlane); #endif #ifdef DO_RGBA - red = solve_plane_chan(fx, fy, line->rPlane); - green = solve_plane_chan(fx, fy, line->gPlane); - blue = solve_plane_chan(fx, fy, line->bPlane); - alpha = solve_plane_chan(fx, fy, line->aPlane); + line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane); + line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane); + line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane); + line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane); #endif #ifdef DO_INDEX - index = (GLint) solve_plane(fx, fy, line->iPlane); + line->span.array->index[i] = (GLint) solve_plane(fx, fy, line->iPlane); #endif #ifdef DO_SPEC - specRed = solve_plane_chan(fx, fy, line->srPlane); - specGreen = solve_plane_chan(fx, fy, line->sgPlane); - specBlue = solve_plane_chan(fx, fy, line->sbPlane); -#else - (void) specRed; - (void) specGreen; - (void) specBlue; + line->span.array->spec[i][RCOMP] = solve_plane_chan(fx, fy, line->srPlane); + line->span.array->spec[i][GCOMP] = solve_plane_chan(fx, fy, line->sgPlane); + line->span.array->spec[i][BCOMP] = solve_plane_chan(fx, fy, line->sbPlane); #endif #ifdef DO_TEX { - GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[0]); - tex[0][0] = solve_plane(fx, fy, line->sPlane[0]) * invQ; - tex[0][1] = solve_plane(fx, fy, line->tPlane[0]) * invQ; - tex[0][2] = solve_plane(fx, fy, line->uPlane[0]) * invQ; - lambda[0] = compute_lambda(line->sPlane[0], line->tPlane[0], invQ, - line->texWidth[0], line->texHeight[0]); + const GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[0]); + line->span.array->texcoords[0][i][0] = solve_plane(fx, fy, line->sPlane[0]) * invQ; + line->span.array->texcoords[0][i][1] = solve_plane(fx, fy, line->tPlane[0]) * invQ; + line->span.array->texcoords[0][i][2] = solve_plane(fx, fy, line->uPlane[0]) * invQ; + line->span.array->lambda[0][i] = compute_lambda(line->sPlane[0], line->tPlane[0], invQ, + line->texWidth[0], line->texHeight[0]); } #elif defined(DO_MULTITEX) { GLuint unit; for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled) { - GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[unit]); - tex[unit][0] = solve_plane(fx, fy, line->sPlane[unit]) * invQ; - tex[unit][1] = solve_plane(fx, fy, line->tPlane[unit]) * invQ; - tex[unit][2] = solve_plane(fx, fy, line->uPlane[unit]) * invQ; - lambda[unit] = compute_lambda(line->sPlane[unit], - line->tPlane[unit], invQ, - line->texWidth[unit], line->texHeight[unit]); + const GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[unit]); + line->span.array->texcoords[unit][i][0] = solve_plane(fx, fy, line->sPlane[unit]) * invQ; + line->span.array->texcoords[unit][i][1] = solve_plane(fx, fy, line->tPlane[unit]) * invQ; + line->span.array->texcoords[unit][i][2] = solve_plane(fx, fy, line->uPlane[unit]) * invQ; + line->span.array->lambda[unit][i] = compute_lambda(line->sPlane[unit], + line->tPlane[unit], invQ, + line->texWidth[unit], line->texHeight[unit]); } } } -#else - (void) tex[0][0]; - (void) lambda[0]; #endif - - PB_COVERAGE(pb, coverage); - -#if defined(DO_MULTITEX) -#if defined(DO_SPEC) - PB_WRITE_MULTITEX_SPEC_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha, - specRed, specGreen, specBlue, tex); -#else - PB_WRITE_MULTITEX_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha, tex); -#endif -#elif defined(DO_TEX) - PB_WRITE_TEX_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha, - tex[0][0], tex[0][1], tex[0][2]); + if (line->span.end == MAX_WIDTH) { +#if defined(DO_TEX) || defined(DO_MULTITEX) + _mesa_write_texture_span(ctx, &(line->span)); #elif defined(DO_RGBA) - PB_WRITE_RGBA_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha); -#elif defined(DO_INDEX) - PB_WRITE_CI_PIXEL(pb, ix, iy, z, fog, index); + _mesa_write_rgba_span(ctx, &(line->span)); +#else + _mesa_write_index_span(ctx, &(line->span)); #endif - - pb->haveCoverage = GL_TRUE; - PB_CHECK_FLUSH(ctx, pb); + line->span.end = 0; /* reset counter */ + } } @@ -146,7 +119,6 @@ static void NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - struct pixel_buffer *pb = SWRAST_CONTEXT(ctx)->PB; GLfloat tStart, tEnd; /* segment start, end along line length */ GLboolean inSegment; GLint iLen, i; @@ -165,18 +137,23 @@ NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) if (line.len == 0.0 || IS_INF_OR_NAN(line.len)) return; + INIT_SPAN(line.span, GL_LINE, 0, 0, SPAN_XY | SPAN_COVERAGE); + line.xAdj = line.dx / line.len * line.halfWidth; line.yAdj = line.dy / line.len * line.halfWidth; #ifdef DO_Z + line.span.arrayMask |= SPAN_Z; compute_plane(line.x0, line.y0, line.x1, line.y1, v0->win[2], v1->win[2], line.zPlane); #endif #ifdef DO_FOG + line.span.arrayMask |= SPAN_FOG; compute_plane(line.x0, line.y0, line.x1, line.y1, v0->fog, v1->fog, line.fPlane); #endif #ifdef DO_RGBA + line.span.arrayMask |= SPAN_RGBA; if (ctx->Light.ShadeModel == GL_SMOOTH) { compute_plane(line.x0, line.y0, line.x1, line.y1, v0->color[RCOMP], v1->color[RCOMP], line.rPlane); @@ -195,6 +172,7 @@ NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) } #endif #ifdef DO_SPEC + line.span.arrayMask |= SPAN_SPEC; if (ctx->Light.ShadeModel == GL_SMOOTH) { compute_plane(line.x0, line.y0, line.x1, line.y1, v0->specular[RCOMP], v1->specular[RCOMP], line.srPlane); @@ -210,6 +188,7 @@ NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) } #endif #ifdef DO_INDEX + line.span.arrayMask |= SPAN_INDEX; if (ctx->Light.ShadeModel == GL_SMOOTH) { compute_plane(line.x0, line.y0, line.x1, line.y1, (GLfloat) v0->index, (GLfloat) v1->index, line.iPlane); @@ -232,6 +211,7 @@ NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) const GLfloat r1 = v1->texcoord[0][2] * invW0; const GLfloat q0 = v0->texcoord[0][3] * invW0; const GLfloat q1 = v1->texcoord[0][3] * invW0; + line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA); compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[0]); compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[0]); compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[0]); @@ -242,6 +222,7 @@ NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) #elif defined(DO_MULTITEX) { GLuint u; + line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA); for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { if (ctx->Texture.Unit[u]._ReallyEnabled) { const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; @@ -291,7 +272,7 @@ NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) /* stipple bit is off */ if (inSegment && (tEnd > tStart)) { /* draw the segment */ - segment(ctx, &line, NAME(plot), pb, tStart, tEnd); + segment(ctx, &line, NAME(plot), tStart, tEnd); inSegment = GL_FALSE; } else { @@ -303,13 +284,21 @@ NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) if (inSegment) { /* draw the final segment of the line */ - segment(ctx, &line, NAME(plot), pb, tStart, 1.0F); + segment(ctx, &line, NAME(plot), tStart, 1.0F); } } else { /* non-stippled */ - segment(ctx, &line, NAME(plot), pb, 0.0, 1.0); + segment(ctx, &line, NAME(plot), 0.0, 1.0); } + +#if defined(DO_TEX) || defined(DO_MULTITEX) + _mesa_write_texture_span(ctx, &(line.span)); +#elif defined(DO_RGBA) + _mesa_write_rgba_span(ctx, &(line.span)); +#else + _mesa_write_index_span(ctx, &(line.span)); +#endif } diff --git a/xc/extras/Mesa/src/swrast/s_aatriangle.c b/xc/extras/Mesa/src/swrast/s_aatriangle.c index e58e93b7e..6a8c38ea3 100644 --- a/xc/extras/Mesa/src/swrast/s_aatriangle.c +++ b/xc/extras/Mesa/src/swrast/s_aatriangle.c @@ -1,10 +1,9 @@ -/* $Id: s_aatriangle.c,v 1.1.1.1 2002/10/22 13:06:45 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.1 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -30,7 +29,9 @@ */ -#include "mem.h" +#include "glheader.h" +#include "macros.h" +#include "imports.h" #include "mmath.h" #include "s_aatriangle.h" #include "s_context.h" @@ -40,6 +41,7 @@ /* * Compute coefficients of a plane using the X,Y coords of the v0, v1, v2 * vertices and the given Z values. + * A point (x,y,z) lies on plane iff a*x+b*y+c*z+d = 0. */ static INLINE void compute_plane(const GLfloat v0[], const GLfloat v1[], const GLfloat v2[], @@ -53,9 +55,15 @@ compute_plane(const GLfloat v0[], const GLfloat v1[], const GLfloat v2[], const GLfloat qy = v2[1] - v0[1]; const GLfloat qz = z2 - z0; + /* Crossproduct "(a,b,c):= dv1 x dv2" is orthogonal to plane. */ const GLfloat a = py * qz - pz * qy; const GLfloat b = pz * qx - px * qz; const GLfloat c = px * qy - py * qx; + /* Point on the plane = "r*(a,b,c) + w", with fixed "r" depending + on the distance of plane from origin and arbitrary "w" parallel + to the plane. */ + /* The scalar product "(r*(a,b,c)+w)*(a,b,c)" is "r*(a^2+b^2+c^2)", + which is equal to "-d" below. */ const GLfloat d = -(a * v0[0] + b * v0[1] + c * z0); plane[0] = a; @@ -93,8 +101,8 @@ do { \ static INLINE GLfloat solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4]) { - const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; - return z; + ASSERT(plane[2] != 0.0F); + return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; } @@ -116,7 +124,6 @@ solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) } - /* * Solve plane and return clamped GLchan value. */ @@ -193,7 +200,7 @@ compute_coveragef(const GLfloat v0[3], const GLfloat v1[3], #ifdef DEBUG { const GLfloat area = dx0 * dy1 - dx1 * dy0; - assert(area >= 0.0); + ASSERT(area >= 0.0); } #endif @@ -276,7 +283,7 @@ compute_coveragei(const GLfloat v0[3], const GLfloat v1[3], #ifdef DEBUG { const GLfloat area = dx0 * dy1 - dx1 * dy0; - assert(area >= 0.0); + ASSERT(area >= 0.0); } #endif @@ -344,23 +351,36 @@ index_aa_tri(GLcontext *ctx, /* * Compute mipmap level of detail. + * XXX we should really include the R coordinate in this computation + * in order to do 3-D texture mipmapping. */ static INLINE GLfloat compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4], - GLfloat invQ, GLfloat width, GLfloat height) + const GLfloat qPlane[4], GLfloat cx, GLfloat cy, + GLfloat invQ, GLfloat texWidth, GLfloat texHeight) { - GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width; - GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width; - GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height; - GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height; - GLfloat r1 = dudx * dudx + dudy * dudy; - GLfloat r2 = dvdx * dvdx + dvdy * dvdy; - GLfloat rho2 = r1 + r2; - /* return log base 2 of rho */ - if (rho2 == 0.0F) - return 0.0; - else - return (GLfloat) (log(rho2) * 1.442695 * 0.5); /* 1.442695 = 1/log(2) */ + const GLfloat s = solve_plane(cx, cy, sPlane); + const GLfloat t = solve_plane(cx, cy, tPlane); + const GLfloat invQ_x1 = solve_plane_recip(cx+1.0F, cy, qPlane); + const GLfloat invQ_y1 = solve_plane_recip(cx, cy+1.0F, qPlane); + const GLfloat s_x1 = s - sPlane[0] / sPlane[2]; + const GLfloat s_y1 = s - sPlane[1] / sPlane[2]; + const GLfloat t_x1 = t - tPlane[0] / tPlane[2]; + const GLfloat t_y1 = t - tPlane[1] / tPlane[2]; + GLfloat dsdx = s_x1 * invQ_x1 - s * invQ; + GLfloat dsdy = s_y1 * invQ_y1 - s * invQ; + GLfloat dtdx = t_x1 * invQ_x1 - t * invQ; + GLfloat dtdy = t_y1 * invQ_y1 - t * invQ; + GLfloat maxU, maxV, rho, lambda; + dsdx = FABSF(dsdx); + dsdy = FABSF(dsdy); + dtdx = FABSF(dtdx); + dtdy = FABSF(dtdy); + maxU = MAX2(dsdx, dsdy) * texWidth; + maxV = MAX2(dtdx, dtdy) * texHeight; + rho = MAX2(maxU, maxV); + lambda = LOG2(rho); + return lambda; } @@ -430,9 +450,9 @@ _mesa_set_aa_triangle_function(GLcontext *ctx) { ASSERT(ctx->Polygon.SmoothFlag); - if (ctx->Texture._ReallyEnabled) { + if (ctx->Texture._EnabledUnits != 0) { if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { - if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { + if (ctx->Texture._EnabledUnits > 1) { SWRAST_CONTEXT(ctx)->Triangle = spec_multitex_aa_tri; } else { @@ -440,7 +460,7 @@ _mesa_set_aa_triangle_function(GLcontext *ctx) } } else { - if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { + if (ctx->Texture._EnabledUnits > 1) { SWRAST_CONTEXT(ctx)->Triangle = multitex_aa_tri; } else { diff --git a/xc/extras/Mesa/src/swrast/s_aatritemp.h b/xc/extras/Mesa/src/swrast/s_aatritemp.h index 0b2e073de..abe99ecf4 100644 --- a/xc/extras/Mesa/src/swrast/s_aatritemp.h +++ b/xc/extras/Mesa/src/swrast/s_aatritemp.h @@ -1,10 +1,9 @@ -/* $Id: s_aatritemp.h,v 1.1.1.1 2002/10/22 13:06:51 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -52,64 +51,40 @@ GLfloat yMin, yMax; GLboolean ltor; GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */ - + + struct sw_span span; + #ifdef DO_Z GLfloat zPlane[4]; - GLdepth z[MAX_WIDTH]; #endif #ifdef DO_FOG GLfloat fogPlane[4]; - GLfloat fog[MAX_WIDTH]; #else GLfloat *fog = NULL; #endif #ifdef DO_RGBA GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; - DEFMARRAY(GLchan, rgba, MAX_WIDTH, 4); /* mac 32k limitation */ #endif #ifdef DO_INDEX GLfloat iPlane[4]; - GLuint index[MAX_WIDTH]; - GLint icoverageSpan[MAX_WIDTH]; -#else - GLfloat coverageSpan[MAX_WIDTH]; #endif #ifdef DO_SPEC GLfloat srPlane[4], sgPlane[4], sbPlane[4]; - DEFMARRAY(GLchan, spec, MAX_WIDTH, 4); #endif #ifdef DO_TEX GLfloat sPlane[4], tPlane[4], uPlane[4], vPlane[4]; GLfloat texWidth, texHeight; - DEFARRAY(GLfloat, s, MAX_WIDTH); /* mac 32k limitation */ - DEFARRAY(GLfloat, t, MAX_WIDTH); - DEFARRAY(GLfloat, u, MAX_WIDTH); - DEFARRAY(GLfloat, lambda, MAX_WIDTH); #elif defined(DO_MULTITEX) - GLfloat sPlane[MAX_TEXTURE_UNITS][4]; - GLfloat tPlane[MAX_TEXTURE_UNITS][4]; - GLfloat uPlane[MAX_TEXTURE_UNITS][4]; - GLfloat vPlane[MAX_TEXTURE_UNITS][4]; + GLfloat sPlane[MAX_TEXTURE_UNITS][4]; /* texture S */ + GLfloat tPlane[MAX_TEXTURE_UNITS][4]; /* texture T */ + GLfloat uPlane[MAX_TEXTURE_UNITS][4]; /* texture R */ + GLfloat vPlane[MAX_TEXTURE_UNITS][4]; /* texture Q */ GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS]; - DEFMARRAY(GLfloat, s, MAX_TEXTURE_UNITS, MAX_WIDTH); /* mac 32k limit */ - DEFMARRAY(GLfloat, t, MAX_TEXTURE_UNITS, MAX_WIDTH); - DEFMARRAY(GLfloat, u, MAX_TEXTURE_UNITS, MAX_WIDTH); - DEFMARRAY(GLfloat, lambda, MAX_TEXTURE_UNITS, MAX_WIDTH); #endif GLfloat bf = SWRAST_CONTEXT(ctx)->_backface_sign; - -#ifdef DO_RGBA - CHECKARRAY(rgba, return); /* mac 32k limitation */ -#endif -#ifdef DO_SPEC - CHECKARRAY(spec, return); -#endif -#if defined(DO_TEX) || defined(DO_MULTITEX) - CHECKARRAY(s, return); - CHECKARRAY(t, return); - CHECKARRAY(u, return); - CHECKARRAY(lambda, return); -#endif + + + INIT_SPAN(span, GL_POLYGON, 0, 0, SPAN_COVERAGE); /* determine bottom to top order of vertices */ { @@ -164,9 +139,11 @@ */ #ifdef DO_Z compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane); + span.arrayMask |= SPAN_Z; #endif #ifdef DO_FOG compute_plane(p0, p1, p2, v0->fog, v1->fog, v2->fog, fogPlane); + span.arrayMask |= SPAN_FOG; #endif #ifdef DO_RGBA if (ctx->Light.ShadeModel == GL_SMOOTH) { @@ -181,6 +158,7 @@ constant_plane(v2->color[BCOMP], bPlane); constant_plane(v2->color[ACOMP], aPlane); } + span.arrayMask |= SPAN_RGBA; #endif #ifdef DO_INDEX if (ctx->Light.ShadeModel == GL_SMOOTH) { @@ -190,6 +168,7 @@ else { constant_plane((GLfloat) v2->index, iPlane); } + span.arrayMask |= SPAN_INDEX; #endif #ifdef DO_SPEC if (ctx->Light.ShadeModel == GL_SMOOTH) { @@ -202,6 +181,7 @@ constant_plane(v2->specular[GCOMP], sgPlane); constant_plane(v2->specular[BCOMP], sbPlane); } + span.arrayMask |= SPAN_SPEC; #endif #ifdef DO_TEX { @@ -229,6 +209,7 @@ texWidth = (GLfloat) texImage->Width; texHeight = (GLfloat) texImage->Height; } + span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA); #elif defined(DO_MULTITEX) { GLuint u; @@ -260,6 +241,7 @@ } } } + span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA); #endif /* Begin bottom-to-top scan over the triangle. @@ -284,8 +266,9 @@ GLint iy; for (iy = iyMin; iy < iyMax; iy++, x += dxdy) { GLint ix, startX = (GLint) (x - xAdj); - GLuint count, n; + GLuint count; GLfloat coverage = 0.0F; + /* skip over fragments with zero coverage */ while (startX < MAX_WIDTH) { coverage = compute_coveragef(pMin, pMid, pMax, startX, iy); @@ -300,39 +283,41 @@ while (coverage > 0.0F) { /* (cx,cy) = center of fragment */ const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; + struct span_arrays *array = span.array; #ifdef DO_INDEX - icoverageSpan[count] = compute_coveragei(pMin, pMid, pMax, ix, iy); + array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy); #else - coverageSpan[count] = coverage; + array->coverage[count] = coverage; #endif #ifdef DO_Z - z[count] = (GLdepth) solve_plane(cx, cy, zPlane); + array->z[count] = (GLdepth) solve_plane(cx, cy, zPlane); #endif #ifdef DO_FOG - fog[count] = solve_plane(cx, cy, fogPlane); + array->fog[count] = solve_plane(cx, cy, fogPlane); #endif #ifdef DO_RGBA - rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane); - rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane); - rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane); - rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane); + array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane); + array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane); + array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane); + array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane); #endif #ifdef DO_INDEX - index[count] = (GLint) solve_plane(cx, cy, iPlane); + array->index[count] = (GLint) solve_plane(cx, cy, iPlane); #endif #ifdef DO_SPEC - spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane); - spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane); - spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane); + array->spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane); + array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane); + array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane); #endif #ifdef DO_TEX { const GLfloat invQ = solve_plane_recip(cx, cy, vPlane); - s[count] = solve_plane(cx, cy, sPlane) * invQ; - t[count] = solve_plane(cx, cy, tPlane) * invQ; - u[count] = solve_plane(cx, cy, uPlane) * invQ; - lambda[count] = compute_lambda(sPlane, tPlane, invQ, - texWidth, texHeight); + array->texcoords[0][count][0] = solve_plane(cx, cy, sPlane) * invQ; + array->texcoords[0][count][1] = solve_plane(cx, cy, tPlane) * invQ; + array->texcoords[0][count][2] = solve_plane(cx, cy, uPlane) * invQ; + array->lambda[0][count] = compute_lambda(sPlane, tPlane, vPlane, + cx, cy, invQ, + texWidth, texHeight); } #elif defined(DO_MULTITEX) { @@ -340,11 +325,12 @@ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled) { GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]); - s[unit][count] = solve_plane(cx, cy, sPlane[unit]) * invQ; - t[unit][count] = solve_plane(cx, cy, tPlane[unit]) * invQ; - u[unit][count] = solve_plane(cx, cy, uPlane[unit]) * invQ; - lambda[unit][count] = compute_lambda(sPlane[unit], - tPlane[unit], invQ, texWidth[unit], texHeight[unit]); + array->texcoords[unit][count][0] = solve_plane(cx, cy, sPlane[unit]) * invQ; + array->texcoords[unit][count][1] = solve_plane(cx, cy, tPlane[unit]) * invQ; + array->texcoords[unit][count][2] = solve_plane(cx, cy, uPlane[unit]) * invQ; + array->lambda[unit][count] = compute_lambda(sPlane[unit], + tPlane[unit], vPlane[unit], cx, cy, invQ, + texWidth[unit], texHeight[unit]); } } } @@ -353,46 +339,20 @@ count++; coverage = compute_coveragef(pMin, pMid, pMax, ix, iy); } - + if (ix <= startX) continue; - - n = (GLuint) ix - (GLuint) startX; - -#ifdef DO_MULTITEX -# ifdef DO_SPEC - _mesa_write_multitexture_span(ctx, n, startX, iy, z, fog, - (const GLfloat (*)[MAX_WIDTH]) s, - (const GLfloat (*)[MAX_WIDTH]) t, - (const GLfloat (*)[MAX_WIDTH]) u, - (GLfloat (*)[MAX_WIDTH]) lambda, - rgba, (const GLchan (*)[4]) spec, - coverageSpan, GL_POLYGON); -# else - _mesa_write_multitexture_span(ctx, n, startX, iy, z, fog, - (const GLfloat (*)[MAX_WIDTH]) s, - (const GLfloat (*)[MAX_WIDTH]) t, - (const GLfloat (*)[MAX_WIDTH]) u, - lambda, rgba, NULL, coverageSpan, - GL_POLYGON); -# endif -#elif defined(DO_TEX) -# ifdef DO_SPEC - _mesa_write_texture_span(ctx, n, startX, iy, z, fog, - s, t, u, lambda, rgba, - (const GLchan (*)[4]) spec, - coverageSpan, GL_POLYGON); -# else - _mesa_write_texture_span(ctx, n, startX, iy, z, fog, - s, t, u, lambda, - rgba, NULL, coverageSpan, GL_POLYGON); -# endif + + span.x = startX; + span.y = iy; + span.end = (GLuint) ix - (GLuint) startX; + ASSERT(span.interpMask == 0); +#if defined(DO_MULTITEX) || defined(DO_TEX) + _mesa_write_texture_span(ctx, &span); #elif defined(DO_RGBA) - _mesa_write_rgba_span(ctx, n, startX, iy, z, fog, rgba, - coverageSpan, GL_POLYGON); + _mesa_write_rgba_span(ctx, &span); #elif defined(DO_INDEX) - _mesa_write_index_span(ctx, n, startX, iy, z, fog, index, - icoverageSpan, GL_POLYGON); + _mesa_write_index_span(ctx, &span); #endif } } @@ -409,7 +369,7 @@ GLint ix, left, startX = (GLint) (x + xAdj); GLuint count, n; GLfloat coverage = 0.0F; - + /* make sure we're not past the window edge */ if (startX >= ctx->DrawBuffer->_Xmax) { startX = ctx->DrawBuffer->_Xmax - 1; @@ -422,46 +382,47 @@ break; startX--; } - + /* enter interior of triangle */ ix = startX; count = 0; while (coverage > 0.0F) { /* (cx,cy) = center of fragment */ const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; + struct span_arrays *array = span.array; #ifdef DO_INDEX - icoverageSpan[ix] = compute_coveragei(pMin, pMid, pMax, ix, iy); + array->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy); #else - coverageSpan[ix] = coverage; + array->coverage[ix] = coverage; #endif #ifdef DO_Z - z[ix] = (GLdepth) solve_plane(cx, cy, zPlane); + array->z[ix] = (GLdepth) solve_plane(cx, cy, zPlane); #endif #ifdef DO_FOG - fog[ix] = solve_plane(cx, cy, fogPlane); + array->fog[ix] = solve_plane(cx, cy, fogPlane); #endif #ifdef DO_RGBA - rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane); - rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane); - rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane); - rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane); + array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane); + array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane); + array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane); + array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane); #endif #ifdef DO_INDEX - index[ix] = (GLint) solve_plane(cx, cy, iPlane); + array->index[ix] = (GLint) solve_plane(cx, cy, iPlane); #endif #ifdef DO_SPEC - spec[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane); - spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane); - spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane); + array->spec[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane); + array->spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane); + array->spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane); #endif #ifdef DO_TEX { const GLfloat invQ = solve_plane_recip(cx, cy, vPlane); - s[ix] = solve_plane(cx, cy, sPlane) * invQ; - t[ix] = solve_plane(cx, cy, tPlane) * invQ; - u[ix] = solve_plane(cx, cy, uPlane) * invQ; - lambda[ix] = compute_lambda(sPlane, tPlane, invQ, - texWidth, texHeight); + array->texcoords[0][ix][0] = solve_plane(cx, cy, sPlane) * invQ; + array->texcoords[0][ix][1] = solve_plane(cx, cy, tPlane) * invQ; + array->texcoords[0][ix][2] = solve_plane(cx, cy, uPlane) * invQ; + array->lambda[0][ix] = compute_lambda(sPlane, tPlane, vPlane, + cx, cy, invQ, texWidth, texHeight); } #elif defined(DO_MULTITEX) { @@ -469,11 +430,15 @@ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled) { GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]); - s[unit][ix] = solve_plane(cx, cy, sPlane[unit]) * invQ; - t[unit][ix] = solve_plane(cx, cy, tPlane[unit]) * invQ; - u[unit][ix] = solve_plane(cx, cy, uPlane[unit]) * invQ; - lambda[unit][ix] = compute_lambda(sPlane[unit], - tPlane[unit], invQ, texWidth[unit], texHeight[unit]); + array->texcoords[unit][ix][0] = solve_plane(cx, cy, sPlane[unit]) * invQ; + array->texcoords[unit][ix][1] = solve_plane(cx, cy, tPlane[unit]) * invQ; + array->texcoords[unit][ix][2] = solve_plane(cx, cy, uPlane[unit]) * invQ; + array->lambda[unit][ix] = compute_lambda(sPlane[unit], + tPlane[unit], + vPlane[unit], + cx, cy, invQ, + texWidth[unit], + texHeight[unit]); } } } @@ -482,83 +447,76 @@ count++; coverage = compute_coveragef(pMin, pMax, pMid, ix, iy); } - + if (startX <= ix) continue; n = (GLuint) startX - (GLuint) ix; left = ix + 1; + + /* shift all values to the left */ + /* XXX this is temporary */ + { + struct span_arrays *array = span.array; + GLint j; + for (j = 0; j < (GLint) n; j++) { +#ifdef DO_RGBA + COPY_4V(array->rgba[j], array->rgba[j + left]); +#endif +#ifdef DO_SPEC + COPY_4V(array->spec[j], array->spec[j + left]); +#endif +#ifdef DO_INDEX + array->index[j] = array->index[j + left]; +#endif +#ifdef DO_Z + array->z[j] = array->z[j + left]; +#endif +#ifdef DO_FOG + array->fog[j] = array->fog[j + left]; +#endif +#ifdef DO_TEX + COPY_4V(array->texcoords[0][j], array->texcoords[0][j + left]); +#endif +#if defined(DO_MULTITEX) || defined(DO_TEX) + array->lambda[0][j] = array->lambda[0][j + left]; +#endif + array->coverage[j] = array->coverage[j + left]; + } + } #ifdef DO_MULTITEX + /* shift texcoords */ { + struct span_arrays *array = span.array; GLuint unit; for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled) { GLint j; for (j = 0; j < (GLint) n; j++) { - s[unit][j] = s[unit][j + left]; - t[unit][j] = t[unit][j + left]; - u[unit][j] = u[unit][j + left]; - lambda[unit][j] = lambda[unit][j + left]; + array->texcoords[unit][j][0] = array->texcoords[unit][j + left][0]; + array->texcoords[unit][j][1] = array->texcoords[unit][j + left][1]; + array->texcoords[unit][j][2] = array->texcoords[unit][j + left][2]; + array->lambda[unit][j] = array->lambda[unit][j + left]; } } } } -# ifdef DO_SPEC - _mesa_write_multitexture_span(ctx, n, left, iy, z + left, fog + left, - (const GLfloat (*)[MAX_WIDTH]) s, - (const GLfloat (*)[MAX_WIDTH]) t, - (const GLfloat (*)[MAX_WIDTH]) u, - lambda, rgba + left, - (const GLchan (*)[4]) (spec + left), - coverageSpan + left, - GL_POLYGON); -# else - _mesa_write_multitexture_span(ctx, n, left, iy, z + left, fog + left, - (const GLfloat (*)[MAX_WIDTH]) s, - (const GLfloat (*)[MAX_WIDTH]) t, - (const GLfloat (*)[MAX_WIDTH]) u, - lambda, - rgba + left, NULL, coverageSpan + left, - GL_POLYGON); -# endif -#elif defined(DO_TEX) -# ifdef DO_SPEC - _mesa_write_texture_span(ctx, n, left, iy, z + left, fog + left, - s + left, t + left, u + left, - lambda + left, rgba + left, - (const GLchan (*)[4]) (spec + left), - coverageSpan + left, - GL_POLYGON); -# else - _mesa_write_texture_span(ctx, n, left, iy, z + left, fog + left, - s + left, t + left, - u + left, lambda + left, - rgba + left, NULL, - coverageSpan + left, GL_POLYGON); -# endif +#endif + + span.x = left; + span.y = iy; + span.end = n; + ASSERT(span.interpMask == 0); +#if defined(DO_MULTITEX) || defined(DO_TEX) + _mesa_write_texture_span(ctx, &span); #elif defined(DO_RGBA) - _mesa_write_rgba_span(ctx, n, left, iy, z + left, fog + left, - rgba + left, coverageSpan + left, GL_POLYGON); + _mesa_write_rgba_span(ctx, &span); #elif defined(DO_INDEX) - _mesa_write_index_span(ctx, n, left, iy, z + left, fog + left, - index + left, icoverageSpan + left, GL_POLYGON); + _mesa_write_index_span(ctx, &span); #endif } } - -#ifdef DO_RGBA - UNDEFARRAY(rgba); /* mac 32k limitation */ -#endif -#ifdef DO_SPEC - UNDEFARRAY(spec); -#endif -#if defined(DO_TEX) || defined(DO_MULTITEX) - UNDEFARRAY(s); - UNDEFARRAY(t); - UNDEFARRAY(u); - UNDEFARRAY(lambda); -#endif } diff --git a/xc/extras/Mesa/src/swrast/s_accum.c b/xc/extras/Mesa/src/swrast/s_accum.c index b93f8379e..16eca43d5 100644 --- a/xc/extras/Mesa/src/swrast/s_accum.c +++ b/xc/extras/Mesa/src/swrast/s_accum.c @@ -1,8 +1,7 @@ -/* $Id: s_accum.c,v 1.1.1.1 2002/10/22 13:06:55 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.2 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -29,7 +28,7 @@ #include "context.h" #include "macros.h" #include "mmath.h" -#include "mem.h" +#include "imports.h" #include "s_accum.h" #include "s_alphabuf.h" @@ -62,10 +61,11 @@ */ -#if CHAN_BITS == 8 +#if CHAN_BITS == 8 && ACCUM_BITS < 32 #define USE_OPTIMIZED_ACCUM /* enable the optimization */ #endif + void _mesa_alloc_accum_buffer( GLframebuffer *buffer ) { @@ -194,7 +194,8 @@ _mesa_clear_accum_buffer( GLcontext *ctx ) ctx->Accum.ClearColor[2]==0.0 && ctx->Accum.ClearColor[3]==0.0) { /* Black */ - BZERO( ctx->DrawBuffer->Accum, buffersize * 4 * sizeof(GLaccum) ); + _mesa_bzero( ctx->DrawBuffer->Accum, + buffersize * 4 * sizeof(GLaccum) ); } else { /* Not black */ @@ -242,6 +243,7 @@ _swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value, GLchan rgba[MAX_WIDTH][4]; const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); + if (SWRAST_CONTEXT(ctx)->NewState) _swrast_validate_derived( ctx ); @@ -304,8 +306,7 @@ _swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value, if (value == 0.0F) return; - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); + _swrast_use_read_buffer(ctx); /* May have to leave optimized accum buffer mode */ if (swrast->_IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0) @@ -357,14 +358,13 @@ _swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value, } } /* restore read buffer = draw buffer (the default) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); + _swrast_use_draw_buffer(ctx); + RENDER_FINISH(swrast,ctx); break; case GL_LOAD: - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); + _swrast_use_read_buffer(ctx); /* This is a change to go into optimized accum buffer mode */ if (value > 0.0 && value <= 1.0) { @@ -431,8 +431,8 @@ _swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value, } /* restore read buffer = draw buffer (the default) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); + _swrast_use_draw_buffer(ctx); + RENDER_FINISH(swrast,ctx); break; @@ -472,7 +472,7 @@ _swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value, rgba[i][ACOMP] = multTable[acc[i4+3]]; } if (colorMask != 0xffffffff) { - _mesa_mask_rgba_span( ctx, width, xpos, ypos, rgba ); + _mesa_mask_rgba_array( ctx, width, xpos, ypos, rgba ); } (*swrast->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, (const GLchan (*)[4])rgba, NULL ); @@ -507,7 +507,7 @@ _swrast_Accum( GLcontext *ctx, GLenum op, GLfloat value, rgba[i][ACOMP] = CLAMP( a, 0, CHAN_MAX ); } if (colorMask != 0xffffffff) { - _mesa_mask_rgba_span( ctx, width, xpos, ypos, rgba ); + _mesa_mask_rgba_array( ctx, width, xpos, ypos, rgba ); } (*swrast->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, (const GLchan (*)[4])rgba, NULL ); diff --git a/xc/extras/Mesa/src/swrast/s_alpha.c b/xc/extras/Mesa/src/swrast/s_alpha.c index 0d6353ec0..22ccff6dc 100644 --- a/xc/extras/Mesa/src/swrast/s_alpha.c +++ b/xc/extras/Mesa/src/swrast/s_alpha.c @@ -1,10 +1,9 @@ -/* $Id: s_alpha.c,v 1.1.1.1 2002/10/22 13:06:58 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -24,6 +23,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** + * \file swrast/s_alpha.c + * \brief Functions to apply alpha test. + */ #include "glheader.h" #include "context.h" @@ -32,67 +35,191 @@ #include "mmath.h" #include "s_alpha.h" +#include "s_context.h" - - - -/* - * Apply the alpha test to a span of pixels. - * In: rgba - array of pixels - * In/Out: mask - current pixel mask. Pixels which fail the alpha test - * will set the corresponding mask flag to 0. - * Return: 0 = all pixels in the span failed the alpha test. - * 1 = one or more pixels passed the alpha test. +/** + * \fn GLint _mesa_alpha_test( const GLcontext *ctx, struct sw_span *span ) + * \brief Apply the alpha test to a span of pixels. + * \return + * - "0" = all pixels in the span failed the alpha test. + * - "1" = one or more pixels passed the alpha test. */ GLint -_mesa_alpha_test( const GLcontext *ctx, - GLuint n, CONST GLchan rgba[][4], GLubyte mask[] ) +_mesa_alpha_test( const GLcontext *ctx, struct sw_span *span ) { + const GLchan (*rgba)[4] = (const GLchan (*)[4]) span->array->rgba; + GLchan ref; + const GLuint n = span->end; + GLubyte *mask = span->array->mask; GLuint i; - GLchan ref = ctx->Color.AlphaRef; - /* switch cases ordered from most frequent to less frequent */ - switch (ctx->Color.AlphaFunc) { - case GL_LESS: - for (i=0;i<n;i++) { - mask[i] &= (rgba[i][ACOMP] < ref); - } - return 1; - case GL_LEQUAL: - for (i=0;i<n;i++) - mask[i] &= (rgba[i][ACOMP] <= ref); - return 1; - case GL_GEQUAL: - for (i=0;i<n;i++) { - mask[i] &= (rgba[i][ACOMP] >= ref); - } - return 1; - case GL_GREATER: - for (i=0;i<n;i++) { - mask[i] &= (rgba[i][ACOMP] > ref); - } - return 1; - case GL_NOTEQUAL: - for (i=0;i<n;i++) { - mask[i] &= (rgba[i][ACOMP] != ref); - } - return 1; - case GL_EQUAL: - for (i=0;i<n;i++) { - mask[i] &= (rgba[i][ACOMP] == ref); - } - return 1; - case GL_ALWAYS: - /* do nothing */ - return 1; - case GL_NEVER: - /* caller should check for zero! */ - return 0; - default: - _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" ); - return 0; + CLAMPED_FLOAT_TO_CHAN(ref, ctx->Color.AlphaRef); + + if (span->arrayMask & SPAN_RGBA) { + /* Use the array values */ + switch (ctx->Color.AlphaFunc) { + case GL_LESS: + for (i = 0; i < n; i++) + mask[i] &= (rgba[i][ACOMP] < ref); + break; + case GL_LEQUAL: + for (i = 0; i < n; i++) + mask[i] &= (rgba[i][ACOMP] <= ref); + break; + case GL_GEQUAL: + for (i = 0; i < n; i++) + mask[i] &= (rgba[i][ACOMP] >= ref); + break; + case GL_GREATER: + for (i = 0; i < n; i++) + mask[i] &= (rgba[i][ACOMP] > ref); + break; + case GL_NOTEQUAL: + for (i = 0; i < n; i++) + mask[i] &= (rgba[i][ACOMP] != ref); + break; + case GL_EQUAL: + for (i = 0; i < n; i++) + mask[i] &= (rgba[i][ACOMP] == ref); + break; + case GL_ALWAYS: + /* do nothing */ + return 1; + case GL_NEVER: + /* caller should check for zero! */ + span->writeAll = GL_FALSE; + return 0; + default: + _mesa_problem( ctx, "Invalid alpha test in _mesa_alpha_test" ); + return 0; + } } - /* Never get here */ - /*return 1;*/ + else { + /* Use the interpolation values */ +#if CHAN_TYPE == GL_FLOAT + const GLfloat alphaStep = span->alphaStep; + GLfloat alpha = span->alpha; + ASSERT(span->interpMask & SPAN_RGBA); + switch (ctx->Color.AlphaFunc) { + case GL_LESS: + for (i = 0; i < n; i++) { + mask[i] &= (alpha < ref); + alpha += alphaStep; + } + break; + case GL_LEQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (alpha <= ref); + alpha += alphaStep; + } + break; + case GL_GEQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (alpha >= ref); + alpha += alphaStep; + } + break; + case GL_GREATER: + for (i = 0; i < n; i++) { + mask[i] &= (alpha > ref); + alpha += alphaStep; + } + break; + case GL_NOTEQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (alpha != ref); + alpha += alphaStep; + } + break; + case GL_EQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (alpha == ref); + alpha += alphaStep; + } + break; + case GL_ALWAYS: + /* do nothing */ + return 1; + case GL_NEVER: + /* caller should check for zero! */ + span->writeAll = GL_FALSE; + return 0; + default: + _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" ); + return 0; + } +#else + /* 8 or 16-bit channel interpolation */ + const GLfixed alphaStep = span->alphaStep; + GLfixed alpha = span->alpha; + ASSERT(span->interpMask & SPAN_RGBA); + switch (ctx->Color.AlphaFunc) { + case GL_LESS: + for (i = 0; i < n; i++) { + mask[i] &= (FixedToChan(alpha) < ref); + alpha += alphaStep; + } + break; + case GL_LEQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (FixedToChan(alpha) <= ref); + alpha += alphaStep; + } + break; + case GL_GEQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (FixedToChan(alpha) >= ref); + alpha += alphaStep; + } + break; + case GL_GREATER: + for (i = 0; i < n; i++) { + mask[i] &= (FixedToChan(alpha) > ref); + alpha += alphaStep; + } + break; + case GL_NOTEQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (FixedToChan(alpha) != ref); + alpha += alphaStep; + } + break; + case GL_EQUAL: + for (i = 0; i < n; i++) { + mask[i] &= (FixedToChan(alpha) == ref); + alpha += alphaStep; + } + break; + case GL_ALWAYS: + /* do nothing */ + return 1; + case GL_NEVER: + /* caller should check for zero! */ + span->writeAll = GL_FALSE; + return 0; + default: + _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" ); + return 0; + } +#endif /* CHAN_TYPE */ + } + +#if 0 + /* XXXX This causes conformance failures!!!! */ + while ((span->start <= span->end) && + (mask[span->start] == 0)) + span->start ++; + + while ((span->end >= span->start) && + (mask[span->end] == 0)) + span->end --; +#endif + + span->writeAll = GL_FALSE; + + if (span->start >= span->end) + return 0; + else + return 1; } diff --git a/xc/extras/Mesa/src/swrast/s_alpha.h b/xc/extras/Mesa/src/swrast/s_alpha.h index 63e872c08..86a7d0654 100644 --- a/xc/extras/Mesa/src/swrast/s_alpha.h +++ b/xc/extras/Mesa/src/swrast/s_alpha.h @@ -1,10 +1,9 @@ -/* $Id: s_alpha.h,v 1.1.1.1 2002/10/22 13:06:58 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -34,9 +33,7 @@ extern GLint -_mesa_alpha_test( const GLcontext *ctx, GLuint n, - CONST GLchan rgba[][4], GLubyte mask[] ); - +_mesa_alpha_test( const GLcontext *ctx, struct sw_span *span ); #endif diff --git a/xc/extras/Mesa/src/swrast/s_alphabuf.c b/xc/extras/Mesa/src/swrast/s_alphabuf.c index ee1c15933..e677fb7d6 100644 --- a/xc/extras/Mesa/src/swrast/s_alphabuf.c +++ b/xc/extras/Mesa/src/swrast/s_alphabuf.c @@ -1,8 +1,7 @@ -/* $Id: s_alphabuf.c,v 1.1.1.1 2002/10/22 13:06:44 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.2 + * Version: 5.0.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -32,26 +31,20 @@ #include "glheader.h" +#include "colormac.h" #include "context.h" -#include "mem.h" +#include "imports.h" +#include "s_context.h" #include "s_alphabuf.h" -#define ALPHA_DRAW_ADDR(X,Y) \ - (ctx->DrawBuffer->Alpha + (Y) * ctx->DrawBuffer->Width + (X)) - -#define ALPHA_READ_ADDR(X,Y) \ - (ctx->ReadBuffer->Alpha + (Y) * ctx->ReadBuffer->Width + (X)) - - /* * Allocate a new front and back alpha buffer. */ void _mesa_alloc_alpha_buffers( GLframebuffer *buffer ) { - GET_CURRENT_CONTEXT(ctx); const GLint bytes = buffer->Width * buffer->Height * sizeof(GLchan); ASSERT(buffer->UseSoftwareAlphaBuffers); @@ -59,7 +52,7 @@ _mesa_alloc_alpha_buffers( GLframebuffer *buffer ) if (buffer->FrontLeftAlpha) { MESA_PBUFFER_FREE( buffer->FrontLeftAlpha ); } - buffer->FrontLeftAlpha = (GLchan *) MESA_PBUFFER_ALLOC( bytes ); + buffer->FrontLeftAlpha = MESA_PBUFFER_ALLOC( bytes ); if (!buffer->FrontLeftAlpha) { /* out of memory */ _mesa_error( NULL, GL_OUT_OF_MEMORY, @@ -70,7 +63,7 @@ _mesa_alloc_alpha_buffers( GLframebuffer *buffer ) if (buffer->BackLeftAlpha) { MESA_PBUFFER_FREE( buffer->BackLeftAlpha ); } - buffer->BackLeftAlpha = (GLchan *) MESA_PBUFFER_ALLOC( bytes ); + buffer->BackLeftAlpha = MESA_PBUFFER_ALLOC( bytes ); if (!buffer->BackLeftAlpha) { /* out of memory */ _mesa_error( NULL, GL_OUT_OF_MEMORY, @@ -82,7 +75,7 @@ _mesa_alloc_alpha_buffers( GLframebuffer *buffer ) if (buffer->FrontRightAlpha) { MESA_PBUFFER_FREE( buffer->FrontRightAlpha ); } - buffer->FrontRightAlpha = (GLchan *) MESA_PBUFFER_ALLOC( bytes ); + buffer->FrontRightAlpha = MESA_PBUFFER_ALLOC( bytes ); if (!buffer->FrontRightAlpha) { /* out of memory */ _mesa_error( NULL, GL_OUT_OF_MEMORY, @@ -93,7 +86,7 @@ _mesa_alloc_alpha_buffers( GLframebuffer *buffer ) if (buffer->BackRightAlpha) { MESA_PBUFFER_FREE( buffer->BackRightAlpha ); } - buffer->BackRightAlpha = (GLchan *) MESA_PBUFFER_ALLOC( bytes ); + buffer->BackRightAlpha = MESA_PBUFFER_ALLOC( bytes ); if (!buffer->BackRightAlpha) { /* out of memory */ _mesa_error( NULL, GL_OUT_OF_MEMORY, @@ -101,17 +94,6 @@ _mesa_alloc_alpha_buffers( GLframebuffer *buffer ) } } } - - if (ctx) { - if (ctx->Color.DriverDrawBuffer == GL_FRONT_LEFT) - buffer->Alpha = buffer->FrontLeftAlpha; - else if (ctx->Color.DriverDrawBuffer == GL_BACK_LEFT) - buffer->Alpha = buffer->BackLeftAlpha; - else if (ctx->Color.DriverDrawBuffer == GL_FRONT_RIGHT) - buffer->Alpha = buffer->FrontRightAlpha; - else if (ctx->Color.DriverDrawBuffer == GL_BACK_RIGHT) - buffer->Alpha = buffer->BackRightAlpha; - } } @@ -121,27 +103,29 @@ _mesa_alloc_alpha_buffers( GLframebuffer *buffer ) void _mesa_clear_alpha_buffers( GLcontext *ctx ) { - const GLchan aclear = ctx->Color.ClearColor[3]; + GLchan aclear; GLuint bufferBit; + CLAMPED_FLOAT_TO_CHAN(aclear, ctx->Color.ClearColor[3]); + ASSERT(ctx->DrawBuffer->UseSoftwareAlphaBuffers); ASSERT(ctx->Color.ColorMask[ACOMP]); /* loop over four possible alpha buffers */ for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) { - if (bufferBit & ctx->Color.DrawDestMask) { + if (bufferBit & ctx->Color._DrawDestMask) { GLchan *buffer; if (bufferBit == FRONT_LEFT_BIT) { - buffer = ctx->DrawBuffer->FrontLeftAlpha; + buffer = (GLchan *) ctx->DrawBuffer->FrontLeftAlpha; } else if (bufferBit == FRONT_RIGHT_BIT) { - buffer = ctx->DrawBuffer->FrontRightAlpha; + buffer = (GLchan *) ctx->DrawBuffer->FrontRightAlpha; } else if (bufferBit == BACK_LEFT_BIT) { - buffer = ctx->DrawBuffer->BackLeftAlpha; + buffer = (GLchan *) ctx->DrawBuffer->BackLeftAlpha; } else { - buffer = ctx->DrawBuffer->BackRightAlpha; + buffer = (GLchan *) ctx->DrawBuffer->BackRightAlpha; } if (ctx->Scissor.Enabled) { @@ -187,13 +171,41 @@ _mesa_clear_alpha_buffers( GLcontext *ctx ) +static INLINE +GLchan *get_alpha_buffer( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + switch (swrast->CurrentBuffer) { + case FRONT_LEFT_BIT: + return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha; + break; + case BACK_LEFT_BIT: + return (GLchan *) ctx->DrawBuffer->BackLeftAlpha; + break; + case FRONT_RIGHT_BIT: + return (GLchan *) ctx->DrawBuffer->FrontRightAlpha; + break; + case BACK_RIGHT_BIT: + return (GLchan *) ctx->DrawBuffer->BackRightAlpha; + break; + default: + _mesa_problem(ctx, "Bad CurrentBuffer in get_alpha_buffer()"); + return (GLchan *) ctx->DrawBuffer->FrontLeftAlpha; + } +} + + void _mesa_write_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y, CONST GLchan rgba[][4], const GLubyte mask[] ) { - GLchan *aptr = ALPHA_DRAW_ADDR( x, y ); + GLchan *buffer, *aptr; GLuint i; + buffer = get_alpha_buffer(ctx); + aptr = buffer + y * ctx->DrawBuffer->Width + x; + if (mask) { for (i=0;i<n;i++) { if (mask[i]) { @@ -214,9 +226,12 @@ void _mesa_write_mono_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y, GLchan alpha, const GLubyte mask[] ) { - GLchan *aptr = ALPHA_DRAW_ADDR( x, y ); + GLchan *buffer, *aptr; GLuint i; + buffer = get_alpha_buffer(ctx); + aptr = buffer + y * ctx->DrawBuffer->Width + x; + if (mask) { for (i=0;i<n;i++) { if (mask[i]) { @@ -238,19 +253,22 @@ _mesa_write_alpha_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], CONST GLchan rgba[][4], const GLubyte mask[] ) { + GLchan *buffer; GLuint i; + buffer = get_alpha_buffer(ctx); + if (mask) { for (i=0;i<n;i++) { if (mask[i]) { - GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] ); + GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i]; *aptr = rgba[i][ACOMP]; } } } else { for (i=0;i<n;i++) { - GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] ); + GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i]; *aptr = rgba[i][ACOMP]; } } @@ -262,19 +280,22 @@ _mesa_write_mono_alpha_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLchan alpha, const GLubyte mask[] ) { + GLchan *buffer; GLuint i; + buffer = get_alpha_buffer(ctx); + if (mask) { for (i=0;i<n;i++) { if (mask[i]) { - GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] ); + GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i]; *aptr = alpha; } } } else { for (i=0;i<n;i++) { - GLchan *aptr = ALPHA_DRAW_ADDR( x[i], y[i] ); + GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i]; *aptr = alpha; } } @@ -286,11 +307,14 @@ void _mesa_read_alpha_span( GLcontext *ctx, GLuint n, GLint x, GLint y, GLchan rgba[][4] ) { - GLchan *aptr = ALPHA_READ_ADDR( x, y ); + const GLchan *buffer, *aptr; GLuint i; - for (i=0;i<n;i++) { + + buffer = get_alpha_buffer(ctx); + aptr = buffer + y * ctx->DrawBuffer->Width + x; + + for (i = 0; i < n; i++) rgba[i][ACOMP] = *aptr++; - } } @@ -299,10 +323,14 @@ _mesa_read_alpha_pixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLchan rgba[][4], const GLubyte mask[] ) { + const GLchan *buffer; GLuint i; - for (i=0;i<n;i++) { + + buffer = get_alpha_buffer(ctx); + + for (i = 0; i < n; i++) { if (mask[i]) { - GLchan *aptr = ALPHA_READ_ADDR( x[i], y[i] ); + const GLchan *aptr = buffer + y[i] * ctx->DrawBuffer->Width + x[i]; rgba[i][ACOMP] = *aptr; } } diff --git a/xc/extras/Mesa/src/swrast/s_bitmap.c b/xc/extras/Mesa/src/swrast/s_bitmap.c index 2cb088369..bc6c103a9 100644 --- a/xc/extras/Mesa/src/swrast/s_bitmap.c +++ b/xc/extras/Mesa/src/swrast/s_bitmap.c @@ -1,10 +1,9 @@ -/* $Id: s_bitmap.c,v 1.1.1.1 2002/10/22 13:06:54 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 5.0 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -24,15 +23,20 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** + * \file swrast/s_bitmap.c + * \brief glBitmap rendering. + * \author Brian Paul + */ #include "glheader.h" #include "image.h" #include "macros.h" +#include "mmath.h" #include "pixel.h" #include "s_context.h" -#include "s_fog.h" -#include "s_pb.h" +#include "s_span.h" @@ -46,10 +50,9 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, const GLubyte *bitmap ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - struct pixel_buffer *PB = swrast->PB; GLint row, col; - GLdepth fragZ; - GLfloat fog; + GLuint count = 0; + struct sw_span span; ASSERT(ctx->RenderMode == GL_RENDER); ASSERT(bitmap); @@ -59,32 +62,146 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, if (SWRAST_CONTEXT(ctx)->NewState) _swrast_validate_derived( ctx ); - /* Set bitmap drawing color */ + INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_XY); + if (ctx->Visual.rgbMode) { - GLint r, g, b, a; - r = (GLint) (ctx->Current.RasterColor[0] * CHAN_MAXF); - g = (GLint) (ctx->Current.RasterColor[1] * CHAN_MAXF); - b = (GLint) (ctx->Current.RasterColor[2] * CHAN_MAXF); - a = (GLint) (ctx->Current.RasterColor[3] * CHAN_MAXF); - PB_SET_COLOR( PB, r, g, b, a ); + span.interpMask |= SPAN_RGBA; + span.red = FloatToFixed(ctx->Current.RasterColor[0] * CHAN_MAXF); + span.green = FloatToFixed(ctx->Current.RasterColor[1] * CHAN_MAXF); + span.blue = FloatToFixed(ctx->Current.RasterColor[2] * CHAN_MAXF); + span.alpha = FloatToFixed(ctx->Current.RasterColor[3] * CHAN_MAXF); + span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0; } else { - PB_SET_INDEX( PB, ctx->Current.RasterIndex ); + span.interpMask |= SPAN_INDEX; + span.index = ChanToFixed(ctx->Current.RasterIndex); + span.indexStep = 0; + } + + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); + if (ctx->Texture._EnabledUnits) + _mesa_span_default_texcoords(ctx, &span); + + for (row = 0; row < height; row++, span.y++) { + const GLubyte *src = (const GLubyte *) _mesa_image_address( unpack, + bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 ); + + if (unpack->LsbFirst) { + /* Lsb first */ + GLubyte mask = 1U << (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + if (*src & mask) { + span.array->x[count] = px + col; + span.array->y[count] = py + row; + count++; + } + if (mask == 128U) { + src++; + mask = 1U; + } + else { + mask = mask << 1; + } + } + + /* get ready for next row */ + if (mask != 1) + src++; + } + else { + /* Msb first */ + GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + if (*src & mask) { + span.array->x[count] = px + col; + span.array->y[count] = py + row; + count++; + } + if (mask == 1U) { + src++; + mask = 128U; + } + else { + mask = mask >> 1; + } + } + + /* get ready for next row */ + if (mask != 128) + src++; + } + + if (count + width >= MAX_WIDTH || row + 1 == height) { + /* flush the span */ + span.end = count; + if (ctx->Visual.rgbMode) + _mesa_write_rgba_span(ctx, &span); + else + _mesa_write_index_span(ctx, &span); + span.end = 0; + count = 0; + } } - fragZ = (GLdepth) ( ctx->Current.RasterPos[2] * ctx->DepthMaxF); + RENDER_FINISH(swrast,ctx); +} + + +#if 0 +/* + * XXX this is another way to implement Bitmap. Use horizontal runs of + * fragments, initializing the mask array to indicate which fragmens to + * draw or skip. + */ +void +_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLint row, col; + struct sw_span span; + + ASSERT(ctx->RenderMode == GL_RENDER); + ASSERT(bitmap); + + RENDER_START(swrast,ctx); - if (ctx->Fog.Enabled) { - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.FogCoord); - else - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); + if (SWRAST_CONTEXT(ctx)->NewState) + _swrast_validate_derived( ctx ); + + INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_MASK); + + /*span.arrayMask |= SPAN_MASK;*/ /* we'll init span.mask[] */ + span.x = px; + span.y = py; + /*span.end = width;*/ + if (ctx->Visual.rgbMode) { + span.interpMask |= SPAN_RGBA; + span.red = FloatToFixed(ctx->Current.RasterColor[0] * CHAN_MAXF); + span.green = FloatToFixed(ctx->Current.RasterColor[1] * CHAN_MAXF); + span.blue = FloatToFixed(ctx->Current.RasterColor[2] * CHAN_MAXF); + span.alpha = FloatToFixed(ctx->Current.RasterColor[3] * CHAN_MAXF); + span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0; } else { - fog = 0.0; + span.interpMask |= SPAN_INDEX; + span.index = ChanToFixed(ctx->Current.RasterIndex); + span.indexStep = 0; } - for (row=0; row<height; row++) { + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); + if (ctx->Texture._EnabledUnits) + _mesa_span_default_texcoords(ctx, &span); + + for (row=0; row<height; row++, span.y++) { const GLubyte *src = (const GLubyte *) _mesa_image_address( unpack, bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 ); @@ -92,9 +209,7 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, /* Lsb first */ GLubyte mask = 1U << (unpack->SkipPixels & 0x7); for (col=0; col<width; col++) { - if (*src & mask) { - PB_WRITE_PIXEL( PB, px+col, py+row, fragZ, fog ); - } + span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE; if (mask == 128U) { src++; mask = 1U; @@ -104,7 +219,10 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, } } - PB_CHECK_FLUSH( ctx, PB ); + if (ctx->Visual.rgbMode) + _mesa_write_rgba_span(ctx, &span); + else + _mesa_write_index_span(ctx, &span); /* get ready for next row */ if (mask != 1) @@ -114,9 +232,7 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, /* Msb first */ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); for (col=0; col<width; col++) { - if (*src & mask) { - PB_WRITE_PIXEL( PB, px+col, py+row, fragZ, fog ); - } + span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE; if (mask == 1U) { src++; mask = 128U; @@ -126,7 +242,10 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, } } - PB_CHECK_FLUSH( ctx, PB ); + if (ctx->Visual.rgbMode) + _mesa_write_rgba_span(ctx, &span); + else + _mesa_write_index_span(ctx, &span); /* get ready for next row */ if (mask != 128) @@ -134,7 +253,6 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, } } - _mesa_flush_pb(ctx); - RENDER_FINISH(swrast,ctx); } +#endif diff --git a/xc/extras/Mesa/src/swrast/s_blend.c b/xc/extras/Mesa/src/swrast/s_blend.c index ad6764f16..acd454811 100644 --- a/xc/extras/Mesa/src/swrast/s_blend.c +++ b/xc/extras/Mesa/src/swrast/s_blend.c @@ -1,8 +1,7 @@ -/* $Id: s_blend.c,v 1.1.1.1 2002/10/22 13:06:41 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -25,14 +24,15 @@ */ + #include "glheader.h" #include "context.h" +#include "colormac.h" #include "macros.h" #include "s_alphabuf.h" #include "s_blend.h" #include "s_context.h" -#include "s_pb.h" #include "s_span.h" @@ -60,10 +60,7 @@ blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[], for (i = 0; i < n; i++) { if (mask[i]) { - rgba[i][RCOMP] = dest[i][RCOMP]; - rgba[i][GCOMP] = dest[i][GCOMP]; - rgba[i][BCOMP] = dest[i][BCOMP]; - rgba[i][ACOMP] = dest[i][ACOMP]; + COPY_CHAN4( rgba[i], dest[i] ); } } } @@ -102,7 +99,7 @@ blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[], for (i=0;i<n;i++) { if (mask[i]) { - const GLint t = rgba[i][ACOMP]; /* t in [0, CHAN_MAX] */ + const GLchan t = rgba[i][ACOMP]; /* t in [0, CHAN_MAX] */ if (t == 0) { /* 0% alpha */ rgba[i][RCOMP] = dest[i][RCOMP]; @@ -132,27 +129,31 @@ blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[], #if CHAN_BITS == 8 /* This satisfies Glean and should be reasonably fast */ /* Contributed by Nathan Hand */ +#if 0 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16 - const GLint s = CHAN_MAX - t; - const GLint r = DIV255(rgba[i][RCOMP] * t + dest[i][RCOMP] * s); - const GLint g = DIV255(rgba[i][GCOMP] * t + dest[i][GCOMP] * s); - const GLint b = DIV255(rgba[i][BCOMP] * t + dest[i][BCOMP] * s); - const GLint a = DIV255(rgba[i][ACOMP] * t + dest[i][ACOMP] * s); +#else + GLint temp; +#define DIV255(X) (temp = (X), ((temp << 8) + temp + 256) >> 16) +#endif + const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP]; + const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP]; + const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP]; + const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP]; + #undef DIV255 #elif CHAN_BITS == 16 const GLfloat tt = (GLfloat) t / CHAN_MAXF; - const GLfloat s = 1.0 - tt; - const GLint r = (GLint) (rgba[i][RCOMP] * tt + dest[i][RCOMP] * s); - const GLint g = (GLint) (rgba[i][GCOMP] * tt + dest[i][GCOMP] * s); - const GLint b = (GLint) (rgba[i][BCOMP] * tt + dest[i][BCOMP] * s); - const GLint a = (GLint) (rgba[i][ACOMP] * tt + dest[i][ACOMP] * s); + const GLint r = (GLint) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]); + const GLint g = (GLint) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]); + const GLint b = (GLint) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]); + const GLint a = (GLint) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]); #else /* CHAN_BITS == 32 */ const GLfloat tt = (GLfloat) t / CHAN_MAXF; - const GLfloat s = 1.0 - tt; - const GLfloat r = rgba[i][RCOMP] * tt + dest[i][RCOMP] * s; - const GLfloat g = rgba[i][GCOMP] * tt + dest[i][GCOMP] * s; - const GLfloat b = rgba[i][BCOMP] * tt + dest[i][BCOMP] * s; - const GLfloat a = rgba[i][ACOMP] * tt + dest[i][ACOMP] * s; + const GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]; + const GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]; + const GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]; + const GLfloat a = CLAMP( rgba[i][ACOMP], 0.0F, CHAN_MAXF ) * t + + CLAMP( dest[i][ACOMP], 0.0F, CHAN_MAXF ) * (1.0F - t); #endif #endif ASSERT(r <= CHAN_MAX); @@ -186,20 +187,22 @@ blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[], for (i=0;i<n;i++) { if (mask[i]) { #if CHAN_TYPE == GL_FLOAT - GLfloat r = rgba[i][RCOMP] + dest[i][RCOMP]; - GLfloat g = rgba[i][GCOMP] + dest[i][GCOMP]; - GLfloat b = rgba[i][BCOMP] + dest[i][BCOMP]; - GLfloat a = rgba[i][ACOMP] + dest[i][ACOMP]; + /* don't RGB clamp to max */ + GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF) + dest[i][ACOMP]; + rgba[i][RCOMP] += dest[i][RCOMP]; + rgba[i][GCOMP] += dest[i][GCOMP]; + rgba[i][BCOMP] += dest[i][BCOMP]; + rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAXF ); #else GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; -#endif rgba[i][RCOMP] = (GLchan) MIN2( r, CHAN_MAX ); rgba[i][GCOMP] = (GLchan) MIN2( g, CHAN_MAX ); rgba[i][BCOMP] = (GLchan) MIN2( b, CHAN_MAX ); rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAX ); +#endif } } } @@ -222,7 +225,12 @@ blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[], rgba[i][RCOMP] = (GLchan) MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); rgba[i][GCOMP] = (GLchan) MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); rgba[i][BCOMP] = (GLchan) MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); +#if CHAN_TYPE == GL_FLOAT + rgba[i][ACOMP] = (GLchan) MIN2(CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF), + dest[i][ACOMP]); +#else rgba[i][ACOMP] = (GLchan) MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); +#endif } } } @@ -245,7 +253,12 @@ blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[], rgba[i][RCOMP] = (GLchan) MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); rgba[i][GCOMP] = (GLchan) MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); rgba[i][BCOMP] = (GLchan) MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); +#if CHAN_TYPE == GL_FLOAT + rgba[i][ACOMP] = (GLchan) MAX2(CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF), + dest[i][ACOMP]); +#else rgba[i][ACOMP] = (GLchan) MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); +#endif } } } @@ -269,11 +282,20 @@ blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[], rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP]; rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP]; rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP]; +#elif CHAN_TYPE == GL_UNSIGNED_SHORT + GLint r = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16; + GLint g = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16; + GLint b = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16; + GLint a = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16; + rgba[i][RCOMP] = (GLchan) r; + rgba[i][GCOMP] = (GLchan) g; + rgba[i][BCOMP] = (GLchan) b; + rgba[i][ACOMP] = (GLchan) a; #else - GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8; - GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8; - GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8; - GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8; + GLint r = (rgba[i][RCOMP] * dest[i][RCOMP] + 255) >> 8; + GLint g = (rgba[i][GCOMP] * dest[i][GCOMP] + 255) >> 8; + GLint b = (rgba[i][BCOMP] * dest[i][BCOMP] + 255) >> 8; + GLint a = (rgba[i][ACOMP] * dest[i][ACOMP] + 255) >> 8; rgba[i][RCOMP] = (GLchan) r; rgba[i][GCOMP] = (GLchan) g; rgba[i][BCOMP] = (GLchan) b; @@ -296,10 +318,10 @@ static void _BLENDAPI blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], GLchan rgba[][4], CONST GLchan dest[][4] ) { - GLfloat rscale = 1.0F / CHAN_MAXF; - GLfloat gscale = 1.0F / CHAN_MAXF; - GLfloat bscale = 1.0F / CHAN_MAXF; - GLfloat ascale = 1.0F / CHAN_MAXF; + const GLfloat rscale = 1.0F / CHAN_MAXF; + const GLfloat gscale = 1.0F / CHAN_MAXF; + const GLfloat bscale = 1.0F / CHAN_MAXF; + const GLfloat ascale = 1.0F / CHAN_MAXF; GLuint i; for (i=0;i<n;i++) { @@ -313,19 +335,33 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], #endif GLfloat sR, sG, sB, sA; /* Source scaling */ GLfloat dR, dG, dB, dA; /* Dest scaling */ - GLfloat r, g, b, a; + GLfloat r, g, b, a; /* result color */ - /* Source Color */ + /* Incoming/source Color */ Rs = rgba[i][RCOMP]; Gs = rgba[i][GCOMP]; Bs = rgba[i][BCOMP]; As = rgba[i][ACOMP]; +#if CHAN_TYPE == GL_FLOAT + /* clamp */ + Rs = MIN2(Rs, CHAN_MAXF); + Gs = MIN2(Gs, CHAN_MAXF); + Bs = MIN2(Bs, CHAN_MAXF); + As = MIN2(As, CHAN_MAXF); +#endif - /* Frame buffer color */ + /* Frame buffer/dest color */ Rd = dest[i][RCOMP]; Gd = dest[i][GCOMP]; Bd = dest[i][BCOMP]; Ad = dest[i][ACOMP]; +#if CHAN_TYPE == GL_FLOAT + /* clamp */ + Rd = MIN2(Rd, CHAN_MAXF); + Gd = MIN2(Gd, CHAN_MAXF); + Bd = MIN2(Bd, CHAN_MAXF); + Ad = MIN2(Ad, CHAN_MAXF); +#endif /* Source RGB factor */ switch (ctx->Color.BlendSrcRGB) { @@ -349,7 +385,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], sR = sG = sB = (GLfloat) As * ascale; break; case GL_ONE_MINUS_SRC_ALPHA: - sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale; + sR = sG = sB = 1.0F - (GLfloat) As * ascale; break; case GL_DST_ALPHA: sR = sG = sB = (GLfloat) Ad * ascale; @@ -415,7 +451,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], sA = (GLfloat) As * ascale; break; case GL_ONE_MINUS_SRC_ALPHA: - sA = (GLfloat) 1.0F - (GLfloat) As * ascale; + sA = 1.0F - (GLfloat) As * ascale; break; case GL_DST_ALPHA: sA =(GLfloat) Ad * ascale; @@ -472,7 +508,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], dR = dG = dB = (GLfloat) As * ascale; break; case GL_ONE_MINUS_SRC_ALPHA: - dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale; + dR = dG = dB = 1.0F - (GLfloat) As * ascale; break; case GL_DST_ALPHA: dR = dG = dB = (GLfloat) Ad * ascale; @@ -530,7 +566,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], dA = (GLfloat) As * ascale; break; case GL_ONE_MINUS_SRC_ALPHA: - dA = (GLfloat) 1.0F - (GLfloat) As * ascale; + dA = 1.0F - (GLfloat) As * ascale; break; case GL_DST_ALPHA: dA = (GLfloat) Ad * ascale; @@ -560,7 +596,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], /* this should never happen */ dA = 0.0F; _mesa_problem(ctx, "Bad blend dest A factor in do_blend"); - return; + return; } /* Due to round-off problems we have to clamp against zero. */ @@ -610,9 +646,9 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], } /* final clamping */ - rgba[i][RCOMP] = CLAMP( r, 0.0F, CHAN_MAXF ); - rgba[i][GCOMP] = CLAMP( g, 0.0F, CHAN_MAXF ); - rgba[i][BCOMP] = CLAMP( b, 0.0F, CHAN_MAXF ); + rgba[i][RCOMP] = MAX2( r, 0.0F ); + rgba[i][GCOMP] = MAX2( g, 0.0F ); + rgba[i][BCOMP] = MAX2( b, 0.0F ); rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF ); #else if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { @@ -669,30 +705,54 @@ void _swrast_choose_blend_func( GLcontext *ctx ) SWRAST_CONTEXT(ctx)->BlendFunc = blend_general; } else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA - && dstRGB==GL_ONE_MINUS_SRC_ALPHA) { + && dstRGB==GL_ONE_MINUS_SRC_ALPHA) { #if defined(USE_MMX_ASM) if ( cpu_has_mmx ) { - SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency; + SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency; } else #endif SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency; } else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) { - SWRAST_CONTEXT(ctx)->BlendFunc = blend_add; +#if defined(USE_MMX_ASM) + if ( cpu_has_mmx ) { + SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_add; + } + else +#endif + SWRAST_CONTEXT(ctx)->BlendFunc = blend_add; } else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT) && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR)) || ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT) && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) { - SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate; +#if defined(USE_MMX_ASM) + if ( cpu_has_mmx ) { + SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_modulate; + } + else +#endif + SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate; } else if (eq==GL_MIN_EXT) { - SWRAST_CONTEXT(ctx)->BlendFunc = blend_min; +#if defined(USE_MMX_ASM) + if ( cpu_has_mmx ) { + SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_min; + } + else +#endif + SWRAST_CONTEXT(ctx)->BlendFunc = blend_min; } else if (eq==GL_MAX_EXT) { - SWRAST_CONTEXT(ctx)->BlendFunc = blend_max; +#if defined(USE_MMX_ASM) + if ( cpu_has_mmx ) { + SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_max; + } + else +#endif + SWRAST_CONTEXT(ctx)->BlendFunc = blend_max; } else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ZERO && dstRGB == GL_ONE) { SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop; @@ -709,58 +769,38 @@ void _swrast_choose_blend_func( GLcontext *ctx ) /* * Apply the blending operator to a span of pixels. - * Input: n - number of pixels in span - * x, y - location of leftmost pixel in span in window coords. - * mask - boolean mask indicating which pixels to blend. - * In/Out: rgba - pixel values + * We can handle horizontal runs of pixels (spans) or arrays of x/y + * pixel coordinates. */ void -_mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - GLchan rgba[][4], const GLubyte mask[] ) +_mesa_blend_span( GLcontext *ctx, const struct sw_span *span, + GLchan rgba[][4] ) { - GLchan dest[MAX_WIDTH][4]; + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLchan framebuffer[MAX_WIDTH][4]; - /* Check if device driver can do the work */ - if (ctx->Color.BlendEquation==GL_LOGIC_OP && - !ctx->Color.ColorLogicOpEnabled) { - return; - } + ASSERT(span->end <= MAX_WIDTH); + ASSERT(span->arrayMask & SPAN_RGBA); + ASSERT(!ctx->Color.ColorLogicOpEnabled); /* Read span of current frame buffer pixels */ - _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); - - SWRAST_CONTEXT(ctx)->BlendFunc( ctx, n, mask, rgba, - (const GLchan (*)[4]) dest ); -} - - - -/* - * Apply the blending operator to an array of pixels. - * Input: n - number of pixels in span - * x, y - array of pixel locations - * mask - boolean mask indicating which pixels to blend. - * In/Out: rgba - pixel values - */ -void -_mesa_blend_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLchan dest[PB_SIZE][4]; - - /* Check if device driver can do the work */ - if (ctx->Color.BlendEquation==GL_LOGIC_OP && - !ctx->Color.ColorLogicOpEnabled) { - return; + if (span->arrayMask & SPAN_XY) { + /* array of x/y pixel coords */ + (*swrast->Driver.ReadRGBAPixels)( ctx, span->end, + span->array->x, span->array->y, + framebuffer, span->array->mask ); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_read_alpha_pixels( ctx, span->end, + span->array->x, span->array->y, + framebuffer, span->array->mask ); + } } - - /* Read pixels from current color buffer */ - (*swrast->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask ); - if (swrast->_RasterMask & ALPHABUF_BIT) { - _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask ); + else { + /* horizontal run of pixels */ + _mesa_read_rgba_span( ctx, ctx->DrawBuffer, span->end, + span->x, span->y, framebuffer ); } - swrast->BlendFunc( ctx, n, mask, rgba, (const GLchan (*)[4])dest ); + SWRAST_CONTEXT(ctx)->BlendFunc( ctx, span->end, span->array->mask, rgba, + (const GLchan (*)[4]) framebuffer ); } diff --git a/xc/extras/Mesa/src/swrast/s_blend.h b/xc/extras/Mesa/src/swrast/s_blend.h index 1882b18e2..c9357748d 100644 --- a/xc/extras/Mesa/src/swrast/s_blend.h +++ b/xc/extras/Mesa/src/swrast/s_blend.h @@ -1,10 +1,9 @@ -/* $Id: s_blend.h,v 1.1.1.1 2002/10/22 13:06:41 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -35,16 +34,11 @@ extern void -_mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - GLchan rgba[][4], const GLubyte mask[] ); +_mesa_blend_span( GLcontext *ctx, const struct sw_span *span, + GLchan rgba[][4] ); extern void -_mesa_blend_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ); - -extern void _swrast_choose_blend_func( GLcontext *ctx ); diff --git a/xc/extras/Mesa/src/swrast/s_buffers.c b/xc/extras/Mesa/src/swrast/s_buffers.c index 59524ba09..18d11891c 100644 --- a/xc/extras/Mesa/src/swrast/s_buffers.c +++ b/xc/extras/Mesa/src/swrast/s_buffers.c @@ -1,10 +1,9 @@ -/* $Id: s_buffers.c,v 1.1.1.1 2002/10/22 13:06:40 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -26,8 +25,9 @@ #include "glheader.h" +#include "colormac.h" #include "macros.h" -#include "mem.h" +#include "imports.h" #include "s_accum.h" #include "s_alphabuf.h" @@ -53,21 +53,19 @@ clear_color_buffer_with_masking( GLcontext *ctx ) if (ctx->Visual.rgbMode) { /* RGBA mode */ - const GLchan r = ctx->Color.ClearColor[0]; - const GLchan g = ctx->Color.ClearColor[1]; - const GLchan b = ctx->Color.ClearColor[2]; - const GLchan a = ctx->Color.ClearColor[3]; + GLchan clearColor[4]; GLint i; + CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]); + CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]); + CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]); + CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]); for (i = 0; i < height; i++) { GLchan rgba[MAX_WIDTH][4]; GLint j; for (j = 0; j < width; j++) { - rgba[j][RCOMP] = r; - rgba[j][GCOMP] = g; - rgba[j][BCOMP] = b; - rgba[j][ACOMP] = a; + COPY_CHAN4(rgba[j], clearColor); } - _mesa_mask_rgba_span( ctx, width, x, y + i, rgba ); + _mesa_mask_rgba_array( ctx, width, x, y + i, rgba ); (*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i, (CONST GLchan (*)[4]) rgba, NULL ); } @@ -82,7 +80,7 @@ clear_color_buffer_with_masking( GLcontext *ctx ) for (j=0;j<width;j++) { span[j] = ctx->Color.ClearIndex; } - _mesa_mask_index_span( ctx, width, x, y + i, span ); + _mesa_mask_index_array( ctx, width, x, y + i, span ); (*swrast->Driver.WriteCI32Span)( ctx, width, x, y + i, span, mask ); } } @@ -104,20 +102,19 @@ clear_color_buffer(GLcontext *ctx) if (ctx->Visual.rgbMode) { /* RGBA mode */ - const GLchan r = ctx->Color.ClearColor[0]; - const GLchan g = ctx->Color.ClearColor[1]; - const GLchan b = ctx->Color.ClearColor[2]; - const GLchan a = ctx->Color.ClearColor[3]; + GLchan clearColor[4]; GLchan span[MAX_WIDTH][4]; GLint i; + CLAMPED_FLOAT_TO_CHAN(clearColor[RCOMP], ctx->Color.ClearColor[0]); + CLAMPED_FLOAT_TO_CHAN(clearColor[GCOMP], ctx->Color.ClearColor[1]); + CLAMPED_FLOAT_TO_CHAN(clearColor[BCOMP], ctx->Color.ClearColor[2]); + CLAMPED_FLOAT_TO_CHAN(clearColor[ACOMP], ctx->Color.ClearColor[3]); + ASSERT(*((GLuint *) &ctx->Color.ColorMask) == 0xffffffff); for (i = 0; i < width; i++) { - span[i][RCOMP] = r; - span[i][GCOMP] = g; - span[i][BCOMP] = b; - span[i][ACOMP] = a; + COPY_CHAN4(span[i], clearColor); } for (i = 0; i < height; i++) { (*swrast->Driver.WriteRGBASpan)( ctx, width, x, y + i, @@ -167,23 +164,8 @@ clear_color_buffers(GLcontext *ctx) /* loop over four possible dest color buffers */ for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) { - if (bufferBit & ctx->Color.DrawDestMask) { - if (bufferBit == FRONT_LEFT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT); - (void) (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_FRONT_LEFT); - } - else if (bufferBit == FRONT_RIGHT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT); - (void) (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_FRONT_RIGHT); - } - else if (bufferBit == BACK_LEFT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT); - (void) (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_BACK_LEFT); - } - else { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT); - (void) (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, GL_BACK_RIGHT); - } + if (bufferBit & ctx->Color._DrawDestMask) { + (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); if (colorMask != 0xffffffff) { clear_color_buffer_with_masking(ctx); @@ -194,9 +176,8 @@ clear_color_buffers(GLcontext *ctx) } } - /* restore default read/draw buffers */ - (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer ); - (void) (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer ); + /* restore default read/draw buffer */ + _swrast_use_draw_buffer(ctx); } @@ -224,7 +205,7 @@ _swrast_Clear( GLcontext *ctx, GLbitfield mask, /* do software clearing here */ if (mask) { - if (mask & ctx->Color.DrawDestMask) clear_color_buffers(ctx); + if (mask & ctx->Color._DrawDestMask) clear_color_buffers(ctx); if (mask & GL_DEPTH_BUFFER_BIT) _mesa_clear_depth_buffer(ctx); if (mask & GL_ACCUM_BUFFER_BIT) _mesa_clear_accum_buffer(ctx); if (mask & GL_STENCIL_BUFFER_BIT) _mesa_clear_stencil_buffer(ctx); @@ -258,3 +239,66 @@ _swrast_alloc_buffers( GLframebuffer *buffer ) _mesa_alloc_alpha_buffers( buffer ); } } + + +/* + * Fallback for ctx->Driver.DrawBuffer() + */ +void +_swrast_DrawBuffer( GLcontext *ctx, GLenum mode ) +{ + _swrast_use_draw_buffer(ctx); +} + + +/* + * Setup things so that we read/write spans from the user-designated + * read buffer (set via glReadPixels). We usually just have to call + * this for glReadPixels, glCopyPixels, etc. + */ +void +_swrast_use_read_buffer( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + /* Do this so the software-emulated alpha plane span functions work! */ + swrast->CurrentBuffer = ctx->Pixel._ReadSrcMask; + /* Tell the device driver where to read/write spans */ + (*swrast->Driver.SetBuffer)( ctx, ctx->ReadBuffer, swrast->CurrentBuffer ); +} + + +/* + * Setup things so that we read/write spans from the default draw buffer. + * This is the usual mode that Mesa's software rasterizer operates in. + */ +void +_swrast_use_draw_buffer( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + /* The user can specify rendering to zero, one, two, or four color + * buffers simultaneously with glDrawBuffer()! + * We don't expect the span/point/line/triangle functions to deal with + * that mess so we'll iterate over the multiple buffers as needed. + * But usually we only render to one color buffer at a time. + * We set ctx->Color._DriverDrawBuffer to that buffer and tell the + * device driver to use that buffer. + * Look in s_span.c's multi_write_rgba_span() function to see how + * we loop over multiple color buffers when needed. + */ + + if (ctx->Color._DrawDestMask & FRONT_LEFT_BIT) + swrast->CurrentBuffer = FRONT_LEFT_BIT; + else if (ctx->Color._DrawDestMask & BACK_LEFT_BIT) + swrast->CurrentBuffer = BACK_LEFT_BIT; + else if (ctx->Color._DrawDestMask & FRONT_RIGHT_BIT) + swrast->CurrentBuffer = FRONT_RIGHT_BIT; + else if (ctx->Color._DrawDestMask & BACK_RIGHT_BIT) + swrast->CurrentBuffer = BACK_RIGHT_BIT; + else + /* glDrawBuffer(GL_NONE) */ + swrast->CurrentBuffer = FRONT_LEFT_BIT; /* we always have this buffer */ + + (*swrast->Driver.SetBuffer)( ctx, ctx->DrawBuffer, swrast->CurrentBuffer ); +} diff --git a/xc/extras/Mesa/src/swrast/s_context.c b/xc/extras/Mesa/src/swrast/s_context.c index 042797d08..16acc154a 100644 --- a/xc/extras/Mesa/src/swrast/s_context.c +++ b/xc/extras/Mesa/src/swrast/s_context.c @@ -1,8 +1,7 @@ -/* $Id: s_context.c,v 1.1.1.1 2002/10/22 13:06:44 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -24,25 +23,24 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> */ #include "glheader.h" +#include "context.h" #include "mtypes.h" -#include "mem.h" +#include "imports.h" -#include "s_pb.h" -#include "s_points.h" -#include "s_lines.h" -#include "s_triangle.h" +#include "swrast.h" #include "s_blend.h" #include "s_context.h" +#include "s_lines.h" +#include "s_points.h" +#include "s_span.h" +#include "s_triangle.h" #include "s_texture.h" - - - /* * Recompute the value of swrast->_RasterMask, etc. according to * the current context. @@ -56,13 +54,13 @@ _swrast_update_rasterflags( GLcontext *ctx ) if (ctx->Color.BlendEnabled) RasterMask |= BLEND_BIT; if (ctx->Depth.Test) RasterMask |= DEPTH_BIT; if (ctx->Fog.Enabled) RasterMask |= FOG_BIT; - if (ctx->Scissor.Enabled) RasterMask |= SCISSOR_BIT; + if (ctx->Scissor.Enabled) RasterMask |= CLIP_BIT; if (ctx->Stencil.Enabled) RasterMask |= STENCIL_BIT; if (ctx->Visual.rgbMode) { const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); if (colorMask != 0xffffffff) RasterMask |= MASKING_BIT; if (ctx->Color.ColorLogicOpEnabled) RasterMask |= LOGIC_OP_BIT; - if (ctx->Texture._ReallyEnabled) RasterMask |= TEXTURE_BIT; + if (ctx->Texture._EnabledUnits) RasterMask |= TEXTURE_BIT; } else { if (ctx->Color.IndexMask != 0xffffffff) RasterMask |= MASKING_BIT; @@ -78,7 +76,7 @@ _swrast_update_rasterflags( GLcontext *ctx ) || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width || ctx->Viewport.Y < 0 || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) { - RasterMask |= WINCLIP_BIT; + RasterMask |= CLIP_BIT; } if (ctx->Depth.OcclusionTest) @@ -89,8 +87,11 @@ _swrast_update_rasterflags( GLcontext *ctx ) * MULTI_DRAW_BIT flag. Also set it if we're drawing to no * buffers or the RGBA or CI mask disables all writes. */ - if (ctx->Color.DrawBuffer == GL_FRONT_AND_BACK || - ctx->Color.DrawBuffer == GL_NONE) { + if (ctx->Color._DrawDestMask != FRONT_LEFT_BIT && + ctx->Color._DrawDestMask != BACK_LEFT_BIT && + ctx->Color._DrawDestMask != FRONT_RIGHT_BIT && + ctx->Color._DrawDestMask != BACK_RIGHT_BIT) { + /* more than one color buffer designated for writing (or zero buffers) */ RasterMask |= MULTI_DRAW_BIT; } else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) { @@ -143,6 +144,26 @@ _swrast_update_hint( GLcontext *ctx ) swrast->AllowPixelFog)); } + +/* + * Update the swrast->_AnyTextureCombine flag. + */ +static void +_swrast_update_texture_env( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint i; + swrast->_AnyTextureCombine = GL_FALSE; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT || + ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) { + swrast->_AnyTextureCombine = GL_TRUE; + return; + } + } +} + + #define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \ _NEW_TEXTURE | \ _NEW_HINT | \ @@ -181,6 +202,8 @@ _swrast_update_hint( GLcontext *ctx ) #define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE +#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE + #define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR @@ -200,7 +223,7 @@ _swrast_validate_triangle( GLcontext *ctx, swrast->choose_triangle( ctx ); if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) && - !ctx->Texture._ReallyEnabled) { + ctx->Texture._EnabledUnits == 0) { swrast->SpecTriangle = swrast->Triangle; swrast->Triangle = _swrast_add_spec_terms_triangle; } @@ -217,7 +240,7 @@ _swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) swrast->choose_line( ctx ); if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) && - !ctx->Texture._ReallyEnabled) { + ctx->Texture._EnabledUnits == 0) { swrast->SpecLine = swrast->Line; swrast->Line = _swrast_add_spec_terms_line; } @@ -235,7 +258,7 @@ _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 ) swrast->choose_point( ctx ); if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) && - !ctx->Texture._ReallyEnabled) { + ctx->Texture._EnabledUnits == 0) { swrast->SpecPoint = swrast->Point; swrast->Point = _swrast_add_spec_terms_point; } @@ -261,17 +284,15 @@ _swrast_validate_blend_func( GLcontext *ctx, GLuint n, static void _swrast_validate_texture_sample( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLuint n, GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); _swrast_choose_texture_sample_func( ctx, texUnit, tObj ); - swrast->TextureSample[texUnit]( ctx, texUnit, tObj, n, s, t, u, + swrast->TextureSample[texUnit]( ctx, texUnit, tObj, n, texcoords, lambda, rgba ); } @@ -315,7 +336,6 @@ _swrast_invalidate_state( GLcontext *ctx, GLuint new_state ) for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) swrast->TextureSample[i] = _swrast_validate_texture_sample; - if (ctx->Visual.rgbMode) { ASSERT(swrast->Driver.WriteRGBASpan); ASSERT(swrast->Driver.WriteRGBSpan); @@ -334,18 +354,15 @@ _swrast_invalidate_state( GLcontext *ctx, GLuint new_state ) ASSERT(swrast->Driver.ReadCI32Span); ASSERT(swrast->Driver.ReadCI32Pixels); } - } - void _swrast_validate_derived( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - if (swrast->NewState) - { + if (swrast->NewState) { if (swrast->NewState & _SWRAST_NEW_RASTERMASK) _swrast_update_rasterflags( ctx ); @@ -355,6 +372,9 @@ _swrast_validate_derived( GLcontext *ctx ) if (swrast->NewState & _NEW_HINT) _swrast_update_hint( ctx ); + if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE) + _swrast_update_texture_env( ctx ); + swrast->NewState = 0; swrast->StateChanges = 0; swrast->InvalidateState = _swrast_invalidate_state; @@ -371,7 +391,7 @@ _swrast_Quad( GLcontext *ctx, const SWvertex *v2, const SWvertex *v3 ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_Quad\n"); + _mesa_debug(ctx, "_swrast_Quad\n"); _swrast_print_vertex( ctx, v0 ); _swrast_print_vertex( ctx, v1 ); _swrast_print_vertex( ctx, v2 ); @@ -386,7 +406,7 @@ _swrast_Triangle( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2 ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_Triangle\n"); + _mesa_debug(ctx, "_swrast_Triangle\n"); _swrast_print_vertex( ctx, v0 ); _swrast_print_vertex( ctx, v1 ); _swrast_print_vertex( ctx, v2 ); @@ -398,7 +418,7 @@ void _swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_Line\n"); + _mesa_debug(ctx, "_swrast_Line\n"); _swrast_print_vertex( ctx, v0 ); _swrast_print_vertex( ctx, v1 ); } @@ -409,7 +429,7 @@ void _swrast_Point( GLcontext *ctx, const SWvertex *v0 ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_Point\n"); + _mesa_debug(ctx, "_swrast_Point\n"); _swrast_print_vertex( ctx, v0 ); } SWRAST_CONTEXT(ctx)->Point( ctx, v0 ); @@ -419,7 +439,7 @@ void _swrast_InvalidateState( GLcontext *ctx, GLuint new_state ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_InvalidateState\n"); + _mesa_debug(ctx, "_swrast_InvalidateState\n"); } SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state ); } @@ -428,7 +448,7 @@ void _swrast_ResetLineStipple( GLcontext *ctx ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_ResetLineStipple\n"); + _mesa_debug(ctx, "_swrast_ResetLineStipple\n"); } SWRAST_CONTEXT(ctx)->StippleCounter = 0; } @@ -437,7 +457,7 @@ void _swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_allow_vertex_fog %d\n", value); + _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value); } SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); SWRAST_CONTEXT(ctx)->AllowVertexFog = value; @@ -447,7 +467,7 @@ void _swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value ) { if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_allow_pixel_fog %d\n", value); + _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value); } SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); SWRAST_CONTEXT(ctx)->AllowPixelFog = value; @@ -461,18 +481,12 @@ _swrast_CreateContext( GLcontext *ctx ) SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext)); if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_CreateContext\n"); + _mesa_debug(ctx, "_swrast_CreateContext\n"); } if (!swrast) return GL_FALSE; - swrast->PB = _mesa_alloc_pb(); - if (!swrast->PB) { - FREE(swrast); - return GL_FALSE; - } - swrast->NewState = ~0; swrast->choose_point = _swrast_choose_point; @@ -492,15 +506,44 @@ _swrast_CreateContext( GLcontext *ctx ) swrast->AllowVertexFog = GL_TRUE; swrast->AllowPixelFog = GL_TRUE; + if (ctx->Visual.doubleBufferMode) + swrast->CurrentBuffer = BACK_LEFT_BIT; + else + swrast->CurrentBuffer = FRONT_LEFT_BIT; + /* Optimized Accum buffer */ swrast->_IntegerAccumMode = GL_TRUE; swrast->_IntegerAccumScaler = 0.0; - for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) swrast->TextureSample[i] = _swrast_validate_texture_sample; + swrast->SpanArrays = MALLOC_STRUCT(span_arrays); + if (!swrast->SpanArrays) { + FREE(swrast); + return GL_FALSE; + } + + /* init point span buffer */ + swrast->PointSpan.primitive = GL_POINT; + swrast->PointSpan.start = 0; + swrast->PointSpan.end = 0; + swrast->PointSpan.facing = 0; + swrast->PointSpan.array = swrast->SpanArrays; + + assert(ctx->Const.MaxTextureUnits > 0); + assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_UNITS); + + swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureUnits * + MAX_WIDTH * 4 * sizeof(GLchan)); + if (!swrast->TexelBuffer) { + FREE(swrast->SpanArrays); + FREE(swrast); + return GL_FALSE; + } + ctx->swrast_context = swrast; + return GL_TRUE; } @@ -510,10 +553,11 @@ _swrast_DestroyContext( GLcontext *ctx ) SWcontext *swrast = SWRAST_CONTEXT(ctx); if (SWRAST_DEBUG) { - fprintf(stderr, "_swrast_DestroyContext\n"); + _mesa_debug(ctx, "_swrast_DestroyContext\n"); } - FREE( swrast->PB ); + FREE( swrast->SpanArrays ); + FREE( swrast->TexelBuffer ); FREE( swrast ); ctx->swrast_context = 0; @@ -527,6 +571,56 @@ _swrast_GetDeviceDriverReference( GLcontext *ctx ) return &swrast->Driver; } +void +_swrast_flush( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + /* flush any pending fragments from rendering points */ + if (swrast->PointSpan.end > 0) { + if (ctx->Visual.rgbMode) { + if (ctx->Texture._EnabledUnits) + _mesa_write_texture_span(ctx, &(swrast->PointSpan)); + else + _mesa_write_rgba_span(ctx, &(swrast->PointSpan)); + } + else { + _mesa_write_index_span(ctx, &(swrast->PointSpan)); + } + swrast->PointSpan.end = 0; + } +} + +void +_swrast_render_primitive( GLcontext *ctx, GLenum prim ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) { + _swrast_flush(ctx); + } + swrast->Primitive = prim; +} + + +void +_swrast_render_start( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + if (swrast->Driver.SpanRenderStart) + swrast->Driver.SpanRenderStart( ctx ); + swrast->PointSpan.end = 0; +} + +void +_swrast_render_finish( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + if (swrast->Driver.SpanRenderFinish) + swrast->Driver.SpanRenderFinish( ctx ); + + _swrast_flush(ctx); +} + + #define SWRAST_DEBUG_VERTICES 0 void @@ -535,29 +629,31 @@ _swrast_print_vertex( GLcontext *ctx, const SWvertex *v ) GLuint i; if (SWRAST_DEBUG_VERTICES) { - fprintf(stderr, "win %f %f %f %f\n", - v->win[0], v->win[1], v->win[2], v->win[3]); + _mesa_debug(ctx, "win %f %f %f %f\n", + v->win[0], v->win[1], v->win[2], v->win[3]); for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) if (ctx->Texture.Unit[i]._ReallyEnabled) - fprintf(stderr, "texcoord[%d] %f %f %f %f\n", i, - v->texcoord[i][0], v->texcoord[i][1], - v->texcoord[i][2], v->texcoord[i][3]); + _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i, + v->texcoord[i][0], v->texcoord[i][1], + v->texcoord[i][2], v->texcoord[i][3]); #if CHAN_TYPE == GL_FLOAT - fprintf(stderr, "color %f %f %f %f\n", - v->color[0], v->color[1], v->color[2], v->color[3]); - fprintf(stderr, "spec %f %f %f %f\n", - v->specular[0], v->specular[1], v->specular[2], v->specular[3]); + _mesa_debug(ctx, "color %f %f %f %f\n", + v->color[0], v->color[1], v->color[2], v->color[3]); + _mesa_debug(ctx, "spec %f %f %f %f\n", + v->specular[0], v->specular[1], + v->specular[2], v->specular[3]); #else - fprintf(stderr, "color %d %d %d %d\n", - v->color[0], v->color[1], v->color[2], v->color[3]); - fprintf(stderr, "spec %d %d %d %d\n", - v->specular[0], v->specular[1], v->specular[2], v->specular[3]); + _mesa_debug(ctx, "color %d %d %d %d\n", + v->color[0], v->color[1], v->color[2], v->color[3]); + _mesa_debug(ctx, "spec %d %d %d %d\n", + v->specular[0], v->specular[1], + v->specular[2], v->specular[3]); #endif - fprintf(stderr, "fog %f\n", v->fog); - fprintf(stderr, "index %d\n", v->index); - fprintf(stderr, "pointsize %f\n", v->pointSize); - fprintf(stderr, "\n"); + _mesa_debug(ctx, "fog %f\n", v->fog); + _mesa_debug(ctx, "index %d\n", v->index); + _mesa_debug(ctx, "pointsize %f\n", v->pointSize); + _mesa_debug(ctx, "\n"); } } diff --git a/xc/extras/Mesa/src/swrast/s_context.h b/xc/extras/Mesa/src/swrast/s_context.h index 79081b809..75b72f3a2 100644 --- a/xc/extras/Mesa/src/swrast/s_context.h +++ b/xc/extras/Mesa/src/swrast/s_context.h @@ -1,10 +1,9 @@ -/* $Id: s_context.h,v 1.1.1.1 2002/10/22 13:06:45 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -24,7 +23,13 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> + */ + +/** + * \file swrast/s_context.h + * \brief fill in description + * \author Keith Whitwell <keith@tungstengraphics.com> */ #ifndef S_CONTEXT_H @@ -38,10 +43,8 @@ */ typedef void (*TextureSampleFunc)( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ); + GLuint n, GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ); @@ -66,25 +69,25 @@ typedef void (*swrast_tri_func)( GLcontext *ctx, const SWvertex *, const SWvertex *, const SWvertex *); - -/* - * Bitmasks to indicate which rasterization options are enabled (RasterMask) +/** \defgroup Bitmasks + * Bitmasks to indicate which rasterization options are enabled + * (RasterMask) */ -#define ALPHATEST_BIT 0x001 /* Alpha-test pixels */ -#define BLEND_BIT 0x002 /* Blend pixels */ -#define DEPTH_BIT 0x004 /* Depth-test pixels */ -#define FOG_BIT 0x008 /* Fog pixels */ -#define LOGIC_OP_BIT 0x010 /* Apply logic op in software */ -#define SCISSOR_BIT 0x020 /* Scissor pixels */ -#define STENCIL_BIT 0x040 /* Stencil pixels */ -#define MASKING_BIT 0x080 /* Do glColorMask or glIndexMask */ -#define ALPHABUF_BIT 0x100 /* Using software alpha buffer */ -#define WINCLIP_BIT 0x200 /* Clip pixels/primitives to window */ -#define MULTI_DRAW_BIT 0x400 /* Write to more than one color- */ - /* buffer or no buffers. */ -#define OCCLUSION_BIT 0x800 /* GL_HP_occlusion_test enabled */ -#define TEXTURE_BIT 0x1000 /* Texturing really enabled */ - +/*@{*/ +#define ALPHATEST_BIT 0x001 /**< Alpha-test pixels */ +#define BLEND_BIT 0x002 /**< Blend pixels */ +#define DEPTH_BIT 0x004 /**< Depth-test pixels */ +#define FOG_BIT 0x008 /**< Fog pixels */ +#define LOGIC_OP_BIT 0x010 /**< Apply logic op in software */ +#define CLIP_BIT 0x020 /**< Scissor or window clip pixels */ +#define STENCIL_BIT 0x040 /**< Stencil pixels */ +#define MASKING_BIT 0x080 /**< Do glColorMask or glIndexMask */ +#define ALPHABUF_BIT 0x100 /**< Using software alpha buffer */ +#define MULTI_DRAW_BIT 0x400 /**< Write to more than one color- */ + /**< buffer or no buffers. */ +#define OCCLUSION_BIT 0x800 /**< GL_HP_occlusion_test enabled */ +#define TEXTURE_BIT 0x1000 /**< Texturing really enabled */ +/*@}*/ #define _SWRAST_NEW_RASTERMASK (_NEW_BUFFERS| \ _NEW_SCISSOR| \ @@ -97,43 +100,49 @@ typedef void (*swrast_tri_func)( GLcontext *ctx, const SWvertex *, _NEW_DEPTH) - +/** + * \struct SWcontext + * \brief SWContext? + */ typedef struct { - /* Driver interface: + /** Driver interface: */ struct swrast_device_driver Driver; - /* Configuration mechanisms to make software rasterizer match + /** Configuration mechanisms to make software rasterizer match * characteristics of the hardware rasterizer (if present): */ GLboolean AllowVertexFog; GLboolean AllowPixelFog; - /* Derived values, invalidated on statechanges, updated from + /** Derived values, invalidated on statechanges, updated from * _swrast_validate_derived(): */ GLuint _RasterMask; GLfloat _MinMagThresh[MAX_TEXTURE_UNITS]; GLfloat _backface_sign; GLboolean _PreferPixelFog; + GLboolean _AnyTextureCombine; /* Accum buffer temporaries. */ - GLboolean _IntegerAccumMode; /* Storing unscaled integers? */ - GLfloat _IntegerAccumScaler; /* Implicit scale factor */ + GLboolean _IntegerAccumMode; /**< Storing unscaled integers? */ + GLfloat _IntegerAccumScaler; /**< Implicit scale factor */ /* Working values: */ - struct pixel_buffer* PB; - GLuint StippleCounter; /* Line stipple counter */ + GLuint StippleCounter; /**< Line stipple counter */ GLuint NewState; GLuint StateChanges; + GLenum Primitive; /* current primitive being drawn (ala glBegin) */ + GLuint CurrentBuffer; /* exactly one of FRONT_LEFT_BIT, BACK_LEFT_BIT, etc*/ - /* Mechanism to allow driver (like X11) to register further + /** Mechanism to allow driver (like X11) to register further * software rasterization routines. */ + /*@{*/ void (*choose_point)( GLcontext * ); void (*choose_line)( GLcontext * ); void (*choose_triangle)( GLcontext * ); @@ -141,29 +150,50 @@ typedef struct GLuint invalidate_point; GLuint invalidate_line; GLuint invalidate_triangle; + /*@}*/ - - /* Function pointers for dispatch behind public entrypoints. - */ + /** Function pointers for dispatch behind public entrypoints. */ + /*@{*/ void (*InvalidateState)( GLcontext *ctx, GLuint new_state ); swrast_point_func Point; swrast_line_func Line; swrast_tri_func Triangle; + /*@}*/ - /* Placeholders for when separate specular (or secondary color) is + /** + * Placeholders for when separate specular (or secondary color) is * enabled but texturing is not. */ + /*@{*/ swrast_point_func SpecPoint; swrast_line_func SpecLine; swrast_tri_func SpecTriangle; + /*@}*/ + /** + * Typically, we'll allocate a sw_span structure as a local variable + * and set its 'array' pointer to point to this object. The reason is + * this object is big and causes problems when allocated on the stack + * on some systems. + */ + struct span_arrays *SpanArrays; - /* Internal hooks, kept uptodate by the same mechanism as above. + /** + * Used to buffer N GL_POINTS, instead of rendering one by one. + */ + struct sw_span PointSpan; + + /** Internal hooks, kept uptodate by the same mechanism as above. */ blend_func BlendFunc; TextureSampleFunc TextureSample[MAX_TEXTURE_UNITS]; + /** Buffer for saving the sampled texture colors. + * Needed for GL_ARB_texture_env_crossbar implementation. + */ + GLchan *TexelBuffer; + } SWcontext; diff --git a/xc/extras/Mesa/src/swrast/s_copypix.c b/xc/extras/Mesa/src/swrast/s_copypix.c index 10c66ef89..eab359090 100644 --- a/xc/extras/Mesa/src/swrast/s_copypix.c +++ b/xc/extras/Mesa/src/swrast/s_copypix.c @@ -1,8 +1,7 @@ -/* $Id: s_copypix.c,v 1.1.1.1 2002/10/22 13:06:52 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 5.0 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -31,13 +30,12 @@ #include "convolve.h" #include "feedback.h" #include "macros.h" -#include "mem.h" +#include "imports.h" #include "mmath.h" #include "pixel.h" #include "s_context.h" #include "s_depth.h" -#include "s_fog.h" #include "s_histogram.h" #include "s_pixeltex.h" #include "s_span.h" @@ -67,6 +65,9 @@ regions_overlap(GLint srcx, GLint srcy, else if (srcy < dsty) { /* this is OK */ return GL_FALSE; } + else if (srcy > dsty + height) { + return GL_FALSE; + } else { return GL_TRUE; } @@ -98,32 +99,21 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLdepth zspan[MAX_WIDTH]; - GLfloat fogSpan[MAX_WIDTH]; GLboolean quick_draw; GLint row; GLboolean changeBuffer; - GLchan *saveReadAlpha; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; const GLuint transferOps = ctx->_ImageTransferState; GLfloat *dest, *tmpImage, *convImage; + struct sw_span span; - if (ctx->Depth.Test || ctx->Fog.Enabled) { - /* fill in array of z values */ - GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMax); - GLfloat fog; - GLint i; + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterFogCoord); - else - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); - for (i = 0; i < width; i++) { - zspan[i] = z; - fogSpan[i] = fog; - } - } if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom @@ -136,7 +126,6 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* If read and draw buffer are different we must do buffer switching */ - saveReadAlpha = ctx->ReadBuffer->Alpha; changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer || ctx->DrawBuffer != ctx->ReadBuffer; @@ -157,16 +146,8 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, dest = tmpImage; if (changeBuffer) { - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontRightAlpha; - else - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackRightAlpha; + /* choose the read buffer */ + _swrast_use_read_buffer(ctx); } /* read source image */ @@ -184,11 +165,9 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } } - /* read from the draw buffer again (in case of blending) */ if (changeBuffer) { - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - ctx->ReadBuffer->Alpha = saveReadAlpha; + /* restore default src/dst buffer */ + _swrast_use_draw_buffer(ctx); } /* do image transfer ops up until convolution */ @@ -251,7 +230,6 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, for (row = 0; row < height; row++) { const GLfloat *src = convImage + row * width * 4; - GLchan rgba[MAX_WIDTH][4]; GLint i, dy; /* clamp to [0,1] and convert float back to chan */ @@ -260,27 +238,15 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint g = (GLint) (src[i * 4 + GCOMP] * CHAN_MAXF); GLint b = (GLint) (src[i * 4 + BCOMP] * CHAN_MAXF); GLint a = (GLint) (src[i * 4 + ACOMP] * CHAN_MAXF); - rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); - rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); - rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); - rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); - } - - if (ctx->Texture._ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { - GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH]; - GLchan primary_rgba[MAX_WIDTH][4]; - GLuint unit; - /* XXX not sure how multitexture is supposed to work here */ - - MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLchan)); - - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { - _mesa_pixeltexgen(ctx, width, (const GLchan (*)[4]) rgba, - s, t, r, q); - _swrast_texture_fragments(ctx, unit, width, s, t, r, NULL, - (CONST GLchan (*)[4]) primary_rgba, - rgba); - } + span.array->rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); + span.array->rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); + span.array->rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); + span.array->rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); + } + + if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) { + span.end = width; + _swrast_pixel_texture(ctx, &span); } /* write row to framebuffer */ @@ -288,15 +254,21 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, dy = desty + row; if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) { (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy, - (const GLchan (*)[4])rgba, NULL ); + (const GLchan (*)[4])span.array->rgba, NULL ); } else if (zoom) { - _mesa_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, fogSpan, - (const GLchan (*)[4])rgba, desty); + span.x = destx; + span.y = dy; + span.end = width; + _mesa_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4])span.array->rgba, + desty); } else { - _mesa_write_rgba_span( ctx, width, destx, dy, zspan, fogSpan, rgba, - NULL, GL_BITMAP ); + span.x = destx; + span.y = dy; + span.end = width; + _mesa_write_rgba_span(ctx, &span); } } @@ -312,18 +284,16 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLdepth zspan[MAX_WIDTH]; - GLfloat fogSpan[MAX_WIDTH]; - GLchan rgba[MAX_WIDTH][4]; GLchan *tmpImage,*p; GLboolean quick_draw; - GLint sy, dy, stepy; - GLint i, j; + GLint sy, dy, stepy, j; GLboolean changeBuffer; - GLchan *saveReadAlpha; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; const GLuint transferOps = ctx->_ImageTransferState; + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty); @@ -347,21 +317,10 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); - if (ctx->Depth.Test || ctx->Fog.Enabled) { - /* fill in array of z values */ - GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMax); - GLfloat fog; - - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterFogCoord); - else - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); - - for (i=0;i<width;i++) { - zspan[i] = z; - fogSpan[i] = fog; - } - } + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom @@ -374,13 +333,9 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* If read and draw buffer are different we must do buffer switching */ - saveReadAlpha = ctx->ReadBuffer->Alpha; changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer || ctx->DrawBuffer != ctx->ReadBuffer; - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (overlapping) { GLint ssy = sy; tmpImage = (GLchan *) MALLOC(width * height * sizeof(GLchan) * 4); @@ -388,25 +343,22 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } + /* setup source */ + if (changeBuffer) + _swrast_use_read_buffer(ctx); + /* read the source image */ p = tmpImage; - if (changeBuffer) { - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontRightAlpha; - else - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackRightAlpha; - } for (j = 0; j < height; j++, ssy += stepy) { _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, ssy, (GLchan (*)[4]) p ); p += width * 4; } p = tmpImage; + /* restore dest */ + if (changeBuffer) { + _swrast_use_draw_buffer(ctx); + changeBuffer = GL_FALSE; + } } else { tmpImage = NULL; /* silence compiler warnings */ @@ -417,35 +369,17 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, /* Get source pixels */ if (overlapping) { /* get from buffered image */ - MEMCPY(rgba, p, width * sizeof(GLchan) * 4); + MEMCPY(span.array->rgba, p, width * sizeof(GLchan) * 4); p += width * 4; } else { /* get from framebuffer */ - if (changeBuffer) { - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT) { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontLeftAlpha; - } - else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT) { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackLeftAlpha; - } - else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT) { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontRightAlpha; - } - else { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackRightAlpha; - } - } - _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, sy, rgba ); - } - - if (changeBuffer) { - /* read from the draw buffer again (in case of blending) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - ctx->ReadBuffer->Alpha = saveReadAlpha; + if (changeBuffer) + _swrast_use_read_buffer(ctx); + _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, sy, + span.array->rgba ); + if (changeBuffer) + _swrast_use_draw_buffer(ctx); } if (transferOps) { @@ -456,10 +390,10 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, /* convert chan to float */ for (k = 0; k < width; k++) { - rgbaFloat[k][RCOMP] = (GLfloat) rgba[k][RCOMP] * scale; - rgbaFloat[k][GCOMP] = (GLfloat) rgba[k][GCOMP] * scale; - rgbaFloat[k][BCOMP] = (GLfloat) rgba[k][BCOMP] * scale; - rgbaFloat[k][ACOMP] = (GLfloat) rgba[k][ACOMP] * scale; + rgbaFloat[k][RCOMP] = (GLfloat) span.array->rgba[k][RCOMP] * scale; + rgbaFloat[k][GCOMP] = (GLfloat) span.array->rgba[k][GCOMP] * scale; + rgbaFloat[k][BCOMP] = (GLfloat) span.array->rgba[k][BCOMP] * scale; + rgbaFloat[k][ACOMP] = (GLfloat) span.array->rgba[k][ACOMP] * scale; } /* scale & bias */ if (transferOps & IMAGE_SCALE_BIAS_BIT) { @@ -479,7 +413,8 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* convolution */ if (transferOps & IMAGE_CONVOLUTION_BIT) { - /* XXX to do */ + _mesa_problem(ctx, "Convolution should not be enabled in copy_rgba_pixels()"); + return; } /* GL_POST_CONVOLUTION_RED/GREEN/BLUE/ALPHA_SCALE/BIAS */ if (transferOps & IMAGE_POST_CONVOLUTION_SCALE_BIAS) { @@ -519,61 +454,39 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint g = (GLint) (rgbaFloat[k][GCOMP] * CHAN_MAXF); GLint b = (GLint) (rgbaFloat[k][BCOMP] * CHAN_MAXF); GLint a = (GLint) (rgbaFloat[k][ACOMP] * CHAN_MAXF); - rgba[k][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); - rgba[k][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); - rgba[k][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); - rgba[k][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); + span.array->rgba[k][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); + span.array->rgba[k][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); + span.array->rgba[k][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); + span.array->rgba[k][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); } UNDEFARRAY(rgbaFloat); /* mac 32k limitation */ } - if (ctx->Texture._ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { - GLuint unit; - GLchan primary_rgba[MAX_WIDTH][4]; - DEFARRAY(GLfloat, s, MAX_WIDTH); /* mac 32k limitation */ - DEFARRAY(GLfloat, t, MAX_WIDTH); /* mac 32k limitation */ - DEFARRAY(GLfloat, r, MAX_WIDTH); /* mac 32k limitation */ - DEFARRAY(GLfloat, q, MAX_WIDTH); /* mac 32k limitation */ - CHECKARRAY(s, return); /* mac 32k limitation */ - CHECKARRAY(t, return); - CHECKARRAY(r, return); - CHECKARRAY(q, return); - - /* XXX not sure how multitexture is supposed to work here */ - MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLchan)); - - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { - _mesa_pixeltexgen(ctx, width, (const GLchan (*)[4]) rgba, - s, t, r, q); - _swrast_texture_fragments(ctx, unit, width, s, t, r, NULL, - (CONST GLchan (*)[4]) primary_rgba, - rgba); - } - - UNDEFARRAY(s); /* mac 32k limitation */ - UNDEFARRAY(t); - UNDEFARRAY(r); - UNDEFARRAY(q); + if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) { + span.end = width; + _swrast_pixel_texture(ctx, &span); } if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) { (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy, - (const GLchan (*)[4])rgba, NULL ); + (const GLchan (*)[4])span.array->rgba, NULL ); } else if (zoom) { - _mesa_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, fogSpan, - (const GLchan (*)[4])rgba, desty); + span.x = destx; + span.y = dy; + span.end = width; + _mesa_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4]) span.array->rgba, + desty); } else { - _mesa_write_rgba_span( ctx, width, destx, dy, zspan, fogSpan, rgba, - NULL, GL_BITMAP ); + span.x = destx; + span.y = dy; + span.end = width; + _mesa_write_rgba_span(ctx, &span); } } - /* Restore pixel source to be the draw buffer (for blending, etc) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - if (overlapping) FREE(tmpImage); } @@ -583,16 +496,16 @@ static void copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty ) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLdepth zspan[MAX_WIDTH]; - GLfloat fogSpan[MAX_WIDTH]; GLuint *tmpImage,*p; GLint sy, dy, stepy; - GLint i, j; + GLint j; GLboolean changeBuffer; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset; GLint overlapping; + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX); /* Determine if copy should be bottom-to-top or top-to-bottom */ if (srcy<desty) { @@ -611,29 +524,15 @@ static void copy_ci_pixels( GLcontext *ctx, overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); - if (ctx->Depth.Test || ctx->Fog.Enabled) { - /* fill in array of z values */ - GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMax); - GLfloat fog; - - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterFogCoord); - else - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); - - for (i=0;i<width;i++) { - zspan[i] = z; - fogSpan[i] = fog; - } - } + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); /* If read and draw buffer are different we must do buffer switching */ changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer || ctx->DrawBuffer != ctx->ReadBuffer; - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (overlapping) { GLint ssy = sy; tmpImage = (GLuint *) MALLOC(width * height * sizeof(GLuint)); @@ -641,16 +540,21 @@ static void copy_ci_pixels( GLcontext *ctx, _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } + /* setup source */ + if (changeBuffer) + _swrast_use_read_buffer(ctx); + /* read the image */ p = tmpImage; - if (changeBuffer) { - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - } for (j = 0; j < height; j++, ssy += stepy) { _mesa_read_index_span( ctx, ctx->ReadBuffer, width, srcx, ssy, p ); p += width; } p = tmpImage; + /* restore to draw buffer */ + if (changeBuffer) { + _swrast_use_draw_buffer(ctx); + changeBuffer = GL_FALSE; + } } else { tmpImage = NULL; /* silence compiler warning */ @@ -658,46 +562,35 @@ static void copy_ci_pixels( GLcontext *ctx, } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { - GLuint indexes[MAX_WIDTH]; if (overlapping) { - MEMCPY(indexes, p, width * sizeof(GLuint)); + MEMCPY(span.array->index, p, width * sizeof(GLuint)); p += width; } else { - if (changeBuffer) { - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - } - _mesa_read_index_span( ctx, ctx->ReadBuffer, width, srcx, sy, indexes ); - } - - if (changeBuffer) { - /* set read buffer back to draw buffer (in case of logicops) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); + if (changeBuffer) + _swrast_use_read_buffer(ctx); + _mesa_read_index_span( ctx, ctx->ReadBuffer, width, srcx, sy, + span.array->index ); + if (changeBuffer) + _swrast_use_draw_buffer(ctx); } if (shift_or_offset) { - _mesa_shift_and_offset_ci( ctx, width, indexes ); + _mesa_shift_and_offset_ci( ctx, width, span.array->index ); } if (ctx->Pixel.MapColorFlag) { - _mesa_map_ci( ctx, width, indexes ); + _mesa_map_ci( ctx, width, span.array->index ); } - if (zoom) { - _mesa_write_zoomed_index_span(ctx, width, destx, dy, zspan, fogSpan, - indexes, desty ); - } - else { - _mesa_write_index_span(ctx, width, destx, dy, zspan, fogSpan, indexes, - NULL, GL_BITMAP); - } + span.x = destx; + span.y = dy; + span.end = width; + if (zoom) + _mesa_write_zoomed_index_span(ctx, &span, desty); + else + _mesa_write_index_span(ctx, &span); } - /* Restore pixel source to be the draw buffer (for blending, etc) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - if (overlapping) FREE(tmpImage); } @@ -712,20 +605,17 @@ static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint destx, GLint desty ) { GLfloat depth[MAX_WIDTH]; - GLdepth zspan[MAX_WIDTH]; - GLfloat fogSpan[MAX_WIDTH]; GLfloat *p, *tmpImage; - GLuint indexes[MAX_WIDTH]; GLint sy, dy, stepy; GLint i, j; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; - DEFMARRAY(GLchan, rgba, MAX_WIDTH, 4); /* mac 32k limitation */ - CHECKARRAY(rgba, return); /* mac 32k limitation */ + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z); if (!ctx->Visual.depthBits) { _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" ); - UNDEFARRAY(rgba); /* mac 32k limitation */ return; } @@ -746,39 +636,15 @@ static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); - /* setup colors or indexes */ - if (ctx->Visual.rgbMode) { - GLuint *rgba32 = (GLuint *) rgba; - GLuint color = *(GLuint*)( ctx->Current.Color ); - for (i = 0; i < width; i++) { - rgba32[i] = color; - } - } - else { - for (i = 0; i < width; i++) { - indexes[i] = ctx->Current.Index; - } - } - - if (ctx->Fog.Enabled) { - GLfloat fog; - - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterFogCoord); - else - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); - - for (i = 0; i < width; i++) { - fogSpan[i] = fog; - } - } + _mesa_span_default_color(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); if (overlapping) { GLint ssy = sy; tmpImage = (GLfloat *) MALLOC(width * height * sizeof(GLfloat)); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); - UNDEFARRAY(rgba); /* mac 32k limitation */ return; } p = tmpImage; @@ -804,33 +670,28 @@ static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, for (i = 0; i < width; i++) { GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; - zspan[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * ctx->DepthMax); + span.array->z[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * ctx->DepthMax); } + span.x = destx; + span.y = dy; + span.end = width; if (ctx->Visual.rgbMode) { - if (zoom) { - _mesa_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, - fogSpan, (const GLchan (*)[4])rgba, desty ); - } - else { - _mesa_write_rgba_span( ctx, width, destx, dy, zspan, fogSpan, - (GLchan (*)[4])rgba, NULL, GL_BITMAP); - } + if (zoom) + _mesa_write_zoomed_rgba_span( ctx, &span, + (const GLchan (*)[4])span.array->rgba, + desty ); + else + _mesa_write_rgba_span(ctx, &span); } else { - if (zoom) { - _mesa_write_zoomed_index_span( ctx, width, destx, dy, - zspan, fogSpan, indexes, desty ); - } - else { - _mesa_write_index_span( ctx, width, destx, dy, - zspan, fogSpan, indexes, NULL, GL_BITMAP ); - } + if (zoom) + _mesa_write_zoomed_index_span( ctx, &span, desty ); + else + _mesa_write_index_span(ctx, &span); } } - UNDEFARRAY(rgba); /* mac 32k limitation */ - if (overlapping) FREE(tmpImage); } diff --git a/xc/extras/Mesa/src/swrast/s_depth.c b/xc/extras/Mesa/src/swrast/s_depth.c index 76ef0d9cb..d3279d634 100644 --- a/xc/extras/Mesa/src/swrast/s_depth.c +++ b/xc/extras/Mesa/src/swrast/s_depth.c @@ -1,8 +1,7 @@ -/* $Id: s_depth.c,v 1.1.1.1 2002/10/22 13:06:45 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -28,25 +27,24 @@ #include "glheader.h" #include "context.h" #include "macros.h" -#include "mem.h" +#include "imports.h" #include "s_depth.h" #include "s_context.h" -#include "s_pb.h" - - -/* +/** * Return address of depth buffer value for given window coord. */ GLvoid * _mesa_zbuffer_address(GLcontext *ctx, GLint x, GLint y) { if (ctx->Visual.depthBits <= 16) - return (GLushort *) ctx->DrawBuffer->DepthBuffer + ctx->DrawBuffer->Width * y + x; + return (GLushort *) ctx->DrawBuffer->DepthBuffer + + ctx->DrawBuffer->Width * y + x; else - return (GLuint *) ctx->DrawBuffer->DepthBuffer + ctx->DrawBuffer->Width * y + x; + return (GLuint *) ctx->DrawBuffer->DepthBuffer + + ctx->DrawBuffer->Width * y + x; } @@ -73,7 +71,7 @@ _mesa_zbuffer_address(GLcontext *ctx, GLint x, GLint y) * Return: number of fragments which pass the test. */ static GLuint -depth_test_span16( GLcontext *ctx, GLuint n, GLint x, GLint y, +depth_test_span16( GLcontext *ctx, GLuint n, GLushort zbuffer[], const GLdepth z[], GLubyte mask[] ) { GLuint passed = 0; @@ -291,7 +289,7 @@ depth_test_span16( GLcontext *ctx, GLuint n, GLint x, GLint y, } break; case GL_NEVER: - BZERO(mask, n * sizeof(GLubyte)); + _mesa_bzero(mask, n * sizeof(GLubyte)); break; default: _mesa_problem(ctx, "Bad depth func in depth_test_span16"); @@ -302,7 +300,7 @@ depth_test_span16( GLcontext *ctx, GLuint n, GLint x, GLint y, static GLuint -depth_test_span32( GLcontext *ctx, GLuint n, GLint x, GLint y, +depth_test_span32( GLcontext *ctx, GLuint n, GLuint zbuffer[], const GLdepth z[], GLubyte mask[] ) { GLuint passed = 0; @@ -520,7 +518,7 @@ depth_test_span32( GLcontext *ctx, GLuint n, GLint x, GLint y, } break; case GL_NEVER: - BZERO(mask, n * sizeof(GLubyte)); + _mesa_bzero(mask, n * sizeof(GLubyte)); break; default: _mesa_problem(ctx, "Bad depth func in depth_test_span32"); @@ -534,33 +532,59 @@ depth_test_span32( GLcontext *ctx, GLuint n, GLint x, GLint y, /* * Apply depth test to span of fragments. Hardware or software z buffer. */ -GLuint -_mesa_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], GLubyte mask[] ) +static GLuint +depth_test_span( GLcontext *ctx, struct sw_span *span) { + const GLint x = span->x; + const GLint y = span->y; + const GLuint n = span->end; SWcontext *swrast = SWRAST_CONTEXT(ctx); + + ASSERT((span->arrayMask & SPAN_XY) == 0); + ASSERT(span->arrayMask & SPAN_Z); + if (swrast->Driver.ReadDepthSpan) { /* hardware-based depth buffer */ GLdepth zbuffer[MAX_WIDTH]; GLuint passed; (*swrast->Driver.ReadDepthSpan)(ctx, n, x, y, zbuffer); - passed = depth_test_span32(ctx, n, x, y, zbuffer, z, mask); - assert(swrast->Driver.WriteDepthSpan); - (*swrast->Driver.WriteDepthSpan)(ctx, n, x, y, zbuffer, mask); + passed = depth_test_span32(ctx, n, zbuffer, span->array->z, + span->array->mask); + ASSERT(swrast->Driver.WriteDepthSpan); + (*swrast->Driver.WriteDepthSpan)(ctx, n, x, y, zbuffer, + span->array->mask); + if (passed < n) + span->writeAll = GL_FALSE; return passed; } else { + GLuint passed; /* software depth buffer */ if (ctx->Visual.depthBits <= 16) { GLushort *zptr = (GLushort *) Z_ADDRESS16(ctx, x, y); - GLuint passed = depth_test_span16(ctx, n, x, y, zptr, z, mask); - return passed; + passed = depth_test_span16(ctx, n, zptr, span->array->z, span->array->mask); } else { GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, x, y); - GLuint passed = depth_test_span32(ctx, n, x, y, zptr, z, mask); - return passed; + passed = depth_test_span32(ctx, n, zptr, span->array->z, span->array->mask); } +#if 1 + if (passed < span->end) { + span->writeAll = GL_FALSE; + } +#else + /* this causes a glDrawPixels(GL_DEPTH_COMPONENT) conformance failure */ + if (passed < span->end) { + span->writeAll = GL_FALSE; + if (passed == 0) { + span->end = 0; + return 0; + } + while (span->end > 0 && span->mask[span->end - 1] == 0) + span->end --; + } +#endif + return passed; } } @@ -804,7 +828,7 @@ software_depth_test_pixels16( GLcontext *ctx, GLuint n, break; case GL_NEVER: /* depth test never passes */ - BZERO(mask, n * sizeof(GLubyte)); + _mesa_bzero(mask, n * sizeof(GLubyte)); break; default: _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels"); @@ -1050,7 +1074,7 @@ software_depth_test_pixels32( GLcontext *ctx, GLuint n, break; case GL_NEVER: /* depth test never passes */ - BZERO(mask, n * sizeof(GLubyte)); + _mesa_bzero(mask, n * sizeof(GLubyte)); break; default: _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels"); @@ -1284,7 +1308,7 @@ hardware_depth_test_pixels( GLcontext *ctx, GLuint n, GLdepth zbuffer[], break; case GL_NEVER: /* depth test never passes */ - BZERO(mask, n * sizeof(GLubyte)); + _mesa_bzero(mask, n * sizeof(GLubyte)); break; default: _mesa_problem(ctx, "Bad depth func in hardware_depth_test_pixels"); @@ -1293,15 +1317,19 @@ hardware_depth_test_pixels( GLcontext *ctx, GLuint n, GLdepth zbuffer[], -void -_mesa_depth_test_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - const GLdepth z[], GLubyte mask[] ) +static GLuint +depth_test_pixels( GLcontext *ctx, struct sw_span *span ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint n = span->end; + const GLint *x = span->array->x; + const GLint *y = span->array->y; + const GLdepth *z = span->array->z; + GLubyte *mask = span->array->mask; + if (swrast->Driver.ReadDepthPixels) { /* read depth values from hardware Z buffer */ - GLdepth zbuffer[PB_SIZE]; + GLdepth zbuffer[MAX_WIDTH]; (*swrast->Driver.ReadDepthPixels)(ctx, n, x, y, zbuffer); hardware_depth_test_pixels( ctx, n, zbuffer, z, mask ); @@ -1317,9 +1345,22 @@ _mesa_depth_test_pixels( GLcontext *ctx, else software_depth_test_pixels32(ctx, n, x, y, z, mask); } + return n; /* not really correct, but OK */ } +/** + * Apply depth (Z) buffer testing to the span. + * \return approx number of pixels that passed (only zero is reliable) + */ +GLuint +_mesa_depth_test_span( GLcontext *ctx, struct sw_span *span) +{ + if (span->arrayMask & SPAN_XY) + return depth_test_pixels(ctx, span); + else + return depth_test_span(ctx, span); +} @@ -1328,7 +1369,7 @@ _mesa_depth_test_pixels( GLcontext *ctx, /**********************************************************************/ -/* +/** * Read a span of depth values from the depth buffer. * This function does clipping before calling the device driver function. */ @@ -1339,7 +1380,7 @@ _mesa_read_depth_span( GLcontext *ctx, SWcontext *swrast = SWRAST_CONTEXT(ctx); if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height || - x + n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) { + x + (GLint) n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) { /* span is completely outside framebuffer */ GLint i; for (i = 0; i < n; i++) @@ -1390,7 +1431,7 @@ _mesa_read_depth_span( GLcontext *ctx, } else { /* no depth buffer */ - BZERO(depth, n * sizeof(GLfloat)); + _mesa_bzero(depth, n * sizeof(GLfloat)); } } @@ -1398,7 +1439,7 @@ _mesa_read_depth_span( GLcontext *ctx, -/* +/** * Return a span of depth values from the depth buffer as floats in [0,1]. * This is used for both hardware and software depth buffers. * Input: n - how many pixels @@ -1413,7 +1454,7 @@ _mesa_read_depth_span_float( GLcontext *ctx, const GLfloat scale = 1.0F / ctx->DepthMaxF; if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height || - x + n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) { + x + (GLint) n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) { /* span is completely outside framebuffer */ GLint i; for (i = 0; i < n; i++) @@ -1469,7 +1510,7 @@ _mesa_read_depth_span_float( GLcontext *ctx, } else { /* no depth buffer */ - BZERO(depth, n * sizeof(GLfloat)); + _mesa_bzero(depth, n * sizeof(GLfloat)); } } @@ -1481,9 +1522,10 @@ _mesa_read_depth_span_float( GLcontext *ctx, -/* +/** * Allocate a new depth buffer. If there's already a depth buffer allocated * it will be free()'d. The new depth buffer will be uniniitalized. + * This function is only called through Driver.alloc_depth_buffer. */ void _mesa_alloc_depth_buffer( GLframebuffer *buffer ) @@ -1504,7 +1546,8 @@ _mesa_alloc_depth_buffer( GLframebuffer *buffer ) else bytesPerValue = sizeof(GLuint); - buffer->DepthBuffer = MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height * bytesPerValue); + buffer->DepthBuffer = MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height + * bytesPerValue); if (!buffer->DepthBuffer) { /* out of memory */ @@ -1518,9 +1561,7 @@ _mesa_alloc_depth_buffer( GLframebuffer *buffer ) } - - -/* +/** * Clear the depth buffer. If the depth buffer doesn't exist yet we'll * allocate it now. * This function is only called through Driver.clear_depth_buffer. @@ -1578,7 +1619,7 @@ _mesa_clear_depth_buffer( GLcontext *ctx ) const GLushort clearValue = (GLushort) (ctx->Depth.Clear * ctx->DepthMax); if ((clearValue & 0xff) == (clearValue >> 8)) { if (clearValue == 0) { - BZERO(ctx->DrawBuffer->DepthBuffer, + _mesa_bzero(ctx->DrawBuffer->DepthBuffer, 2*ctx->DrawBuffer->Width*ctx->DrawBuffer->Height); } else { @@ -1612,7 +1653,7 @@ _mesa_clear_depth_buffer( GLcontext *ctx ) /* >16 bit depth buffer */ const GLuint clearValue = (GLuint) (ctx->Depth.Clear * ctx->DepthMax); if (clearValue == 0) { - BZERO(ctx->DrawBuffer->DepthBuffer, + _mesa_bzero(ctx->DrawBuffer->DepthBuffer, ctx->DrawBuffer->Width*ctx->DrawBuffer->Height*sizeof(GLuint)); } else { diff --git a/xc/extras/Mesa/src/swrast/s_depth.h b/xc/extras/Mesa/src/swrast/s_depth.h index 9f04d727b..f1bd65e3a 100644 --- a/xc/extras/Mesa/src/swrast/s_depth.h +++ b/xc/extras/Mesa/src/swrast/s_depth.h @@ -1,8 +1,7 @@ -/* $Id: s_depth.h,v 1.1.1.1 2002/10/22 13:06:46 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.2 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -37,14 +36,10 @@ extern GLvoid * _mesa_zbuffer_address(GLcontext *ctx, GLint x, GLint y); + extern GLuint -_mesa_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], GLubyte mask[] ); +_mesa_depth_test_span( GLcontext *ctx, struct sw_span *span); -extern void -_mesa_depth_test_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - const GLdepth z[], GLubyte mask[] ); extern void diff --git a/xc/extras/Mesa/src/swrast/s_drawpix.c b/xc/extras/Mesa/src/swrast/s_drawpix.c index 7f5ed8077..3bcee0fc6 100644 --- a/xc/extras/Mesa/src/swrast/s_drawpix.c +++ b/xc/extras/Mesa/src/swrast/s_drawpix.c @@ -1,8 +1,7 @@ -/* $Id: s_drawpix.c,v 1.1.1.1 2002/10/22 13:06:58 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 5.0 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -31,13 +30,12 @@ #include "convolve.h" #include "image.h" #include "macros.h" -#include "mem.h" +#include "imports.h" #include "mmath.h" #include "pixel.h" #include "s_context.h" #include "s_drawpix.h" -#include "s_fog.h" #include "s_pixeltex.h" #include "s_span.h" #include "s_stencil.h" @@ -103,15 +101,23 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, { SWcontext *swrast = SWRAST_CONTEXT(ctx); const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; - GLchan rgb[MAX_WIDTH][3]; - GLchan rgba[MAX_WIDTH][4]; + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); if (!ctx->Current.RasterPosValid) { return GL_TRUE; /* no-op */ } - if ((SWRAST_CONTEXT(ctx)->_RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0 - && ctx->Texture._ReallyEnabled == 0 + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); + if (ctx->Texture._EnabledUnits) + _mesa_span_default_texcoords(ctx, &span); + + if ((SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) == 0 + && ctx->Texture._EnabledUnits == 0 && unpack->Alignment == 1 && !unpack->SwapBytes && !unpack->LsbFirst) { @@ -232,8 +238,11 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, /* with zooming */ GLint row; for (row=0; row<drawHeight; row++) { - _mesa_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, - zSpan, 0, (CONST GLchan (*)[4]) src, zoomY0); + span.x = destX; + span.y = destY; + span.end = drawWidth; + _mesa_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4]) src, zoomY0); src += rowLength * 4; destY++; } @@ -269,8 +278,11 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, /* with zooming */ GLint row; for (row=0; row<drawHeight; row++) { - _mesa_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, - zSpan, 0, (CONST GLchan (*)[3]) src, zoomY0); + span.x = destX; + span.y = destY; + span.end = drawWidth; + _mesa_write_zoomed_rgb_span(ctx, &span, + (CONST GLchan (*)[3]) src, zoomY0); src += rowLength * 3; destY++; } @@ -290,12 +302,12 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, for (row=0; row<drawHeight; row++) { GLint i; for (i=0;i<drawWidth;i++) { - rgb[i][0] = src[i]; - rgb[i][1] = src[i]; - rgb[i][2] = src[i]; + span.array->rgb[i][0] = src[i]; + span.array->rgb[i][1] = src[i]; + span.array->rgb[i][2] = src[i]; } (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, - (CONST GLchan (*)[3]) rgb, NULL); + (CONST GLchan (*)[3]) span.array->rgb, NULL); src += rowLength; destY++; } @@ -307,13 +319,13 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, for (row=0; row<drawHeight; row++) { GLint i; for (i=0;i<drawWidth;i++) { - rgb[i][0] = src[i]; - rgb[i][1] = src[i]; - rgb[i][2] = src[i]; + span.array->rgb[i][0] = src[i]; + span.array->rgb[i][1] = src[i]; + span.array->rgb[i][2] = src[i]; } destY--; (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, - (CONST GLchan (*)[3]) rgb, NULL); + (CONST GLchan (*)[3]) span.array->rgb, NULL); src += rowLength; } } @@ -324,12 +336,15 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, for (row=0; row<drawHeight; row++) { GLint i; for (i=0;i<drawWidth;i++) { - rgb[i][0] = src[i]; - rgb[i][1] = src[i]; - rgb[i][2] = src[i]; + span.array->rgb[i][0] = src[i]; + span.array->rgb[i][1] = src[i]; + span.array->rgb[i][2] = src[i]; } - _mesa_write_zoomed_rgb_span(ctx, drawWidth, destX, destY, - zSpan, 0, (CONST GLchan (*)[3]) rgb, zoomY0); + span.x = destX; + span.y = destY; + span.end = drawWidth; + _mesa_write_zoomed_rgb_span(ctx, &span, + (CONST GLchan (*)[3]) span.array->rgb, zoomY0); src += rowLength; destY++; } @@ -350,13 +365,13 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLint i; GLchan *ptr = src; for (i=0;i<drawWidth;i++) { - rgba[i][0] = *ptr; - rgba[i][1] = *ptr; - rgba[i][2] = *ptr++; - rgba[i][3] = *ptr++; + span.array->rgba[i][0] = *ptr; + span.array->rgba[i][1] = *ptr; + span.array->rgba[i][2] = *ptr++; + span.array->rgba[i][3] = *ptr++; } (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, - (CONST GLchan (*)[4]) rgba, NULL); + (CONST GLchan (*)[4]) span.array->rgba, NULL); src += rowLength*2; destY++; } @@ -369,14 +384,14 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLint i; GLchan *ptr = src; for (i=0;i<drawWidth;i++) { - rgba[i][0] = *ptr; - rgba[i][1] = *ptr; - rgba[i][2] = *ptr++; - rgba[i][3] = *ptr++; + span.array->rgba[i][0] = *ptr; + span.array->rgba[i][1] = *ptr; + span.array->rgba[i][2] = *ptr++; + span.array->rgba[i][3] = *ptr++; } destY--; (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, - (CONST GLchan (*)[4]) rgba, NULL); + (CONST GLchan (*)[4]) span.array->rgba, NULL); src += rowLength*2; } } @@ -388,13 +403,16 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLchan *ptr = src; GLint i; for (i=0;i<drawWidth;i++) { - rgba[i][0] = *ptr; - rgba[i][1] = *ptr; - rgba[i][2] = *ptr++; - rgba[i][3] = *ptr++; + span.array->rgba[i][0] = *ptr; + span.array->rgba[i][1] = *ptr; + span.array->rgba[i][2] = *ptr++; + span.array->rgba[i][3] = *ptr++; } - _mesa_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, - zSpan, 0, (CONST GLchan (*)[4]) rgba, zoomY0); + span.x = destX; + span.y = destY; + span.end = drawWidth; + _mesa_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4]) span.array->rgba, zoomY0); src += rowLength*2; destY++; } @@ -411,10 +429,9 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLint row; for (row=0; row<drawHeight; row++) { ASSERT(drawWidth < MAX_WIDTH); - _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba); + _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, - (const GLchan (*)[4]) rgba, - NULL); + (const GLchan (*)[4]) span.array->rgba, NULL); src += rowLength; destY++; } @@ -425,11 +442,10 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLint row; for (row=0; row<drawHeight; row++) { ASSERT(drawWidth < MAX_WIDTH); - _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba); + _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); destY--; (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, - (CONST GLchan (*)[4]) rgba, - NULL); + (CONST GLchan (*)[4]) span.array->rgba, NULL); src += rowLength; } return GL_TRUE; @@ -439,9 +455,12 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLint row; for (row=0; row<drawHeight; row++) { ASSERT(drawWidth < MAX_WIDTH); - _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba); - _mesa_write_zoomed_rgba_span(ctx, drawWidth, destX, destY, - zSpan, 0, (CONST GLchan (*)[4]) rgba, zoomY0); + _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); + span.x = destX; + span.y = destY; + span.end = drawWidth; + _mesa_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4]) span.array->rgba, zoomY0); src += rowLength; destY++; } @@ -489,47 +508,33 @@ draw_index_pixels( GLcontext *ctx, GLint x, GLint y, { const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; const GLint desty = y; - GLint row, drawWidth; - GLdepth zspan[MAX_WIDTH]; - GLfloat fogSpan[MAX_WIDTH]; + GLint row, drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; + struct sw_span span; - drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; - - /* Fragment depth values */ - if (ctx->Depth.Test || ctx->Fog.Enabled) { - GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF); - GLfloat fog; - GLint i; + INIT_SPAN(span, GL_BITMAP, drawWidth, 0, SPAN_INDEX); - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterFogCoord); - else - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); - - for (i = 0; i < drawWidth; i++) { - zspan[i] = zval; - fogSpan[i] = fog; - } - } + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); /* * General solution */ for (row = 0; row < height; row++, y++) { - GLuint indexes[MAX_WIDTH]; const GLvoid *source = _mesa_image_address(&ctx->Unpack, pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0); - _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes, + _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, + span.array->index, type, source, &ctx->Unpack, ctx->_ImageTransferState); - if (zoom) { - _mesa_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, fogSpan, - indexes, desty); - } - else { - _mesa_write_index_span(ctx, drawWidth, x, y, zspan, fogSpan, indexes, - NULL, GL_BITMAP); - } + span.x = x; + span.y = y; + span.end = drawWidth; + if (zoom) + _mesa_write_zoomed_index_span(ctx, &span, desty); + else + _mesa_write_index_span(ctx, &span); } } @@ -594,7 +599,6 @@ draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, } - /* * Do a glDrawPixels of depth values. */ @@ -606,9 +610,10 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0; const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; const GLint desty = y; - GLchan rgba[MAX_WIDTH][4]; - GLuint ispan[MAX_WIDTH]; GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, drawWidth, 0, SPAN_Z); if (type != GL_BYTE && type != GL_UNSIGNED_BYTE @@ -621,62 +626,53 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, return; } - /* Colors or indexes */ - if (ctx->Visual.rgbMode) { - GLint i; - GLint r, g, b, a; - UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]); - UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]); - UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]); - UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]); - for (i = 0; i < drawWidth; i++) { - rgba[i][RCOMP] = r; - rgba[i][GCOMP] = g; - rgba[i][BCOMP] = b; - rgba[i][ACOMP] = a; - } - } - else { - GLint i; - for (i = 0; i < drawWidth; i++) { - ispan[i] = ctx->Current.RasterIndex; - } - } + _mesa_span_default_color(ctx, &span); + + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); + if (ctx->Texture._EnabledUnits) + _mesa_span_default_texcoords(ctx, &span); if (type==GL_UNSIGNED_SHORT && ctx->Visual.depthBits == 16 && !bias_or_scale && !zoom && ctx->Visual.rgbMode) { /* Special case: directly write 16-bit depth values */ GLint row; - for (row = 0; row < height; row++, y++) { - GLdepth zspan[MAX_WIDTH]; + span.x = x; + span.y = y; + span.end = drawWidth; + for (row = 0; row < height; row++, span.y++) { const GLushort *zptr = (const GLushort *) _mesa_image_address(&ctx->Unpack, pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); GLint i; - for (i = 0; i < width; i++) - zspan[i] = zptr[i]; - _mesa_write_rgba_span(ctx, width, x, y, zspan, 0, rgba, - NULL, GL_BITMAP); + for (i = 0; i < drawWidth; i++) + span.array->z[i] = zptr[i]; + _mesa_write_rgba_span(ctx, &span); } } else if (type==GL_UNSIGNED_INT && ctx->Visual.depthBits == 32 && !bias_or_scale && !zoom && ctx->Visual.rgbMode) { /* Special case: directly write 32-bit depth values */ GLint row; - for (row = 0; row < height; row++, y++) { + span.x = x; + span.y = y; + span.end = drawWidth; + for (row = 0; row < height; row++, span.y++) { const GLuint *zptr = (const GLuint *) _mesa_image_address(&ctx->Unpack, pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); - _mesa_write_rgba_span(ctx, width, x, y, zptr, 0, rgba, - NULL, GL_BITMAP); + MEMCPY(span.array->z, zptr, drawWidth * sizeof(GLdepth)); + _mesa_write_rgba_span(ctx, &span); } } else { /* General case */ GLint row; - for (row = 0; row < height; row++, y++) { + span.x = x; + span.y = y; + span.end = drawWidth; + for (row = 0; row < height; row++, span.y++) { GLfloat fspan[MAX_WIDTH]; - GLdepth zspan[MAX_WIDTH]; const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0); _mesa_unpack_depth_span( ctx, drawWidth, fspan, type, src, @@ -686,31 +682,23 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, const GLfloat zs = ctx->DepthMaxF; GLint i; for (i = 0; i < drawWidth; i++) { - zspan[i] = (GLdepth) (fspan[i] * zs + 0.5F); + span.array->z[i] = (GLdepth) (fspan[i] * zs + 0.5F); } } - if (ctx->Visual.rgbMode) { if (zoom) { - _mesa_write_zoomed_rgba_span(ctx, width, x, y, zspan, 0, - (const GLchan (*)[4]) rgba, desty); - } - else { - _mesa_write_rgba_span(ctx, width, x, y, zspan, 0, - rgba, NULL, GL_BITMAP); + _mesa_write_zoomed_rgba_span(ctx, &span, + (const GLchan (*)[4]) span.array->rgba, desty); } + else + _mesa_write_rgba_span(ctx, &span); } else { - if (zoom) { - _mesa_write_zoomed_index_span(ctx, width, x, y, zspan, 0, - ispan, GL_BITMAP); - } - else { - _mesa_write_index_span(ctx, width, x, y, zspan, 0, - ispan, NULL, GL_BITMAP); - } + if (zoom) + _mesa_write_zoomed_index_span(ctx, &span, desty); + else + _mesa_write_index_span(ctx, &span); } - } } } @@ -728,11 +716,12 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; const GLint desty = y; - GLdepth zspan[MAX_WIDTH]; - GLfloat fogSpan[MAX_WIDTH]; GLboolean quickDraw; GLfloat *convImage = NULL; GLuint transferOps = ctx->_ImageTransferState; + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); if (!_mesa_is_legal_format_and_type(format, type)) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)"); @@ -743,24 +732,12 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels)) return; - /* Fragment depth values */ - if (ctx->Depth.Test || ctx->Fog.Enabled) { - /* fill in array of z values */ - GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF); - GLfloat fog; - GLint i; - - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterFogCoord); - else - fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); - - for (i=0;i<width;i++) { - zspan[i] = z; - fogSpan[i] = fog; - } - } - + if (ctx->Depth.Test) + _mesa_span_default_z(ctx, &span); + if (ctx->Fog.Enabled) + _mesa_span_default_fog(ctx, &span); + if (ctx->Texture._EnabledUnits) + _mesa_span_default_texcoords(ctx, &span); if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && x >= 0 && y >= 0 && x + width <= (GLint) ctx->DrawBuffer->Width @@ -827,61 +804,44 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, * General solution */ { - GLchan rgba[MAX_WIDTH][4]; GLint row; if (width > MAX_WIDTH) width = MAX_WIDTH; + for (row = 0; row < height; row++, y++) { const GLvoid *source = _mesa_image_address(unpack, pixels, width, height, format, type, 0, row, 0); - _mesa_unpack_chan_color_span(ctx, width, GL_RGBA, (GLchan *) rgba, + + _mesa_unpack_chan_color_span(ctx, width, GL_RGBA, + (GLchan *) span.array->rgba, format, type, source, unpack, transferOps); + if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink)) continue; - if (ctx->Texture._ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { - GLchan primary_rgba[MAX_WIDTH][4]; - GLuint unit; - DEFARRAY(GLfloat, s, MAX_WIDTH); /* mac 32k limitation */ - DEFARRAY(GLfloat, t, MAX_WIDTH); - DEFARRAY(GLfloat, r, MAX_WIDTH); - DEFARRAY(GLfloat, q, MAX_WIDTH); - CHECKARRAY(s, return); /* mac 32k limitation */ - CHECKARRAY(t, return); - CHECKARRAY(r, return); - CHECKARRAY(q, return); - - /* XXX not sure how multitexture is supposed to work here */ - MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLchan)); - - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { - if (ctx->Texture.Unit[unit]._ReallyEnabled) { - _mesa_pixeltexgen(ctx, width, (const GLchan (*)[4]) rgba, - s, t, r, q); - _swrast_texture_fragments(ctx, unit, width, s, t, r, NULL, - (CONST GLchan (*)[4]) primary_rgba, - rgba); - } - } - UNDEFARRAY(s); /* mac 32k limitation */ - UNDEFARRAY(t); - UNDEFARRAY(r); - UNDEFARRAY(q); + if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) { + span.end = width; + _swrast_pixel_texture(ctx, &span); } if (quickDraw) { (*swrast->Driver.WriteRGBASpan)(ctx, width, x, y, - (CONST GLchan (*)[4]) rgba, NULL); + (CONST GLchan (*)[4]) span.array->rgba, NULL); } else if (zoom) { - _mesa_write_zoomed_rgba_span(ctx, width, x, y, zspan, fogSpan, - (CONST GLchan (*)[4]) rgba, desty); + span.x = x; + span.y = y; + span.end = width; + _mesa_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4]) span.array->rgba, desty); } else { - _mesa_write_rgba_span(ctx, (GLuint) width, x, y, zspan, fogSpan, - rgba, NULL, GL_BITMAP); + span.x = x; + span.y = y; + span.end = width; + _mesa_write_rgba_span(ctx, &span); } } } @@ -907,7 +867,6 @@ _swrast_DrawPixels( GLcontext *ctx, SWcontext *swrast = SWRAST_CONTEXT(ctx); (void) unpack; - if (swrast->NewState) _swrast_validate_derived( ctx ); @@ -945,3 +904,55 @@ _swrast_DrawPixels( GLcontext *ctx, RENDER_FINISH(swrast,ctx); } + + + +#if 0 /* experimental */ +/* + * Execute glDrawDepthPixelsMESA(). + */ +void +_swrast_DrawDepthPixelsMESA( GLcontext *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum colorFormat, GLenum colorType, + const GLvoid *colors, + GLenum depthType, const GLvoid *depths, + const struct gl_pixelstore_attrib *unpack ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + (void) unpack; + + if (swrast->NewState) + _swrast_validate_derived( ctx ); + + RENDER_START(swrast,ctx); + + switch (colorFormat) { + case GL_COLOR_INDEX: + if (ctx->Visual.rgbMode) + draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType, colors); + else + draw_index_pixels(ctx, x, y, width, height, colorType, colors); + break; + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_RGB: + case GL_BGR: + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType, colors); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, + "glDrawDepthPixelsMESA(colorFormat)" ); + } + + RENDER_FINISH(swrast,ctx); +} +#endif diff --git a/xc/extras/Mesa/src/swrast/s_fog.c b/xc/extras/Mesa/src/swrast/s_fog.c index b7e880528..2e2390c08 100644 --- a/xc/extras/Mesa/src/swrast/s_fog.c +++ b/xc/extras/Mesa/src/swrast/s_fog.c @@ -1,8 +1,7 @@ -/* $Id: s_fog.c,v 1.1.1.1 2002/10/22 13:06:41 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -33,12 +32,12 @@ #include "s_context.h" #include "s_fog.h" -#include "s_pb.h" +#include "s_span.h" -/* +/** * Used to convert current raster distance to a fog factor in [0,1]. */ GLfloat @@ -63,67 +62,14 @@ _mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z) f = (GLfloat) exp(-(d * d * z * z)); return f; default: - _mesa_problem(ctx, "Bad fog mode in make_fog_coord"); + _mesa_problem(ctx, "Bad fog mode in _mesa_z_to_fogfactor"); return 0.0; } } -/* - * Apply fog to an array of RGBA pixels. - * Input: n - number of pixels - * fog - array of fog factors in [0,1] - * red, green, blue, alpha - pixel colors - * Output: red, green, blue, alpha - fogged pixel colors - */ -void -_mesa_fog_rgba_pixels( const GLcontext *ctx, - GLuint n, - const GLfloat fog[], - GLchan rgba[][4] ) -{ - GLuint i; - GLchan rFog, gFog, bFog; - - UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); - UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); - UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); - - for (i = 0; i < n; i++) { - const GLfloat f = fog[i]; - const GLfloat g = 1.0F - f; - rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + g * rFog); - rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + g * gFog); - rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + g * bFog); - } -} - - - -/* - * Apply fog to an array of color index pixels. - * Input: n - number of pixels - * fog - array of fog factors in [0,1] - * index - pixel color indexes - * Output: index - fogged pixel color indexes - */ -void -_mesa_fog_ci_pixels( const GLcontext *ctx, - GLuint n, const GLfloat fog[], GLuint index[] ) -{ - GLuint idx = (GLuint) ctx->Fog.Index; - GLuint i; - - for (i = 0; i < n; i++) { - const GLfloat f = CLAMP(fog[i], 0.0F, 1.0F); - index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); - } -} - - - -/* +/** * Calculate fog factors (in [0,1]) from window z values * Input: n - number of pixels * z - array of integer depth values @@ -138,9 +84,10 @@ compute_fog_factors_from_z( const GLcontext *ctx, const GLdepth z[], GLfloat fogFact[] ) { - const GLboolean ortho = (ctx->ProjectionMatrix.m[15] != 0.0F); - const GLfloat p10 = ctx->ProjectionMatrix.m[10]; - const GLfloat p14 = ctx->ProjectionMatrix.m[14]; + const GLfloat *proj = ctx->ProjectionMatrixStack.Top->m; + const GLboolean ortho = (proj[15] != 0.0F); + const GLfloat p10 = proj[10]; + const GLfloat p14 = proj[14]; const GLfloat tz = ctx->Viewport._WindowMap.m[MAT_TZ]; GLfloat szInv; GLuint i; @@ -267,37 +214,101 @@ compute_fog_factors_from_z( const GLcontext *ctx, } -/* - * Apply fog to an array of RGBA pixels. - * Input: n - number of pixels - * z - array of integer depth values - * red, green, blue, alpha - pixel colors - * Output: red, green, blue, alpha - fogged pixel colors + +/** + * Apply fog to a span of RGBA pixels. + * The fog factors are either in the span->array->fog or stored as base/step. + * These are fog _factors_, not fog coords. Fog coords were converted to + * fog factors per vertex. */ void -_mesa_depth_fog_rgba_pixels( const GLcontext *ctx, - GLuint n, const GLdepth z[], GLchan rgba[][4] ) +_mesa_fog_rgba_span( const GLcontext *ctx, struct sw_span *span ) { - GLfloat fogFact[PB_SIZE]; - ASSERT(n <= PB_SIZE); - compute_fog_factors_from_z( ctx, n, z, fogFact ); - _mesa_fog_rgba_pixels( ctx, n, fogFact, rgba ); + const SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint n = span->end; + GLchan (*rgba)[4] = (GLchan (*)[4]) span->array->rgba; + GLchan rFog, gFog, bFog; + + ASSERT(ctx->Fog.Enabled); + ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); + ASSERT(span->arrayMask & SPAN_RGBA); + + UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); + + if (swrast->_PreferPixelFog) { + /* compute fog factor from each fragment's Z value */ + if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0) + _mesa_span_interpolate_z(ctx, span); + compute_fog_factors_from_z(ctx, n, span->array->z, span->array->fog); + span->arrayMask |= SPAN_FOG; + } + + if (span->arrayMask & SPAN_FOG) { + /* use fog array in span */ + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat fog = span->array->fog[i]; + const GLfloat oneMinusFog = 1.0F - fog; + rgba[i][RCOMP] = (GLchan) (fog * rgba[i][RCOMP] + oneMinusFog * rFog); + rgba[i][GCOMP] = (GLchan) (fog * rgba[i][GCOMP] + oneMinusFog * gFog); + rgba[i][BCOMP] = (GLchan) (fog * rgba[i][BCOMP] + oneMinusFog * bFog); + } + } + else { + /* interpolate fog factors */ + GLfloat fog = span->fog, dFog = span->fogStep; + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat oneMinusFog = 1.0F - fog; + rgba[i][RCOMP] = (GLchan) (fog * rgba[i][RCOMP] + oneMinusFog * rFog); + rgba[i][GCOMP] = (GLchan) (fog * rgba[i][GCOMP] + oneMinusFog * gFog); + rgba[i][BCOMP] = (GLchan) (fog * rgba[i][BCOMP] + oneMinusFog * bFog); + fog += dFog; + } + } } -/* - * Apply fog to an array of color index pixels. - * Input: n - number of pixels - * z - array of integer depth values - * index - pixel color indexes - * Output: index - fogged pixel color indexes +/** + * As above, but color index mode. */ void -_mesa_depth_fog_ci_pixels( const GLcontext *ctx, - GLuint n, const GLdepth z[], GLuint index[] ) +_mesa_fog_ci_span( const GLcontext *ctx, struct sw_span *span ) { - GLfloat fogFact[PB_SIZE]; - ASSERT(n <= PB_SIZE); - compute_fog_factors_from_z( ctx, n, z, fogFact ); - _mesa_fog_ci_pixels( ctx, n, fogFact, index ); + const SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint n = span->end; + GLuint *index = span->array->index; + + ASSERT(ctx->Fog.Enabled); + ASSERT(span->arrayMask & SPAN_INDEX); + ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); + + if (swrast->_PreferPixelFog) { + /* compute fog factor from each fragment's Z value */ + if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0) + _mesa_span_interpolate_z(ctx, span); + compute_fog_factors_from_z(ctx, n, span->array->z, span->array->fog); + span->arrayMask |= SPAN_FOG; + } + + if (span->arrayMask & SPAN_FOG) { + const GLuint idx = (GLuint) ctx->Fog.Index; + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat f = CLAMP(span->array->fog[i], 0.0F, 1.0F); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); + } + } + else { + GLfloat fog = span->fog, dFog = span->fogStep; + const GLuint idx = (GLuint) ctx->Fog.Index; + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat f = CLAMP(fog, 0.0F, 1.0F); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); + fog += dFog; + } + } } diff --git a/xc/extras/Mesa/src/swrast/s_fog.h b/xc/extras/Mesa/src/swrast/s_fog.h index a3c35759c..6e23647d1 100644 --- a/xc/extras/Mesa/src/swrast/s_fog.h +++ b/xc/extras/Mesa/src/swrast/s_fog.h @@ -1,10 +1,9 @@ -/* $Id: s_fog.h,v 1.1.1.1 2002/10/22 13:06:41 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -36,29 +35,11 @@ extern GLfloat _mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z); - -extern void -_mesa_fog_rgba_pixels( const GLcontext *ctx, - GLuint n, const GLfloat fog[], - GLchan rgba[][4] ); - -extern void -_mesa_fog_ci_pixels( const GLcontext *ctx, - GLuint n, const GLfloat fog[], GLuint indx[] ); - -extern void -_mesa_win_fog_coords_from_z( const GLcontext *ctx, - GLuint n, - const GLdepth z[], - GLfloat fogcoord[] ); - extern void -_mesa_depth_fog_rgba_pixels( const GLcontext *ctx, - GLuint n, const GLdepth z[], GLchan rgba[][4] ); +_mesa_fog_rgba_span( const GLcontext *ctx, struct sw_span *span ); extern void -_mesa_depth_fog_ci_pixels( const GLcontext *ctx, - GLuint n, const GLdepth z[], GLuint index[] ); +_mesa_fog_ci_span( const GLcontext *ctx, struct sw_span *span ); #endif diff --git a/xc/extras/Mesa/src/swrast/s_imaging.c b/xc/extras/Mesa/src/swrast/s_imaging.c index 495ef3197..4b5438f88 100644 --- a/xc/extras/Mesa/src/swrast/s_imaging.c +++ b/xc/extras/Mesa/src/swrast/s_imaging.c @@ -1,8 +1,7 @@ -/* $Id: s_imaging.c,v 1.1.1.1 2002/10/22 13:06:48 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -37,12 +36,10 @@ _swrast_CopyColorTable( GLcontext *ctx, GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan data[MAX_WIDTH][4]; /* Select buffer to read from */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); + _swrast_use_read_buffer(ctx); if (width > MAX_WIDTH) width = MAX_WIDTH; @@ -51,8 +48,7 @@ _swrast_CopyColorTable( GLcontext *ctx, _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y, data ); /* Restore reading from draw buffer (the default) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); + _swrast_use_draw_buffer(ctx); glColorTable(target, internalformat, width, GL_RGBA, CHAN_TYPE, data); } @@ -61,12 +57,10 @@ void _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan data[MAX_WIDTH][4]; /* Select buffer to read from */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); + _swrast_use_read_buffer(ctx); if (width > MAX_WIDTH) width = MAX_WIDTH; @@ -75,8 +69,7 @@ _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start, _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y, data ); /* Restore reading from draw buffer (the default) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); + _swrast_use_draw_buffer(ctx); glColorSubTable(target, start, width, GL_RGBA, CHAN_TYPE, data); } @@ -90,6 +83,9 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target, SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan rgba[MAX_CONVOLUTION_WIDTH][4]; + /* Select buffer to read from */ + _swrast_use_read_buffer(ctx); + RENDER_START( swrast, ctx ); /* read the data from framebuffer */ @@ -98,6 +94,9 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target, RENDER_FINISH( swrast, ctx ); + /* Restore reading from draw buffer (the default) */ + _swrast_use_draw_buffer(ctx); + /* store as convolution filter */ glConvolutionFilter1D(target, internalFormat, width, GL_RGBA, CHAN_TYPE, rgba); @@ -114,6 +113,9 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target, GLchan rgba[MAX_CONVOLUTION_HEIGHT][MAX_CONVOLUTION_WIDTH][4]; GLint i; + /* Select buffer to read from */ + _swrast_use_read_buffer(ctx); + RENDER_START(swrast,ctx); /* read pixels from framebuffer */ @@ -124,6 +126,9 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target, RENDER_FINISH(swrast,ctx); + /* Restore reading from draw buffer (the default) */ + _swrast_use_draw_buffer(ctx); + /* * HACK: save & restore context state so we can store this as a * convolution filter via the GL api. Doesn't call any callbacks diff --git a/xc/extras/Mesa/src/swrast/s_lines.c b/xc/extras/Mesa/src/swrast/s_lines.c index ec8c343e3..eabfdcce0 100644 --- a/xc/extras/Mesa/src/swrast/s_lines.c +++ b/xc/extras/Mesa/src/swrast/s_lines.c @@ -1,10 +1,9 @@ -/* $Id: s_lines.c,v 1.1.1.1 2002/10/22 13:06:48 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 5.0 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -30,334 +29,294 @@ #include "macros.h" #include "mmath.h" #include "s_aaline.h" -#include "s_pb.h" #include "s_context.h" #include "s_depth.h" -#include "s_lines.h" #include "s_feedback.h" +#include "s_lines.h" +#include "s_span.h" +/* + * Init the mask[] array to implement a line stipple. + */ +static void +compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint i; -/**********************************************************************/ -/***** Rasterization *****/ -/**********************************************************************/ + for (i = 0; i < len; i++) { + GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf; + if ((1 << bit) & ctx->Line.StipplePattern) { + mask[i] = GL_TRUE; + } + else { + mask[i] = GL_FALSE; + } + swrast->StippleCounter++; + } +} /* - * There are 4 pairs (RGBA, CI) of line drawing functions: - * 1. simple: width=1 and no special rasterization functions (fastest) - * 2. flat: width=1, non-stippled, flat-shaded, any raster operations - * 3. smooth: width=1, non-stippled, smooth-shaded, any raster operations - * 4. general: any other kind of line (slowest) + * To draw a wide line we can simply redraw the span N times, side by side. */ - - -/* Flat, color index line */ -static void flat_ci_line( GLcontext *ctx, - const SWvertex *vert0, - const SWvertex *vert1 ) +static void +draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; + GLint width, start; - PB_SET_INDEX( PB, vert0->index ); + ASSERT(span->end < MAX_WIDTH); -#define INTERP_XY 1 -#define PLOT(X,Y) PB_WRITE_PIXEL(PB, X, Y, 0, 0); + width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH ); -#include "s_linetemp.h" - - _mesa_flush_pb(ctx); + if (width & 1) + start = width / 2; + else + start = width / 2 - 1; + + if (xMajor) { + GLint *y = span->array->y; + GLuint i; + GLint w; + for (w = 0; w < width; w++) { + if (w == 0) { + for (i = 0; i < span->end; i++) + y[i] -= start; + } + else { + for (i = 0; i < span->end; i++) + y[i]++; + } + if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE) + _mesa_write_texture_span(ctx, span); + else if ((span->interpMask | span->arrayMask) & SPAN_RGBA) + _mesa_write_rgba_span(ctx, span); + else + _mesa_write_index_span(ctx, span); + } + } + else { + GLint *x = span->array->x; + GLuint i; + GLint w; + for (w = 0; w < width; w++) { + if (w == 0) { + for (i = 0; i < span->end; i++) + x[i] -= start; + } + else { + for (i = 0; i < span->end; i++) + x[i]++; + } + if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE) + _mesa_write_texture_span(ctx, span); + else if ((span->interpMask | span->arrayMask) & SPAN_RGBA) + _mesa_write_rgba_span(ctx, span); + else + _mesa_write_index_span(ctx, span); + } + } } -/* Flat, color index line with Z interpolation/testing */ -static void flat_ci_z_line( GLcontext *ctx, - const SWvertex *vert0, - const SWvertex *vert1 ) +/**********************************************************************/ +/***** Rasterization *****/ +/**********************************************************************/ + + +/* Flat, color index line */ +static void flat_ci_line( GLcontext *ctx, + const SWvertex *vert0, + const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - PB_SET_INDEX( PB, vert0->index ); + GLint *x, *y; + struct sw_span span; + + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + ASSERT(!ctx->Line.StippleFlag); + ASSERT(ctx->Line.Width == 1.0F); + + INIT_SPAN(span, GL_LINE, 0, SPAN_INDEX, SPAN_XY); + span.index = IntToFixed(vert1->index); + span.indexStep = 0; + x = span.array->x; + y = span.array->y; #define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define PLOT(X,Y) PB_WRITE_PIXEL(PB, X, Y, Z, fog0); +#define PLOT(X,Y) \ + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + span.end++; \ + } #include "s_linetemp.h" - _mesa_flush_pb(ctx); + _mesa_write_index_span(ctx, &span); } - /* Flat-shaded, RGBA line */ static void flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - const GLchan *color = vert1->color; - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - PB_SET_COLOR( PB, color[0], color[1], color[2], color[3] ); + struct sw_span span; + GLint *x, *y; + + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + ASSERT(!ctx->Line.StippleFlag); + ASSERT(ctx->Line.Width == 1.0F); + + INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA, SPAN_XY); + span.red = ChanToFixed(vert1->color[0]); + span.green = ChanToFixed(vert1->color[1]); + span.blue = ChanToFixed(vert1->color[2]); + span.alpha = ChanToFixed(vert1->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + x = span.array->x; + y = span.array->y; #define INTERP_XY 1 -#define PLOT(X,Y) PB_WRITE_PIXEL(PB, X, Y, 0, 0); - -#include "s_linetemp.h" - - _mesa_flush_pb(ctx); -} - - - -/* Flat-shaded, RGBA line with Z interpolation/testing */ -static void flat_rgba_z_line( GLcontext *ctx, - const SWvertex *vert0, - const SWvertex *vert1 ) -{ - const GLchan *color = vert1->color; - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - PB_SET_COLOR( PB, color[0], color[1], color[2], color[3] ); - -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define PLOT(X,Y) PB_WRITE_PIXEL(PB, X, Y, Z, fog0); +#define PLOT(X,Y) \ + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + span.end++; \ + } #include "s_linetemp.h" - _mesa_flush_pb(ctx); + _mesa_write_rgba_span(ctx, &span); } - /* Smooth shaded, color index line */ static void smooth_ci_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLuint *pbi = PB->index; + struct sw_span span; + GLint *x, *y; + GLuint *index; - PB->mono = GL_FALSE; + ASSERT(ctx->Light.ShadeModel == GL_SMOOTH); + ASSERT(!ctx->Line.StippleFlag); + ASSERT(ctx->Line.Width == 1.0F); -#define INTERP_XY 1 -#define INTERP_INDEX 1 - -#define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbi[count] = I; \ - count++; - -#include "s_linetemp.h" - - PB->count = count; - _mesa_flush_pb(ctx); -} - - - -/* Smooth shaded, color index line with Z interpolation/testing */ -static void smooth_ci_z_line( GLcontext *ctx, - const SWvertex *vert0, - const SWvertex *vert1 ) -{ - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLuint *pbi = PB->index; - - PB->mono = GL_FALSE; + INIT_SPAN(span, GL_LINE, 0, 0, SPAN_XY | SPAN_INDEX); + x = span.array->x; + y = span.array->y; + index = span.array->index; #define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 #define INTERP_INDEX 1 - #define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbi[count] = I; \ - count++; + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + index[span.end] = I; \ + span.end++; \ + } #include "s_linetemp.h" - PB->count = count; - _mesa_flush_pb(ctx); + _mesa_write_index_span(ctx, &span); } - /* Smooth-shaded, RGBA line */ static void smooth_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLchan (*pbrgba)[4] = PB->rgba; - - PB->mono = GL_FALSE; - -#define INTERP_XY 1 -#define INTERP_RGB 1 -#define INTERP_ALPHA 1 - -#define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - count++; - -#include "s_linetemp.h" - - PB->count = count; - _mesa_flush_pb(ctx); -} - - - -/* Smooth-shaded, RGBA line with Z interpolation/testing */ -static void smooth_rgba_z_line( GLcontext *ctx, - const SWvertex *vert0, - const SWvertex *vert1 ) -{ - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - GLchan (*pbrgba)[4] = PB->rgba; + struct sw_span span; + GLint *x, *y; + GLchan (*rgba)[4]; + ASSERT(ctx->Light.ShadeModel == GL_SMOOTH); + ASSERT(!ctx->Line.StippleFlag); + ASSERT(ctx->Line.Width == 1.0F); - PB->mono = GL_FALSE; + INIT_SPAN(span, GL_LINE, 0, 0, SPAN_XY | SPAN_RGBA); + x = span.array->x; + y = span.array->y; + rgba = span.array->rgba; #define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 #define INTERP_RGB 1 #define INTERP_ALPHA 1 - #define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - count++; + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + rgba[span.end][RCOMP] = FixedToInt(r0); \ + rgba[span.end][GCOMP] = FixedToInt(g0); \ + rgba[span.end][BCOMP] = FixedToInt(b0); \ + rgba[span.end][ACOMP] = FixedToInt(a0); \ + span.end++; \ + } #include "s_linetemp.h" - PB->count = count; - _mesa_flush_pb(ctx); + _mesa_write_rgba_span(ctx, &span); } -#define CHECK_FULL(count) \ - if (count >= PB_SIZE-MAX_WIDTH) { \ - PB->count = count; \ - _mesa_flush_pb(ctx); \ - count = PB->count; \ - } - - - /* Smooth shaded, color index, any width, maybe stippled */ static void general_smooth_ci_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - GLuint *pbi = PB->index; - - PB->mono = GL_FALSE; - - if (ctx->Line.StippleFlag) { - /* stippled */ + GLboolean xMajor = GL_FALSE; + struct sw_span span; + GLint *x, *y; + GLdepth *z; + GLfloat *fog; + GLuint *index; + + ASSERT(ctx->Light.ShadeModel == GL_SMOOTH); + + INIT_SPAN(span, GL_LINE, 0, 0, + SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_INDEX); + x = span.array->x; + y = span.array->y; + z = span.array->z; + fog = span.array->fog; + index = span.array->index; + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 #define INTERP_INDEX 1 -#define WIDE 1 -#define STIPPLE 1 #define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbi[count] = I; \ - count++; \ - CHECK_FULL(count); -#include "s_linetemp.h" + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + z[span.end] = Z; \ + fog[span.end] = fog0; \ + index[span.end] = I; \ + span.end++; \ } - else { - /* unstippled */ - if (ctx->Line.Width==2.0F) { - /* special case: unstippled and width=2 */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_INDEX 1 -#define XMAJOR_PLOT(X,Y) \ - pbx[count] = X; pbx[count+1] = X; \ - pby[count] = Y; pby[count+1] = Y+1; \ - pbz[count] = Z; pbz[count+1] = Z; \ - pbfog[count] = fog0; pbfog[count+1] = fog0; \ - pbi[count] = I; pbi[count+1] = I; \ - count += 2; \ - CHECK_FULL(count); -#define YMAJOR_PLOT(X,Y) \ - pbx[count] = X; pbx[count+1] = X+1; \ - pby[count] = Y; pby[count+1] = Y; \ - pbz[count] = Z; pbz[count+1] = Z; \ - pbfog[count] = fog0; pbfog[count+1] = fog0; \ - pbi[count] = I; pbi[count+1] = I; \ - count += 2; \ - CHECK_FULL(count); -#include "s_linetemp.h" - } - else { - /* unstippled, any width */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_INDEX 1 -#define WIDE 1 -#define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbi[count] = I; \ - pbfog[count] = fog0; \ - count++; \ - CHECK_FULL(count); #include "s_linetemp.h" - } + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - PB->count = count; - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_index_span(ctx, &span); + } } @@ -366,73 +325,48 @@ static void general_flat_ci_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - PB_SET_INDEX( PB, vert0->index ); - count = PB->count; - - if (ctx->Line.StippleFlag) { - /* stippled, any width */ + GLboolean xMajor = GL_FALSE; + struct sw_span span; + GLint *x, *y; + GLdepth *z; + GLfloat *fog; + + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + + INIT_SPAN(span, GL_LINE, 0, SPAN_INDEX, + SPAN_XY | SPAN_Z | SPAN_FOG); + span.index = IntToFixed(vert1->index); + span.indexStep = 0; + x = span.array->x; + y = span.array->y; + z = span.array->z; + fog = span.array->fog; + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 -#define WIDE 1 -#define STIPPLE 1 #define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - count++; \ - CHECK_FULL(count); -#include "s_linetemp.h" + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + z[span.end] = Z; \ + fog[span.end] = fog0; \ + span.end++; \ } - else { - /* unstippled */ - if (ctx->Line.Width==2.0F) { - /* special case: unstippled and width=2 */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define XMAJOR_PLOT(X,Y) \ - pbx[count] = X; pbx[count+1] = X; \ - pby[count] = Y; pby[count+1] = Y+1; \ - pbz[count] = Z; pbz[count+1] = Z; \ - pbfog[count] = fog0; pbfog[count+1] = fog0; \ - count += 2; \ - CHECK_FULL(count); -#define YMAJOR_PLOT(X,Y) \ - pbx[count] = X; pbx[count+1] = X+1; \ - pby[count] = Y; pby[count+1] = Y; \ - pbz[count] = Z; pbz[count+1] = Z; \ - pbfog[count] = fog0; pbfog[count+1] = fog0; \ - count += 2; \ - CHECK_FULL(count); #include "s_linetemp.h" - } - else { - /* unstippled, any width */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define WIDE 1 -#define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - count++; \ - CHECK_FULL(count); -#include "s_linetemp.h" - } + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - PB->count = count; - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_index_span(ctx, &span); + } } @@ -441,104 +375,54 @@ static void general_smooth_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - GLchan (*pbrgba)[4] = PB->rgba; - - PB->mono = GL_FALSE; - - if (ctx->Line.StippleFlag) { - /* stippled */ + GLboolean xMajor = GL_FALSE; + struct sw_span span; + GLint *x, *y; + GLdepth *z; + GLchan (*rgba)[4]; + GLfloat *fog; + + ASSERT(ctx->Light.ShadeModel == GL_SMOOTH); + + INIT_SPAN(span, GL_LINE, 0, 0, + SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA); + x = span.array->x; + y = span.array->y; + z = span.array->z; + rgba = span.array->rgba; + fog = span.array->fog; + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 #define INTERP_RGB 1 #define INTERP_ALPHA 1 -#define WIDE 1 -#define STIPPLE 1 #define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - count++; \ - CHECK_FULL(count); -#include "s_linetemp.h" + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + z[span.end] = Z; \ + rgba[span.end][RCOMP] = FixedToInt(r0); \ + rgba[span.end][GCOMP] = FixedToInt(g0); \ + rgba[span.end][BCOMP] = FixedToInt(b0); \ + rgba[span.end][ACOMP] = FixedToInt(a0); \ + fog[span.end] = fog0; \ + span.end++; \ } - else { - /* unstippled */ - if (ctx->Line.Width==2.0F) { - /* special case: unstippled and width=2 */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_RGB 1 -#define INTERP_ALPHA 1 -#define XMAJOR_PLOT(X,Y) \ - pbx[count] = X; pbx[count+1] = X; \ - pby[count] = Y; pby[count+1] = Y+1; \ - pbz[count] = Z; pbz[count+1] = Z; \ - pbfog[count] = fog0; pbfog[count+1] = fog0; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - pbrgba[count+1][RCOMP] = FixedToInt(r0); \ - pbrgba[count+1][GCOMP] = FixedToInt(g0); \ - pbrgba[count+1][BCOMP] = FixedToInt(b0); \ - pbrgba[count+1][ACOMP] = FixedToInt(a0); \ - count += 2; \ - CHECK_FULL(count); -#define YMAJOR_PLOT(X,Y) \ - pbx[count] = X; pbx[count+1] = X+1; \ - pby[count] = Y; pby[count+1] = Y; \ - pbz[count] = Z; pbz[count+1] = Z; \ - pbfog[count] = fog0; pbfog[count+1] = fog0; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - pbrgba[count+1][RCOMP] = FixedToInt(r0); \ - pbrgba[count+1][GCOMP] = FixedToInt(g0); \ - pbrgba[count+1][BCOMP] = FixedToInt(b0); \ - pbrgba[count+1][ACOMP] = FixedToInt(a0); \ - count += 2; \ - CHECK_FULL(count); -#include "s_linetemp.h" - } - else { - /* unstippled, any width */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_RGB 1 -#define INTERP_ALPHA 1 -#define WIDE 1 -#define PLOT(X,Y) \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - count++; \ - CHECK_FULL(count); #include "s_linetemp.h" - } + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - PB->count = count; - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_rgba_span(ctx, &span); + } } @@ -546,52 +430,54 @@ static void general_flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - const GLchan *color = vert1->color; - GLuint count; - PB_SET_COLOR( PB, color[0], color[1], color[2], color[3] ); - - if (ctx->Line.StippleFlag) { - /* stippled */ + GLboolean xMajor = GL_FALSE; + struct sw_span span; + GLint *x, *y; + GLdepth *z; + GLfloat *fog; + + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + + INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA, + SPAN_XY | SPAN_Z | SPAN_FOG); + span.red = ChanToFixed(vert1->color[0]); + span.green = ChanToFixed(vert1->color[1]); + span.blue = ChanToFixed(vert1->color[2]); + span.alpha = ChanToFixed(vert1->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + x = span.array->x; + y = span.array->y; + z = span.array->z; + fog = span.array->fog; + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 -#define WIDE 1 -#define STIPPLE 1 -#define PLOT(X,Y) \ - PB_WRITE_PIXEL(PB, X, Y, Z, fog0); \ - count = PB->count; \ - CHECK_FULL(count); -#include "s_linetemp.h" +#define PLOT(X,Y) \ + { \ + x[span.end] = X; \ + y[span.end] = Y; \ + z[span.end] = Z; \ + fog[span.end] = fog0; \ + span.end++; \ } - else { - /* unstippled */ - if (ctx->Line.Width==2.0F) { - /* special case: unstippled and width=2 */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define XMAJOR_PLOT(X,Y) PB_WRITE_PIXEL(PB, X, Y, Z, fog0); \ - PB_WRITE_PIXEL(PB, X, Y+1, Z, fog0); -#define YMAJOR_PLOT(X,Y) PB_WRITE_PIXEL(PB, X, Y, Z, fog0); \ - PB_WRITE_PIXEL(PB, X+1, Y, Z, fog0); #include "s_linetemp.h" - } - else { - /* unstippled, any width */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define WIDE 1 -#define PLOT(X,Y) \ - PB_WRITE_PIXEL(PB, X, Y, Z, fog0); \ - count = PB->count; \ - CHECK_FULL(count); -#include "s_linetemp.h" - } + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_rgba_span(ctx, &span); + } } @@ -600,65 +486,58 @@ static void flat_textured_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - GLfloat *pbs = PB->s[0]; - GLfloat *pbt = PB->t[0]; - GLfloat *pbu = PB->u[0]; - GLchan *color = (GLchan*) vert1->color; - PB_SET_COLOR( PB, color[0], color[1], color[2], color[3] ); - count = PB->count; - - if (ctx->Line.StippleFlag) { - /* stippled */ + GLboolean xMajor = GL_FALSE; + struct sw_span span; + + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + + INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA | SPAN_SPEC, + SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA); + span.red = ChanToFixed(vert1->color[0]); + span.green = ChanToFixed(vert1->color[1]); + span.blue = ChanToFixed(vert1->color[2]); + span.alpha = ChanToFixed(vert1->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + span.specRed = ChanToFixed(vert1->specular[0]); + span.specGreen = ChanToFixed(vert1->specular[1]); + span.specBlue = ChanToFixed(vert1->specular[2]); + span.specRedStep = 0; + span.specGreenStep = 0; + span.specBlueStep = 0; + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 #define INTERP_TEX 1 -#define WIDE 1 -#define STIPPLE 1 -#define PLOT(X,Y) \ - { \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbs[count] = fragTexcoord[0];\ - pbt[count] = fragTexcoord[1];\ - pbu[count] = fragTexcoord[2];\ - count++; \ - CHECK_FULL(count); \ - } -#include "s_linetemp.h" +#define PLOT(X,Y) \ + { \ + span.array->x[span.end] = X; \ + span.array->y[span.end] = Y; \ + span.array->z[span.end] = Z; \ + span.array->fog[span.end] = fog0; \ + span.array->texcoords[0][span.end][0] = fragTexcoord[0]; \ + span.array->texcoords[0][span.end][1] = fragTexcoord[1]; \ + span.array->texcoords[0][span.end][2] = fragTexcoord[2]; \ + span.array->lambda[0][span.end] = 0.0; \ + span.end++; \ } - else { - /* unstippled */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_TEX 1 -#define WIDE 1 -#define PLOT(X,Y) \ - { \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbs[count] = fragTexcoord[0];\ - pbt[count] = fragTexcoord[1];\ - pbu[count] = fragTexcoord[2];\ - count++; \ - CHECK_FULL(count); \ - } #include "s_linetemp.h" + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - PB->count = count; - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_texture_span(ctx, &span); + } } @@ -668,77 +547,50 @@ static void smooth_textured_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - GLfloat *pbs = PB->s[0]; - GLfloat *pbt = PB->t[0]; - GLfloat *pbu = PB->u[0]; - GLchan (*pbrgba)[4] = PB->rgba; - - PB->mono = GL_FALSE; + GLboolean xMajor = GL_FALSE; + struct sw_span span; - if (ctx->Line.StippleFlag) { - /* stippled */ + ASSERT(ctx->Light.ShadeModel == GL_SMOOTH); + + INIT_SPAN(span, GL_LINE, 0, 0, + SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_TEXTURE | SPAN_LAMBDA); + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 #define INTERP_RGB 1 #define INTERP_ALPHA 1 #define INTERP_TEX 1 -#define WIDE 1 -#define STIPPLE 1 -#define PLOT(X,Y) \ - { \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbs[count] = fragTexcoord[0]; \ - pbt[count] = fragTexcoord[1]; \ - pbu[count] = fragTexcoord[2]; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - count++; \ - CHECK_FULL(count); \ - } -#include "s_linetemp.h" +#define PLOT(X,Y) \ + { \ + span.array->x[span.end] = X; \ + span.array->y[span.end] = Y; \ + span.array->z[span.end] = Z; \ + span.array->fog[span.end] = fog0; \ + span.array->rgba[span.end][RCOMP] = FixedToInt(r0); \ + span.array->rgba[span.end][GCOMP] = FixedToInt(g0); \ + span.array->rgba[span.end][BCOMP] = FixedToInt(b0); \ + span.array->rgba[span.end][ACOMP] = FixedToInt(a0); \ + span.array->texcoords[0][span.end][0] = fragTexcoord[0]; \ + span.array->texcoords[0][span.end][1] = fragTexcoord[1]; \ + span.array->texcoords[0][span.end][2] = fragTexcoord[2]; \ + span.array->lambda[0][span.end] = 0.0; \ + span.end++; \ } - else { - /* unstippled */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_RGB 1 -#define INTERP_ALPHA 1 -#define INTERP_TEX 1 -#define WIDE 1 -#define PLOT(X,Y) \ - { \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbs[count] = fragTexcoord[0]; \ - pbt[count] = fragTexcoord[1]; \ - pbu[count] = fragTexcoord[2]; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - count++; \ - CHECK_FULL(count); \ - } #include "s_linetemp.h" + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - PB->count = count; - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_texture_span(ctx, &span); + } } @@ -749,20 +601,16 @@ static void smooth_multitextured_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - GLchan (*pbrgba)[4] = PB->rgba; - GLchan (*pbspec)[3] = PB->spec; - - PB->mono = GL_FALSE; - PB->haveSpec = GL_TRUE; + GLboolean xMajor = GL_FALSE; + struct sw_span span; + GLuint u; - if (ctx->Line.StippleFlag) { - /* stippled */ + ASSERT(ctx->Light.ShadeModel == GL_SMOOTH); + + INIT_SPAN(span, GL_LINE, 0, 0, + SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_SPEC | SPAN_TEXTURE | SPAN_LAMBDA); + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 @@ -770,73 +618,42 @@ static void smooth_multitextured_line( GLcontext *ctx, #define INTERP_SPEC 1 #define INTERP_ALPHA 1 #define INTERP_MULTITEX 1 -#define WIDE 1 -#define STIPPLE 1 -#define PLOT(X,Y) \ - { \ - GLuint u; \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - pbspec[count][RCOMP] = FixedToInt(sr0); \ - pbspec[count][GCOMP] = FixedToInt(sg0); \ - pbspec[count][BCOMP] = FixedToInt(sb0); \ - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ - if (ctx->Texture.Unit[u]._ReallyEnabled) { \ - PB->s[u][count] = fragTexcoord[u][0]; \ - PB->t[u][count] = fragTexcoord[u][1]; \ - PB->u[u][count] = fragTexcoord[u][2]; \ - } \ - } \ - count++; \ - CHECK_FULL(count); \ - } -#include "s_linetemp.h" +#define PLOT(X,Y) \ + { \ + span.array->x[span.end] = X; \ + span.array->y[span.end] = Y; \ + span.array->z[span.end] = Z; \ + span.array->fog[span.end] = fog0; \ + span.array->rgba[span.end][RCOMP] = FixedToInt(r0); \ + span.array->rgba[span.end][GCOMP] = FixedToInt(g0); \ + span.array->rgba[span.end][BCOMP] = FixedToInt(b0); \ + span.array->rgba[span.end][ACOMP] = FixedToInt(a0); \ + span.array->spec[span.end][RCOMP] = FixedToInt(sr0); \ + span.array->spec[span.end][GCOMP] = FixedToInt(sg0); \ + span.array->spec[span.end][BCOMP] = FixedToInt(sb0); \ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ + if (ctx->Texture.Unit[u]._ReallyEnabled) { \ + span.array->texcoords[u][span.end][0] = fragTexcoord[u][0]; \ + span.array->texcoords[u][span.end][1] = fragTexcoord[u][1]; \ + span.array->texcoords[u][span.end][2] = fragTexcoord[u][2]; \ + span.array->lambda[u][span.end] = 0.0; \ + } \ + } \ + span.end++; \ } - else { - /* unstippled */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_RGB 1 -#define INTERP_SPEC 1 -#define INTERP_ALPHA 1 -#define INTERP_MULTITEX 1 -#define WIDE 1 -#define PLOT(X,Y) \ - { \ - GLuint u; \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbrgba[count][RCOMP] = FixedToInt(r0); \ - pbrgba[count][GCOMP] = FixedToInt(g0); \ - pbrgba[count][BCOMP] = FixedToInt(b0); \ - pbrgba[count][ACOMP] = FixedToInt(a0); \ - pbspec[count][RCOMP] = FixedToInt(sr0); \ - pbspec[count][GCOMP] = FixedToInt(sg0); \ - pbspec[count][BCOMP] = FixedToInt(sb0); \ - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ - if (ctx->Texture.Unit[u]._ReallyEnabled) { \ - PB->s[u][count] = fragTexcoord[u][0]; \ - PB->t[u][count] = fragTexcoord[u][1]; \ - PB->u[u][count] = fragTexcoord[u][2]; \ - } \ - } \ - count++; \ - CHECK_FULL(count); \ - } #include "s_linetemp.h" + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - PB->count = count; - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_texture_span(ctx, &span); + } } @@ -847,94 +664,63 @@ static void flat_multitextured_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) { - struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; - GLint count = PB->count; - GLint *pbx = PB->x; - GLint *pby = PB->y; - GLdepth *pbz = PB->z; - GLfloat *pbfog = PB->fog; - GLchan (*pbrgba)[4] = PB->rgba; - GLchan (*pbspec)[3] = PB->spec; - GLchan *color = (GLchan*) vert1->color; - GLchan sRed = vert1->specular[0]; - GLchan sGreen = vert1->specular[1]; - GLchan sBlue = vert1->specular[2]; - - PB->mono = GL_FALSE; - PB->haveSpec = GL_TRUE; - - if (ctx->Line.StippleFlag) { - /* stippled */ + GLboolean xMajor = GL_FALSE; + struct sw_span span; + GLuint u; + + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + + INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA | SPAN_SPEC, + SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA); + span.red = ChanToFixed(vert1->color[0]); + span.green = ChanToFixed(vert1->color[1]); + span.blue = ChanToFixed(vert1->color[2]); + span.alpha = ChanToFixed(vert1->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + span.specRed = ChanToFixed(vert1->specular[0]); + span.specGreen = ChanToFixed(vert1->specular[1]); + span.specBlue = ChanToFixed(vert1->specular[2]); + span.specRedStep = 0; + span.specGreenStep = 0; + span.specBlueStep = 0; + +#define SET_XMAJOR 1 #define INTERP_XY 1 #define INTERP_Z 1 #define INTERP_FOG 1 -#define INTERP_ALPHA 1 #define INTERP_MULTITEX 1 -#define WIDE 1 -#define STIPPLE 1 -#define PLOT(X,Y) \ - { \ - GLuint u; \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbrgba[count][RCOMP] = color[0]; \ - pbrgba[count][GCOMP] = color[1]; \ - pbrgba[count][BCOMP] = color[2]; \ - pbrgba[count][ACOMP] = color[3]; \ - pbspec[count][RCOMP] = sRed; \ - pbspec[count][GCOMP] = sGreen; \ - pbspec[count][BCOMP] = sBlue; \ - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ - if (ctx->Texture.Unit[u]._ReallyEnabled) { \ - PB->s[u][count] = fragTexcoord[u][0]; \ - PB->t[u][count] = fragTexcoord[u][1]; \ - PB->u[u][count] = fragTexcoord[u][2]; \ - } \ - } \ - count++; \ - CHECK_FULL(count); \ - } -#include "s_linetemp.h" +#define PLOT(X,Y) \ + { \ + span.array->x[span.end] = X; \ + span.array->y[span.end] = Y; \ + span.array->z[span.end] = Z; \ + span.array->fog[span.end] = fog0; \ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ + if (ctx->Texture.Unit[u]._ReallyEnabled) { \ + span.array->texcoords[u][span.end][0] = fragTexcoord[u][0]; \ + span.array->texcoords[u][span.end][1] = fragTexcoord[u][1]; \ + span.array->texcoords[u][span.end][2] = fragTexcoord[u][2]; \ + span.array->lambda[u][span.end] = 0.0; \ + } \ + } \ + span.end++; \ } - else { - /* unstippled */ -#define INTERP_XY 1 -#define INTERP_Z 1 -#define INTERP_FOG 1 -#define INTERP_ALPHA 1 -#define INTERP_MULTITEX 1 -#define WIDE 1 -#define PLOT(X,Y) \ - { \ - GLuint u; \ - pbx[count] = X; \ - pby[count] = Y; \ - pbz[count] = Z; \ - pbfog[count] = fog0; \ - pbrgba[count][RCOMP] = color[0]; \ - pbrgba[count][GCOMP] = color[1]; \ - pbrgba[count][BCOMP] = color[2]; \ - pbrgba[count][ACOMP] = color[3]; \ - pbspec[count][RCOMP] = sRed; \ - pbspec[count][GCOMP] = sGreen; \ - pbspec[count][BCOMP] = sBlue; \ - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ - if (ctx->Texture.Unit[u]._ReallyEnabled) { \ - PB->s[u][count] = fragTexcoord[u][0]; \ - PB->t[u][count] = fragTexcoord[u][1]; \ - PB->u[u][count] = fragTexcoord[u][2]; \ - } \ - } \ - count++; \ - CHECK_FULL(count); \ - } #include "s_linetemp.h" + + if (ctx->Line.StippleFlag) { + span.arrayMask |= SPAN_MASK; + compute_stipple_mask(ctx, span.end, span.array->mask); } - PB->count = count; - _mesa_flush_pb(ctx); + if (ctx->Line.Width > 1.0) { + draw_wide_line(ctx, &span, xMajor); + } + else { + _mesa_write_texture_span(ctx, &span); + } } @@ -963,41 +749,33 @@ _mesa_print_line_function(GLcontext *ctx) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - printf("Line Func == "); + _mesa_printf("Line Func == "); if (swrast->Line == flat_ci_line) - printf("flat_ci_line\n"); - else if (swrast->Line == flat_ci_z_line) - printf("flat_ci_z_line\n"); + _mesa_printf("flat_ci_line\n"); else if (swrast->Line == flat_rgba_line) - printf("flat_rgba_line\n"); - else if (swrast->Line == flat_rgba_z_line) - printf("flat_rgba_z_line\n"); + _mesa_printf("flat_rgba_line\n"); else if (swrast->Line == smooth_ci_line) - printf("smooth_ci_line\n"); - else if (swrast->Line == smooth_ci_z_line) - printf("smooth_ci_z_line\n"); + _mesa_printf("smooth_ci_line\n"); else if (swrast->Line == smooth_rgba_line) - printf("smooth_rgba_line\n"); - else if (swrast->Line == smooth_rgba_z_line) - printf("smooth_rgba_z_line\n"); + _mesa_printf("smooth_rgba_line\n"); else if (swrast->Line == general_smooth_ci_line) - printf("general_smooth_ci_line\n"); + _mesa_printf("general_smooth_ci_line\n"); else if (swrast->Line == general_flat_ci_line) - printf("general_flat_ci_line\n"); + _mesa_printf("general_flat_ci_line\n"); else if (swrast->Line == general_smooth_rgba_line) - printf("general_smooth_rgba_line\n"); + _mesa_printf("general_smooth_rgba_line\n"); else if (swrast->Line == general_flat_rgba_line) - printf("general_flat_rgba_line\n"); + _mesa_printf("general_flat_rgba_line\n"); else if (swrast->Line == flat_textured_line) - printf("flat_textured_line\n"); + _mesa_printf("flat_textured_line\n"); else if (swrast->Line == smooth_textured_line) - printf("smooth_textured_line\n"); + _mesa_printf("smooth_textured_line\n"); else if (swrast->Line == smooth_multitextured_line) - printf("smooth_multitextured_line\n"); + _mesa_printf("smooth_multitextured_line\n"); else if (swrast->Line == flat_multitextured_line) - printf("flat_multitextured_line\n"); + _mesa_printf("flat_multitextured_line\n"); else - printf("Driver func %p\n", (void *) swrast->Line); + _mesa_printf("Driver func %p\n", (void *) swrast->Line); } #endif @@ -1011,7 +789,7 @@ static const char *lineFuncName = NULL; #define USE(lineFunc) \ do { \ lineFuncName = #lineFunc; \ - /*printf("%s\n", lineFuncName);*/ \ + /*_mesa_printf("%s\n", lineFuncName);*/ \ swrast->Line = lineFunc; \ } while (0) @@ -1036,23 +814,23 @@ _swrast_choose_line( GLcontext *ctx ) SWcontext *swrast = SWRAST_CONTEXT(ctx); const GLboolean rgbmode = ctx->Visual.rgbMode; - if (ctx->RenderMode==GL_RENDER) { + if (ctx->RenderMode == GL_RENDER) { if (ctx->Line.SmoothFlag) { /* antialiased lines */ _swrast_choose_aa_line_function(ctx); ASSERT(swrast->Triangle); } - else if (ctx->Texture._ReallyEnabled) { - if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY || + else if (ctx->Texture._EnabledUnits) { + if (ctx->Texture._EnabledUnits > 1 || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) { /* multi-texture and/or separate specular color */ - if (ctx->Light.ShadeModel==GL_SMOOTH) + if (ctx->Light.ShadeModel == GL_SMOOTH) USE(smooth_multitextured_line); else USE(flat_multitextured_line); } else { - if (ctx->Light.ShadeModel==GL_SMOOTH) { + if (ctx->Light.ShadeModel == GL_SMOOTH) { USE(smooth_textured_line); } else { @@ -1060,28 +838,14 @@ _swrast_choose_line( GLcontext *ctx ) } } } - else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag) { - if (ctx->Light.ShadeModel==GL_SMOOTH) { - if (rgbmode) - USE(general_smooth_rgba_line); - else - USE(general_smooth_ci_line); - } - else { - if (rgbmode) - USE(general_flat_rgba_line); - else - USE(general_flat_ci_line); - } - } else { - if (ctx->Light.ShadeModel==GL_SMOOTH) { - /* Width==1, non-stippled, smooth-shaded */ - if (ctx->Depth.Test || ctx->Fog.Enabled) { + if (ctx->Light.ShadeModel == GL_SMOOTH) { + if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0 + || ctx->Line.StippleFlag) { if (rgbmode) - USE(smooth_rgba_z_line); + USE(general_smooth_rgba_line); else - USE(smooth_ci_z_line); + USE(general_smooth_ci_line); } else { if (rgbmode) @@ -1091,12 +855,12 @@ _swrast_choose_line( GLcontext *ctx ) } } else { - /* Width==1, non-stippled, flat-shaded */ - if (ctx->Depth.Test || ctx->Fog.Enabled) { + if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0 + || ctx->Line.StippleFlag) { if (rgbmode) - USE(flat_rgba_z_line); + USE(general_flat_rgba_line); else - USE(flat_ci_z_line); + USE(general_flat_ci_line); } else { if (rgbmode) @@ -1107,11 +871,11 @@ _swrast_choose_line( GLcontext *ctx ) } } } - else if (ctx->RenderMode==GL_FEEDBACK) { + else if (ctx->RenderMode == GL_FEEDBACK) { USE(_mesa_feedback_line); } else { - /* GL_SELECT mode */ + ASSERT(ctx->RenderMode == GL_SELECT); USE(_mesa_select_line); } diff --git a/xc/extras/Mesa/src/swrast/s_linetemp.h b/xc/extras/Mesa/src/swrast/s_linetemp.h index c5e7984c5..9c7541315 100644 --- a/xc/extras/Mesa/src/swrast/s_linetemp.h +++ b/xc/extras/Mesa/src/swrast/s_linetemp.h @@ -1,8 +1,7 @@ -/* $Id: s_linetemp.h,v 1.1.1.1 2002/10/22 13:06:55 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.2 + * Version: 5.0 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -56,11 +55,7 @@ * Optionally, one may provide one-time setup code * SETUP_CODE - code which is to be executed once per line * - * To enable line stippling define STIPPLE = 1 - * To enable wide lines define WIDE = 1 - * - * To actually "plot" each pixel either the PLOT macro or - * (XMAJOR_PLOT and YMAJOR_PLOT macros) must be defined... + * To actually "plot" each pixel the PLOT macro must be defined... * PLOT(X,Y) - code to plot a pixel. Example: * if (Z < *zPtr) { * *zPtr = Z; @@ -140,16 +135,6 @@ PIXEL_TYPE *pixelPtr; GLint pixelXstep, pixelYstep; #endif -#ifdef STIPPLE - SWcontext *swrast = SWRAST_CONTEXT(ctx); -#endif -#ifdef WIDE - /* for wide lines, draw all X in [x+min, x+max] or Y in [y+min, y+max] */ - GLint width, min, max; - width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH ); - min = (width-1) / -2; - max = min + width - 1; -#endif #ifdef INTERP_TEX { tex[0] = invw0 * vert0->texcoord[0][0]; @@ -188,6 +173,19 @@ return; } + /* + printf("%s():\n", __FUNCTION__); + printf(" (%f, %f, %f) -> (%f, %f, %f)\n", + vert0->win[0], vert0->win[1], vert0->win[2], + vert1->win[0], vert1->win[1], vert1->win[2]); + printf(" (%d, %d, %d) -> (%d, %d, %d)\n", + vert0->color[0], vert0->color[1], vert0->color[2], + vert1->color[0], vert1->color[1], vert1->color[2]); + printf(" (%d, %d, %d) -> (%d, %d, %d)\n", + vert0->specular[0], vert0->specular[1], vert0->specular[2], + vert1->specular[0], vert1->specular[1], vert1->specular[2]); + */ + /* * Despite being clipped to the view volume, the line's window coordinates * may just lie outside the window bounds. That is, if the legal window @@ -231,8 +229,8 @@ zPtr = (DEPTH_TYPE *) _mesa_zbuffer_address(ctx, x0, y0); # endif if (depthBits <= 16) { - z0 = FloatToFixed(vert0->win[2]); - z1 = FloatToFixed(vert1->win[2]); + z0 = FloatToFixed(vert0->win[2]) + FIXED_HALF; + z1 = FloatToFixed(vert1->win[2]) + FIXED_HALF; } else { z0 = (int) vert0->win[2]; @@ -301,6 +299,9 @@ GLint errorInc = dy+dy; GLint error = errorInc-dx; GLint errorDec = error-dx; +#ifdef SET_XMAJOR + xMajor = GL_TRUE; +#endif #ifdef INTERP_Z dz = (z1-z0) / dx; #endif @@ -348,11 +349,6 @@ #endif for (i=0;i<dx;i++) { -#ifdef STIPPLE - GLushort m; - m = 1 << ((swrast->StippleCounter/ctx->Line.StippleFactor) & 0xf); - if (ctx->Line.StipplePattern & m) { -#endif #ifdef INTERP_Z GLdepth Z = FixedToDepth(z0); #endif @@ -382,26 +378,9 @@ } } #endif -#ifdef WIDE - { - GLint yy; - GLint ymin = y0 + min; - GLint ymax = y0 + max; - for (yy=ymin;yy<=ymax;yy++) { - PLOT( x0, yy ); - } - } -#else -# ifdef XMAJOR_PLOT - XMAJOR_PLOT( x0, y0 ); -# else + PLOT( x0, y0 ); -# endif -#endif /*WIDE*/ -#ifdef STIPPLE - } - swrast->StippleCounter++; -#endif + #ifdef INTERP_XY x0 += xstep; #endif @@ -523,11 +502,6 @@ #endif for (i=0;i<dy;i++) { -#ifdef STIPPLE - GLushort m; - m = 1 << ((swrast->StippleCounter/ctx->Line.StippleFactor) & 0xf); - if (ctx->Line.StipplePattern & m) { -#endif #ifdef INTERP_Z GLdepth Z = FixedToDepth(z0); #endif @@ -557,26 +531,9 @@ } } #endif -#ifdef WIDE - { - GLint xx; - GLint xmin = x0 + min; - GLint xmax = x0 + max; - for (xx=xmin;xx<=xmax;xx++) { - PLOT( xx, y0 ); - } - } -#else -# ifdef YMAJOR_PLOT - YMAJOR_PLOT( x0, y0 ); -# else + PLOT( x0, y0 ); -# endif -#endif /*WIDE*/ -#ifdef STIPPLE - } - swrast->StippleCounter++; -#endif + #ifdef INTERP_XY y0 += ystep; #endif @@ -663,9 +620,6 @@ #undef BYTES_PER_ROW #undef SETUP_CODE #undef PLOT -#undef XMAJOR_PLOT -#undef YMAJOR_PLOT #undef CLIP_HACK -#undef STIPPLE -#undef WIDE #undef FixedToDepth +#undef SET_XMAJOR diff --git a/xc/extras/Mesa/src/swrast/s_logic.c b/xc/extras/Mesa/src/swrast/s_logic.c index 3521418bf..4f5b3b387 100644 --- a/xc/extras/Mesa/src/swrast/s_logic.c +++ b/xc/extras/Mesa/src/swrast/s_logic.c @@ -1,10 +1,9 @@ -/* $Id: s_logic.c,v 1.1.1.1 2002/10/22 13:06:51 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -27,12 +26,12 @@ #include "glheader.h" #include "context.h" +#include "imports.h" #include "macros.h" #include "s_alphabuf.h" #include "s_context.h" #include "s_logic.h" -#include "s_pb.h" #include "s_span.h" @@ -40,9 +39,9 @@ /* * Apply logic op to array of CI pixels. */ -static void index_logicop( GLcontext *ctx, GLuint n, - GLuint index[], const GLuint dest[], - const GLubyte mask[] ) +static void +index_logicop( GLcontext *ctx, GLuint n, GLuint index[], const GLuint dest[], + const GLubyte mask[] ) { GLuint i; switch (ctx->Color.LogicOp) { @@ -166,32 +165,25 @@ static void index_logicop( GLcontext *ctx, GLuint n, * used if the device driver can't do logic ops. */ void -_mesa_logicop_ci_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - GLuint index[], const GLubyte mask[] ) +_mesa_logicop_ci_span( GLcontext *ctx, const struct sw_span *span, + GLuint index[] ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLuint dest[MAX_WIDTH]; - /* Read dest values from frame buffer */ - (*swrast->Driver.ReadCI32Span)( ctx, n, x, y, dest ); - index_logicop( ctx, n, index, dest, mask ); -} + ASSERT(span->end < MAX_WIDTH); - -/* - * Apply the current logic operator to an array of CI pixels. This is only - * used if the device driver can't do logic ops. - */ -void -_mesa_logicop_ci_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLuint index[], const GLubyte mask[] ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLuint dest[PB_SIZE]; /* Read dest values from frame buffer */ - (*swrast->Driver.ReadCI32Pixels)( ctx, n, x, y, dest, mask ); - index_logicop( ctx, n, index, dest, mask ); + if (span->arrayMask & SPAN_XY) { + (*swrast->Driver.ReadCI32Pixels)( ctx, span->end, + span->array->x, span->array->y, + dest, span->array->mask ); + } + else { + (*swrast->Driver.ReadCI32Span)( ctx, span->end, span->x, span->y, dest ); + } + + index_logicop( ctx, span->end, index, dest, span->array->mask ); } @@ -207,9 +199,9 @@ _mesa_logicop_ci_pixels( GLcontext *ctx, * Note: Since the R, G, B, and A channels are all treated the same we * process them as 4-byte GLuints instead of four GLubytes. */ -static void rgba_logicop_ui( const GLcontext *ctx, GLuint n, - const GLubyte mask[], - GLuint src[], const GLuint dest[] ) +static void +rgba_logicop_ui( const GLcontext *ctx, GLuint n, const GLubyte mask[], + GLuint src[], const GLuint dest[] ) { GLuint i; switch (ctx->Color.LogicOp) { @@ -332,9 +324,9 @@ static void rgba_logicop_ui( const GLcontext *ctx, GLuint n, * As above, but operate on GLchan values * Note: need to pass n = numPixels * 4. */ -static void rgba_logicop_chan( const GLcontext *ctx, GLuint n, - const GLubyte mask[], - GLchan srcPtr[], const GLchan destPtr[] ) +static void +rgba_logicop_chan( const GLcontext *ctx, GLuint n, const GLubyte mask[], + GLchan srcPtr[], const GLchan destPtr[] ) { #if CHAN_TYPE == GL_FLOAT GLuint *src = (GLuint *) srcPtr; @@ -466,46 +458,40 @@ static void rgba_logicop_chan( const GLcontext *ctx, GLuint n, /* * Apply the current logic operator to a span of RGBA pixels. - * This is only used if the device driver can't do logic ops. + * We can handle horizontal runs of pixels (spans) or arrays of x/y + * pixel coordinates. */ void -_mesa_logicop_rgba_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, - GLchan rgba[][4], const GLubyte mask[] ) +_mesa_logicop_rgba_span( GLcontext *ctx, const struct sw_span *span, + GLchan rgba[][4] ) { + SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan dest[MAX_WIDTH][4]; - _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); - if (sizeof(GLchan) * 4 == sizeof(GLuint)) { - rgba_logicop_ui(ctx, n, mask, (GLuint *) rgba, (const GLuint *) dest); + + ASSERT(span->end < MAX_WIDTH); + ASSERT(span->arrayMask & SPAN_RGBA); + + if (span->arrayMask & SPAN_XY) { + (*swrast->Driver.ReadRGBAPixels)(ctx, span->end, + span->array->x, span->array->y, + dest, span->array->mask); + if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { + _mesa_read_alpha_pixels(ctx, span->end, + span->array->x, span->array->y, + dest, span->array->mask); + } } else { - rgba_logicop_chan(ctx, 4 * n, mask, - (GLchan *) rgba, (const GLchan *) dest); + _mesa_read_rgba_span(ctx, ctx->DrawBuffer, span->end, + span->x, span->y, dest); } -} - - -/* - * Apply the current logic operator to an array of RGBA pixels. - * This is only used if the device driver can't do logic ops. - */ -void -_mesa_logicop_rgba_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLchan dest[PB_SIZE][4]; - (*swrast->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask ); - if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { - _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask ); - } if (sizeof(GLchan) * 4 == sizeof(GLuint)) { - rgba_logicop_ui(ctx, n, mask, (GLuint *) rgba, (const GLuint *) dest); + rgba_logicop_ui(ctx, span->end, span->array->mask, + (GLuint *) rgba, (const GLuint *) dest); } else { - rgba_logicop_chan(ctx, 4 * n, mask, + rgba_logicop_chan(ctx, 4 * span->end, span->array->mask, (GLchan *) rgba, (const GLchan *) dest); } } diff --git a/xc/extras/Mesa/src/swrast/s_logic.h b/xc/extras/Mesa/src/swrast/s_logic.h index 8ac68f830..820451d9b 100644 --- a/xc/extras/Mesa/src/swrast/s_logic.h +++ b/xc/extras/Mesa/src/swrast/s_logic.h @@ -1,10 +1,9 @@ -/* $Id: s_logic.h,v 1.1.1.1 2002/10/22 13:06:51 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -34,26 +33,13 @@ extern void -_mesa_logicop_ci_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, GLuint index[], - const GLubyte mask[] ); +_mesa_logicop_ci_span( GLcontext *ctx, const struct sw_span *span, + GLuint index[] ); extern void -_mesa_logicop_ci_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLuint index[], const GLubyte mask[] ); - - -extern void -_mesa_logicop_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - GLchan rgba[][4], const GLubyte mask[] ); - - -extern void -_mesa_logicop_rgba_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ); +_mesa_logicop_rgba_span( GLcontext *ctx, const struct sw_span *span, + GLchan rgba[][4] ); #endif diff --git a/xc/extras/Mesa/src/swrast/s_masking.c b/xc/extras/Mesa/src/swrast/s_masking.c index d4d57140d..74e1fb5bc 100644 --- a/xc/extras/Mesa/src/swrast/s_masking.c +++ b/xc/extras/Mesa/src/swrast/s_masking.c @@ -1,10 +1,9 @@ -/* $Id: s_masking.c,v 1.1.1.1 2002/10/22 13:06:44 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -37,62 +36,70 @@ #include "s_alphabuf.h" #include "s_context.h" #include "s_masking.h" -#include "s_pb.h" #include "s_span.h" -/* - * Apply glColorMask to a span of RGBA pixels. - */ + void -_mesa_mask_rgba_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, GLchan rgba[][4] ) +_mesa_mask_rgba_span( GLcontext *ctx, const struct sw_span *span, + GLchan rgba[][4] ) { + SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan dest[MAX_WIDTH][4]; - GLuint i; - #if CHAN_BITS == 8 - GLuint srcMask = *((GLuint*)ctx->Color.ColorMask); GLuint dstMask = ~srcMask; GLuint *rgba32 = (GLuint *) rgba; GLuint *dest32 = (GLuint *) dest; +#else + const GLboolean rMask = ctx->Color.ColorMask[RCOMP]; + const GLboolean gMask = ctx->Color.ColorMask[GCOMP]; + const GLboolean bMask = ctx->Color.ColorMask[BCOMP]; + const GLboolean aMask = ctx->Color.ColorMask[ACOMP]; +#endif + const GLuint n = span->end; + GLuint i; - _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); + ASSERT(n < MAX_WIDTH); + ASSERT(span->arrayMask & SPAN_RGBA); + + if (span->arrayMask & SPAN_XY) { + (*swrast->Driver.ReadRGBAPixels)(ctx, n, span->array->x, span->array->y, + dest, span->array->mask); + if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { + _mesa_read_alpha_pixels(ctx, n, span->array->x, span->array->y, + dest, span->array->mask); + } + } + else { + _mesa_read_rgba_span(ctx, ctx->DrawBuffer, n, span->x, span->y, dest); + } + +#if CHAN_BITS == 8 for (i = 0; i < n; i++) { rgba32[i] = (rgba32[i] & srcMask) | (dest32[i] & dstMask); } - #else - - const GLint rMask = ctx->Color.ColorMask[RCOMP]; - const GLint gMask = ctx->Color.ColorMask[GCOMP]; - const GLint bMask = ctx->Color.ColorMask[BCOMP]; - const GLint aMask = ctx->Color.ColorMask[ACOMP]; - - _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); for (i = 0; i < n; i++) { if (!rMask) rgba[i][RCOMP] = dest[i][RCOMP]; if (!gMask) rgba[i][GCOMP] = dest[i][GCOMP]; if (!bMask) rgba[i][BCOMP] = dest[i][BCOMP]; if (!aMask) rgba[i][ACOMP] = dest[i][ACOMP]; } - #endif } + /* - * Apply glColorMask to an array of RGBA pixels. + * Apply glColorMask to a span of RGBA pixels. */ void -_mesa_mask_rgba_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ) +_mesa_mask_rgba_array( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLchan rgba[][4] ) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLchan dest[PB_SIZE][4]; + GLchan dest[MAX_WIDTH][4]; GLuint i; #if CHAN_BITS == 8 @@ -102,12 +109,8 @@ _mesa_mask_rgba_pixels( GLcontext *ctx, GLuint *rgba32 = (GLuint *) rgba; GLuint *dest32 = (GLuint *) dest; - (*swrast->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask ); - if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { - _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask ); - } - - for (i=0; i<n; i++) { + _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); + for (i = 0; i < n; i++) { rgba32[i] = (rgba32[i] & srcMask) | (dest32[i] & dstMask); } @@ -118,11 +121,7 @@ _mesa_mask_rgba_pixels( GLcontext *ctx, const GLint bMask = ctx->Color.ColorMask[BCOMP]; const GLint aMask = ctx->Color.ColorMask[ACOMP]; - (*swrast->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask ); - if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { - _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask ); - } - + _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); for (i = 0; i < n; i++) { if (!rMask) rgba[i][RCOMP] = dest[i][RCOMP]; if (!gMask) rgba[i][GCOMP] = dest[i][GCOMP]; @@ -135,43 +134,53 @@ _mesa_mask_rgba_pixels( GLcontext *ctx, -/* - * Apply glIndexMask to a span of CI pixels. - */ void -_mesa_mask_index_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, GLuint index[] ) +_mesa_mask_index_span( GLcontext *ctx, const struct sw_span *span, + GLuint index[] ) { - GLuint i; + SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint msrc = ctx->Color.IndexMask; + const GLuint mdest = ~msrc; GLuint fbindexes[MAX_WIDTH]; - GLuint msrc, mdest; + GLuint i; - _mesa_read_index_span( ctx, ctx->DrawBuffer, n, x, y, fbindexes ); + ASSERT(span->arrayMask & SPAN_INDEX); + ASSERT(span->end < MAX_WIDTH); - msrc = ctx->Color.IndexMask; - mdest = ~msrc; + if (span->arrayMask & SPAN_XY) { - for (i=0;i<n;i++) { - index[i] = (index[i] & msrc) | (fbindexes[i] & mdest); + (*swrast->Driver.ReadCI32Pixels)(ctx, span->end, span->array->x, + span->array->y, fbindexes, + span->array->mask); + + for (i = 0; i < span->end; i++) { + index[i] = (index[i] & msrc) | (fbindexes[i] & mdest); + } + } + else { + _mesa_read_index_span(ctx, ctx->DrawBuffer, span->end, span->x, span->y, + fbindexes ); + + for (i = 0; i < span->end; i++) { + index[i] = (index[i] & msrc) | (fbindexes[i] & mdest); + } } } /* - * Apply glIndexMask to an array of CI pixels. + * Apply glIndexMask to a span of CI pixels. */ void -_mesa_mask_index_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLuint index[], const GLubyte mask[] ) +_mesa_mask_index_array( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLuint index[] ) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); GLuint i; - GLuint fbindexes[PB_SIZE]; + GLuint fbindexes[MAX_WIDTH]; GLuint msrc, mdest; - (*swrast->Driver.ReadCI32Pixels)( ctx, n, x, y, fbindexes, mask ); + _mesa_read_index_span( ctx, ctx->DrawBuffer, n, x, y, fbindexes ); msrc = ctx->Color.IndexMask; mdest = ~msrc; diff --git a/xc/extras/Mesa/src/swrast/s_masking.h b/xc/extras/Mesa/src/swrast/s_masking.h index f79acf413..8b5c86366 100644 --- a/xc/extras/Mesa/src/swrast/s_masking.h +++ b/xc/extras/Mesa/src/swrast/s_masking.h @@ -1,10 +1,9 @@ -/* $Id: s_masking.h,v 1.1.1.1 2002/10/22 13:06:44 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -37,39 +36,26 @@ * Implement glColorMask for a span of RGBA pixels. */ extern void -_mesa_mask_rgba_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, +_mesa_mask_rgba_span( GLcontext *ctx, const struct sw_span *span, GLchan rgba[][4] ); - -/* - * Implement glColorMask for an array of RGBA pixels. - */ extern void -_mesa_mask_rgba_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLchan rgba[][4], const GLubyte mask[] ); - +_mesa_mask_rgba_array( GLcontext *ctx, GLuint n, GLint x, GLint y, + GLchan rgba[][4] ); /* * Implement glIndexMask for a span of CI pixels. */ extern void -_mesa_mask_index_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, GLuint index[] ); +_mesa_mask_index_span( GLcontext *ctx, const struct sw_span *span, + GLuint index[] ); - -/* - * Implement glIndexMask for an array of CI pixels. - */ extern void -_mesa_mask_index_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - GLuint index[], const GLubyte mask[] ); - +_mesa_mask_index_array( GLcontext *ctx, + GLuint n, GLint x, GLint y, GLuint index[] ); #endif diff --git a/xc/extras/Mesa/src/swrast/s_pb.c b/xc/extras/Mesa/src/swrast/s_pb.c deleted file mode 100644 index a0da3a6b3..000000000 --- a/xc/extras/Mesa/src/swrast/s_pb.c +++ /dev/null @@ -1,517 +0,0 @@ -/* $Id: s_pb.c,v 1.1.1.1 2002/10/22 13:06:53 alanh Exp $ */ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2001 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 - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - - -/* - * Pixel buffer: - * - * As fragments are produced (by point, line, and bitmap drawing) they - * are accumlated in a buffer. When the buffer is full or has to be - * flushed (glEnd), we apply all enabled rasterization functions to the - * pixels and write the results to the display buffer. The goal is to - * maximize the number of pixels processed inside loops and to minimize - * the number of function calls. - */ - - -#include "glheader.h" -#include "macros.h" -#include "mem.h" - -#include "s_alpha.h" -#include "s_alphabuf.h" -#include "s_blend.h" -#include "s_context.h" -#include "s_depth.h" -#include "s_fog.h" -#include "s_logic.h" -#include "s_masking.h" -#include "s_pb.h" -#include "s_scissor.h" -#include "s_stencil.h" -#include "s_texture.h" - - - -/* - * Allocate and initialize a new pixel buffer structure. - */ -struct pixel_buffer *_mesa_alloc_pb(void) -{ - struct pixel_buffer *pb; - pb = CALLOC_STRUCT(pixel_buffer); - if (pb) { - int i, j; - /* set non-zero fields */ - pb->mono = GL_TRUE; - - /* Set all lambda values to 0.0 since we don't do mipmapping for - * points or lines and want to use the level 0 texture image. - */ - for (j=0;j<MAX_TEXTURE_UNITS;j++) { - for (i=0; i<PB_SIZE; i++) { - pb->lambda[j][i] = 0.0; - } - } - } - return pb; -} - - - -/* - * Draw to more than one color buffer (or none). - */ -static void multi_write_index_pixels( GLcontext *ctx, GLuint n, - const GLint x[], const GLint y[], - const GLuint indexes[], - const GLubyte mask[] ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLuint bufferBit; - - if (ctx->Color.DrawBuffer == GL_NONE) - return; - - /* loop over four possible dest color buffers */ - for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) { - if (bufferBit & ctx->Color.DrawDestMask) { - GLuint indexTmp[PB_SIZE]; - ASSERT(n < PB_SIZE); - - if (bufferBit == FRONT_LEFT_BIT) - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT); - else if (bufferBit == FRONT_RIGHT_BIT) - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT); - else if (bufferBit == BACK_LEFT_BIT) - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT); - else - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT); - - /* make copy of incoming indexes */ - MEMCPY( indexTmp, indexes, n * sizeof(GLuint) ); - if (ctx->Color.IndexLogicOpEnabled) { - _mesa_logicop_ci_pixels( ctx, n, x, y, indexTmp, mask ); - } - if (ctx->Color.IndexMask != 0xffffffff) { - _mesa_mask_index_pixels( ctx, n, x, y, indexTmp, mask ); - } - (*swrast->Driver.WriteCI32Pixels)( ctx, n, x, y, indexTmp, mask ); - } - } - - /* restore default dest buffer */ - (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer); -} - - - -/* - * Draw to more than one RGBA color buffer (or none). - */ -static void multi_write_rgba_pixels( GLcontext *ctx, GLuint n, - const GLint x[], const GLint y[], - CONST GLchan rgba[][4], - const GLubyte mask[] ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLuint bufferBit; - - if (ctx->Color.DrawBuffer == GL_NONE) - return; - - /* loop over four possible dest color buffers */ - for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) { - if (bufferBit & ctx->Color.DrawDestMask) { - GLchan rgbaTmp[PB_SIZE][4]; - ASSERT(n < PB_SIZE); - - if (bufferBit == FRONT_LEFT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha; - } - else if (bufferBit == FRONT_RIGHT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha; - } - else if (bufferBit == BACK_LEFT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha; - } - else { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha; - } - - /* make copy of incoming colors */ - MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLchan) ); - - if (ctx->Color.ColorLogicOpEnabled) { - _mesa_logicop_rgba_pixels( ctx, n, x, y, rgbaTmp, mask ); - } - else if (ctx->Color.BlendEnabled) { - _mesa_blend_pixels( ctx, n, x, y, rgbaTmp, mask ); - } - if (*((GLuint *) &ctx->Color.ColorMask) != 0xffffffff) { - _mesa_mask_rgba_pixels( ctx, n, x, y, rgbaTmp, mask ); - } - - (*swrast->Driver.WriteRGBAPixels)( ctx, n, x, y, - (const GLchan (*)[4])rgbaTmp, mask ); - if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { - _mesa_write_alpha_pixels( ctx, n, x, y, - (const GLchan (*)[4])rgbaTmp, mask ); - } - } - } - - /* restore default dest buffer */ - (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer); -} - - - -/* - * Add specular color to primary color. This is used only when - * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR. - */ -static void add_colors( GLuint n, GLchan rgba[][4], CONST GLchan spec[][3] ) -{ - GLuint i; - for (i=0; i<n; i++) { - GLint r = rgba[i][RCOMP] + spec[i][RCOMP]; - GLint g = rgba[i][GCOMP] + spec[i][GCOMP]; - GLint b = rgba[i][BCOMP] + spec[i][BCOMP]; - rgba[i][RCOMP] = MIN2(r, CHAN_MAX); - rgba[i][GCOMP] = MIN2(g, CHAN_MAX); - rgba[i][BCOMP] = MIN2(b, CHAN_MAX); - } -} - - - -/* - * When the pixel buffer is full, or needs to be flushed, call this - * function. All the pixels in the pixel buffer will be subjected - * to texturing, scissoring, stippling, alpha testing, stenciling, - * depth testing, blending, and finally written to the frame buffer. - */ -void _mesa_flush_pb( GLcontext *ctx ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLuint RasterMask = swrast->_RasterMask; - - /* Pixel colors may be changed if any of these raster ops enabled */ - const GLuint modBits = FOG_BIT | TEXTURE_BIT | BLEND_BIT | - MASKING_BIT | LOGIC_OP_BIT; - struct pixel_buffer *PB = swrast->PB; - GLubyte mask[PB_SIZE]; - - if (PB->count == 0) - goto CleanUp; - - /* initialize mask array and clip pixels simultaneously */ - { - const GLint xmin = ctx->DrawBuffer->_Xmin; - const GLint xmax = ctx->DrawBuffer->_Xmax; - const GLint ymin = ctx->DrawBuffer->_Ymin; - const GLint ymax = ctx->DrawBuffer->_Ymax; - const GLuint n = PB->count; - GLint *x = PB->x; - GLint *y = PB->y; - GLuint i; - for (i = 0; i < n; i++) { - mask[i] = (x[i] >= xmin) & (x[i] < xmax) & (y[i] >= ymin) & (y[i] < ymax); - } - } - - if (ctx->Visual.rgbMode) { - /* - * RGBA COLOR PIXELS - */ - - /* If each pixel can be of a different color... */ - if ((RasterMask & modBits) || !PB->mono) { - - if (PB->mono) { - /* copy mono color into rgba array */ - GLuint i; - for (i = 0; i < PB->count; i++) { - COPY_CHAN4(PB->rgba[i], PB->currentColor); - } - } - - if (ctx->Texture._ReallyEnabled) { - GLchan primary_rgba[PB_SIZE][4]; - GLuint texUnit; - - /* must make a copy of primary colors since they may be modified */ - MEMCPY(primary_rgba, PB->rgba, 4 * PB->count * sizeof(GLchan)); - - for (texUnit = 0; texUnit < ctx->Const.MaxTextureUnits; texUnit++){ - _swrast_texture_fragments( ctx, texUnit, PB->count, - PB->s[texUnit], PB->t[texUnit], - PB->u[texUnit], PB->lambda[texUnit], - (CONST GLchan (*)[4]) primary_rgba, - PB->rgba ); - } - } - - if ((ctx->Fog.ColorSumEnabled || - (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR - && ctx->Light.Enabled)) && PB->haveSpec) { - /* add specular color to primary color */ - add_colors( PB->count, PB->rgba, (const GLchan (*)[3]) PB->spec ); - } - - if (ctx->Fog.Enabled) { - if (swrast->_PreferPixelFog) - _mesa_depth_fog_rgba_pixels( ctx, PB->count, PB->z, PB->rgba ); - else - _mesa_fog_rgba_pixels( ctx, PB->count, PB->fog, PB->rgba ); - } - - /* Antialias coverage application */ - if (PB->haveCoverage) { - const GLuint n = PB->count; - GLuint i; - for (i = 0; i < n; i++) { - PB->rgba[i][ACOMP] = (GLchan) (PB->rgba[i][ACOMP] * PB->coverage[i]); - } - } - - /* Scissoring already done above */ - - if (ctx->Color.AlphaEnabled) { - if (_mesa_alpha_test( ctx, PB->count, - (const GLchan (*)[4]) PB->rgba, mask )==0) { - goto CleanUp; - } - } - - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_pixels(ctx, PB->count, - PB->x, PB->y, PB->z, mask) == 0) { - goto CleanUp; - } - } - else if (ctx->Depth.Test) { - /* regular depth testing */ - _mesa_depth_test_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask ); - } - - - if (RasterMask & MULTI_DRAW_BIT) { - multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y, - (const GLchan (*)[4])PB->rgba, mask ); - } - else { - /* normal case: write to exactly one buffer */ - const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); - - if (ctx->Color.ColorLogicOpEnabled) { - _mesa_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y, - PB->rgba, mask); - } - else if (ctx->Color.BlendEnabled) { - _mesa_blend_pixels( ctx, PB->count, PB->x, PB->y, PB->rgba, mask); - } - if (colorMask == 0x0) { - goto CleanUp; - } - else if (colorMask != 0xffffffff) { - _mesa_mask_rgba_pixels(ctx, PB->count, PB->x, PB->y, PB->rgba, mask); - } - - (*swrast->Driver.WriteRGBAPixels)( ctx, PB->count, PB->x, PB->y, - (const GLchan (*)[4]) PB->rgba, - mask ); - if (RasterMask & ALPHABUF_BIT) { - _mesa_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, - (const GLchan (*)[4]) PB->rgba, mask ); - } - } - } - else { - /* Same color for all pixels */ - - /* Scissoring already done above */ - - if (ctx->Color.AlphaEnabled) { - if (_mesa_alpha_test( ctx, PB->count, - (const GLchan (*)[4]) PB->rgba, mask )==0) { - goto CleanUp; - } - } - - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_pixels(ctx, PB->count, - PB->x, PB->y, PB->z, mask) == 0) { - goto CleanUp; - } - } - else if (ctx->Depth.Test) { - /* regular depth testing */ - _mesa_depth_test_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask ); - } - - if (ctx->Color.DrawBuffer == GL_NONE) { - goto CleanUp; - } - - if (RasterMask & MULTI_DRAW_BIT) { - if (PB->mono) { - /* copy mono color into rgba array */ - GLuint i; - for (i = 0; i < PB->count; i++) { - COPY_CHAN4(PB->rgba[i], PB->currentColor); - } - } - multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y, - (const GLchan (*)[4]) PB->rgba, mask ); - } - else { - /* normal case: write to exactly one buffer */ - (*swrast->Driver.WriteMonoRGBAPixels)( ctx, PB->count, PB->x, PB->y, - PB->currentColor, mask ); - if (RasterMask & ALPHABUF_BIT) { - _mesa_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y, - PB->currentColor[ACOMP], mask ); - } - } - /*** ALL DONE ***/ - } - } - else { - /* - * COLOR INDEX PIXELS - */ - - /* If we may be writting pixels with different indexes... */ - if ((RasterMask & modBits) || !PB->mono) { - - if (PB->mono) { - GLuint i; - for (i = 0; i < PB->count; i++) { - PB->index[i] = PB->currentIndex; - } - } - if (ctx->Fog.Enabled) { - if (swrast->_PreferPixelFog) - _mesa_depth_fog_ci_pixels( ctx, PB->count, PB->z, PB->index ); - else - _mesa_fog_ci_pixels( ctx, PB->count, PB->fog, PB->index ); - } - - /* Antialias coverage application */ - if (PB->haveCoverage) { - const GLuint n = PB->count; - GLuint i; - for (i = 0; i < n; i++) { - GLint frac = (GLint) (15.0 * PB->coverage[i]); - PB->index[i] = (PB->index[i] & ~0xf) | frac; - } - } - - /* Scissoring already done above */ - - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_pixels(ctx, PB->count, - PB->x, PB->y, PB->z, mask) == 0) { - goto CleanUp; - } - } - else if (ctx->Depth.Test) { - /* regular depth testing */ - _mesa_depth_test_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask ); - } - if (RasterMask & MULTI_DRAW_BIT) { - multi_write_index_pixels( ctx, PB->count, PB->x, PB->y, PB->index, mask ); - } - else { - /* normal case: write to exactly one buffer */ - - if (ctx->Color.IndexLogicOpEnabled) { - _mesa_logicop_ci_pixels(ctx, PB->count, PB->x, PB->y, - PB->index, mask); - } - if (ctx->Color.IndexMask != 0xffffffff) { - _mesa_mask_index_pixels(ctx, PB->count, PB->x, PB->y, - PB->index, mask); - } - (*swrast->Driver.WriteCI32Pixels)( ctx, PB->count, PB->x, PB->y, - PB->index, mask ); - } - - /*** ALL DONE ***/ - } - else { - /* Same color index for all pixels */ - - /* Scissoring already done above */ - - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_pixels(ctx, PB->count, - PB->x, PB->y, PB->z, mask) == 0) { - goto CleanUp; - } - } - else if (ctx->Depth.Test) { - /* regular depth testing */ - _mesa_depth_test_pixels(ctx, PB->count, PB->x, PB->y, PB->z, mask); - } - - if (RasterMask & MULTI_DRAW_BIT) { - multi_write_index_pixels(ctx, PB->count, PB->x, PB->y, - PB->index, mask); - } - else { - /* normal case: write to exactly one buffer */ - (*swrast->Driver.WriteMonoCIPixels)(ctx, PB->count, PB->x, PB->y, - PB->currentIndex, mask); - } - } - } - -CleanUp: - PB->count = 0; - PB->mono = GL_TRUE; - PB->haveSpec = GL_FALSE; - PB->haveCoverage = GL_FALSE; -} - - -void -_swrast_flush( GLcontext *ctx ) -{ - if (SWRAST_CONTEXT(ctx)->PB->count > 0) - _mesa_flush_pb(ctx); -} diff --git a/xc/extras/Mesa/src/swrast/s_pb.h b/xc/extras/Mesa/src/swrast/s_pb.h deleted file mode 100644 index 72d2df353..000000000 --- a/xc/extras/Mesa/src/swrast/s_pb.h +++ /dev/null @@ -1,244 +0,0 @@ -/* $Id: s_pb.h,v 1.1.1.1 2002/10/22 13:06:53 alanh Exp $ */ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2001 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 - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#ifndef PB_H -#define PB_H - - -#include "mtypes.h" -#include "swrast.h" -#include "colormac.h" - - -/* - * Pixel buffer size, must be larger than MAX_WIDTH. - */ -#define PB_SIZE (3*MAX_WIDTH) - - -struct pixel_buffer { - GLchan currentColor[4]; /* Current color, for subsequent pixels */ - GLuint currentIndex; /* Current index, for subsequent pixels */ - GLuint count; /* Number of pixels in buffer */ - GLboolean mono; /* Same color or index for all pixels? */ - GLboolean haveSpec; /* any specular colors? */ - GLboolean haveCoverage; /* apply AA coverage? */ - - GLint x[PB_SIZE]; /* X window coord in [0,MAX_WIDTH) */ - GLint y[PB_SIZE]; /* Y window coord in [0,MAX_HEIGHT) */ - GLdepth z[PB_SIZE]; /* Z window coord in [0,Visual.MaxDepth] */ - GLfloat fog[PB_SIZE]; /* Fog window coord in [0,1] */ - GLchan rgba[PB_SIZE][4]; /* Colors */ - GLchan spec[PB_SIZE][3]; /* Separate specular colors */ - GLuint index[PB_SIZE]; /* Color indexes */ - GLfloat coverage[PB_SIZE]; /* Antialiasing coverage in [0,1] */ - GLfloat s[MAX_TEXTURE_UNITS][PB_SIZE]; /* Texture S coordinates */ - GLfloat t[MAX_TEXTURE_UNITS][PB_SIZE]; /* Texture T coordinates */ - GLfloat u[MAX_TEXTURE_UNITS][PB_SIZE]; /* Texture R coordinates */ - GLfloat lambda[MAX_TEXTURE_UNITS][PB_SIZE]; /* Texture lambda values */ -}; - - - -/* - * Set the color used for all subsequent pixels in the buffer. - */ -#define PB_SET_COLOR( PB, R, G, B, A ) \ -do { \ - if ((PB)->count > 0) \ - (PB)->mono = GL_FALSE; \ - (PB)->currentColor[RCOMP] = (R); \ - (PB)->currentColor[GCOMP] = (G); \ - (PB)->currentColor[BCOMP] = (B); \ - (PB)->currentColor[ACOMP] = (A); \ -} while (0) - - -/* - * Set the color index used for all subsequent pixels in the buffer. - */ -#define PB_SET_INDEX( PB, I ) \ -do { \ - if ((PB)->count > 0) \ - (PB)->mono = GL_FALSE; \ - (PB)->currentIndex = (I); \ -} while (0) - - -/* - * "write" a pixel using current color or index - */ -#define PB_WRITE_PIXEL( PB, X, Y, Z, FOG ) \ -do { \ - GLuint count = (PB)->count; \ - (PB)->x[count] = X; \ - (PB)->y[count] = Y; \ - (PB)->z[count] = Z; \ - (PB)->fog[count] = FOG; \ - COPY_CHAN4((PB)->rgba[count], (PB)->currentColor); \ - (PB)->index[count] = (PB)->currentIndex; \ - (PB)->count++; \ -} while (0) - - -/* - * "write" an RGBA pixel - */ -#define PB_WRITE_RGBA_PIXEL( PB, X, Y, Z, FOG, R, G, B, A ) \ -do { \ - GLuint count = (PB)->count; \ - (PB)->x[count] = X; \ - (PB)->y[count] = Y; \ - (PB)->z[count] = Z; \ - (PB)->fog[count] = FOG; \ - (PB)->rgba[count][RCOMP] = R; \ - (PB)->rgba[count][GCOMP] = G; \ - (PB)->rgba[count][BCOMP] = B; \ - (PB)->rgba[count][ACOMP] = A; \ - (PB)->mono = GL_FALSE; \ - (PB)->count++; \ -} while (0) - - -/* - * "write" a color-index pixel - */ -#define PB_WRITE_CI_PIXEL( PB, X, Y, Z, FOG, I ) \ -do { \ - GLuint count = (PB)->count; \ - (PB)->x[count] = X; \ - (PB)->y[count] = Y; \ - (PB)->z[count] = Z; \ - (PB)->fog[count] = FOG; \ - (PB)->index[count] = I; \ - (PB)->mono = GL_FALSE; \ - (PB)->count++; \ -} while (0) - - - -/* - * "write" an RGBA pixel with texture coordinates - */ -#define PB_WRITE_TEX_PIXEL( PB, X, Y, Z, FOG, R, G, B, A, S, T, U ) \ -do { \ - GLuint count = (PB)->count; \ - (PB)->x[count] = X; \ - (PB)->y[count] = Y; \ - (PB)->z[count] = Z; \ - (PB)->fog[count] = FOG; \ - (PB)->rgba[count][RCOMP] = R; \ - (PB)->rgba[count][GCOMP] = G; \ - (PB)->rgba[count][BCOMP] = B; \ - (PB)->rgba[count][ACOMP] = A; \ - (PB)->s[0][count] = S; \ - (PB)->t[0][count] = T; \ - (PB)->u[0][count] = U; \ - (PB)->mono = GL_FALSE; \ - (PB)->count++; \ -} while (0) - - -/* - * "write" an RGBA pixel with multiple texture coordinates - */ -#define PB_WRITE_MULTITEX_PIXEL( PB, X, Y, Z, FOG, R, G, B, A, TEXCOORDS ) \ -do { \ - GLuint count = (PB)->count; \ - GLuint unit; \ - (PB)->x[count] = X; \ - (PB)->y[count] = Y; \ - (PB)->z[count] = Z; \ - (PB)->fog[count] = FOG; \ - (PB)->rgba[count][RCOMP] = R; \ - (PB)->rgba[count][GCOMP] = G; \ - (PB)->rgba[count][BCOMP] = B; \ - (PB)->rgba[count][ACOMP] = A; \ - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \ - if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ - (PB)->s[unit][count] = TEXCOORDS[unit][0]; \ - (PB)->t[unit][count] = TEXCOORDS[unit][1]; \ - (PB)->u[unit][count] = TEXCOORDS[unit][2]; \ - } \ - } \ - (PB)->mono = GL_FALSE; \ - (PB)->count++; \ -} while (0) - - -/* - * "write" an RGBA pixel with multiple texture coordinates and specular color - */ -#define PB_WRITE_MULTITEX_SPEC_PIXEL( PB, X, Y, Z, FOG, R, G, B, A, SR, SG, SB, TEXCOORDS )\ -do { \ - GLuint count = (PB)->count; \ - GLuint unit; \ - (PB)->haveSpec = GL_TRUE; \ - (PB)->x[count] = X; \ - (PB)->y[count] = Y; \ - (PB)->z[count] = Z; \ - (PB)->fog[count] = FOG; \ - (PB)->rgba[count][RCOMP] = R; \ - (PB)->rgba[count][GCOMP] = G; \ - (PB)->rgba[count][BCOMP] = B; \ - (PB)->rgba[count][ACOMP] = A; \ - (PB)->spec[count][RCOMP] = SR; \ - (PB)->spec[count][GCOMP] = SG; \ - (PB)->spec[count][BCOMP] = SB; \ - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \ - if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ - (PB)->s[unit][count] = TEXCOORDS[unit][0]; \ - (PB)->t[unit][count] = TEXCOORDS[unit][1]; \ - (PB)->u[unit][count] = TEXCOORDS[unit][2]; \ - } \ - } \ - (PB)->mono = GL_FALSE; \ - (PB)->count++; \ -} while (0) - - -#define PB_COVERAGE(PB, COVERAGE) \ - (PB)->coverage[(PB)->count] = COVERAGE; - - -/* - * Call this function at least every MAX_WIDTH pixels: - */ -#define PB_CHECK_FLUSH( CTX, PB ) \ -do { \ - if ((PB)->count >= PB_SIZE - MAX_WIDTH) { \ - _mesa_flush_pb( CTX ); \ - } \ -} while(0) - - -extern struct pixel_buffer *_mesa_alloc_pb(void); - -extern void _mesa_flush_pb( GLcontext *ctx ); - - -#endif diff --git a/xc/extras/Mesa/src/swrast/s_pixeltex.c b/xc/extras/Mesa/src/swrast/s_pixeltex.c index f52972ff7..776a38c91 100644 --- a/xc/extras/Mesa/src/swrast/s_pixeltex.c +++ b/xc/extras/Mesa/src/swrast/s_pixeltex.c @@ -1,10 +1,9 @@ -/* $Id: s_pixeltex.c,v 1.1.1.1 2002/10/22 13:06:56 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -35,47 +34,84 @@ #include "glheader.h" #include "colormac.h" +#include "imports.h" #include "s_context.h" #include "s_pixeltex.h" +#include "s_texture.h" /* * Convert RGBA values into strq texture coordinates. */ -void -_mesa_pixeltexgen(GLcontext *ctx, GLuint n, const GLchan rgba[][4], - GLfloat s[], GLfloat t[], GLfloat r[], GLfloat q[]) +static void +pixeltexgen(GLcontext *ctx, GLuint n, const GLchan rgba[][4], + GLfloat texcoord[][4]) { if (ctx->Pixel.FragmentRgbSource == GL_CURRENT_RASTER_COLOR) { GLuint i; for (i = 0; i < n; i++) { - s[i] = ctx->Current.RasterColor[RCOMP]; - t[i] = ctx->Current.RasterColor[GCOMP]; - r[i] = ctx->Current.RasterColor[BCOMP]; + texcoord[i][0] = ctx->Current.RasterColor[RCOMP]; + texcoord[i][1] = ctx->Current.RasterColor[GCOMP]; + texcoord[i][2] = ctx->Current.RasterColor[BCOMP]; } } else { GLuint i; ASSERT(ctx->Pixel.FragmentRgbSource == GL_PIXEL_GROUP_COLOR_SGIS); for (i = 0; i < n; i++) { - s[i] = CHAN_TO_FLOAT(rgba[i][RCOMP]); - t[i] = CHAN_TO_FLOAT(rgba[i][GCOMP]); - r[i] = CHAN_TO_FLOAT(rgba[i][BCOMP]); + texcoord[i][0] = CHAN_TO_FLOAT(rgba[i][RCOMP]); + texcoord[i][1] = CHAN_TO_FLOAT(rgba[i][GCOMP]); + texcoord[i][2] = CHAN_TO_FLOAT(rgba[i][BCOMP]); } } if (ctx->Pixel.FragmentAlphaSource == GL_CURRENT_RASTER_COLOR) { GLuint i; for (i = 0; i < n; i++) { - q[i] = ctx->Current.RasterColor[ACOMP]; + texcoord[i][3] = ctx->Current.RasterColor[ACOMP]; } } else { GLuint i; ASSERT(ctx->Pixel.FragmentAlphaSource == GL_PIXEL_GROUP_COLOR_SGIS); for (i = 0; i < n; i++) { - q[i] = CHAN_TO_FLOAT(rgba[i][ACOMP]); + texcoord[i][3] = CHAN_TO_FLOAT(rgba[i][ACOMP]); + } + } +} + + + +/* + * Used by glDraw/CopyPixels: the incoming image colors are treated + * as texture coordinates. Use those coords to texture the image. + * This is for GL_SGIS_pixel_texture / GL_SGIX_pixel_texture. + */ +void +_swrast_pixel_texture(GLcontext *ctx, struct sw_span *span) +{ + GLuint unit; + + ASSERT(!(span->arrayMask & SPAN_TEXTURE)); + span->arrayMask |= SPAN_TEXTURE; + + /* convert colors into texture coordinates */ + pixeltexgen( ctx, span->end, + (const GLchan (*)[4]) span->array->rgba, + span->array->texcoords[0] ); + + /* copy the new texture units for all enabled units */ + for (unit = 1; unit < ctx->Const.MaxTextureUnits; unit++) { + if (ctx->Texture.Unit[unit]._ReallyEnabled) { + MEMCPY( span->array->texcoords[unit], span->array->texcoords[0], + span->end * 4 * sizeof(GLfloat) ); } } + + /* apply texture mapping */ + _swrast_texture_span( ctx, span ); + + /* this is a work-around to be fixed by initializing again span */ + span->arrayMask &= ~SPAN_TEXTURE; } diff --git a/xc/extras/Mesa/src/swrast/s_pixeltex.h b/xc/extras/Mesa/src/swrast/s_pixeltex.h index 7d1d8047c..6ef7a44df 100644 --- a/xc/extras/Mesa/src/swrast/s_pixeltex.h +++ b/xc/extras/Mesa/src/swrast/s_pixeltex.h @@ -1,10 +1,9 @@ -/* $Id: s_pixeltex.h,v 1.1.1.1 2002/10/22 13:06:56 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -31,9 +30,9 @@ #include "mtypes.h" #include "swrast.h" + extern void -_mesa_pixeltexgen(GLcontext *ctx, GLuint n, const GLchan rgba[][4], - GLfloat s[], GLfloat t[], GLfloat r[], GLfloat q[]); +_swrast_pixel_texture(GLcontext *ctx, struct sw_span *span); #endif diff --git a/xc/extras/Mesa/src/swrast/s_points.c b/xc/extras/Mesa/src/swrast/s_points.c index 75f4b7811..5ef41d9fb 100644 --- a/xc/extras/Mesa/src/swrast/s_points.c +++ b/xc/extras/Mesa/src/swrast/s_points.c @@ -1,10 +1,9 @@ -/* $Id: s_points.c,v 1.1.1.1 2002/10/22 13:06:58 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -33,20 +32,19 @@ #include "texstate.h" #include "s_context.h" #include "s_feedback.h" -#include "s_pb.h" #include "s_points.h" #include "s_span.h" -#define INDEX 0x0 #define RGBA 0x1 -#define SMOOTH 0x2 -#define TEXTURE 0x4 -#define SPECULAR 0x8 -#define LARGE 0x10 -#define ATTENUATE 0x20 -#define SPRITE 0x40 +#define INDEX 0x2 +#define SMOOTH 0x4 +#define TEXTURE 0x8 +#define SPECULAR 0x10 +#define LARGE 0x20 +#define ATTENUATE 0x40 +#define SPRITE 0x80 /* @@ -148,12 +146,12 @@ /* * Sprite (textured point) */ -#define FLAGS (RGBA | TEXTURE | SPRITE) +#define FLAGS (RGBA | SPRITE) #define NAME sprite_point #include "s_pointtemp.h" -#define FLAGS (RGBA | ATTENUATE | TEXTURE | SPRITE) +#define FLAGS (RGBA | ATTENUATE | SPRITE) #define NAME atten_sprite_point #include "s_pointtemp.h" @@ -202,7 +200,8 @@ _swrast_choose_point( GLcontext *ctx ) GLboolean rgbMode = ctx->Visual.rgbMode; if (ctx->RenderMode==GL_RENDER) { - if (ctx->Point.SpriteMode) { + if (ctx->Point.PointSprite) { + /* GL_NV_point_sprite */ /* XXX this might not be good enough */ if (ctx->Point._Attenuated) USE(atten_sprite_point); @@ -212,10 +211,10 @@ _swrast_choose_point( GLcontext *ctx ) else if (ctx->Point.SmoothFlag) { /* Smooth points */ if (rgbMode) { - if (ctx->Point._Attenuated) { + if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) { USE(atten_antialiased_rgba_point); } - else if (ctx->Texture._ReallyEnabled) { + else if (ctx->Texture._EnabledUnits) { USE(antialiased_tex_rgba_point); } else { @@ -226,9 +225,9 @@ _swrast_choose_point( GLcontext *ctx ) USE(antialiased_ci_point); } } - else if (ctx->Point._Attenuated) { + else if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) { if (rgbMode) { - if (ctx->Texture._ReallyEnabled) { + if (ctx->Texture._EnabledUnits) { if (ctx->Point.SmoothFlag) { USE(atten_antialiased_rgba_point); } @@ -245,7 +244,7 @@ _swrast_choose_point( GLcontext *ctx ) USE(atten_general_ci_point); } } - else if (ctx->Texture._ReallyEnabled && rgbMode) { + else if (ctx->Texture._EnabledUnits && rgbMode) { /* textured */ USE(textured_rgba_point); } diff --git a/xc/extras/Mesa/src/swrast/s_points.h b/xc/extras/Mesa/src/swrast/s_points.h index 0b2ec5ba6..40b442e95 100644 --- a/xc/extras/Mesa/src/swrast/s_points.h +++ b/xc/extras/Mesa/src/swrast/s_points.h @@ -1,4 +1,3 @@ -/* $Id: s_points.h,v 1.1.1.1 2002/10/22 13:06:58 alanh Exp $ */ /* * Mesa 3-D graphics library @@ -30,10 +29,10 @@ #include "mtypes.h" -void +extern void _swrast_choose_point( GLcontext *ctx ); -void +extern void _swrast_add_spec_terms_point( GLcontext *ctx, const SWvertex *v0 ); diff --git a/xc/extras/Mesa/src/swrast/s_pointtemp.h b/xc/extras/Mesa/src/swrast/s_pointtemp.h index efef56bc0..8f07fa25a 100644 --- a/xc/extras/Mesa/src/swrast/s_pointtemp.h +++ b/xc/extras/Mesa/src/swrast/s_pointtemp.h @@ -1,10 +1,9 @@ -/* $Id: s_pointtemp.h,v 1.1.1.1 2002/10/22 13:06:54 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 5.0 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -36,7 +35,7 @@ * SPECULAR = do separate specular color * LARGE = do points with diameter > 1 pixel * ATTENUATE = compute point size attenuation - * SPRITE = GL_MESA_sprite_point + * SPRITE = GL_NV_point_sprite * * Notes: LARGE and ATTENUATE are exclusive of each other. * TEXTURE requires RGBA @@ -53,7 +52,7 @@ * else if d > rmax2 then * fragment has 0% coverage * else - * fragement has % coverage = (d - rmin2) / (rmax2 - rmin2) + * fragment has % coverage = (d - rmin2) / (rmax2 - rmin2) */ @@ -61,49 +60,76 @@ static void NAME ( GLcontext *ctx, const SWvertex *vert ) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); - struct pixel_buffer *PB = swrast->PB; - - const GLint z = (GLint) (vert->win[2]); - +#if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE) + GLfloat size; +#endif +#if FLAGS & ATTENUATE + GLfloat alphaAtten; +#endif #if FLAGS & RGBA const GLchan red = vert->color[0]; const GLchan green = vert->color[1]; const GLchan blue = vert->color[2]; - GLchan alpha = vert->color[3]; + const GLchan alpha = vert->color[3]; +#endif #if FLAGS & SPECULAR - const GLchan sRed = vert->specular[0]; - const GLchan sGreen = vert->specular[1]; - const GLchan sBlue = vert->specular[2]; + const GLchan specRed = vert->specular[0]; + const GLchan specGreen = vert->specular[1]; + const GLchan specBlue = vert->specular[2]; #endif -#else - GLint index = vert->index; +#if FLAGS & INDEX + const GLuint colorIndex = vert->index; #endif -#if FLAGS & (ATTENUATE | LARGE | SMOOTH) - GLfloat size; -#endif -#if FLAGS & ATTENUATE - GLfloat alphaAtten; -#endif - #if FLAGS & TEXTURE GLfloat texcoord[MAX_TEXTURE_UNITS][4]; GLuint u; +#endif + SWcontext *swrast = SWRAST_CONTEXT(ctx); + struct sw_span *span = &(swrast->PointSpan); + + /* Cull primitives with malformed coordinates. + */ + { + float tmp = vert->win[0] + vert->win[1]; + if (IS_INF_OR_NAN(tmp)) + return; + } + + /* + * Span init + */ + span->interpMask = SPAN_FOG; + span->arrayMask = SPAN_XY | SPAN_Z; + span->fog = vert->fog; + span->fogStep = 0.0; +#if FLAGS & RGBA + span->arrayMask |= SPAN_RGBA; +#endif +#if FLAGS & SPECULAR + span->arrayMask |= SPAN_SPEC; +#endif +#if FLAGS & INDEX + span->arrayMask |= SPAN_INDEX; +#endif +#if FLAGS & TEXTURE + span->arrayMask |= SPAN_TEXTURE; for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { if (ctx->Texture.Unit[u]._ReallyEnabled) { - if (vert->texcoord[u][3] != 1.0 && vert->texcoord[u][3] != 0.0) { - texcoord[u][0] = vert->texcoord[u][0] / vert->texcoord[u][3]; - texcoord[u][1] = vert->texcoord[u][1] / vert->texcoord[u][3]; - texcoord[u][2] = vert->texcoord[u][2] / vert->texcoord[u][3]; - } - else { - texcoord[u][0] = vert->texcoord[u][0]; - texcoord[u][1] = vert->texcoord[u][1]; - texcoord[u][2] = vert->texcoord[u][2]; - } + const GLfloat q = vert->texcoord[u][3]; + const GLfloat invQ = (q == 0.0F || q == 1.0F) ? 1.0F : (1.0F / q); + texcoord[u][0] = vert->texcoord[u][0] * invQ; + texcoord[u][1] = vert->texcoord[u][1] * invQ; + texcoord[u][2] = vert->texcoord[u][2] * invQ; + texcoord[u][3] = q; } } #endif +#if FLAGS & SMOOTH + span->arrayMask |= SPAN_COVERAGE; +#endif +#if FLAGS & SPRITE + span->arrayMask |= SPAN_TEXTURE; +#endif #if FLAGS & ATTENUATE if (vert->pointSize >= ctx->Point.Threshold) { @@ -115,78 +141,19 @@ NAME ( GLcontext *ctx, const SWvertex *vert ) size = MAX2(ctx->Point.Threshold, ctx->Point.MinSize); alphaAtten = dsize * dsize; } -#elif FLAGS & (LARGE | SMOOTH) +#elif FLAGS & (LARGE | SMOOTH | SPRITE) size = ctx->Point._Size; #endif - /* Cull primitives with malformed coordinates. +#if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE) + /* + * Multi-pixel points */ - { - float tmp = vert->win[0] + vert->win[1]; - if (IS_INF_OR_NAN(tmp)) - return; - } - -#if FLAGS & SPRITE - { - SWcontext *swctx = SWRAST_CONTEXT(ctx); - const GLfloat radius = 0.5F * vert->pointSize; /* XXX threshold, alpha */ - SWvertex v0, v1, v2, v3; - GLuint unit; - - (void) red; - (void) green; - (void) blue; - (void) alpha; - (void) z; - - /* lower left corner */ - v0 = *vert; - v0.win[0] -= radius; - v0.win[1] -= radius; - - /* lower right corner */ - v1 = *vert; - v1.win[0] += radius; - v1.win[1] -= radius; - - /* upper right corner */ - v2 = *vert; - v2.win[0] += radius; - v2.win[1] += radius; - - /* upper left corner */ - v3 = *vert; - v3.win[0] -= radius; - v3.win[1] += radius; - - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { - if (ctx->Texture.Unit[unit]._ReallyEnabled) { - v0.texcoord[unit][0] = 0.0; - v0.texcoord[unit][1] = 0.0; - v1.texcoord[unit][0] = 1.0; - v1.texcoord[unit][1] = 0.0; - v2.texcoord[unit][0] = 1.0; - v2.texcoord[unit][1] = 1.0; - v3.texcoord[unit][0] = 0.0; - v3.texcoord[unit][1] = 1.0; - } - } - - /* XXX if radius < threshold, attenuate alpha? */ - - /* XXX need to implement clipping!!! */ - - /* render */ - swctx->Triangle(ctx, &v0, &v1, &v2); - swctx->Triangle(ctx, &v0, &v2, &v3); - } - -#elif FLAGS & (LARGE | ATTENUATE | SMOOTH) - - { + {{ GLint x, y; const GLfloat radius = 0.5F * size; + const GLint z = (GLint) (vert->win[2] + 0.5F); + GLuint count; #if FLAGS & SMOOTH const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ const GLfloat rmax = radius + 0.7071F; @@ -218,109 +185,186 @@ NAME ( GLcontext *ctx, const SWvertex *vert ) ymin = (GLint) vert->win[1] - iRadius + 1; ymax = ymin + iSize - 1; } +#endif /*SMOOTH*/ + + /* check if we need to flush */ + if (span->end + (xmax-xmin+1) * (ymax-ymin+1) >= MAX_WIDTH || + (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) { +#if FLAGS & (TEXTURE | SPRITE) + if (ctx->Texture._EnabledUnits) + _mesa_write_texture_span(ctx, span); + else + _mesa_write_rgba_span(ctx, span); +#elif FLAGS & RGBA + _mesa_write_rgba_span(ctx, span); +#else + _mesa_write_index_span(ctx, span); #endif - (void) radius; + span->end = 0; + } + /* + * OK, generate fragments + */ + count = span->end; + (void) radius; for (y = ymin; y <= ymax; y++) { for (x = xmin; x <= xmax; x++) { -#if FLAGS & SMOOTH - /* compute coverage */ - const GLfloat dx = x - vert->win[0] + 0.5F; - const GLfloat dy = y - vert->win[1] + 0.5F; - const GLfloat dist2 = dx * dx + dy * dy; - if (dist2 < rmax2) { -#if FLAGS & RGBA - alpha = vert->color[3]; +#if FLAGS & (SPRITE | TEXTURE) + GLuint u; #endif - if (dist2 >= rmin2) { - /* compute partial coverage */ - PB_COVERAGE(PB, 1.0F - (dist2 - rmin2) * cscale); - } - else { - /* full coverage */ - PB_COVERAGE(PB, 1.0F); - } - -#endif /* SMOOTH */ -#if ((FLAGS & (ATTENUATE | RGBA)) == (ATTENUATE | RGBA)) - alpha = (GLchan) (alpha * alphaAtten); +#if FLAGS & RGBA + span->array->rgba[count][RCOMP] = red; + span->array->rgba[count][GCOMP] = green; + span->array->rgba[count][BCOMP] = blue; + span->array->rgba[count][ACOMP] = alpha; #endif - #if FLAGS & SPECULAR - PB_WRITE_MULTITEX_SPEC_PIXEL(PB, x, y, z, vert->fog, - red, green, blue, alpha, - sRed, sGreen, sBlue, - texcoord); -#elif FLAGS & TEXTURE - if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { - PB_WRITE_MULTITEX_PIXEL(PB, x, y, z, vert->fog, - red, green, blue, alpha, - texcoord); - } - else if (ctx->Texture._ReallyEnabled) { - PB_WRITE_TEX_PIXEL(PB, x,y,z, vert->fog, - red, green, blue, alpha, - texcoord[0][0], - texcoord[0][1], - texcoord[0][2]); - } - else { - PB_WRITE_RGBA_PIXEL(PB, x, y, z, vert->fog, - red, green, blue, alpha); - } -#elif FLAGS & RGBA - PB_WRITE_RGBA_PIXEL(PB, x, y, z, vert->fog, - red, green, blue, alpha); -#else /* color index */ - PB_WRITE_CI_PIXEL(PB, x, y, z, vert->fog, index); + span->array->spec[count][RCOMP] = specRed; + span->array->spec[count][GCOMP] = specGreen; + span->array->spec[count][BCOMP] = specBlue; #endif -#if FLAGS & SMOOTH - } +#if FLAGS & INDEX + span->array->index[count] = colorIndex; +#endif +#if FLAGS & TEXTURE + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + COPY_4V(span->array->texcoords[u][count], texcoord[u]); + } + } #endif - } - } #if FLAGS & SMOOTH - PB->haveCoverage = GL_TRUE; + /* compute coverage */ + { + const GLfloat dx = x - vert->win[0] + 0.5F; + const GLfloat dy = y - vert->win[1] + 0.5F; + const GLfloat dist2 = dx * dx + dy * dy; + if (dist2 < rmax2) { + if (dist2 >= rmin2) { + /* compute partial coverage */ + span->array->coverage[count] = 1.0F - (dist2 - rmin2) * cscale; +#if FLAGS & INDEX + /* coverage in [0,15] */ + span->array->coverage[count] *= 15.0; #endif + } + else { + /* full coverage */ + span->array->coverage[count] = 1.0F; + } + + span->array->x[count] = x; + span->array->y[count] = y; + span->array->z[count] = z; + +#if (FLAGS & ATTENUATE) && (FLAGS & RGBA) + span->array->rgba[count][ACOMP] = (GLchan) (alpha * alphaAtten); +#elif FLAGS & RGBA + span->array->rgba[count][ACOMP] = alpha; +#endif /*ATTENUATE*/ + count++; + } /*if*/ + } - PB_CHECK_FLUSH(ctx,PB); - } +#else /*SMOOTH*/ -#else /* LARGE || ATTENUATE || SMOOTH*/ + /* not smooth (square points) */ + span->array->x[count] = x; + span->array->y[count] = y; + span->array->z[count] = z; - { - /* size == 1 */ - GLint x = (GLint) vert->win[0]; - GLint y = (GLint) vert->win[1]; -#if ((FLAGS & (SPECULAR | TEXTURE)) == (SPECULAR | TEXTURE)) - PB_WRITE_MULTITEX_SPEC_PIXEL(PB, x, y, z, vert->fog, - red, green, blue, alpha, - sRed, sGreen, sBlue, - texcoord); -#elif FLAGS & TEXTURE - if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { - PB_WRITE_MULTITEX_PIXEL(PB, x, y, z, vert->fog, - red, green, blue, alpha, texcoord ); - } - else { - PB_WRITE_TEX_PIXEL(PB, x, y, z, vert->fog, - red, green, blue, alpha, - texcoord[0][0], texcoord[0][1], texcoord[0][2]); - } +#if FLAGS & SPRITE + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + if (ctx->Point.CoordReplace[u]) { + GLfloat s = 0.5F + (x + 0.5F - vert->win[0]) / size; + GLfloat t = 0.5F - (y + 0.5F - vert->win[1]) / size; + span->array->texcoords[u][count][0] = s; + span->array->texcoords[u][count][1] = t; + span->array->texcoords[u][count][3] = 1.0F; + if (ctx->Point.SpriteRMode == GL_ZERO) + span->array->texcoords[u][count][2] = 0.0F; + else if (ctx->Point.SpriteRMode == GL_S) + span->array->texcoords[u][count][2] = vert->texcoord[u][0]; + else /* GL_R */ + span->array->texcoords[u][count][2] = vert->texcoord[u][2]; + } + else { + COPY_4V(span->array->texcoords[u][count], vert->texcoord[u]); + } + } + } +#endif /*SPRITE*/ + + count++; /* square point */ + +#endif /*SMOOTH*/ + + } /*for x*/ + } /*for y*/ + span->end = count; + }} + +#else /* LARGE | ATTENUATE | SMOOTH | SPRITE */ + + /* + * Single-pixel points + */ + {{ + GLuint count; + + /* check if we need to flush */ + if (span->end >= MAX_WIDTH || + (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) { +#if FLAGS & (TEXTURE | SPRITE) + if (ctx->Texture._EnabledUnits) + _mesa_write_texture_span(ctx, span); + else + _mesa_write_rgba_span(ctx, span); #elif FLAGS & RGBA - /* rgba size 1 point */ - alpha = vert->color[3]; - PB_WRITE_RGBA_PIXEL(PB, x, y, z, vert->fog, red, green, blue, alpha); + _mesa_write_rgba_span(ctx, span); #else - /* color index size 1 point */ - PB_WRITE_CI_PIXEL(PB, x, y, z, vert->fog, index); + _mesa_write_index_span(ctx, span); #endif - } + span->end = 0; + } + + count = span->end; + +#if FLAGS & RGBA + span->array->rgba[count][RCOMP] = red; + span->array->rgba[count][GCOMP] = green; + span->array->rgba[count][BCOMP] = blue; + span->array->rgba[count][ACOMP] = alpha; +#endif +#if FLAGS & SPECULAR + span->array->spec[count][RCOMP] = specRed; + span->array->spec[count][GCOMP] = specGreen; + span->array->spec[count][BCOMP] = specBlue; +#endif +#if FLAGS & INDEX + span->array->index[count] = colorIndex; +#endif +#if FLAGS & TEXTURE + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + COPY_4V(span->array->texcoords[u][count], texcoord[u]); + } + } +#endif + + span->array->x[count] = (GLint) vert->win[0]; + span->array->y[count] = (GLint) vert->win[1]; + span->array->z[count] = (GLint) (vert->win[2] + 0.5F); + span->end = count + 1; + }} + #endif /* LARGE || ATTENUATE || SMOOTH */ - PB_CHECK_FLUSH(ctx, PB); + ASSERT(span->end <= MAX_WIDTH); } diff --git a/xc/extras/Mesa/src/swrast/s_readpix.c b/xc/extras/Mesa/src/swrast/s_readpix.c index 666baa286..672109982 100644 --- a/xc/extras/Mesa/src/swrast/s_readpix.c +++ b/xc/extras/Mesa/src/swrast/s_readpix.c @@ -1,8 +1,7 @@ -/* $Id: s_readpix.c,v 1.1.1.1 2002/10/22 13:06:56 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -32,7 +31,7 @@ #include "feedback.h" #include "image.h" #include "macros.h" -#include "mem.h" +#include "imports.h" #include "pixel.h" #include "s_alphabuf.h" @@ -62,9 +61,7 @@ read_index_pixels( GLcontext *ctx, return; } - ASSERT(swrast->Driver.SetReadBuffer); - (*swrast->Driver.SetReadBuffer)(ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer); + _swrast_use_read_buffer(ctx); readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width; @@ -82,8 +79,7 @@ read_index_pixels( GLcontext *ctx, &ctx->Pack, ctx->_ImageTransferState); } - (*swrast->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer); + _swrast_use_draw_buffer(ctx); } @@ -282,8 +278,15 @@ read_fast_rgba_pixels( GLcontext *ctx, if (0) { #endif GLchan *dest = (GLchan *) pixels - + (skipRows * rowLength + skipPixels) * 4; + + (skipRows * rowLength + skipPixels) * 4; GLint row; + + if (packing->Invert) { + /* start at top and go down */ + dest += (readHeight - 1) * rowLength * 4; + rowLength = -rowLength; + } + for (row=0; row<readHeight; row++) { (*swrast->Driver.ReadRGBASpan)(ctx, readWidth, srcX, srcY, (GLchan (*)[4]) dest); @@ -318,13 +321,13 @@ read_rgba_pixels( GLcontext *ctx, SWcontext *swrast = SWRAST_CONTEXT(ctx); GLint readWidth; - (*swrast->Driver.SetReadBuffer)(ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer); + _swrast_use_read_buffer(ctx); /* Try optimized path first */ if (read_fast_rgba_pixels( ctx, x, y, width, height, format, type, pixels, packing )) { - (*swrast->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer); + _swrast_use_draw_buffer(ctx); return; /* done! */ } @@ -470,7 +473,7 @@ read_rgba_pixels( GLcontext *ctx, } } - (*swrast->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer); + _swrast_use_draw_buffer(ctx); } diff --git a/xc/extras/Mesa/src/swrast/s_scissor.c b/xc/extras/Mesa/src/swrast/s_scissor.c deleted file mode 100644 index 3558b91d0..000000000 --- a/xc/extras/Mesa/src/swrast/s_scissor.c +++ /dev/null @@ -1,64 +0,0 @@ -/* $Id: s_scissor.c,v 1.1.1.1 2002/10/22 13:06:51 alanh Exp $ */ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2001 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 - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#include "glheader.h" -#include "macros.h" -#include "mem.h" -#include "s_context.h" -#include "s_scissor.h" - - -/* - * Apply the scissor test to a span of pixels. - * Return: 0 = all pixels in the span are outside the scissor box. - * n = mask[n-1] is the last one to be visible - */ -GLuint -_mesa_scissor_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte mask[]) -{ - /* first check if whole span is outside the scissor box */ - if (y < ctx->DrawBuffer->_Ymin - || y >= ctx->DrawBuffer->_Ymax - || x > ctx->DrawBuffer->_Xmax - || x + (GLint) n - 1 < ctx->DrawBuffer->_Xmin) { - return 0; - } - else { - const GLint xMin = ctx->DrawBuffer->_Xmin; - const GLint xMax = ctx->DrawBuffer->_Xmax; - - if (x < xMin) - BZERO(mask, (xMin-x) * sizeof(GLubyte)); - - if (x + (GLint) n > xMax) { - BZERO(mask + xMax - x, (n - (xMax - x)) * sizeof(GLubyte)); - return (GLuint) (xMax - x); - } - - return n; - } -} diff --git a/xc/extras/Mesa/src/swrast/s_scissor.h b/xc/extras/Mesa/src/swrast/s_scissor.h deleted file mode 100644 index ec454e4dd..000000000 --- a/xc/extras/Mesa/src/swrast/s_scissor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $Id: s_scissor.h,v 1.1.1.1 2002/10/22 13:06:51 alanh Exp $ */ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2001 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 - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#ifndef S_SCISSOR_H -#define S_SCISSOR_H - - -#include "mtypes.h" -#include "swrast.h" - - -extern GLuint -_mesa_scissor_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte mask[]); - - -#endif diff --git a/xc/extras/Mesa/src/swrast/s_span.c b/xc/extras/Mesa/src/swrast/s_span.c index 375fe6a96..784279c7d 100644 --- a/xc/extras/Mesa/src/swrast/s_span.c +++ b/xc/extras/Mesa/src/swrast/s_span.c @@ -1,8 +1,7 @@ -/* $Id: s_span.c,v 1.1.1.1 2002/10/22 13:06:57 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 5.0.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -25,16 +24,19 @@ */ -/* - * pixel span rasterization: - * These functions implement the rasterization pipeline. +/** + * \file swrast/s_span.c + * \brief Span processing functions used by all rasterization functions. + * This is where all the per-fragment tests are performed + * \author Brian Paul */ - #include "glheader.h" #include "colormac.h" +#include "context.h" #include "macros.h" -#include "mem.h" +#include "mmath.h" +#include "imports.h" #include "s_alpha.h" #include "s_alphabuf.h" @@ -44,743 +46,1050 @@ #include "s_fog.h" #include "s_logic.h" #include "s_masking.h" -#include "s_scissor.h" #include "s_span.h" #include "s_stencil.h" #include "s_texture.h" +/** + * Init span's Z interpolation values to the RasterPos Z. + * Used during setup for glDraw/CopyPixels. + */ +void +_mesa_span_default_z( GLcontext *ctx, struct sw_span *span ) +{ + if (ctx->Visual.depthBits <= 16) + span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F); + else + span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F); + span->zStep = 0; + span->interpMask |= SPAN_Z; +} -/* - * Apply the current polygon stipple pattern to a span of pixels. + +/** + * Init span's fog interpolation values to the RasterPos fog. + * Used during setup for glDraw/CopyPixels. */ -static void -stipple_polygon_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - GLubyte mask[] ) +void +_mesa_span_default_fog( GLcontext *ctx, struct sw_span *span ) { - const GLuint highbit = 0x80000000; - GLuint i, m, stipple; + span->fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance); + span->fogStep = 0; + span->interpMask |= SPAN_FOG; +} - stipple = ctx->PolygonStipple[y % 32]; - m = highbit >> (GLuint) (x % 32); - for (i = 0; i < n; i++) { - if ((m & stipple) == 0) { - mask[i] = 0; - } - m = m >> 1; - if (m == 0) { - m = highbit; - } +/** + * Init span's color or index interpolation values to the RasterPos color. + * Used during setup for glDraw/CopyPixels. + */ +void +_mesa_span_default_color( GLcontext *ctx, struct sw_span *span ) +{ + if (ctx->Visual.rgbMode) { + GLchan r, g, b, a; + UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]); + UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]); + UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]); + UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]); +#if CHAN_TYPE == GL_FLOAT + span->red = r; + span->green = g; + span->blue = b; + span->alpha = a; +#else + span->red = IntToFixed(r); + span->green = IntToFixed(g); + span->blue = IntToFixed(b); + span->alpha = IntToFixed(a); +#endif + span->redStep = 0; + span->greenStep = 0; + span->blueStep = 0; + span->alphaStep = 0; + span->interpMask |= SPAN_RGBA; + } + else { + span->index = IntToFixed(ctx->Current.RasterIndex); + span->indexStep = 0; + span->interpMask |= SPAN_INDEX; } } - -/* - * Clip a pixel span to the current buffer/window boundaries. - * Return: 'n' such that pixel 'n', 'n+1' etc. are clipped, - * as a special case: - * 0 = all pixels clipped +/** + * Init span's texcoord interpolation values to the RasterPos texcoords. + * Used during setup for glDraw/CopyPixels. */ -static GLuint -clip_span( GLcontext *ctx, GLint n, GLint x, GLint y, GLubyte mask[] ) +void +_mesa_span_default_texcoords( GLcontext *ctx, struct sw_span *span ) { - /* Clip to top and bottom */ - if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height) { - return 0; + GLuint i; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + COPY_4V(span->tex[i], ctx->Current.RasterTexCoords[i]); + 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); } + span->interpMask |= SPAN_TEXTURE; +} + + +/* Fill in the span.color.rgba array from the interpolation values */ +static void +interpolate_colors(GLcontext *ctx, struct sw_span *span) +{ + GLfixed r = span->red; + GLfixed g = span->green; + GLfixed b = span->blue; + GLfixed a = span->alpha; + const GLint dr = span->redStep; + const GLint dg = span->greenStep; + const GLint db = span->blueStep; + const GLint da = span->alphaStep; + const GLuint n = span->end; + GLchan (*rgba)[4] = span->array->rgba; + GLuint i; - /* Clip to the left */ - if (x < 0) { - if (x + n <= 0) { - /* completely off left side */ - return 0; + ASSERT((span->interpMask & SPAN_RGBA) && + !(span->arrayMask & SPAN_RGBA)); + + if (span->interpMask & SPAN_FLAT) { + /* constant color */ + GLchan color[4]; + color[RCOMP] = FixedToChan(r); + color[GCOMP] = FixedToChan(g); + color[BCOMP] = FixedToChan(b); + color[ACOMP] = FixedToChan(a); + for (i = 0; i < n; i++) { + COPY_CHAN4(span->array->rgba[i], color); } - else { - /* partially off left side */ - BZERO(mask, -x * sizeof(GLubyte)); + } + else { + /* interpolate */ + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = FixedToChan(r); + rgba[i][GCOMP] = FixedToChan(g); + rgba[i][BCOMP] = FixedToChan(b); + rgba[i][ACOMP] = FixedToChan(a); + r += dr; + g += dg; + b += db; + a += da; } } + span->arrayMask |= SPAN_RGBA; +} + - /* Clip to right */ - if (x + n > (GLint) ctx->DrawBuffer->Width) { - if (x >= (GLint) ctx->DrawBuffer->Width) { - /* completely off right side */ - return 0; +/* Fill in the span.color.index array from the interpolation values */ +static void +interpolate_indexes(GLcontext *ctx, struct sw_span *span) +{ + GLfixed index = span->index; + const GLint indexStep = span->indexStep; + const GLuint n = span->end; + GLuint *indexes = span->array->index; + GLuint i; + ASSERT((span->interpMask & SPAN_INDEX) && + !(span->arrayMask & SPAN_INDEX)); + + if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) { + /* constant color */ + index = FixedToInt(index); + for (i = 0; i < n; i++) { + indexes[i] = index; } - else { - /* partially off right side */ - return ctx->DrawBuffer->Width - x; + } + else { + /* interpolate */ + for (i = 0; i < n; i++) { + indexes[i] = FixedToInt(index); + index += indexStep; } } - - return n; + span->arrayMask |= SPAN_INDEX; } - -/* - * Draw to more than one color buffer (or none). - */ +/* Fill in the span.->array->spec array from the interpolation values */ static void -multi_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLuint indexes[], const GLubyte mask[] ) +interpolate_specular(GLcontext *ctx, struct sw_span *span) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLuint bufferBit; + if (span->interpMask & SPAN_FLAT) { + /* constant color */ + 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->end; i++) { + span->array->spec[i][RCOMP] = r; + span->array->spec[i][GCOMP] = g; + span->array->spec[i][BCOMP] = b; + } + } + else { + /* interpolate */ +#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->end; i++) { + span->array->spec[i][RCOMP] = FixedToChan(r); + span->array->spec[i][GCOMP] = FixedToChan(g); + span->array->spec[i][BCOMP] = FixedToChan(b); + r += span->specRedStep; + g += span->specGreenStep; + b += span->specBlueStep; + } + } + span->arrayMask |= SPAN_SPEC; +} - if (ctx->Color.DrawBuffer == GL_NONE) - return; - /* loop over four possible dest color buffers */ - for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) { - if (bufferBit & ctx->Color.DrawDestMask) { - GLuint indexTmp[MAX_WIDTH]; - ASSERT(n < MAX_WIDTH); +/* Fill in the span.zArray array from the interpolation values */ +void +_mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span ) +{ + const GLuint n = span->end; + GLuint i; - if (bufferBit == FRONT_LEFT_BIT) - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT); - else if (bufferBit == FRONT_RIGHT_BIT) - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT); - else if (bufferBit == BACK_LEFT_BIT) - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT); - else - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT); + ASSERT((span->interpMask & SPAN_Z) && + !(span->arrayMask & SPAN_Z)); - /* make copy of incoming indexes */ - MEMCPY( indexTmp, indexes, n * sizeof(GLuint) ); - if (ctx->Color.IndexLogicOpEnabled) { - _mesa_logicop_ci_span( ctx, n, x, y, indexTmp, mask ); - } - if (ctx->Color.IndexMask == 0) { - break; - } - else if (ctx->Color.IndexMask != 0xffffffff) { - _mesa_mask_index_span( ctx, n, x, y, indexTmp ); - } - (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, indexTmp, mask ); + if (ctx->Visual.depthBits <= 16) { + GLfixed zval = span->z; + GLdepth *z = span->array->z; + for (i = 0; i < n; i++) { + z[i] = FixedToInt(zval); + zval += span->zStep; } } - - /* restore default dest buffer */ - (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer); + else { + /* Deep Z buffer, no fixed->int shift */ + GLfixed zval = span->z; + GLdepth *z = span->array->z; + for (i = 0; i < n; i++) { + z[i] = zval; + zval += span->zStep; + } + } + span->arrayMask |= SPAN_Z; } - /* - * Write a horizontal span of color index pixels to the frame buffer. - * Stenciling, Depth-testing, etc. are done as needed. - * Input: n - number of pixels in the span - * x, y - location of leftmost pixel in the span - * z - array of [n] z-values - * fog - array of fog factor values in [0,1] - * index - array of [n] color indexes - * primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP + * This the ideal solution, as given in the OpenGL spec. */ -void -_mesa_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - GLuint indexIn[], const GLint coverage[], - GLenum primitive ) +#if 0 +static GLfloat +compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, + GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, + GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) { - const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT | LOGIC_OP_BIT; - GLubyte mask[MAX_WIDTH]; - GLuint indexBackup[MAX_WIDTH]; - GLuint *index; /* points to indexIn or indexBackup */ - SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); + GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); + GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); + GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); + GLfloat x = sqrt(dudx * dudx + dvdx * dvdx); + GLfloat y = sqrt(dudy * dudy + dvdy * dvdy); + GLfloat rho = MAX2(x, y); + GLfloat lambda = LOG2(rho); + return lambda; +} +#endif - /* init mask to 1's (all pixels are to be written) */ - MEMSET(mask, 1, n); - if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { - if ((n = clip_span(ctx,n,x,y,mask)) == 0) { - return; - } - } +/* + * This is a faster approximation + */ +static GLfloat +compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, + GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, + GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) +{ + GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ; + GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ; + GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ; + GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ; + GLfloat maxU, maxV, rho, lambda; + dsdx2 = FABSF(dsdx2); + dsdy2 = FABSF(dsdy2); + dtdx2 = FABSF(dtdx2); + dtdy2 = FABSF(dtdy2); + maxU = MAX2(dsdx2, dsdy2) * texW; + maxV = MAX2(dtdx2, dtdy2) * texH; + rho = MAX2(maxU, maxV); + lambda = LOG2(rho); + return lambda; +} - if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits)) - || (swrast->_RasterMask & MULTI_DRAW_BIT)) { - /* Make copy of color indexes */ - MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) ); - index = indexBackup; +/* + * 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. + */ +static void +interpolate_texcoords(GLcontext *ctx, struct sw_span *span) +{ + ASSERT(span->interpMask & SPAN_TEXTURE); + ASSERT(!(span->arrayMask & SPAN_TEXTURE)); + + if (ctx->Texture._EnabledUnits > 1) { + /* multitexture */ + GLuint u; + span->arrayMask |= SPAN_TEXTURE; + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + if (ctx->Texture.Unit[u]._ReallyEnabled) { + const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current; + const struct gl_texture_image *img = obj->Image[obj->BaseLevel]; + GLboolean needLambda = (obj->MinFilter != obj->MagFilter); + if (needLambda) { + GLfloat (*texcoord)[4] = span->array->texcoords[u]; + GLfloat *lambda = span->array->lambda[u]; + const GLfloat texW = (GLfloat) img->WidthScale; + const GLfloat texH = (GLfloat) img->HeightScale; + const GLfloat dsdx = span->texStepX[u][0]; + const GLfloat dsdy = span->texStepY[u][0]; + const GLfloat dtdx = span->texStepX[u][1]; + const GLfloat dtdy = span->texStepY[u][1]; + const GLfloat drdx = span->texStepX[u][2]; + const GLfloat dqdx = span->texStepX[u][3]; + const GLfloat dqdy = span->texStepY[u][3]; + 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->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; + lambda[i] = 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; + } + else { + GLfloat (*texcoord)[4] = span->array->texcoords[u]; + GLfloat *lambda = span->array->lambda[u]; + const GLfloat dsdx = span->texStepX[u][0]; + const GLfloat dtdx = span->texStepX[u][1]; + const GLfloat drdx = span->texStepX[u][2]; + const GLfloat dqdx = span->texStepX[u][3]; + 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; + if (dqdx == 0.0) { + /* 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++) { + texcoord[i][0] = s * invQ; + texcoord[i][1] = t * invQ; + texcoord[i][2] = r * invQ; + lambda[i] = 0.0; + s += dsdx; + t += dtdx; + r += drdx; + } + } + 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; + lambda[i] = 0.0; + s += dsdx; + t += dtdx; + r += drdx; + q += dqdx; + } + } + } /* lambda */ + } /* if */ + } /* for */ } else { - index = indexIn; - } - - - /* Do the scissor test */ - if (ctx->Scissor.Enabled) { - if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) { - return; + /* single texture */ + const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; + const struct gl_texture_image *img = obj->Image[obj->BaseLevel]; + GLboolean needLambda = (obj->MinFilter != obj->MagFilter); + span->arrayMask |= SPAN_TEXTURE; + if (needLambda) { + /* just texture unit 0, with lambda */ + GLfloat (*texcoord)[4] = span->array->texcoords[0]; + GLfloat *lambda = span->array->lambda[0]; + const GLfloat texW = (GLfloat) img->WidthScale; + const GLfloat texH = (GLfloat) img->HeightScale; + const GLfloat dsdx = span->texStepX[0][0]; + const GLfloat dsdy = span->texStepY[0][0]; + const GLfloat dtdx = span->texStepX[0][1]; + const GLfloat dtdy = span->texStepY[0][1]; + const GLfloat drdx = span->texStepX[0][2]; + const GLfloat dqdx = span->texStepX[0][3]; + const GLfloat dqdy = span->texStepY[0][3]; + 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->end; i++) { + const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); + lambda[i] = 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; + s += dsdx; + t += dtdx; + r += drdx; + q += dqdx; + } + span->arrayMask |= SPAN_LAMBDA; } - } - - /* Polygon Stippling */ - if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { - stipple_polygon_span( ctx, n, x, y, mask ); - } - - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) { - return; + else { + /* just texture 0, without lambda */ + GLfloat (*texcoord)[4] = span->array->texcoords[0]; + const GLfloat dsdx = span->texStepX[0][0]; + const GLfloat dtdx = span->texStepX[0][1]; + const GLfloat drdx = span->texStepX[0][2]; + const GLfloat dqdx = span->texStepX[0][3]; + 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; + if (dqdx == 0.0) { + /* 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++) { + texcoord[i][0] = s * invQ; + texcoord[i][1] = t * invQ; + texcoord[i][2] = r * invQ; + s += dsdx; + t += dtdx; + r += drdx; + } + } + 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; + s += dsdx; + t += dtdx; + r += drdx; + q += dqdx; + } + } } } - else if (ctx->Depth.Test) { - /* regular depth testing */ - if (_mesa_depth_test_span( ctx, n, x, y, z, mask ) == 0) - return; - } +} - /* if we get here, something passed the depth test */ - ctx->OcclusionResult = GL_TRUE; - /* Per-pixel fog */ - if (ctx->Fog.Enabled) { - if (fog && !swrast->_PreferPixelFog) - _mesa_fog_ci_pixels( ctx, n, fog, index ); - else - _mesa_depth_fog_ci_pixels( ctx, n, z, index ); - } +/** + * Apply the current polygon stipple pattern to a span of pixels. + */ +static void +stipple_polygon_span( GLcontext *ctx, struct sw_span *span ) +{ + const GLuint highbit = 0x80000000; + const GLuint stipple = ctx->PolygonStipple[span->y % 32]; + GLubyte *mask = span->array->mask; + GLuint i, m; - /* Antialias coverage application */ - if (coverage) { - GLuint i; - for (i = 0; i < n; i++) { - ASSERT(coverage[i] < 16); - index[i] = (index[i] & ~0xf) | coverage[i]; - } - } + ASSERT(ctx->Polygon.StippleFlag); + ASSERT((span->arrayMask & SPAN_XY) == 0); - if (swrast->_RasterMask & MULTI_DRAW_BIT) { - /* draw to zero or two or more buffers */ - multi_write_index_span( ctx, n, x, y, index, mask ); - } - else { - /* normal situation: draw to exactly one buffer */ - if (ctx->Color.IndexLogicOpEnabled) { - _mesa_logicop_ci_span( ctx, n, x, y, index, mask ); - } + m = highbit >> (GLuint) (span->x % 32); - if (ctx->Color.IndexMask == 0) { - return; + for (i = 0; i < span->end; i++) { + if ((m & stipple) == 0) { + mask[i] = 0; } - else if (ctx->Color.IndexMask != 0xffffffff) { - _mesa_mask_index_span( ctx, n, x, y, index ); + m = m >> 1; + if (m == 0) { + m = highbit; } - - /* write pixels */ - (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, index, mask ); } + span->writeAll = GL_FALSE; } - - -void -_mesa_write_monoindex_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - GLuint index, const GLint coverage[], - GLenum primitive ) +/** + * Clip a pixel span to the current buffer/window boundaries: + * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish + * window clipping and scissoring. + * Return: GL_TRUE some pixels still visible + * GL_FALSE nothing visible + */ +static GLuint +clip_span( GLcontext *ctx, struct sw_span *span ) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLubyte mask[MAX_WIDTH]; - GLuint i; - - /* init mask to 1's (all pixels are to be written) */ - MEMSET(mask, 1, n); - - if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { - if ((n = clip_span( ctx, n, x, y, mask)) == 0) { - return; + const GLint xmin = ctx->DrawBuffer->_Xmin; + const GLint xmax = ctx->DrawBuffer->_Xmax; + const GLint ymin = ctx->DrawBuffer->_Ymin; + const GLint ymax = ctx->DrawBuffer->_Ymax; + + if (span->arrayMask & SPAN_XY) { + /* arrays of x/y pixel coords */ + const GLint *x = span->array->x; + const GLint *y = span->array->y; + const GLint n = span->end; + GLubyte *mask = span->array->mask; + GLint i; + if (span->arrayMask & SPAN_MASK) { + /* note: using & intead of && to reduce branches */ + for (i = 0; i < n; i++) { + mask[i] &= (x[i] >= xmin) & (x[i] < xmax) + & (y[i] >= ymin) & (y[i] < ymax); + } + } + else { + /* note: using & intead of && to reduce branches */ + for (i = 0; i < n; i++) { + mask[i] = (x[i] >= xmin) & (x[i] < xmax) + & (y[i] >= ymin) & (y[i] < ymax); + } } + return GL_TRUE; /* some pixels visible */ } + else { + /* horizontal span of pixels */ + const GLint x = span->x; + const GLint y = span->y; + const GLint n = span->end; - /* Do the scissor test */ - if (ctx->Scissor.Enabled) { - if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) { - return; + /* Trivial rejection tests */ + if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) { + span->end = 0; + return GL_FALSE; /* all pixels clipped */ } - } - /* Polygon Stippling */ - if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { - stipple_polygon_span( ctx, n, x, y, mask ); - } + /* Clip to the left */ + if (x < xmin) { + ASSERT(x + n > xmin); + span->writeAll = GL_FALSE; + _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte)); + } - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) { - return; + /* Clip to right */ + if (x + n > xmax) { + ASSERT(x < xmax); + span->end = xmax - x; } + + return GL_TRUE; /* some pixels visible */ } - else if (ctx->Depth.Test) { - /* regular depth testing */ - if (_mesa_depth_test_span( ctx, n, x, y, z, mask ) == 0) - return; - } +} - /* if we get here, something passed the depth test */ - ctx->OcclusionResult = GL_TRUE; - if (ctx->Color.DrawBuffer == GL_NONE) { - /* write no pixels */ - return; - } - if (ctx->Fog.Enabled - || ctx->Color.IndexLogicOpEnabled - || ctx->Color.IndexMask != 0xffffffff - || coverage) { - /* different index per pixel */ - GLuint indexes[MAX_WIDTH]; - for (i = 0; i < n; i++) { - indexes[i] = index; - } +/** + * Draw to more than one color buffer (or none). + */ +static void +multi_write_index_span( GLcontext *ctx, struct sw_span *span ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint bufferBit; - if (ctx->Fog.Enabled) { - if (fog && !swrast->_PreferPixelFog) - _mesa_fog_ci_pixels( ctx, n, fog, indexes ); - else - _mesa_depth_fog_ci_pixels( ctx, n, z, indexes ); - } + /* loop over four possible dest color buffers */ + for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) { + if (bufferBit & ctx->Color._DrawDestMask) { + GLuint indexTmp[MAX_WIDTH]; + ASSERT(span->end < MAX_WIDTH); - /* Antialias coverage application */ - if (coverage) { - GLuint i; - for (i = 0; i < n; i++) { - ASSERT(coverage[i] < 16); - indexes[i] = (indexes[i] & ~0xf) | coverage[i]; - } - } + /* Set the current read/draw buffer */ + swrast->CurrentBuffer = bufferBit; + (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); + + /* make copy of incoming indexes */ + MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) ); - if (swrast->_RasterMask & MULTI_DRAW_BIT) { - /* draw to zero or two or more buffers */ - multi_write_index_span( ctx, n, x, y, indexes, mask ); - } - else { - /* normal situation: draw to exactly one buffer */ if (ctx->Color.IndexLogicOpEnabled) { - _mesa_logicop_ci_span( ctx, n, x, y, indexes, mask ); + _mesa_logicop_ci_span(ctx, span, indexTmp); } - if (ctx->Color.IndexMask == 0) { - return; + + if (ctx->Color.IndexMask != 0xffffffff) { + _mesa_mask_index_span(ctx, span, indexTmp); } - else if (ctx->Color.IndexMask != 0xffffffff) { - _mesa_mask_index_span( ctx, n, x, y, indexes ); + + if (span->arrayMask & SPAN_XY) { + /* array of pixel coords */ + (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, + span->array->x, span->array->y, + indexTmp, span->array->mask); + } + else { + /* horizontal run of pixels */ + (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y, + indexTmp, span->array->mask); } - (*swrast->Driver.WriteCI32Span)( ctx, n, x, y, indexes, mask ); - } - } - else { - /* same color index for all pixels */ - ASSERT(!ctx->Color.IndexLogicOpEnabled); - ASSERT(ctx->Color.IndexMask == 0xffffffff); - if (swrast->_RasterMask & MULTI_DRAW_BIT) { - /* draw to zero or two or more buffers */ - GLuint indexes[MAX_WIDTH]; - for (i = 0; i < n; i++) - indexes[i] = index; - multi_write_index_span( ctx, n, x, y, indexes, mask ); - } - else { - /* normal situation: draw to exactly one buffer */ - (*swrast->Driver.WriteMonoCISpan)( ctx, n, x, y, index, mask ); } } -} + /* restore default dest buffer */ + _swrast_use_draw_buffer(ctx); +} -/* +/** * Draw to more than one RGBA color buffer (or none). + * All fragment operations, up to (but not) blending/logicop should + * have been done first. */ static void -multi_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - CONST GLchan rgba[][4], const GLubyte mask[] ) +multi_write_rgba_span( GLcontext *ctx, struct sw_span *span ) { const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); GLuint bufferBit; SWcontext *swrast = SWRAST_CONTEXT(ctx); + ASSERT(colorMask != 0x0); + if (ctx->Color.DrawBuffer == GL_NONE) return; /* loop over four possible dest color buffers */ - for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) { - if (bufferBit & ctx->Color.DrawDestMask) { + for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) { + if (bufferBit & ctx->Color._DrawDestMask) { GLchan rgbaTmp[MAX_WIDTH][4]; - ASSERT(n < MAX_WIDTH); + ASSERT(span->end < MAX_WIDTH); - if (bufferBit == FRONT_LEFT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha; - } - else if (bufferBit == FRONT_RIGHT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha; - } - else if (bufferBit == BACK_LEFT_BIT) { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha; - } - else { - (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT); - ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha; - } + /* Set the current read/draw buffer */ + swrast->CurrentBuffer = bufferBit; + (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); /* make copy of incoming colors */ - MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLchan) ); + MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) ); if (ctx->Color.ColorLogicOpEnabled) { - _mesa_logicop_rgba_span( ctx, n, x, y, rgbaTmp, mask ); + _mesa_logicop_rgba_span(ctx, span, rgbaTmp); } else if (ctx->Color.BlendEnabled) { - _mesa_blend_span( ctx, n, x, y, rgbaTmp, mask ); + _mesa_blend_span(ctx, span, rgbaTmp); } - if (colorMask == 0x0) { - break; - } - else if (colorMask != 0xffffffff) { - _mesa_mask_rgba_span( ctx, n, x, y, rgbaTmp ); + + if (colorMask != 0xffffffff) { + _mesa_mask_rgba_span(ctx, span, rgbaTmp); } - (*swrast->Driver.WriteRGBASpan)( ctx, n, x, y, - (const GLchan (*)[4]) rgbaTmp, mask ); - if (swrast->_RasterMask & ALPHABUF_BIT) { - _mesa_write_alpha_span( ctx, n, x, y, - (const GLchan (*)[4])rgbaTmp, mask ); + if (span->arrayMask & SPAN_XY) { + /* array of pixel coords */ + (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, + span->array->x, span->array->y, + (const GLchan (*)[4]) rgbaTmp, + span->array->mask); + if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { + _mesa_write_alpha_pixels(ctx, span->end, + span->array->x, span->array->y, + (const GLchan (*)[4]) rgbaTmp, + span->array->mask); + } + } + else { + /* horizontal run of pixels */ + (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y, + (const GLchan (*)[4]) rgbaTmp, + span->array->mask); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_write_alpha_span(ctx, span->end, span->x, span->y, + (const GLchan (*)[4]) rgbaTmp, + span->array->mask); + } } } } /* restore default dest buffer */ - (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer ); + _swrast_use_draw_buffer(ctx); } -/* - * Apply fragment processing to a span of RGBA fragments. - * Input: - * n - number of fragments in the span - * x,y - location of first (left) fragment - * fog - array of fog factor values in [0,1] +/** + * This function may modify any of the array values in the span. + * span->interpMask and span->arrayMask may be changed but will be restored + * to their original values before returning. */ void -_mesa_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - GLchan rgbaIn[][4], const GLfloat coverage[], - GLenum primitive ) +_mesa_write_index_span( GLcontext *ctx, struct sw_span *span) { - const GLuint modBits = FOG_BIT | BLEND_BIT | MASKING_BIT | - LOGIC_OP_BIT | TEXTURE_BIT; - GLubyte mask[MAX_WIDTH]; - GLboolean write_all = GL_TRUE; - GLchan rgbaBackup[MAX_WIDTH][4]; - GLchan (*rgba)[4]; - const GLubyte *Null = 0; SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint origInterpMask = span->interpMask; + const GLuint origArrayMask = span->arrayMask; - /* init mask to 1's (all pixels are to be written) */ - MEMSET(mask, 1, n); + ASSERT(span->end <= MAX_WIDTH); + ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || + span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); + ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX); + ASSERT((span->interpMask & span->arrayMask) == 0); - if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { - if ((n = clip_span( ctx,n,x,y,mask)) == 0) { - return; - } - if (mask[0] == 0) - write_all = GL_FALSE; - } - - if ((primitive==GL_BITMAP && (swrast->_RasterMask & modBits)) - || (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; + if (span->arrayMask & SPAN_MASK) { + /* mask was initialized by caller, probably glBitmap */ + span->writeAll = GL_FALSE; } else { - rgba = rgbaIn; + MEMSET(span->array->mask, 1, span->end); + span->writeAll = GL_TRUE; } - /* Do the scissor test */ - if (ctx->Scissor.Enabled) { - if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) { + /* Clipping */ + if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { + if (!clip_span(ctx, span)) { return; } - if (mask[0] == 0) - write_all = GL_FALSE; - } - - /* Polygon Stippling */ - if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { - stipple_polygon_span( ctx, n, x, y, mask ); - write_all = GL_FALSE; } - /* Do the alpha test */ - if (ctx->Color.AlphaEnabled) { - if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) { - return; +#ifdef DEBUG + if (span->arrayMask & SPAN_XY) { + GLuint i; + for (i = 0; i < span->end; i++) { + if (span->array->mask[i]) { + assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); + assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); + assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); + assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); + } } - write_all = GL_FALSE; } +#endif - 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; + /* Polygon Stippling */ + if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { + stipple_polygon_span(ctx, span); } - else if (ctx->Depth.Test) { - /* regular depth testing */ - GLuint m = _mesa_depth_test_span( ctx, n, x, y, z, mask ); - if (m == 0) { - return; + + /* Depth test and stencil */ + if (ctx->Depth.Test || ctx->Stencil.Enabled) { + if (span->interpMask & SPAN_Z) + _mesa_span_interpolate_z(ctx, span); + + if (ctx->Stencil.Enabled) { + if (!_mesa_stencil_and_ztest_span(ctx, span)) { + span->arrayMask = origArrayMask; + return; + } } - if (m < n) { - write_all = GL_FALSE; + else { + ASSERT(ctx->Depth.Test); + if (!_mesa_depth_test_span(ctx, span)) { + span->arrayMask = origArrayMask; + return; + } } } /* if we get here, something passed the depth test */ ctx->OcclusionResult = GL_TRUE; - /* Per-pixel fog */ + /* we have to wait until after occlusion to do this test */ + if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) { + /* write no pixels */ + span->arrayMask = origArrayMask; + return; + } + + /* Interpolate the color indexes if needed */ + if (span->interpMask & SPAN_INDEX) { + interpolate_indexes(ctx, span); + /* clear the bit - this allows the WriteMonoCISpan optimization below */ + span->interpMask &= ~SPAN_INDEX; + } + + /* 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 ); + _mesa_fog_ci_span(ctx, span); } /* Antialias coverage application */ - if (coverage) { + if (span->arrayMask & SPAN_COVERAGE) { GLuint i; - for (i = 0; i < n; i++) { - rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); + GLuint *index = span->array->index; + GLfloat *coverage = span->array->coverage; + for (i = 0; i < span->end; i++) { + ASSERT(coverage[i] < 16); + index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]); } } if (swrast->_RasterMask & MULTI_DRAW_BIT) { - multi_write_rgba_span( ctx, n, x, y, (const GLchan (*)[4]) rgba, mask ); + /* draw to zero or two or more buffers */ + multi_write_index_span(ctx, span); } else { - /* normal: write to exactly one buffer */ - /* logic op or blending */ - 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 ); + /* normal situation: draw to exactly one buffer */ + if (ctx->Color.IndexLogicOpEnabled) { + _mesa_logicop_ci_span(ctx, span, span->array->index); } - /* Color component masking */ - if (colorMask == 0x0) { - return; - } - else if (colorMask != 0xffffffff) { - _mesa_mask_rgba_span( ctx, n, x, y, rgba ); + if (ctx->Color.IndexMask != 0xffffffff) { + _mesa_mask_index_span(ctx, span, span->array->index); } /* write pixels */ - (*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 ); + if (span->arrayMask & SPAN_XY) { + /* array of pixel coords */ + if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) { + /* all pixels have same color index */ + (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end, + span->array->x, span->array->y, + FixedToInt(span->index), + span->array->mask); + } + else { + (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x, + span->array->y, span->array->index, + span->array->mask ); + } + } + else { + /* horizontal run of pixels */ + if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) { + /* all pixels have same color index */ + (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y, + FixedToInt(span->index), + span->array->mask); + } + else { + (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y, + span->array->index, + span->array->mask); + } } } -} + span->interpMask = origInterpMask; + span->arrayMask = origArrayMask; +} -/* - * Write a horizontal span of color pixels to the frame buffer. - * The color is initially constant for the whole span. - * Alpha-testing, stenciling, depth-testing, and blending are done as needed. - * Input: n - number of pixels in the span - * x, y - location of leftmost pixel in the span - * z - array of [n] z-values - * fog - array of fog factor values in [0,1] - * r, g, b, a - the color of the pixels - * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP. +/** + * This function may modify any of the array values in the span. + * span->interpMask and span->arrayMask may be changed but will be restored + * to their original values before returning. */ void -_mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - const GLchan color[4], const GLfloat coverage[], - GLenum primitive ) +_mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span) { - const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); - GLuint i; - GLubyte mask[MAX_WIDTH]; - GLboolean write_all = GL_TRUE; - GLchan rgba[MAX_WIDTH][4]; - const GLubyte *Null = 0; SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); + const GLuint origInterpMask = span->interpMask; + const GLuint origArrayMask = span->arrayMask; + GLboolean monoColor; + + ASSERT(span->end <= MAX_WIDTH); + ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || + span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); + ASSERT((span->interpMask & span->arrayMask) == 0); + ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA); +#ifdef DEBUG + if (ctx->Fog.Enabled) + ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); + if (ctx->Depth.Test) + ASSERT((span->interpMask | span->arrayMask) & SPAN_Z); +#endif - /* init mask to 1's (all pixels are to be written) */ - MEMSET(mask, 1, n); + if (span->arrayMask & SPAN_MASK) { + /* mask was initialized by caller, probably glBitmap */ + span->writeAll = GL_FALSE; + } + else { + MEMSET(span->array->mask, 1, span->end); + span->writeAll = GL_TRUE; + } - if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { - if ((n = clip_span( ctx,n,x,y,mask)) == 0) { - return; + /* Determine if we have mono-chromatic colors */ + monoColor = (span->interpMask & SPAN_RGBA) && + span->redStep == 0 && span->greenStep == 0 && + span->blueStep == 0 && span->alphaStep == 0; + + /* Clipping */ + if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { + if (!clip_span(ctx, span)) { + return; } - if (mask[0] == 0) - write_all = GL_FALSE; } - /* Do the scissor test */ - if (ctx->Scissor.Enabled) { - if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) { - return; +#ifdef DEBUG + if (span->arrayMask & SPAN_XY) { + GLuint i; + for (i = 0; i < span->end; i++) { + if (span->array->mask[i]) { + assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); + assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); + assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); + assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); + } } - if (mask[0] == 0) - write_all = GL_FALSE; } +#endif /* Polygon Stippling */ - if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { - stipple_polygon_span( ctx, n, x, y, mask ); - write_all = GL_FALSE; + if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { + stipple_polygon_span(ctx, span); } /* Do the alpha test */ if (ctx->Color.AlphaEnabled) { - for (i = 0; i < n; i++) { - rgba[i][ACOMP] = color[ACOMP]; - } - if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) { + if (!_mesa_alpha_test(ctx, span)) { + span->interpMask = origInterpMask; + span->arrayMask = origArrayMask; return; } - write_all = GL_FALSE; } - 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; + /* Stencil and Z testing */ + if (ctx->Stencil.Enabled || ctx->Depth.Test) { + if (span->interpMask & SPAN_Z) + _mesa_span_interpolate_z(ctx, span); + + if (ctx->Stencil.Enabled) { + if (!_mesa_stencil_and_ztest_span(ctx, span)) { + span->interpMask = origInterpMask; + span->arrayMask = origArrayMask; + return; + } } - if (m < n) { - write_all = GL_FALSE; + else { + ASSERT(ctx->Depth.Test); + ASSERT(span->arrayMask & SPAN_Z); + /* regular depth testing */ + if (!_mesa_depth_test_span(ctx, span)) { + span->interpMask = origInterpMask; + span->arrayMask = origArrayMask; + return; + } } } /* if we get here, something passed the depth test */ ctx->OcclusionResult = GL_TRUE; - if (ctx->Color.DrawBuffer == GL_NONE) { - /* write no pixels */ + /* can't abort span-writing until after occlusion testing */ + if (colorMask == 0x0) { + span->interpMask = origInterpMask; + span->arrayMask = origArrayMask; return; } - if (ctx->Color.ColorLogicOpEnabled || colorMask != 0xffffffff || - (swrast->_RasterMask & (BLEND_BIT | FOG_BIT)) || coverage) { - /* assign same color to each pixel */ - for (i = 0; i < n; i++) { - if (mask[i]) { - COPY_CHAN4(rgba[i], color); - } - } + /* Now we may need to interpolate the colors */ + if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) { + interpolate_colors(ctx, span); + /* clear the bit - this allows the WriteMonoCISpan optimization below */ + span->interpMask &= ~SPAN_RGBA; + } - /* 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 ); - } + /* Fog */ + if (ctx->Fog.Enabled) { + _mesa_fog_rgba_span(ctx, span); + monoColor = GL_FALSE; + } - /* Antialias coverage application */ - if (coverage) { - GLuint i; - for (i = 0; i < n; i++) { - rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); - } + /* Antialias coverage application */ + if (span->arrayMask & SPAN_COVERAGE) { + GLchan (*rgba)[4] = span->array->rgba; + GLfloat *coverage = span->array->coverage; + GLuint i; + for (i = 0; i < span->end; i++) { + rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); } + monoColor = GL_FALSE; + } - if (swrast->_RasterMask & MULTI_DRAW_BIT) { - multi_write_rgba_span( ctx, n, x, y, - (const GLchan (*)[4]) rgba, mask ); + if (swrast->_RasterMask & MULTI_DRAW_BIT) { + multi_write_rgba_span(ctx, span); + } + else { + /* normal: write to exactly one buffer */ + if (ctx->Color.ColorLogicOpEnabled) { + _mesa_logicop_rgba_span(ctx, span, span->array->rgba); + monoColor = GL_FALSE; + } + else if (ctx->Color.BlendEnabled) { + _mesa_blend_span(ctx, span, span->array->rgba); + monoColor = GL_FALSE; } - 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 ); - } - - /* Color component masking */ - if (colorMask == 0x0) { - return; - } - else if (colorMask != 0xffffffff) { - _mesa_mask_rgba_span( ctx, n, x, y, rgba ); - } - /* write pixels */ - (*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 ); - } + /* Color component masking */ + if (colorMask != 0xffffffff) { + _mesa_mask_rgba_span(ctx, span, span->array->rgba); + monoColor = GL_FALSE; } - } - else { - /* same color for all pixels */ - ASSERT(!ctx->Color.BlendEnabled); - ASSERT(!ctx->Color.ColorLogicOpEnabled); - if (swrast->_RasterMask & MULTI_DRAW_BIT) { - for (i = 0; i < n; i++) { - if (mask[i]) { - COPY_CHAN4(rgba[i], color); - } + /* 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) { + _mesa_write_alpha_pixels(ctx, span->end, + span->array->x, span->array->y, + (const GLchan (*)[4]) span->array->rgba, + span->array->mask); } - multi_write_rgba_span( ctx, n, x, y, - (const GLchan (*)[4]) rgba, mask ); } else { - (*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 ); + /* horizontal run of pixels */ + 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.WriteMonoRGBASpan)(ctx, span->end, span->x, + span->y, color, span->array->mask); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_write_mono_alpha_span(ctx, span->end, span->x, span->y, + color[ACOMP], + span->writeAll ? ((const GLubyte *) NULL) : span->array->mask); + } + } + else { + /* each pixel is a different color */ + (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y, + (const GLchan (*)[4]) span->array->rgba, + span->writeAll ? ((const GLubyte *) NULL) : span->array->mask); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_write_alpha_span(ctx, span->end, span->x, span->y, + (const GLchan (*)[4]) span->array->rgba, + span->writeAll ? ((const GLubyte *) NULL) : span->array->mask); + } } } } -} + span->interpMask = origInterpMask; + span->arrayMask = origArrayMask; +} -/* +/** * Add specular color to base color. This is used only when * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR. */ static void -add_colors(GLuint n, GLchan rgba[][4], CONST GLchan specular[][4] ) +add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] ) { GLuint i; for (i = 0; i < n; i++) { @@ -801,330 +1110,205 @@ 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. - * Alpha-testing, stenciling, depth-testing, and blending are done - * as needed. - * Input: n - number of pixels in the span - * x, y - location of leftmost pixel in the span - * z - array of [n] z-values - * fog - array of fog factor values in [0,1] - * s, t - array of (s,t) texture coordinates for each pixel - * lambda - array of texture lambda values - * rgba - array of [n] color components - * primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP. +/** + * This function may modify any of the array values in the span. + * span->interpMask and span->arrayMask may be changed but will be restored + * to their original values before returning. */ 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[], - const GLfloat u[], GLfloat lambda[], - GLchan rgbaIn[][4], CONST GLchan spec[][4], - const GLfloat coverage[], GLenum primitive ) +_mesa_write_texture_span( GLcontext *ctx, struct sw_span *span) { const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); - GLubyte mask[MAX_WIDTH]; - 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); + const GLuint origArrayMask = span->arrayMask; - /* init mask to 1's (all pixels are to be written) */ - MEMSET(mask, 1, n); - - if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { - if ((n=clip_span(ctx, n, x, y, mask)) == 0) { - return; - } - if (mask[0] == 0) - write_all = GL_FALSE; - } + ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || + span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); + ASSERT(span->end <= MAX_WIDTH); + ASSERT((span->interpMask & span->arrayMask) == 0); + ASSERT(ctx->Texture._EnabledUnits); + /* + printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask); + */ - if (primitive==GL_BITMAP || (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; + if (span->arrayMask & SPAN_MASK) { + /* mask was initialized by caller, probably glBitmap */ + span->writeAll = GL_FALSE; } else { - rgba = rgbaIn; - } - - /* Do the scissor test */ - if (ctx->Scissor.Enabled) { - if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) { - return; - } - if (mask[0] == 0) - write_all = GL_FALSE; - } - - /* Polygon Stippling */ - if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { - stipple_polygon_span( ctx, n, x, y, mask ); - write_all = GL_FALSE; + MEMSET(span->array->mask, 1, span->end); + span->writeAll = GL_TRUE; } - /* Texture with alpha test */ - if (ctx->Color.AlphaEnabled) { - /* Texturing without alpha is done after depth-testing which - gives a potential speed-up. */ - ASSERT(ctx->Texture._ReallyEnabled); - _swrast_texture_fragments( ctx, 0, n, s, t, u, lambda, - (CONST GLchan (*)[4]) rgba, rgba ); - - /* Do the alpha test */ - if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4]) rgba, mask ) == 0) { - return; - } - write_all = GL_FALSE; - } - - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) { + /* Clipping */ + if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { + if (!clip_span(ctx, span)) { 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; - - /* Texture without alpha test */ - if (! ctx->Color.AlphaEnabled) { - ASSERT(ctx->Texture._ReallyEnabled); - _swrast_texture_fragments( ctx, 0, n, s, t, u, lambda, - (CONST GLchan (*)[4]) rgba, rgba ); - } - - /* 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) { +#ifdef DEBUG + if (span->arrayMask & SPAN_XY) { 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. - */ -void -_mesa_write_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[], - GLenum primitive ) -{ - GLubyte mask[MAX_WIDTH]; - GLboolean write_all = GL_TRUE; - GLchan rgbaBackup[MAX_WIDTH][4]; - GLchan (*rgba)[4]; /* points to either rgbaIn or rgbaBackup */ - GLuint i; - const GLubyte *Null = 0; - const GLuint texUnits = ctx->Const.MaxTextureUnits; - SWcontext *swrast = SWRAST_CONTEXT(ctx); - - /* init mask to 1's (all pixels are to be written) */ - MEMSET(mask, 1, n); - - if ((swrast->_RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) { - if ((n=clip_span(ctx, n, x, y, mask)) == 0) { - return; - } - if (mask[0] == 0) - write_all = GL_FALSE; - } - - - if (primitive==GL_BITMAP || (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; - } - - /* Do the scissor test */ - if (ctx->Scissor.Enabled) { - if ((n = _mesa_scissor_span( ctx, n, x, y, mask )) == 0) { - return; + for (i = 0; i < span->end; i++) { + if (span->array->mask[i]) { + assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); + assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); + assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); + assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); + } } - if (mask[0] == 0) - write_all = GL_FALSE; } +#endif /* Polygon Stippling */ - if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) { - stipple_polygon_span( ctx, n, x, y, mask ); - write_all = GL_FALSE; + if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { + stipple_polygon_span(ctx, span); } + /* Need texture coordinates now */ + if ((span->interpMask & SPAN_TEXTURE) + && (span->arrayMask & SPAN_TEXTURE) == 0) + interpolate_texcoords(ctx, span); + /* Texture with alpha test */ if (ctx->Color.AlphaEnabled) { + + /* Now we need the rgba array, fill it in if needed */ + if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) + interpolate_colors(ctx, span); + /* Texturing without alpha is done after depth-testing which * gives a potential speed-up. */ - 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 ); + _swrast_texture_span( ctx, span ); /* Do the alpha test */ - if (_mesa_alpha_test( ctx, n, (const GLchan (*)[4])rgba, mask ) == 0) { - return; - } - write_all = GL_FALSE; - } - - if (ctx->Stencil.Enabled) { - /* first stencil test */ - if (_mesa_stencil_and_ztest_span(ctx, n, x, y, z, mask) == GL_FALSE) { + if (!_mesa_alpha_test(ctx, span)) { + span->arrayMask = origArrayMask; 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; + + /* Stencil and Z testing */ + if (ctx->Stencil.Enabled || ctx->Depth.Test) { + if (span->interpMask & SPAN_Z) + _mesa_span_interpolate_z(ctx, span); + + if (ctx->Stencil.Enabled) { + if (!_mesa_stencil_and_ztest_span(ctx, span)) { + span->arrayMask = origArrayMask; + return; + } } - if (m < n) { - write_all = GL_FALSE; + else { + ASSERT(ctx->Depth.Test); + ASSERT(span->arrayMask & SPAN_Z); + /* regular depth testing */ + if (!_mesa_depth_test_span(ctx, span)) { + span->arrayMask = origArrayMask; + return; + } } } - /* if we get here, something passed the depth test */ + /* if we get here, some fragments passed the depth test */ ctx->OcclusionResult = GL_TRUE; + /* We had to wait until now to check for glColorMask(F,F,F,F) because of + * the occlusion test. + */ + if (colorMask == 0x0) { + span->arrayMask = origArrayMask; + return; + } + /* Texture without alpha test */ - if (! ctx->Color.AlphaEnabled) { - 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 ); + if (!ctx->Color.AlphaEnabled) { + + /* Now we need the rgba array, fill it in if needed */ + if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) + interpolate_colors(ctx, span); + + _swrast_texture_span( ctx, span ); } + ASSERT(span->arrayMask & SPAN_RGBA); + /* 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 */ + if (ctx->Fog.ColorSumEnabled || + (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { + if (span->interpMask & SPAN_SPEC) { + interpolate_specular(ctx, span); + } + ASSERT(span->arrayMask & SPAN_SPEC); + add_colors( span->end, span->array->rgba, span->array->spec ); + } - /* Per-pixel fog */ + /* 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 ); + _mesa_fog_rgba_span(ctx, span); } /* Antialias coverage application */ - if (coverage) { + if (span->arrayMask & SPAN_COVERAGE) { + GLchan (*rgba)[4] = span->array->rgba; + GLfloat *coverage = span->array->coverage; GLuint i; - for (i = 0; i < n; i++) { + for (i = 0; i < span->end; 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 ); + multi_write_rgba_span(ctx, span); } 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 ); + _mesa_logicop_rgba_span(ctx, span, span->array->rgba); } - else if (ctx->Color.BlendEnabled) { - _mesa_blend_span( ctx, n, x, y, rgba, mask ); + else if (ctx->Color.BlendEnabled) { + _mesa_blend_span(ctx, span, span->array->rgba); } - if (colorMask == 0x0) { - return; - } - else if (colorMask != 0xffffffff) { - _mesa_mask_rgba_span( ctx, n, x, y, rgba ); + if (colorMask != 0xffffffff) { + _mesa_mask_rgba_span(ctx, span, span->array->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 ); + + if (span->arrayMask & SPAN_XY) { + /* array of pixel coords */ + (*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) { + _mesa_write_alpha_pixels(ctx, span->end, + span->array->x, span->array->y, + (const GLchan (*)[4]) span->array->rgba, + span->array->mask); + } + } + else { + /* horizontal run of pixels */ + (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y, + (const GLchan (*)[4]) span->array->rgba, + span->writeAll ? NULL : span->array->mask); + if (swrast->_RasterMask & ALPHABUF_BIT) { + _mesa_write_alpha_span(ctx, span->end, span->x, span->y, + (const GLchan (*)[4]) span->array->rgba, + span->writeAll ? NULL : span->array->mask); + } } } + + span->arrayMask = origArrayMask; } -/* +/** * Read RGBA pixels from frame buffer. Clipping will be done to prevent * reading ouside the buffer's boundaries. */ @@ -1139,7 +1323,7 @@ _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer, if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { /* completely above, below, or right */ /* XXX maybe leave undefined? */ - BZERO(rgba, 4 * n * sizeof(GLchan)); + _mesa_bzero(rgba, 4 * n * sizeof(GLchan)); } else { GLint skip, length; @@ -1152,7 +1336,7 @@ _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer, return; } if (length > bufWidth) { - length = buffer->Width; + length = bufWidth; } } else if ((GLint) (x + n) > bufWidth) { @@ -1172,15 +1356,13 @@ _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer, (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip ); if (buffer->UseSoftwareAlphaBuffers) { - _mesa_read_alpha_span( ctx, length, x + skip, y, rgba + skip ); + _mesa_read_alpha_span(ctx, length, x + skip, y, rgba + skip); } } } - - -/* +/** * Read CI pixels from frame buffer. Clipping will be done to prevent * reading ouside the buffer's boundaries. */ @@ -1194,7 +1376,7 @@ _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer, if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { /* completely above, below, or right */ - BZERO(indx, n * sizeof(GLuint)); + _mesa_bzero(indx, n * sizeof(GLuint)); } else { GLint skip, length; diff --git a/xc/extras/Mesa/src/swrast/s_span.h b/xc/extras/Mesa/src/swrast/s_span.h index 063494258..d37961e98 100644 --- a/xc/extras/Mesa/src/swrast/s_span.h +++ b/xc/extras/Mesa/src/swrast/s_span.h @@ -1,10 +1,9 @@ -/* $Id: s_span.h,v 1.1.1.1 2002/10/22 13:06:57 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -34,61 +33,38 @@ extern void -_mesa_write_index_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - GLuint index[], const GLint coverage[], - GLenum primitive ); - +_mesa_span_default_z( GLcontext *ctx, struct sw_span *span ); extern void -_mesa_write_monoindex_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - GLuint index, const GLint coverage[], - GLenum primitive ); +_mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span ); +extern void +_mesa_span_default_fog( GLcontext *ctx, struct sw_span *span ); extern void -_mesa_write_rgba_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - GLchan rgba[][4], const GLfloat coverage[], - GLenum primitive ); +_mesa_span_default_color( GLcontext *ctx, struct sw_span *span ); +extern void +_mesa_span_default_texcoords( GLcontext *ctx, struct sw_span *span ); extern void -_mesa_write_monocolor_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], const GLfloat fog[], - const GLchan color[4], const GLfloat coverage[], - GLenum primitive ); +_mesa_write_index_span( GLcontext *ctx, struct sw_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[], - const GLfloat u[], GLfloat lambda[], - GLchan rgba[][4], CONST GLchan spec[][4], - const GLfloat coverage[], GLenum primitive ); +_mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span); extern void -_mesa_write_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_TEXTURE_UNITS][MAX_WIDTH], - GLchan rgba[][4], CONST GLchan spec[][4], - const GLfloat coverage[], GLenum primitive ); +_mesa_write_texture_span( GLcontext *ctx, struct sw_span *span); extern void _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer, GLuint n, GLint x, GLint y, GLchan rgba[][4] ); - extern void _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer, GLuint n, GLint x, GLint y, GLuint indx[] ); - #endif diff --git a/xc/extras/Mesa/src/swrast/s_stencil.c b/xc/extras/Mesa/src/swrast/s_stencil.c index 13ecc70da..b535830fe 100644 --- a/xc/extras/Mesa/src/swrast/s_stencil.c +++ b/xc/extras/Mesa/src/swrast/s_stencil.c @@ -1,8 +1,7 @@ -/* $Id: s_stencil.c,v 1.1.1.1 2002/10/22 13:06:41 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -28,17 +27,14 @@ #include "glheader.h" #include "context.h" #include "macros.h" -#include "mem.h" +#include "imports.h" #include "s_context.h" #include "s_depth.h" -#include "s_pb.h" #include "s_stencil.h" - - /* Stencil Logic: IF stencil test fails THEN @@ -55,8 +51,6 @@ ENDIF */ - - /* * Return the address of a stencil buffer value given the window coords: */ @@ -65,22 +59,23 @@ ENDIF -/* +/** * Apply the given stencil operator to the array of stencil values. * Don't touch stencil[i] if mask[i] is zero. * Input: n - size of stencil array * oper - the stencil buffer operator + * face - 0 or 1 for front or back face operation * stencil - array of stencil values * mask - array [n] of flag: 1=apply operator, 0=don't apply operator * Output: stencil - modified values */ -static void apply_stencil_op( const GLcontext *ctx, GLenum oper, - GLuint n, GLstencil stencil[], - const GLubyte mask[] ) +static void +apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face, + GLuint n, GLstencil stencil[], const GLubyte mask[] ) { - const GLstencil ref = ctx->Stencil.Ref; - const GLstencil wrtmask = ctx->Stencil.WriteMask; - const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask); + const GLstencil ref = ctx->Stencil.Ref[face]; + const GLstencil wrtmask = ctx->Stencil.WriteMask[face]; + const GLstencil invmask = (GLstencil) (~wrtmask); GLuint i; switch (oper) { @@ -226,9 +221,10 @@ static void apply_stencil_op( const GLcontext *ctx, GLenum oper, -/* +/** * Apply stencil test to an array of stencil values (before depth buffering). - * Input: n - number of pixels in the array + * Input: face - 0 or 1 for front or back-face polygons + * n - number of pixels in the array * stencil - array of [n] stencil values * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel * Output: mask - pixels which fail the stencil test will have their @@ -237,15 +233,16 @@ static void apply_stencil_op( const GLcontext *ctx, GLenum oper, * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. */ static GLboolean -do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], +do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[], GLubyte mask[] ) { - GLubyte fail[PB_SIZE]; + GLubyte fail[MAX_WIDTH]; GLboolean allfail = GL_FALSE; GLuint i; GLstencil r, s; + const GLuint valueMask = ctx->Stencil.ValueMask[face]; - ASSERT(n <= PB_SIZE); + ASSERT(n <= MAX_WIDTH); /* * Perform stencil test. The results of this operation are stored @@ -256,9 +253,9 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], * the stencil fail operator is not to be applied * ENDIF */ - switch (ctx->Stencil.Function) { + switch (ctx->Stencil.Function[face]) { case GL_NEVER: - /* always fail */ + /* never pass; always fail */ for (i=0;i<n;i++) { if (mask[i]) { mask[i] = 0; @@ -271,10 +268,10 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], allfail = GL_TRUE; break; case GL_LESS: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { - s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); + s = (GLstencil) (stencil[i] & valueMask); if (r < s) { /* passed */ fail[i] = 0; @@ -290,10 +287,10 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], } break; case GL_LEQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { - s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); + s = (GLstencil) (stencil[i] & valueMask); if (r <= s) { /* pass */ fail[i] = 0; @@ -309,10 +306,10 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], } break; case GL_GREATER: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { - s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); + s = (GLstencil) (stencil[i] & valueMask); if (r > s) { /* passed */ fail[i] = 0; @@ -328,10 +325,10 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], } break; case GL_GEQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { - s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); + s = (GLstencil) (stencil[i] & valueMask); if (r >= s) { /* passed */ fail[i] = 0; @@ -347,10 +344,10 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], } break; case GL_EQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { - s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); + s = (GLstencil) (stencil[i] & valueMask); if (r == s) { /* passed */ fail[i] = 0; @@ -366,10 +363,10 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], } break; case GL_NOTEQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { - s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask); + s = (GLstencil) (stencil[i] & valueMask); if (r != s) { /* passed */ fail[i] = 0; @@ -395,8 +392,8 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], return 0; } - if (ctx->Stencil.FailFunc != GL_KEEP) { - apply_stencil_op( ctx, ctx->Stencil.FailFunc, n, stencil, fail ); + if (ctx->Stencil.FailFunc[face] != GL_KEEP) { + apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail ); } return !allfail; @@ -404,47 +401,69 @@ do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[], - -/* - * Apply stencil and depth testing to an array of pixels. - * Hardware or software stencil buffer acceptable. +/** + * Apply stencil and depth testing to the span of pixels. + * Both software and hardware stencil buffers are acceptable. * Input: n - number of pixels in the span + * x, y - location of leftmost pixel in span * z - array [n] of z values - * stencil - array [n] of stencil values * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) - * Output: stencil - modified stencil values - * mask - array [n] of flags (1=stencil and depth test passed) - * Return: GL_TRUE - all fragments failed the testing - * GL_FALSE - one or more fragments passed the testing + * Output: mask - array [n] of flags (1=stencil and depth test passed) + * Return: GL_FALSE - all fragments failed the testing + * GL_TRUE - one or more fragments passed the testing * */ static GLboolean -stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], GLstencil stencil[], - GLubyte mask[] ) +stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face) { - ASSERT(ctx->Stencil.Enabled); - ASSERT(n <= PB_SIZE); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLstencil stencilRow[MAX_WIDTH]; + GLstencil *stencil; + const GLuint n = span->end; + const GLint x = span->x; + const GLint y = span->y; + GLubyte *mask = span->array->mask; + ASSERT((span->arrayMask & SPAN_XY) == 0); + ASSERT(ctx->Stencil.Enabled); + ASSERT(n <= MAX_WIDTH); +#ifdef DEBUG + if (ctx->Depth.Test) { + ASSERT(span->arrayMask & SPAN_Z); + } +#endif + + /* Get initial stencil values */ + if (swrast->Driver.WriteStencilSpan) { + /* Get stencil values from the hardware stencil buffer */ + ASSERT(swrast->Driver.ReadStencilSpan); + (*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow); + stencil = stencilRow; + } + else { + /* Get pointer into software stencil buffer */ + stencil = STENCIL_ADDRESS(x, y); + } + /* * Apply the stencil test to the fragments. * failMask[i] is 1 if the stencil test failed. */ - if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) { + if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) { /* all fragments failed the stencil test, we're done. */ + span->writeAll = GL_FALSE; return GL_FALSE; } - /* * Some fragments passed the stencil test, apply depth test to them * and apply Zpass and Zfail stencil ops. */ - if (ctx->Depth.Test==GL_FALSE) { + if (ctx->Depth.Test == GL_FALSE) { /* * No depth buffer, just apply zpass stencil function to active pixels. */ - apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask ); + apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask ); } else { /* @@ -457,7 +476,7 @@ stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y, MEMCPY(oldmask, mask, n * sizeof(GLubyte)); /* apply the depth test */ - _mesa_depth_test_span(ctx, n, x, y, z, mask); + _mesa_depth_test_span(ctx, span); /* Set the stencil pass/fail flags according to result of depth testing. * if oldmask[i] == 0 then @@ -476,72 +495,36 @@ stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y, } /* apply the pass and fail operations */ - if (ctx->Stencil.ZFailFunc != GL_KEEP) { - apply_stencil_op( ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask ); + if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { + apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face, + n, stencil, failmask ); } - if (ctx->Stencil.ZPassFunc != GL_KEEP) { - apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask ); + if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { + apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, + n, stencil, passmask ); } } - return GL_TRUE; /* one or more fragments passed both tests */ -} - - - -/* - * Apply stencil and depth testing to the span of pixels. - * Both software and hardware stencil buffers are acceptable. - * Input: n - number of pixels in the span - * x, y - location of leftmost pixel in span - * z - array [n] of z values - * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) - * Output: mask - array [n] of flags (1=stencil and depth test passed) - * Return: GL_TRUE - all fragments failed the testing - * GL_FALSE - one or more fragments passed the testing - * - */ -GLboolean -_mesa_stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], GLubyte mask[] ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - GLstencil stencilRow[MAX_WIDTH]; - GLstencil *stencil; - GLboolean result; - - ASSERT(ctx->Stencil.Enabled); - ASSERT(n <= MAX_WIDTH); - - /* Get initial stencil values */ - if (swrast->Driver.WriteStencilSpan) { - ASSERT(swrast->Driver.ReadStencilSpan); - /* Get stencil values from the hardware stencil buffer */ - (*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow); - stencil = stencilRow; - } - else { - /* software stencil buffer */ - stencil = STENCIL_ADDRESS(x, y); - } - - /* do all the stencil/depth testing/updating */ - result = stencil_and_ztest_span( ctx, n, x, y, z, stencil, mask ); - + /* + * Write updated stencil values back into hardware stencil buffer. + */ if (swrast->Driver.WriteStencilSpan) { - /* Write updated stencil values into hardware stencil buffer */ + ASSERT(stencil == stencilRow); (swrast->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask ); } - - return result; + + span->writeAll = GL_FALSE; + + return GL_TRUE; /* one or more fragments passed both tests */ } -/* +/** * Apply the given stencil operator for each pixel in the array whose - * mask flag is set. This is for software stencil buffers only. + * mask flag is set. + * \note This is for software stencil buffers only. * Input: n - number of pixels in the span * x, y - array of [n] pixels * operator - the stencil buffer operator @@ -550,11 +533,11 @@ _mesa_stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y, static void apply_stencil_op_to_pixels( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], - GLenum oper, const GLubyte mask[] ) + GLenum oper, GLuint face, const GLubyte mask[] ) { - const GLstencil ref = ctx->Stencil.Ref; - const GLstencil wrtmask = ctx->Stencil.WriteMask; - const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask); + const GLstencil ref = ctx->Stencil.Ref[face]; + const GLstencil wrtmask = ctx->Stencil.WriteMask[face]; + const GLstencil invmask = (GLstencil) (~wrtmask); GLuint i; ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* software stencil buffer only! */ @@ -704,26 +687,31 @@ apply_stencil_op_to_pixels( const GLcontext *ctx, -/* +/** * Apply stencil test to an array of pixels before depth buffering. - * Used for software stencil buffer only. + * + * \note Used for software stencil buffer only. * Input: n - number of pixels in the span * x, y - array of [n] pixels to stencil * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel * Output: mask - pixels which fail the stencil test will have their * mask flag set to 0. - * Return: 0 = all pixels failed, 1 = zero or more pixels passed. + * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. */ static GLboolean -stencil_test_pixels( GLcontext *ctx, GLuint n, +stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n, const GLint x[], const GLint y[], GLubyte mask[] ) { - GLubyte fail[PB_SIZE]; + GLubyte fail[MAX_WIDTH]; GLstencil r, s; GLuint i; GLboolean allfail = GL_FALSE; + const GLuint valueMask = ctx->Stencil.ValueMask[face]; - ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* software stencil buffer only! */ + /* software stencil buffer only! */ + ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer); + ASSERT(!SWRAST_CONTEXT(ctx)->Driver.ReadStencilSpan); + ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* * Perform stencil test. The results of this operation are stored @@ -735,7 +723,7 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, * ENDIF */ - switch (ctx->Stencil.Function) { + switch (ctx->Stencil.Function[face]) { case GL_NEVER: /* always fail */ for (i=0;i<n;i++) { @@ -750,11 +738,11 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, allfail = GL_TRUE; break; case GL_LESS: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); + s = (GLstencil) (*sptr & valueMask); if (r < s) { /* passed */ fail[i] = 0; @@ -770,11 +758,11 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, } break; case GL_LEQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); + s = (GLstencil) (*sptr & valueMask); if (r <= s) { /* pass */ fail[i] = 0; @@ -790,11 +778,11 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, } break; case GL_GREATER: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); + s = (GLstencil) (*sptr & valueMask); if (r > s) { /* passed */ fail[i] = 0; @@ -810,11 +798,11 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, } break; case GL_GEQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); + s = (GLstencil) (*sptr & valueMask); if (r >= s) { /* passed */ fail[i] = 0; @@ -830,11 +818,11 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, } break; case GL_EQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); + s = (GLstencil) (*sptr & valueMask); if (r == s) { /* passed */ fail[i] = 0; @@ -850,11 +838,11 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, } break; case GL_NOTEQUAL: - r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask); + r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i<n;i++) { if (mask[i]) { GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLstencil) (*sptr & ctx->Stencil.ValueMask); + s = (GLstencil) (*sptr & valueMask); if (r != s) { /* passed */ fail[i] = 0; @@ -880,8 +868,9 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, return 0; } - if (ctx->Stencil.FailFunc != GL_KEEP) { - apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail ); + if (ctx->Stencil.FailFunc[face] != GL_KEEP) { + apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face], + face, fail ); } return !allfail; @@ -890,7 +879,7 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, -/* +/** * Apply stencil and depth testing to an array of pixels. * This is used both for software and hardware stencil buffers. * @@ -903,54 +892,60 @@ stencil_test_pixels( GLcontext *ctx, GLuint n, * z - array [n] of z values * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) * Output: mask - array [n] of flags (1=stencil and depth test passed) - * Return: GL_TRUE - all fragments failed the testing - * GL_FALSE - one or more fragments passed the testing + * Return: GL_FALSE - all fragments failed the testing + * GL_TRUE - one or more fragments passed the testing */ -GLboolean -_mesa_stencil_and_ztest_pixels( GLcontext *ctx, - GLuint n, const GLint x[], const GLint y[], - const GLdepth z[], GLubyte mask[] ) +static GLboolean +stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face ) { + const GLuint n = span->end; + const GLint *x = span->array->x; + const GLint *y = span->array->y; + GLubyte *mask = span->array->mask; SWcontext *swrast = SWRAST_CONTEXT(ctx); + + ASSERT(span->arrayMask & SPAN_XY); ASSERT(ctx->Stencil.Enabled); - ASSERT(n <= PB_SIZE); + ASSERT(n <= MAX_WIDTH); if (swrast->Driver.WriteStencilPixels) { /*** Hardware stencil buffer ***/ - GLstencil stencil[PB_SIZE]; - GLubyte origMask[PB_SIZE]; + GLstencil stencil[MAX_WIDTH]; + GLubyte origMask[MAX_WIDTH]; + ASSERT(!ctx->DrawBuffer->UseSoftwareStencilBuffer); ASSERT(swrast->Driver.ReadStencilPixels); (*swrast->Driver.ReadStencilPixels)(ctx, n, x, y, stencil); MEMCPY(origMask, mask, n * sizeof(GLubyte)); - (void) do_stencil_test(ctx, n, stencil, mask); + (void) do_stencil_test(ctx, face, n, stencil, mask); if (ctx->Depth.Test == GL_FALSE) { - apply_stencil_op(ctx, ctx->Stencil.ZPassFunc, n, stencil, mask); + apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, + n, stencil, mask); } else { - _mesa_depth_test_pixels(ctx, n, x, y, z, mask); + _mesa_depth_test_span(ctx, span); - if (ctx->Stencil.ZFailFunc != GL_KEEP) { - GLubyte failmask[PB_SIZE]; + if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { + GLubyte failmask[MAX_WIDTH]; GLuint i; for (i = 0; i < n; i++) { ASSERT(mask[i] == 0 || mask[i] == 1); failmask[i] = origMask[i] & (mask[i] ^ 1); } - apply_stencil_op(ctx, ctx->Stencil.ZFailFunc, + apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face, n, stencil, failmask); } - if (ctx->Stencil.ZPassFunc != GL_KEEP) { - GLubyte passmask[PB_SIZE]; + if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { + GLubyte passmask[MAX_WIDTH]; GLuint i; for (i = 0; i < n; i++) { ASSERT(mask[i] == 0 || mask[i] == 1); passmask[i] = origMask[i] & mask[i]; } - apply_stencil_op(ctx, ctx->Stencil.ZPassFunc, + apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, passmask); } } @@ -963,22 +958,24 @@ _mesa_stencil_and_ztest_pixels( GLcontext *ctx, else { /*** Software stencil buffer ***/ - if (stencil_test_pixels(ctx, n, x, y, mask) == GL_FALSE) { + ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer); + + if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) { /* all fragments failed the stencil test, we're done. */ return GL_FALSE; } if (ctx->Depth.Test==GL_FALSE) { apply_stencil_op_to_pixels(ctx, n, x, y, - ctx->Stencil.ZPassFunc, mask); + ctx->Stencil.ZPassFunc[face], face, mask); } else { - GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE]; + GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH]; GLuint i; MEMCPY(oldmask, mask, n * sizeof(GLubyte)); - _mesa_depth_test_pixels(ctx, n, x, y, z, mask); + _mesa_depth_test_span(ctx, span); for (i=0;i<n;i++) { ASSERT(mask[i] == 0 || mask[i] == 1); @@ -986,13 +983,15 @@ _mesa_stencil_and_ztest_pixels( GLcontext *ctx, failmask[i] = oldmask[i] & (mask[i] ^ 1); } - if (ctx->Stencil.ZFailFunc != GL_KEEP) { + if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { apply_stencil_op_to_pixels(ctx, n, x, y, - ctx->Stencil.ZFailFunc, failmask); + ctx->Stencil.ZFailFunc[face], + face, failmask); } - if (ctx->Stencil.ZPassFunc != GL_KEEP) { + if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { apply_stencil_op_to_pixels(ctx, n, x, y, - ctx->Stencil.ZPassFunc, passmask); + ctx->Stencil.ZPassFunc[face], + face, passmask); } } @@ -1001,8 +1000,23 @@ _mesa_stencil_and_ztest_pixels( GLcontext *ctx, } +/** + * /return GL_TRUE = one or more fragments passed, + * GL_FALSE = all fragments failed. + */ +GLboolean +_mesa_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span) +{ + /* span->facing can only be non-zero if using two-sided stencil */ + ASSERT(ctx->Stencil.TestTwoSide || span->facing == 0); + if (span->arrayMask & SPAN_XY) + return stencil_and_ztest_pixels(ctx, span, span->facing); + else + return stencil_and_ztest_span(ctx, span, span->facing); +} -/* + +/** * Return a span of stencil values from the stencil buffer. * Used for glRead/CopyPixels * Input: n - how many pixels @@ -1014,8 +1028,10 @@ _mesa_read_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y, GLstencil stencil[] ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height || - x + n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) { + const GLint bufWidth = (GLint) ctx->DrawBuffer->Width; + const GLint bufHeight = (GLint) ctx->DrawBuffer->Height; + + if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) { /* span is completely outside framebuffer */ return; /* undefined values OK */ } @@ -1026,8 +1042,8 @@ _mesa_read_stencil_span( GLcontext *ctx, n -= dx; stencil += dx; } - if (x + n > (GLint) ctx->DrawBuffer->Width) { - GLint dx = x + n - (GLint) ctx->DrawBuffer->Width; + if (x + n > bufWidth) { + GLint dx = x + n - bufWidth; n -= dx; } if (n <= 0) { @@ -1053,7 +1069,7 @@ _mesa_read_stencil_span( GLcontext *ctx, -/* +/** * Write a span of stencil values to the stencil buffer. * Used for glDraw/CopyPixels * Input: n - how many pixels @@ -1066,9 +1082,10 @@ _mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y, { SWcontext *swrast = SWRAST_CONTEXT(ctx); const GLstencil *ssrc = stencil; + const GLint bufWidth = (GLint) ctx->DrawBuffer->Width; + const GLint bufHeight = (GLint) ctx->DrawBuffer->Height; - if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height || - x + n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) { + if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) { /* span is completely outside framebuffer */ return; /* undefined values OK */ } @@ -1079,8 +1096,8 @@ _mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y, n -= dx; ssrc += dx; } - if (x + n > (GLint) ctx->DrawBuffer->Width) { - GLint dx = x + n - (GLint) ctx->DrawBuffer->Width; + if (x + n > bufWidth) { + GLint dx = x + n - bufWidth; n -= dx; } if (n <= 0) { @@ -1104,7 +1121,7 @@ _mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y, -/* +/** * Allocate a new stencil buffer. If there's an old one it will be * deallocated first. The new stencil buffer will be uninitialized. */ @@ -1118,8 +1135,8 @@ _mesa_alloc_stencil_buffer( GLframebuffer *buffer ) } /* allocate new stencil buffer */ - buffer->Stencil = (GLstencil *) MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height - * sizeof(GLstencil)); + buffer->Stencil = (GLstencil *) + MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height * sizeof(GLstencil)); if (!buffer->Stencil) { /* out of memory */ _mesa_error( NULL, GL_OUT_OF_MEMORY, "_mesa_alloc_stencil_buffer" ); @@ -1128,7 +1145,7 @@ _mesa_alloc_stencil_buffer( GLframebuffer *buffer ) -/* +/** * Clear the software (malloc'd) stencil buffer. */ static void @@ -1142,11 +1159,11 @@ clear_software_stencil_buffer( GLcontext *ctx ) if (ctx->Scissor.Enabled) { /* clear scissor region only */ const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - if (ctx->Stencil.WriteMask != STENCIL_MAX) { + if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { /* must apply mask to the clear */ GLint y; for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) { - const GLstencil mask = ctx->Stencil.WriteMask; + const GLstencil mask = ctx->Stencil.WriteMask[0]; const GLstencil invMask = ~mask; const GLstencil clearVal = (ctx->Stencil.Clear & mask); GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y ); @@ -1173,11 +1190,11 @@ clear_software_stencil_buffer( GLcontext *ctx ) } else { /* clear whole stencil buffer */ - if (ctx->Stencil.WriteMask != STENCIL_MAX) { + if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { /* must apply mask to the clear */ const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; GLstencil *stencil = ctx->DrawBuffer->Stencil; - const GLstencil mask = ctx->Stencil.WriteMask; + const GLstencil mask = ctx->Stencil.WriteMask[0]; const GLstencil invMask = ~mask; const GLstencil clearVal = (ctx->Stencil.Clear & mask); GLuint i; @@ -1204,7 +1221,7 @@ clear_software_stencil_buffer( GLcontext *ctx ) -/* +/** * Clear the hardware (in graphics card) stencil buffer. * This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan() * functions. @@ -1224,11 +1241,11 @@ clear_hardware_stencil_buffer( GLcontext *ctx ) /* clear scissor region only */ const GLint x = ctx->DrawBuffer->_Xmin; const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - if (ctx->Stencil.WriteMask != STENCIL_MAX) { + if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { /* must apply mask to the clear */ GLint y; for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) { - const GLstencil mask = ctx->Stencil.WriteMask; + const GLstencil mask = ctx->Stencil.WriteMask[0]; const GLstencil invMask = ~mask; const GLstencil clearVal = (ctx->Stencil.Clear & mask); GLstencil stencil[MAX_WIDTH]; @@ -1254,9 +1271,9 @@ clear_hardware_stencil_buffer( GLcontext *ctx ) } else { /* clear whole stencil buffer */ - if (ctx->Stencil.WriteMask != STENCIL_MAX) { + if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { /* must apply mask to the clear */ - const GLstencil mask = ctx->Stencil.WriteMask; + const GLstencil mask = ctx->Stencil.WriteMask[0]; const GLstencil invMask = ~mask; const GLstencil clearVal = (ctx->Stencil.Clear & mask); const GLint width = ctx->DrawBuffer->Width; @@ -1292,8 +1309,8 @@ clear_hardware_stencil_buffer( GLcontext *ctx ) -/* - * Clear the stencil buffer. +/** + * Clear the stencil buffer (hardware or software). */ void _mesa_clear_stencil_buffer( GLcontext *ctx ) diff --git a/xc/extras/Mesa/src/swrast/s_stencil.h b/xc/extras/Mesa/src/swrast/s_stencil.h index 03e0de901..30b390e1b 100644 --- a/xc/extras/Mesa/src/swrast/s_stencil.h +++ b/xc/extras/Mesa/src/swrast/s_stencil.h @@ -1,8 +1,7 @@ -/* $Id: s_stencil.h,v 1.1.1.1 2002/10/22 13:06:41 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.2 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -33,14 +32,10 @@ #include "swrast.h" -extern GLboolean -_mesa_stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLdepth z[], GLubyte mask[] ); extern GLboolean -_mesa_stencil_and_ztest_pixels( GLcontext *ctx, GLuint n, - const GLint x[], const GLint y[], - const GLdepth z[], GLubyte mask[] ); +_mesa_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span); + extern void diff --git a/xc/extras/Mesa/src/swrast/s_texstore.c b/xc/extras/Mesa/src/swrast/s_texstore.c index 0ec021b70..1865b22e3 100644 --- a/xc/extras/Mesa/src/swrast/s_texstore.c +++ b/xc/extras/Mesa/src/swrast/s_texstore.c @@ -1,10 +1,9 @@ -/* $Id: s_texstore.c,v 1.1.1.1 2002/10/22 13:06:53 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -42,8 +41,8 @@ #include "context.h" #include "convolve.h" #include "image.h" +#include "imports.h" #include "macros.h" -#include "mem.h" #include "texformat.h" #include "teximage.h" #include "texstore.h" @@ -73,8 +72,7 @@ read_color_image( GLcontext *ctx, GLint x, GLint y, return NULL; /* Select buffer to read from */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); + _swrast_use_read_buffer(ctx); RENDER_START(swrast,ctx); @@ -89,8 +87,7 @@ read_color_image( GLcontext *ctx, GLint x, GLint y, RENDER_FINISH(swrast,ctx); /* Read from draw buffer (the default) */ - (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); + _swrast_use_draw_buffer(ctx); return image; } @@ -146,8 +143,8 @@ is_depth_format(GLenum format) */ void _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLint border ) + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLint border ) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; @@ -194,7 +191,7 @@ _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level, /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, texUnit, texObj); + _mesa_generate_mipmap(ctx, target, texUnit, texObj); } } @@ -204,9 +201,9 @@ _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level, */ void _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border ) + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border ) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; @@ -253,7 +250,7 @@ _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level, /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, texUnit, texObj); + _mesa_generate_mipmap(ctx, target, texUnit, texObj); } } @@ -262,8 +259,8 @@ _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level, * Fallback for Driver.CopyTexSubImage1D(). */ void -_swrast_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLint x, GLint y, GLsizei width) +_swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; @@ -277,55 +274,38 @@ _swrast_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, ASSERT(ctx->Driver.TexImage1D); - if (texImage->Format != GL_DEPTH_COMPONENT) { - /* read RGBA image from framebuffer */ - GLchan *image = read_color_image(ctx, x, y, width, 1); + if (texImage->Format == GL_DEPTH_COMPONENT) { + /* read depth image from framebuffer */ + GLfloat *image = read_depth_image(ctx, x, y, width, 1); if (!image) { - _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" ); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D"); return; } -#if 0 - /* - * XXX this is a bit of a hack. We need to be sure that the alpha - * channel is 1.0 if the internal texture format is not supposed to - * have an alpha channel. This is because some drivers may store - * RGB textures as RGBA and the texutil.c code isn't smart enough - * to set the alpha channel to 1.0 in this situation. - */ - if (texImage->Format == GL_LUMINANCE || - texImage->Format == GL_RGB) { - const GLuint n = width * 4; - GLuint i; - for (i = 0; i < n; i += 4) { - image[i + 3] = CHAN_MAX; - } - } -#endif - /* now call glTexSubImage1D to do the real work */ + /* call glTexSubImage1D to redefine the texture */ (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, - GL_RGBA, CHAN_TYPE, image, + GL_DEPTH_COMPONENT, GL_FLOAT, image, &_mesa_native_packing, texObj, texImage); FREE(image); } else { - /* read depth image from framebuffer */ - GLfloat *image = read_depth_image(ctx, x, y, width, 1); + /* read RGBA image from framebuffer */ + GLchan *image = read_color_image(ctx, x, y, width, 1); if (!image) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D"); + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" ); return; } - /* call glTexSubImage1D to redefine the texture */ + /* now call glTexSubImage1D to do the real work */ (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, - GL_DEPTH_COMPONENT, GL_FLOAT, image, + GL_RGBA, CHAN_TYPE, image, &_mesa_native_packing, texObj, texImage); FREE(image); } /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, texUnit, texObj); + _mesa_generate_mipmap(ctx, target, texUnit, texObj); } } @@ -335,9 +315,9 @@ _swrast_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, */ void _swrast_copy_texsubimage2d( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint x, GLint y, GLsizei width, GLsizei height ) + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; @@ -351,57 +331,40 @@ _swrast_copy_texsubimage2d( GLcontext *ctx, ASSERT(ctx->Driver.TexImage2D); - if (texImage->Format != GL_DEPTH_COMPONENT) { - /* read RGBA image from framebuffer */ - GLchan *image = read_color_image(ctx, x, y, width, height); + if (texImage->Format == GL_DEPTH_COMPONENT) { + /* read depth image from framebuffer */ + GLfloat *image = read_depth_image(ctx, x, y, width, height); if (!image) { - _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" ); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D"); return; } -#if 0 - /* - * XXX this is a bit of a hack. We need to be sure that the alpha - * channel is 1.0 if the internal texture format is not supposed to - * have an alpha channel. This is because some drivers may store - * RGB textures as RGBA and the texutil.c code isn't smart enough - * to set the alpha channel to 1.0 in this situation. - */ - if (texImage->Format == GL_LUMINANCE || - texImage->Format == GL_RGB) { - const GLuint n = width * height * 4; - GLuint i; - for (i = 0; i < n; i += 4) { - image[i + 3] = CHAN_MAX; - } - } -#endif - /* now call glTexSubImage2D to do the real work */ + /* call glTexImage1D to redefine the texture */ (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, width, height, - GL_RGBA, CHAN_TYPE, image, + GL_DEPTH_COMPONENT, GL_FLOAT, image, &_mesa_native_packing, texObj, texImage); FREE(image); } else { - /* read depth image from framebuffer */ - GLfloat *image = read_depth_image(ctx, x, y, width, height); + /* read RGBA image from framebuffer */ + GLchan *image = read_color_image(ctx, x, y, width, height); if (!image) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D"); + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" ); return; } - /* call glTexImage1D to redefine the texture */ + /* now call glTexSubImage2D to do the real work */ (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, width, height, - GL_DEPTH_COMPONENT, GL_FLOAT, image, + GL_RGBA, CHAN_TYPE, image, &_mesa_native_packing, texObj, texImage); FREE(image); } /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, texUnit, texObj); + _mesa_generate_mipmap(ctx, target, texUnit, texObj); } } @@ -411,9 +374,9 @@ _swrast_copy_texsubimage2d( GLcontext *ctx, */ void _swrast_copy_texsubimage3d( GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height ) + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) { struct gl_texture_unit *texUnit; struct gl_texture_object *texObj; @@ -427,55 +390,39 @@ _swrast_copy_texsubimage3d( GLcontext *ctx, ASSERT(ctx->Driver.TexImage3D); - if (texImage->Format != GL_DEPTH_COMPONENT) { - /* read RGBA image from framebuffer */ - GLchan *image = read_color_image(ctx, x, y, width, height); + if (texImage->Format == GL_DEPTH_COMPONENT) { + /* read depth image from framebuffer */ + GLfloat *image = read_depth_image(ctx, x, y, width, height); if (!image) { - _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" ); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D"); return; } -#if 0 - /* - * XXX this is a bit of a hack. We need to be sure that the alpha - * channel is 1.0 if the internal texture format is not supposed to - * have an alpha channel. This is because some drivers may store - * RGB textures as RGBA and the texutil.c code isn't smart enough - * to set the alpha channel to 1.0 in this situation. - */ - if (texImage->Format == GL_LUMINANCE || - texImage->Format == GL_RGB) { - const GLuint n = width * height * 4; - GLuint i; - for (i = 0; i < n; i += 4) { - image[i + 3] = CHAN_MAX; - } - } -#endif - /* now call glTexSubImage3D to do the real work */ + + /* call glTexImage1D to redefine the texture */ (*ctx->Driver.TexSubImage3D)(ctx, target, level, xoffset, yoffset, zoffset, width, height, 1, - GL_RGBA, CHAN_TYPE, image, + GL_DEPTH_COMPONENT, GL_FLOAT, image, &_mesa_native_packing, texObj, texImage); FREE(image); } else { - /* read depth image from framebuffer */ - GLfloat *image = read_depth_image(ctx, x, y, width, height); + /* read RGBA image from framebuffer */ + GLchan *image = read_color_image(ctx, x, y, width, height); if (!image) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D"); + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" ); return; } - /* call glTexImage1D to redefine the texture */ + /* now call glTexSubImage3D to do the real work */ (*ctx->Driver.TexSubImage3D)(ctx, target, level, xoffset, yoffset, zoffset, width, height, 1, - GL_DEPTH_COMPONENT, GL_FLOAT, image, + GL_RGBA, CHAN_TYPE, image, &_mesa_native_packing, texObj, texImage); FREE(image); } /* GL_SGIS_generate_mipmap */ if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, texUnit, texObj); + _mesa_generate_mipmap(ctx, target, texUnit, texObj); } } diff --git a/xc/extras/Mesa/src/swrast/s_texture.c b/xc/extras/Mesa/src/swrast/s_texture.c index 66672a94f..5286601f8 100644 --- a/xc/extras/Mesa/src/swrast/s_texture.c +++ b/xc/extras/Mesa/src/swrast/s_texture.c @@ -1,8 +1,6 @@ -/* $Id: s_texture.c,v 1.1.1.1 2002/10/22 13:06:51 alanh Exp $ */ - /* * Mesa 3-D graphics library - * Version: 4.0.4 + * Version: 5.0 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -30,12 +28,11 @@ #include "colormac.h" #include "macros.h" #include "mmath.h" -#include "mem.h" +#include "imports.h" #include "texformat.h" #include "teximage.h" #include "s_context.h" -#include "s_pb.h" #include "s_texture.h" @@ -50,7 +47,7 @@ /* * Used to compute texel locations for linear sampling. * Input: - * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB + * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER * S = texcoord in [0,1] * SIZE = width (or height or depth) of texture * Output: @@ -79,7 +76,7 @@ if (I1 >= (GLint) SIZE) \ I1 = SIZE - 1; \ } \ - else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \ + else if (wrapMode == GL_CLAMP_TO_BORDER) { \ const GLfloat min = -1.0F / (2.0F * SIZE); \ const GLfloat max = 1.0F - min; \ if (S <= min) \ @@ -92,12 +89,37 @@ I0 = IFLOOR(U); \ I1 = I0 + 1; \ } \ - else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \ + else if (wrapMode == GL_MIRRORED_REPEAT) { \ const GLint flr = IFLOOR(S); \ if (flr & 1) \ U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \ else \ U = S - (GLfloat) flr; /* flr is even */ \ + U = (U * SIZE) - 0.5F; \ + I0 = IFLOOR(U); \ + I1 = I0 + 1; \ + if (I0 < 0) \ + I0 = 0; \ + if (I1 >= (GLint) SIZE) \ + I1 = SIZE - 1; \ + } \ + else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \ + U = (GLfloat) fabs(S); \ + if (U >= 1.0F) \ + U = (GLfloat) SIZE; \ + else \ + U *= SIZE; \ + U -= 0.5F; \ + I0 = IFLOOR(U); \ + I1 = I0 + 1; \ + } \ + else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \ + U = (GLfloat) fabs(S); \ + if (U >= 1.0F) \ + U = (GLfloat) SIZE; \ + else \ + U *= SIZE; \ + U -= 0.5F; \ I0 = IFLOOR(U); \ I1 = I0 + 1; \ if (I0 < 0) \ @@ -143,7 +165,7 @@ else \ I = IFLOOR(S * SIZE); \ } \ - else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \ + else if (wrapMode == GL_CLAMP_TO_BORDER) { \ /* s limited to [min,max] */ \ /* i limited to [-1, size] */ \ const GLfloat min = -1.0F / (2.0F * SIZE); \ @@ -155,7 +177,7 @@ else \ I = IFLOOR(S * SIZE); \ } \ - else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \ + else if (wrapMode == GL_MIRRORED_REPEAT) { \ const GLfloat min = 1.0F / (2.0F * SIZE); \ const GLfloat max = 1.0F - min; \ const GLint flr = IFLOOR(S); \ @@ -171,6 +193,30 @@ else \ I = IFLOOR(u * SIZE); \ } \ + else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \ + /* s limited to [0,1] */ \ + /* i limited to [0,size-1] */ \ + const GLfloat u = (GLfloat) fabs(S); \ + if (u <= 0.0F) \ + I = 0; \ + else if (u >= 1.0F) \ + I = SIZE - 1; \ + else \ + I = IFLOOR(u * SIZE); \ + } \ + else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \ + /* s limited to [min,max] */ \ + /* i limited to [0, size-1] */ \ + const GLfloat min = 1.0F / (2.0F * SIZE); \ + const GLfloat max = 1.0F - min; \ + const GLfloat u = (GLfloat) fabs(S); \ + if (u < min) \ + I = 0; \ + else if (u > max) \ + I = SIZE - 1; \ + else \ + I = IFLOOR(u * SIZE); \ + } \ else { \ ASSERT(wrapMode == GL_CLAMP); \ /* s limited to [0,1] */ \ @@ -185,16 +231,25 @@ } +#define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \ +{ \ + U = S * SIZE - 0.5F; \ + I0 = IFLOOR(U) & (SIZE - 1); \ + I1 = (I0 + 1) & (SIZE - 1); \ +} + + /* * Compute linear mipmap levels for given lambda. */ #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \ { \ if (lambda < 0.0F) \ - lambda = 0.0F; \ + level = tObj->BaseLevel; \ else if (lambda > tObj->_MaxLambda) \ - lambda = tObj->_MaxLambda; \ - level = (GLint) (tObj->BaseLevel + lambda); \ + level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \ + else \ + level = (GLint) (tObj->BaseLevel + lambda); \ } @@ -203,11 +258,14 @@ */ #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \ { \ + GLfloat l; \ if (lambda <= 0.5F) \ - lambda = 0.0F; \ + l = 0.0F; \ else if (lambda > tObj->_MaxLambda + 0.4999F) \ - lambda = tObj->_MaxLambda + 0.4999F; \ - level = (GLint) (tObj->BaseLevel + lambda + 0.5F); \ + l = tObj->_MaxLambda + 0.4999F; \ + else \ + l = lambda; \ + level = (GLint) (tObj->BaseLevel + l + 0.5F); \ if (level > tObj->_MaxLevel) \ level = tObj->_MaxLevel; \ } @@ -236,7 +294,6 @@ #define K1BIT 32 - /* * Get texture palette entry. */ @@ -288,6 +345,100 @@ palette_sample(const GLcontext *ctx, } +/* + * The lambda[] array values are always monotonic. Either the whole span + * will be minified, magnified, or split between the two. This function + * determines the subranges in [0, n-1] that are to be minified or magnified. + */ +static INLINE void +compute_min_mag_ranges( GLfloat minMagThresh, GLuint n, const GLfloat lambda[], + GLuint *minStart, GLuint *minEnd, + GLuint *magStart, GLuint *magEnd ) +{ + ASSERT(lambda != NULL); +#if 0 + /* Verify that lambda[] is monotonous. + * We can't really use this because the inaccuracy in the LOG2 function + * causes this test to fail, yet the resulting texturing is correct. + */ + if (n > 1) { + GLuint i; + printf("lambda delta = %g\n", lambda[0] - lambda[n-1]); + if (lambda[0] >= lambda[n-1]) { /* decreasing */ + for (i = 0; i < n - 1; i++) { + ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10)); + } + } + else { /* increasing */ + for (i = 0; i < n - 1; i++) { + ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10)); + } + } + } +#endif /* DEBUG */ + + /* since lambda is monotonous-array use this check first */ + if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) { + /* magnification for whole span */ + *magStart = 0; + *magEnd = n; + *minStart = *minEnd = 0; + } + else if (lambda[0] > minMagThresh && lambda[n-1] > minMagThresh) { + /* minification for whole span */ + *minStart = 0; + *minEnd = n; + *magStart = *magEnd = 0; + } + else { + /* a mix of minification and magnification */ + GLuint i; + if (lambda[0] > minMagThresh) { + /* start with minification */ + for (i = 1; i < n; i++) { + if (lambda[i] <= minMagThresh) + break; + } + *minStart = 0; + *minEnd = i; + *magStart = i; + *magEnd = n; + } + else { + /* start with magnification */ + for (i = 1; i < n; i++) { + if (lambda[i] > minMagThresh) + break; + } + *magStart = 0; + *magEnd = i; + *minStart = i; + *minEnd = n; + } + } + +#if 0 + /* Verify the min/mag Start/End values + * We don't use this either (see above) + */ + { + GLint i; + for (i = 0; i < n; i++) { + if (lambda[i] > minMagThresh) { + /* minification */ + ASSERT(i >= *minStart); + ASSERT(i < *minEnd); + } + else { + /* magnification */ + ASSERT(i >= *magStart); + ASSERT(i < *magEnd); + } + } + } +#endif +} + /**********************************************************************/ /* 1-D Texture Sampling Functions */ @@ -300,19 +451,19 @@ static void sample_1d_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, - GLfloat s, GLchan rgba[4]) + const GLfloat texcoord[4], GLchan rgba[4]) { const GLint width = img->Width2; /* without border, power of two */ GLint i; - COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i); /* skip over the border, if any */ i += img->Border; if (i < 0 || i >= (GLint) img->Width) { - /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */ - COPY_CHAN4(rgba, tObj->BorderColor); + /* Need this test for GL_CLAMP_TO_BORDER mode */ + COPY_CHAN4(rgba, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba); @@ -331,14 +482,14 @@ static void sample_1d_linear(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, - GLfloat s, GLchan rgba[4]) + const GLfloat texcoord[4], GLchan rgba[4]) { const GLint width = img->Width2; GLint i0, i1; GLfloat u; GLuint useBorderColor; - COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1); useBorderColor = 0; if (img->Border) { @@ -364,7 +515,7 @@ sample_1d_linear(GLcontext *ctx, GLchan t0[4], t1[4]; /* texels */ if (useBorderColor & I0BIT) { - COPY_CHAN4(t0, tObj->BorderColor); + COPY_CHAN4(t0, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0); @@ -373,7 +524,7 @@ sample_1d_linear(GLcontext *ctx, } } if (useBorderColor & I1BIT) { - COPY_CHAN4(t1, tObj->BorderColor); + COPY_CHAN4(t1, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1); @@ -406,24 +557,32 @@ sample_1d_linear(GLcontext *ctx, static void sample_1d_nearest_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat lambda, - GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - sample_1d_nearest(ctx, tObj, tObj->Image[level], s, rgba); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + sample_1d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); + } } static void sample_1d_linear_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat lambda, - GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - sample_1d_linear(ctx, tObj, tObj->Image[level], s, rgba); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + sample_1d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); + } } @@ -432,34 +591,37 @@ sample_1d_linear_mipmap_nearest(GLcontext *ctx, * This is really just needed in order to prevent warnings with some compilers. */ #if CHAN_TYPE == GL_FLOAT -#define INTCAST +#define CHAN_CAST #else -#define INTCAST (GLint) +#define CHAN_CAST (GLchan) (GLint) #endif static void sample_1d_nearest_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat lambda, - GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - - if (level >= tObj->_MaxLevel) { - sample_1d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, rgba); - } - else { - GLchan t0[4], t1[4]; - const GLfloat f = FRAC(lambda); - sample_1d_nearest(ctx, tObj, tObj->Image[level ], s, t0); - sample_1d_nearest(ctx, tObj, tObj->Image[level+1], s, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + if (level >= tObj->_MaxLevel) { + sample_1d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLchan t0[4], t1[4]; + const GLfloat f = FRAC(lambda[i]); + sample_1d_nearest(ctx, tObj, tObj->Image[level ], texcoord[i], t0); + sample_1d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } @@ -468,25 +630,28 @@ sample_1d_nearest_mipmap_linear(GLcontext *ctx, static void sample_1d_linear_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat lambda, - GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - - if (level >= tObj->_MaxLevel) { - sample_1d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, rgba); - } - else { - GLchan t0[4], t1[4]; - const GLfloat f = FRAC(lambda); - sample_1d_linear(ctx, tObj, tObj->Image[level ], s, t0); - sample_1d_linear(ctx, tObj, tObj->Image[level+1], s, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + if (level >= tObj->_MaxLevel) { + sample_1d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLchan t0[4], t1[4]; + const GLfloat f = FRAC(lambda[i]); + sample_1d_linear(ctx, tObj, tObj->Image[level ], texcoord[i], t0); + sample_1d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } @@ -495,17 +660,14 @@ sample_1d_linear_mipmap_linear(GLcontext *ctx, static void sample_nearest_1d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4] ) { GLuint i; struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; - (void) t; - (void) u; (void) lambda; for (i=0;i<n;i++) { - sample_1d_nearest(ctx, tObj, image, s[i], rgba[i]); + sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); } } @@ -514,17 +676,14 @@ sample_nearest_1d( GLcontext *ctx, GLuint texUnit, static void sample_linear_1d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4] ) { GLuint i; struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; - (void) t; - (void) u; (void) lambda; for (i=0;i<n;i++) { - sample_1d_linear(ctx, tObj, image, s[i], rgba[i]); + sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]); } } @@ -537,71 +696,74 @@ sample_linear_1d( GLcontext *ctx, GLuint texUnit, static void sample_lambda_1d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { - GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit]; + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ GLuint i; - (void) t; - (void) u; + ASSERT(lambda != NULL); + compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], + n, lambda, &minStart, &minEnd, &magStart, &magEnd); - for (i=0;i<n;i++) { - if (lambda[i] > MinMagThresh) { - /* minification */ - switch (tObj->MinFilter) { - case GL_NEAREST: - sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], rgba[i]); - break; - case GL_LINEAR: - sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], rgba[i]); - break; - case GL_NEAREST_MIPMAP_NEAREST: - sample_1d_nearest_mipmap_nearest(ctx, tObj, lambda[i], s[i], - rgba[i]); - break; - case GL_LINEAR_MIPMAP_NEAREST: - sample_1d_linear_mipmap_nearest(ctx, tObj, s[i], lambda[i], - rgba[i]); - break; - case GL_NEAREST_MIPMAP_LINEAR: - sample_1d_nearest_mipmap_linear(ctx, tObj, s[i], lambda[i], - rgba[i]); - break; - case GL_LINEAR_MIPMAP_LINEAR: - sample_1d_linear_mipmap_linear(ctx, tObj, s[i], lambda[i], - rgba[i]); - break; - default: - _mesa_problem(NULL, "Bad min filter in sample_1d_texture"); - return; - } + if (minStart < minEnd) { + /* do the minified texels */ + const GLuint m = minEnd - minStart; + switch (tObj->MinFilter) { + case GL_NEAREST: + for (i = minStart; i < minEnd; i++) + sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = minStart; i < minEnd; i++) + sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_1d_texture"); + return; } - else { - /* magnification */ - switch (tObj->MagFilter) { - case GL_NEAREST: - sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], rgba[i]); - break; - case GL_LINEAR: - sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], rgba[i]); - break; - default: - _mesa_problem(NULL, "Bad mag filter in sample_1d_texture"); - return; - } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + switch (tObj->MagFilter) { + case GL_NEAREST: + for (i = magStart; i < magEnd; i++) + sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = magStart; i < magEnd; i++) + sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_1d_texture"); + return; } } } - - /**********************************************************************/ /* 2-D Texture Sampling Functions */ /**********************************************************************/ @@ -610,27 +772,27 @@ sample_lambda_1d( GLcontext *ctx, GLuint texUnit, /* * Return the texture sample for coordinate (s,t) using GL_NEAREST filter. */ -static void +static INLINE void sample_2d_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, - GLfloat s, GLfloat t, + const GLfloat texcoord[4], GLchan rgba[]) { const GLint width = img->Width2; /* without border, power of two */ const GLint height = img->Height2; /* without border, power of two */ GLint i, j; - COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i); - COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j); /* skip over the border, if any */ i += img->Border; j += img->Border; if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) { - /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */ - COPY_CHAN4(rgba, tObj->BorderColor); + /* Need this test for GL_CLAMP_TO_BORDER mode */ + COPY_CHAN4(rgba, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba); @@ -646,11 +808,11 @@ sample_2d_nearest(GLcontext *ctx, * Return the texture sample for coordinate (s,t) using GL_LINEAR filter. * New sampling code contributed by Lynn Quam <quam@ai.sri.com>. */ -static void +static INLINE void sample_2d_linear(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, - GLfloat s, GLfloat t, + const GLfloat texcoord[4], GLchan rgba[]) { const GLint width = img->Width2; @@ -659,8 +821,8 @@ sample_2d_linear(GLcontext *ctx, GLuint useBorderColor; GLfloat u, v; - COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1); - COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1); useBorderColor = 0; if (img->Border) { @@ -698,7 +860,7 @@ sample_2d_linear(GLcontext *ctx, GLchan t11[4]; if (useBorderColor & (I0BIT | J0BIT)) { - COPY_CHAN4(t00, tObj->BorderColor); + COPY_CHAN4(t00, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00); @@ -707,7 +869,7 @@ sample_2d_linear(GLcontext *ctx, } } if (useBorderColor & (I1BIT | J0BIT)) { - COPY_CHAN4(t10, tObj->BorderColor); + COPY_CHAN4(t10, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10); @@ -716,7 +878,7 @@ sample_2d_linear(GLcontext *ctx, } } if (useBorderColor & (I0BIT | J1BIT)) { - COPY_CHAN4(t01, tObj->BorderColor); + COPY_CHAN4(t01, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01); @@ -725,7 +887,7 @@ sample_2d_linear(GLcontext *ctx, } } if (useBorderColor & (I1BIT | J1BIT)) { - COPY_CHAN4(t11, tObj->BorderColor); + COPY_CHAN4(t11, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11); @@ -763,16 +925,99 @@ sample_2d_linear(GLcontext *ctx, } +/* + * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT + * and we're not using a paletted texture. + */ +static INLINE void +sample_2d_linear_repeat(GLcontext *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLchan rgba[]) +{ + const GLint width = img->Width2; + const GLint height = img->Height2; + GLint i0, j0, i1, j1; + GLfloat u, v; + + ASSERT(tObj->WrapS == GL_REPEAT); + ASSERT(tObj->WrapT == GL_REPEAT); + ASSERT(img->Border == 0); + ASSERT(img->Format != GL_COLOR_INDEX); + + COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[0], u, width, i0, i1); + COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[1], v, height, j0, j1); + + { + const GLfloat a = FRAC(u); + const GLfloat b = FRAC(v); + +#if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT + const GLfloat w00 = (1.0F-a) * (1.0F-b); + const GLfloat w10 = a * (1.0F-b); + const GLfloat w01 = (1.0F-a) * b ; + const GLfloat w11 = a * b ; +#else /* CHAN_BITS == 8 */ + /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */ + const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE); + const GLint w10 = IROUND_POS( a * (1.0F-b) * WEIGHT_SCALE); + const GLint w01 = IROUND_POS((1.0F-a) * b * WEIGHT_SCALE); + const GLint w11 = IROUND_POS( a * b * WEIGHT_SCALE); +#endif + GLchan t00[4]; + GLchan t10[4]; + GLchan t01[4]; + GLchan t11[4]; + + (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00); + (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10); + (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01); + (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11); + +#if CHAN_TYPE == GL_FLOAT + rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]; + rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]; + rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]; + rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]; +#elif CHAN_TYPE == GL_UNSIGNED_SHORT + rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] + + w01 * t01[0] + w11 * t11[0] + 0.5); + rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] + + w01 * t01[1] + w11 * t11[1] + 0.5); + rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] + + w01 * t01[2] + w11 * t11[2] + 0.5); + rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] + + w01 * t01[3] + w11 * t11[3] + 0.5); +#else /* CHAN_BITS == 8 */ + rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] + + w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT); + rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] + + w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT); + rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] + + w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT); + rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] + + w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT); +#endif + + } + +} + + static void sample_2d_nearest_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat lambda, - GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - sample_2d_nearest(ctx, tObj, tObj->Image[level], s, t, rgba); + GLuint i; + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + sample_2d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); + } } @@ -780,12 +1025,16 @@ sample_2d_nearest_mipmap_nearest(GLcontext *ctx, static void sample_2d_linear_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat lambda, - GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - sample_2d_linear(ctx, tObj, tObj->Image[level], s, t, rgba); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + sample_2d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); + } } @@ -793,70 +1042,105 @@ sample_2d_linear_mipmap_nearest(GLcontext *ctx, static void sample_2d_nearest_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat lambda, - GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - - if (level >= tObj->_MaxLevel) { - sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, rgba); - } - else { - GLchan t0[4], t1[4]; /* texels */ - const GLfloat f = FRAC(lambda); - sample_2d_nearest(ctx, tObj, tObj->Image[level ], s, t, t0); - sample_2d_nearest(ctx, tObj, tObj->Image[level+1], s, t, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + if (level >= tObj->_MaxLevel) { + sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLchan t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_nearest(ctx, tObj, tObj->Image[level ], texcoord[i], t0); + sample_2d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } +/* Trilinear filtering */ static void -sample_2d_linear_mipmap_linear(GLcontext *ctx, - const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat lambda, - GLchan rgba[4]) +sample_2d_linear_mipmap_linear( GLcontext *ctx, + const struct gl_texture_object *tObj, + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { - GLint level; + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + if (level >= tObj->_MaxLevel) { + sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLchan t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_linear(ctx, tObj, tObj->Image[level ], texcoord[i], t0); + sample_2d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } + } +} - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - if (level >= tObj->_MaxLevel) { - sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, rgba); - } - else { - GLchan t0[4], t1[4]; /* texels */ - const GLfloat f = FRAC(lambda); - sample_2d_linear(ctx, tObj, tObj->Image[level ], s, t, t0); - sample_2d_linear(ctx, tObj, tObj->Image[level+1], s, t, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); +static void +sample_2d_linear_mipmap_linear_repeat( GLcontext *ctx, + const struct gl_texture_object *tObj, + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4] ) +{ + GLuint i; + ASSERT(lambda != NULL); + ASSERT(tObj->WrapS == GL_REPEAT); + ASSERT(tObj->WrapT == GL_REPEAT); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + if (level >= tObj->_MaxLevel) { + sample_2d_linear_repeat(ctx, tObj, tObj->Image[tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLchan t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_linear_repeat(ctx, tObj, tObj->Image[level ], texcoord[i], t0); + sample_2d_linear_repeat(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } - static void sample_nearest_2d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { GLuint i; struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; - (void) u; (void) lambda; for (i=0;i<n;i++) { - sample_2d_nearest(ctx, tObj, image, s[i], t[i], rgba[i]); + sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); } } @@ -865,16 +1149,14 @@ sample_nearest_2d( GLcontext *ctx, GLuint texUnit, static void sample_linear_2d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { GLuint i; struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; - (void) u; (void) lambda; for (i=0;i<n;i++) { - sample_2d_linear(ctx, tObj, image, s[i], t[i], rgba[i]); + sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]); } } @@ -883,15 +1165,15 @@ sample_linear_2d( GLcontext *ctx, GLuint texUnit, * Optimized 2-D texture sampling: * S and T wrap mode == GL_REPEAT * GL_NEAREST min/mag filter - * No border + * No border, + * RowStride == Width, * Format = GL_RGB */ static void opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLuint n, const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLuint n, GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel]; const GLfloat width = (GLfloat) img->Width; @@ -900,7 +1182,6 @@ opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit, const GLint rowMask = img->Height - 1; const GLint shift = img->WidthLog2; GLuint k; - (void) u; (void) lambda; ASSERT(tObj->WrapS==GL_REPEAT); ASSERT(tObj->WrapT==GL_REPEAT); @@ -908,8 +1189,8 @@ opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit, ASSERT(img->Format==GL_RGB); for (k=0; k<n; k++) { - GLint i = IFLOOR(s[k] * width) & colMask; - GLint j = IFLOOR(t[k] * height) & rowMask; + GLint i = IFLOOR(texcoords[k][0] * width) & colMask; + GLint j = IFLOOR(texcoords[k][1] * height) & rowMask; GLint pos = (j << shift) | i; GLchan *texel = ((GLchan *) img->Data) + 3*pos; rgba[k][RCOMP] = texel[0]; @@ -924,14 +1205,14 @@ opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit, * S and T wrap mode == GL_REPEAT * GL_NEAREST min/mag filter * No border + * RowStride == Width, * Format = GL_RGBA */ static void opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLuint n, const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLuint n, GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel]; const GLfloat width = (GLfloat) img->Width; @@ -940,7 +1221,6 @@ opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit, const GLint rowMask = img->Height - 1; const GLint shift = img->WidthLog2; GLuint i; - (void) u; (void) lambda; ASSERT(tObj->WrapS==GL_REPEAT); ASSERT(tObj->WrapT==GL_REPEAT); @@ -948,8 +1228,8 @@ opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit, ASSERT(img->Format==GL_RGBA); for (i = 0; i < n; i++) { - const GLint col = IFLOOR(s[i] * width) & colMask; - const GLint row = IFLOOR(t[i] * height) & rowMask; + const GLint col = IFLOOR(texcoords[i][0] * width) & colMask; + const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask; const GLint pos = (row << shift) | col; const GLchan *texel = ((GLchan *) img->Data) + (pos << 2); /* pos*4 */ COPY_CHAN4(rgba[i], texel); @@ -958,105 +1238,115 @@ opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit, /* - * Given an array of (s,t) texture coordinate and lambda (level of detail) + * Given an array of texture coordinate and lambda (level of detail) * values, return an array of texture sample. */ static void sample_lambda_2d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLuint n, GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { - const GLfloat minMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit]; - GLuint i; - (void) u; - - /* since lambda is monotonous-array use this check first */ - if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) { - /* magnification for whole span */ - const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel]; - switch (tObj->MagFilter) { + const struct gl_texture_image *tImg = tObj->Image[tObj->BaseLevel]; + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ + + const GLboolean repeatNoBorder = (tObj->WrapS == GL_REPEAT) + && (tObj->WrapT == GL_REPEAT) + && (tImg->Border == 0 && (tImg->Width == tImg->RowStride)) + && (tImg->Format != GL_COLOR_INDEX); + + ASSERT(lambda != NULL); + compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], + n, lambda, &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + const GLuint m = minEnd - minStart; + switch (tObj->MinFilter) { case GL_NEAREST: - if (tObj->WrapS == GL_REPEAT && tObj->WrapT == GL_REPEAT && - img->Border == 0) { - switch (img->Format) { + if (repeatNoBorder) { + switch (tImg->Format) { case GL_RGB: - opt_sample_rgb_2d(ctx, texUnit, tObj, n, s, t, NULL, - NULL, rgba); + opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + minStart, + NULL, rgba + minStart); break; case GL_RGBA: - opt_sample_rgba_2d(ctx, texUnit, tObj, n, s, t, NULL, - NULL, rgba); + opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + minStart, + NULL, rgba + minStart); break; default: - sample_nearest_2d(ctx, texUnit, tObj, n, s, t, NULL, - NULL, rgba); + sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart, + NULL, rgba + minStart ); } } else { - sample_nearest_2d(ctx, texUnit, tObj, n, s, t, NULL, - NULL, rgba); + sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart, + NULL, rgba + minStart); } break; case GL_LINEAR: - sample_linear_2d(ctx, texUnit, tObj, n, s, t, NULL, - NULL, rgba); + sample_linear_2d(ctx, texUnit, tObj, m, texcoords + minStart, + NULL, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_2d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + if (repeatNoBorder) + sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m, + texcoords + minStart, lambda + minStart, rgba + minStart); + else + sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); break; default: - _mesa_problem(NULL, "Bad mag filter in sample_lambda_2d"); + _mesa_problem(ctx, "Bad min filter in sample_2d_texture"); + return; } } - else { - for (i = 0; i < n; i++) { - if (lambda[i] > minMagThresh) { - /* minification */ - switch (tObj->MinFilter) { - case GL_NEAREST: - sample_2d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], rgba[i]); - break; - case GL_LINEAR: - sample_2d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], rgba[i]); - break; - case GL_NEAREST_MIPMAP_NEAREST: - sample_2d_nearest_mipmap_nearest(ctx, tObj, s[i], t[i], - lambda[i], rgba[i]); - break; - case GL_LINEAR_MIPMAP_NEAREST: - sample_2d_linear_mipmap_nearest(ctx,tObj, s[i], t[i], - lambda[i], rgba[i]); - break; - case GL_NEAREST_MIPMAP_LINEAR: - sample_2d_nearest_mipmap_linear(ctx,tObj, s[i], t[i], - lambda[i], rgba[i]); - break; - case GL_LINEAR_MIPMAP_LINEAR: - sample_2d_linear_mipmap_linear(ctx,tObj, s[i], t[i], - lambda[i], rgba[i] ); - break; - default: - _mesa_problem(NULL, "Bad min filter in sample_2d_texture"); - return; + + if (magStart < magEnd) { + /* do the magnified texels */ + const GLuint m = magEnd - magStart; + + switch (tObj->MagFilter) { + case GL_NEAREST: + if (repeatNoBorder) { + switch (tImg->Format) { + case GL_RGB: + opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + magStart, + NULL, rgba + magStart); + break; + case GL_RGBA: + opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + magStart, + NULL, rgba + magStart); + break; + default: + sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart, + NULL, rgba + magStart ); } } else { - /* magnification */ - switch (tObj->MagFilter) { - case GL_NEAREST: - sample_2d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], rgba[i]); - break; - case GL_LINEAR: - sample_2d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], rgba[i] ); - break; - default: - _mesa_problem(NULL, "Bad mag filter in sample_2d_texture"); - } + sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart, + NULL, rgba + magStart); } + break; + case GL_LINEAR: + sample_linear_2d(ctx, texUnit, tObj, m, texcoords + magStart, + NULL, rgba + magStart); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d"); } } } @@ -1074,7 +1364,7 @@ static void sample_3d_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, - GLfloat s, GLfloat t, GLfloat r, + const GLfloat texcoord[4], GLchan rgba[4]) { const GLint width = img->Width2; /* without border, power of two */ @@ -1082,15 +1372,15 @@ sample_3d_nearest(GLcontext *ctx, const GLint depth = img->Depth2; /* without border, power of two */ GLint i, j, k; - COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i); - COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j); - COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, r, depth, k); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, texcoord[2], depth, k); if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height || k < 0 || k >= (GLint) img->Depth) { - /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */ - COPY_CHAN4(rgba, tObj->BorderColor); + /* Need this test for GL_CLAMP_TO_BORDER mode */ + COPY_CHAN4(rgba, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba); @@ -1109,7 +1399,7 @@ static void sample_3d_linear(GLcontext *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, - GLfloat s, GLfloat t, GLfloat r, + const GLfloat texcoord[4], GLchan rgba[4]) { const GLint width = img->Width2; @@ -1119,9 +1409,9 @@ sample_3d_linear(GLcontext *ctx, GLuint useBorderColor; GLfloat u, v, w; - COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1); - COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1); - COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, r, w, depth, k0, k1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, texcoord[2], w, depth, k0, k1); useBorderColor = 0; if (img->Border) { @@ -1173,7 +1463,7 @@ sample_3d_linear(GLcontext *ctx, GLchan t100[4], t110[4], t101[4], t111[4]; if (useBorderColor & (I0BIT | J0BIT | K0BIT)) { - COPY_CHAN4(t000, tObj->BorderColor); + COPY_CHAN4(t000, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000); @@ -1182,7 +1472,7 @@ sample_3d_linear(GLcontext *ctx, } } if (useBorderColor & (I1BIT | J0BIT | K0BIT)) { - COPY_CHAN4(t100, tObj->BorderColor); + COPY_CHAN4(t100, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100); @@ -1191,7 +1481,7 @@ sample_3d_linear(GLcontext *ctx, } } if (useBorderColor & (I0BIT | J1BIT | K0BIT)) { - COPY_CHAN4(t010, tObj->BorderColor); + COPY_CHAN4(t010, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010); @@ -1200,7 +1490,7 @@ sample_3d_linear(GLcontext *ctx, } } if (useBorderColor & (I1BIT | J1BIT | K0BIT)) { - COPY_CHAN4(t110, tObj->BorderColor); + COPY_CHAN4(t110, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110); @@ -1210,7 +1500,7 @@ sample_3d_linear(GLcontext *ctx, } if (useBorderColor & (I0BIT | J0BIT | K1BIT)) { - COPY_CHAN4(t001, tObj->BorderColor); + COPY_CHAN4(t001, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001); @@ -1219,7 +1509,7 @@ sample_3d_linear(GLcontext *ctx, } } if (useBorderColor & (I1BIT | J0BIT | K1BIT)) { - COPY_CHAN4(t101, tObj->BorderColor); + COPY_CHAN4(t101, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101); @@ -1228,7 +1518,7 @@ sample_3d_linear(GLcontext *ctx, } } if (useBorderColor & (I0BIT | J1BIT | K1BIT)) { - COPY_CHAN4(t011, tObj->BorderColor); + COPY_CHAN4(t011, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011); @@ -1237,7 +1527,7 @@ sample_3d_linear(GLcontext *ctx, } } if (useBorderColor & (I1BIT | J1BIT | K1BIT)) { - COPY_CHAN4(t111, tObj->BorderColor); + COPY_CHAN4(t111, tObj->_BorderChan); } else { (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111); @@ -1299,50 +1589,59 @@ sample_3d_linear(GLcontext *ctx, static void sample_3d_nearest_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat r, - GLfloat lambda, GLchan rgba[4] ) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { - GLint level; - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - sample_3d_nearest(ctx, tObj, tObj->Image[level], s, t, r, rgba); + GLuint i; + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + sample_3d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); + } } static void sample_3d_linear_mipmap_nearest(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat r, - GLfloat lambda, GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - sample_3d_linear(ctx, tObj, tObj->Image[level], s, t, r, rgba); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + sample_3d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); + } } static void sample_3d_nearest_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat r, - GLfloat lambda, GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - - if (level >= tObj->_MaxLevel) { - sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], - s, t, r, rgba); - } - else { - GLchan t0[4], t1[4]; /* texels */ - const GLfloat f = FRAC(lambda); - sample_3d_nearest(ctx, tObj, tObj->Image[level ], s, t, r, t0); - sample_3d_nearest(ctx, tObj, tObj->Image[level+1], s, t, r, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + if (level >= tObj->_MaxLevel) { + sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLchan t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_3d_nearest(ctx, tObj, tObj->Image[level ], texcoord[i], t0); + sample_3d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } @@ -1350,25 +1649,28 @@ sample_3d_nearest_mipmap_linear(GLcontext *ctx, static void sample_3d_linear_mipmap_linear(GLcontext *ctx, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat r, - GLfloat lambda, GLchan rgba[4] ) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - GLint level; - - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - - if (level >= tObj->_MaxLevel) { - sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, r, rgba); - } - else { - GLchan t0[4], t1[4]; /* texels */ - const GLfloat f = FRAC(lambda); - sample_3d_linear(ctx, tObj, tObj->Image[level ], s, t, r, t0); - sample_3d_linear(ctx, tObj, tObj->Image[level+1], s, t, r, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + if (level >= tObj->_MaxLevel) { + sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLchan t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_3d_linear(ctx, tObj, tObj->Image[level ], texcoord[i], t0); + sample_3d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } @@ -1376,15 +1678,14 @@ sample_3d_linear_mipmap_linear(GLcontext *ctx, static void sample_nearest_3d(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]) { GLuint i; struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; (void) lambda; for (i=0;i<n;i++) { - sample_3d_nearest(ctx, tObj, image, s[i], t[i], u[i], rgba[i]); + sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); } } @@ -1393,15 +1694,14 @@ sample_nearest_3d(GLcontext *ctx, GLuint texUnit, static void sample_linear_3d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4] ) + GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4] ) { GLuint i; struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; (void) lambda; for (i=0;i<n;i++) { - sample_3d_linear(ctx, tObj, image, s[i], t[i], u[i], rgba[i]); + sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]); } } @@ -1413,60 +1713,69 @@ sample_linear_3d( GLcontext *ctx, GLuint texUnit, static void sample_lambda_3d( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4] ) { + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ GLuint i; - GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit]; - for (i=0;i<n;i++) { + ASSERT(lambda != NULL); + compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], + n, lambda, &minStart, &minEnd, &magStart, &magEnd); - if (lambda[i] > MinMagThresh) { - /* minification */ - switch (tObj->MinFilter) { - case GL_NEAREST: - sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], u[i], rgba[i]); - break; - case GL_LINEAR: - sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], u[i], rgba[i]); - break; - case GL_NEAREST_MIPMAP_NEAREST: - sample_3d_nearest_mipmap_nearest(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - case GL_LINEAR_MIPMAP_NEAREST: - sample_3d_linear_mipmap_nearest(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - case GL_NEAREST_MIPMAP_LINEAR: - sample_3d_nearest_mipmap_linear(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - case GL_LINEAR_MIPMAP_LINEAR: - sample_3d_linear_mipmap_linear(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - default: - _mesa_problem(NULL, "Bad min filterin sample_3d_texture"); - } + if (minStart < minEnd) { + /* do the minified texels */ + GLuint m = minEnd - minStart; + switch (tObj->MinFilter) { + case GL_NEAREST: + for (i = minStart; i < minEnd; i++) + sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = minStart; i < minEnd; i++) + sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_3d_texture"); + return; } - else { - /* magnification */ - switch (tObj->MagFilter) { - case GL_NEAREST: - sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], u[i], rgba[i]); - break; - case GL_LINEAR: - sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], - s[i], t[i], u[i], rgba[i]); - break; - default: - _mesa_problem(NULL, "Bad mag filter in sample_3d_texture"); - } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + switch (tObj->MagFilter) { + case GL_NEAREST: + for (i = magStart; i < magEnd; i++) + sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = magStart; i < magEnd; i++) + sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_3d_texture"); + return; } } } @@ -1483,8 +1792,7 @@ sample_lambda_3d( GLcontext *ctx, GLuint texUnit, */ static const struct gl_texture_image ** choose_cube_face(const struct gl_texture_object *texObj, - GLfloat rx, GLfloat ry, GLfloat rz, - GLfloat *newS, GLfloat *newT) + const GLfloat texcoord[4], GLfloat newCoord[4]) { /* major axis @@ -1497,6 +1805,9 @@ choose_cube_face(const struct gl_texture_object *texObj, +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz */ + const GLfloat rx = texcoord[0]; + const GLfloat ry = texcoord[1]; + const GLfloat rz = texcoord[2]; const struct gl_texture_image **imgArray; const GLfloat arx = ABSF(rx), ary = ABSF(ry), arz = ABSF(rz); GLfloat sc, tc, ma; @@ -1544,8 +1855,8 @@ choose_cube_face(const struct gl_texture_object *texObj, } } - *newS = ( sc / ma + 1.0F ) * 0.5F; - *newT = ( tc / ma + 1.0F ) * 0.5F; + newCoord[0] = ( sc / ma + 1.0F ) * 0.5F; + newCoord[1] = ( tc / ma + 1.0F ) * 0.5F; return imgArray; } @@ -1553,18 +1864,17 @@ choose_cube_face(const struct gl_texture_object *texObj, static void sample_nearest_cube(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]) { GLuint i; (void) lambda; for (i = 0; i < n; i++) { const struct gl_texture_image **images; - GLfloat newS, newT; - images = choose_cube_face(tObj, s[i], t[i], u[i], &newS, &newT); + GLfloat newCoord[4]; + images = choose_cube_face(tObj, texcoords[i], newCoord); sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel], - newS, newT, rgba[i]); + newCoord, rgba[i]); } } @@ -1572,112 +1882,119 @@ sample_nearest_cube(GLcontext *ctx, GLuint texUnit, static void sample_linear_cube(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4]) + GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4]) { GLuint i; (void) lambda; for (i = 0; i < n; i++) { const struct gl_texture_image **images; - GLfloat newS, newT; - images = choose_cube_face(tObj, s[i], t[i], u[i], &newS, &newT); + GLfloat newCoord[4]; + images = choose_cube_face(tObj, texcoords[i], newCoord); sample_2d_linear(ctx, tObj, images[tObj->BaseLevel], - newS, newT, rgba[i]); + newCoord, rgba[i]); } } static void -sample_cube_nearest_mipmap_nearest(GLcontext *ctx, +sample_cube_nearest_mipmap_nearest(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat u, - GLfloat lambda, GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - const struct gl_texture_image **images; - GLfloat newS, newT; - GLint level; - - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - - images = choose_cube_face(tObj, s, t, u, &newS, &newT); - sample_2d_nearest(ctx, tObj, images[level], newS, newT, rgba); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + images = choose_cube_face(tObj, texcoord[i], newCoord); + sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]); + } } static void -sample_cube_linear_mipmap_nearest(GLcontext *ctx, +sample_cube_linear_mipmap_nearest(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat u, - GLfloat lambda, GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - const struct gl_texture_image **images; - GLfloat newS, newT; - GLint level; - - COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level); - - images = choose_cube_face(tObj, s, t, u, &newS, &newT); - sample_2d_linear(ctx, tObj, images[level], newS, newT, rgba); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level; + COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); + images = choose_cube_face(tObj, texcoord[i], newCoord); + sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]); + } } static void -sample_cube_nearest_mipmap_linear(GLcontext *ctx, +sample_cube_nearest_mipmap_linear(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat u, - GLfloat lambda, GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - const struct gl_texture_image **images; - GLfloat newS, newT; - GLint level; - - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - - images = choose_cube_face(tObj, s, t, u, &newS, &newT); - - if (level >= tObj->_MaxLevel) { - sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], newS, newT, rgba); - } - else { - GLchan t0[4], t1[4]; /* texels */ - const GLfloat f = FRAC(lambda); - sample_2d_nearest(ctx, tObj, images[level ], newS, newT, t0); - sample_2d_nearest(ctx, tObj, images[level+1], newS, newT, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + images = choose_cube_face(tObj, texcoord[i], newCoord); + if (level >= tObj->_MaxLevel) { + sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], + newCoord, rgba[i]); + } + else { + GLchan t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0); + sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } static void -sample_cube_linear_mipmap_linear(GLcontext *ctx, +sample_cube_linear_mipmap_linear(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, - GLfloat s, GLfloat t, GLfloat u, - GLfloat lambda, GLchan rgba[4]) + GLuint n, GLfloat texcoord[][4], + const GLfloat lambda[], GLchan rgba[][4]) { - const struct gl_texture_image **images; - GLfloat newS, newT; - GLint level; - - COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level); - - images = choose_cube_face(tObj, s, t, u, &newS, &newT); - - if (level >= tObj->_MaxLevel) { - sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], newS, newT, rgba); - } - else { - GLchan t0[4], t1[4]; - const GLfloat f = FRAC(lambda); - sample_2d_linear(ctx, tObj, images[level ], newS, newT, t0); - sample_2d_linear(ctx, tObj, images[level+1], newS, newT, t1); - rgba[RCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); - rgba[GCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); - rgba[BCOMP] = (GLchan) INTCAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); - rgba[ACOMP] = (GLchan) INTCAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level; + COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); + images = choose_cube_face(tObj, texcoord[i], newCoord); + if (level >= tObj->_MaxLevel) { + sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], + newCoord, rgba[i]); + } + else { + GLchan t0[4], t1[4]; + const GLfloat f = FRAC(lambda[i]); + sample_2d_linear(ctx, tObj, images[level ], newCoord, t0); + sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1); + rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); + rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); + rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); + rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); + } } } @@ -1685,81 +2002,72 @@ sample_cube_linear_mipmap_linear(GLcontext *ctx, static void sample_lambda_cube( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]) { - GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit]; - GLuint i; + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ - for (i = 0; i < n; i++) { - if (lambda[i] > MinMagThresh) { - /* minification */ - switch (tObj->MinFilter) { - case GL_NEAREST: - { - const struct gl_texture_image **images; - GLfloat newS, newT; - images = choose_cube_face(tObj, s[i], t[i], u[i], - &newS, &newT); - sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel], - newS, newT, rgba[i]); - } - break; - case GL_LINEAR: - { - const struct gl_texture_image **images; - GLfloat newS, newT; - images = choose_cube_face(tObj, s[i], t[i], u[i], - &newS, &newT); - sample_2d_linear(ctx, tObj, images[tObj->BaseLevel], - newS, newT, rgba[i]); - } - break; - case GL_NEAREST_MIPMAP_NEAREST: - sample_cube_nearest_mipmap_nearest(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - case GL_LINEAR_MIPMAP_NEAREST: - sample_cube_linear_mipmap_nearest(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - case GL_NEAREST_MIPMAP_LINEAR: - sample_cube_nearest_mipmap_linear(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - case GL_LINEAR_MIPMAP_LINEAR: - sample_cube_linear_mipmap_linear(ctx, tObj, s[i], t[i], u[i], - lambda[i], rgba[i]); - break; - default: - _mesa_problem(NULL, "Bad min filter in sample_lambda_cube"); - } + ASSERT(lambda != NULL); + compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], + n, lambda, &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + const GLuint m = minEnd - minStart; + switch (tObj->MinFilter) { + case GL_NEAREST: + sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR: + sample_linear_cube(ctx, texUnit, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_cube_nearest_mipmap_nearest(ctx, texUnit, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_cube_linear_mipmap_nearest(ctx, texUnit, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_cube_nearest_mipmap_linear(ctx, texUnit, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_cube_linear_mipmap_linear(ctx, texUnit, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_lambda_cube"); } - else { - /* magnification */ - const struct gl_texture_image **images; - GLfloat newS, newT; - images = choose_cube_face(tObj, s[i], t[i], u[i], - &newS, &newT); - switch (tObj->MagFilter) { - case GL_NEAREST: - sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel], - newS, newT, rgba[i]); - break; - case GL_LINEAR: - sample_2d_linear(ctx, tObj, images[tObj->BaseLevel], - newS, newT, rgba[i]); - break; - default: - _mesa_problem(NULL, "Bad mag filter in sample_lambda_cube"); - } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + const GLuint m = magEnd - magStart; + switch (tObj->MagFilter) { + case GL_NEAREST: + sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + magStart, + lambda + magStart, rgba + magStart); + break; + case GL_LINEAR: + sample_linear_cube(ctx, texUnit, tObj, m, texcoords + magStart, + lambda + magStart, rgba + magStart); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube"); } } } - /**********************************************************************/ /* Texture Rectangle Sampling Functions */ /**********************************************************************/ @@ -1767,8 +2075,7 @@ sample_lambda_cube( GLcontext *ctx, GLuint texUnit, static void sample_nearest_rect(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]) { const struct gl_texture_image *img = tObj->Image[0]; @@ -1783,10 +2090,10 @@ sample_nearest_rect(GLcontext *ctx, GLuint texUnit, ASSERT(tObj->WrapS == GL_CLAMP || tObj->WrapS == GL_CLAMP_TO_EDGE || - tObj->WrapS == GL_CLAMP_TO_BORDER_ARB); + tObj->WrapS == GL_CLAMP_TO_BORDER); ASSERT(tObj->WrapT == GL_CLAMP || tObj->WrapT == GL_CLAMP_TO_EDGE || - tObj->WrapT == GL_CLAMP_TO_BORDER_ARB); + tObj->WrapT == GL_CLAMP_TO_BORDER); ASSERT(img->Format != GL_COLOR_INDEX); /* XXX move Wrap mode tests outside of loops for common cases */ @@ -1794,22 +2101,22 @@ sample_nearest_rect(GLcontext *ctx, GLuint texUnit, GLint row, col; /* NOTE: we DO NOT use [0, 1] texture coordinates! */ if (tObj->WrapS == GL_CLAMP) { - col = IFLOOR( CLAMP(s[i], 0.0F, width) ); + col = IFLOOR( CLAMP(texcoords[i][0], 0.0F, width) ); } else if (tObj->WrapS == GL_CLAMP_TO_EDGE) { - col = IFLOOR( CLAMP(s[i], 0.5F, width - 0.5F) ); + col = IFLOOR( CLAMP(texcoords[i][0], 0.5F, width - 0.5F) ); } else { - col = IFLOOR( CLAMP(s[i], -0.5F, width + 0.5F) ); + col = IFLOOR( CLAMP(texcoords[i][0], -0.5F, width + 0.5F) ); } if (tObj->WrapT == GL_CLAMP) { - row = IFLOOR( CLAMP(t[i], 0.0F, height) ); + row = IFLOOR( CLAMP(texcoords[i][1], 0.0F, height) ); } else if (tObj->WrapT == GL_CLAMP_TO_EDGE) { - row = IFLOOR( CLAMP(t[i], 0.5F, height - 0.5F) ); + row = IFLOOR( CLAMP(texcoords[i][1], 0.5F, height - 0.5F) ); } else { - row = IFLOOR( CLAMP(t[i], -0.5F, height + 0.5F) ); + row = IFLOOR( CLAMP(texcoords[i][1], -0.5F, height + 0.5F) ); } col = CLAMP(col, 0, width_minus_1); @@ -1823,9 +2130,8 @@ sample_nearest_rect(GLcontext *ctx, GLuint texUnit, static void sample_linear_rect(GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], - GLchan rgba[][4]) + GLfloat texcoords[][4], + const GLfloat lambda[], GLchan rgba[][4]) { const struct gl_texture_image *img = tObj->Image[0]; const GLfloat width = (GLfloat) img->Width; @@ -1839,10 +2145,10 @@ sample_linear_rect(GLcontext *ctx, GLuint texUnit, ASSERT(tObj->WrapS == GL_CLAMP || tObj->WrapS == GL_CLAMP_TO_EDGE || - tObj->WrapS == GL_CLAMP_TO_BORDER_ARB); + tObj->WrapS == GL_CLAMP_TO_BORDER); ASSERT(tObj->WrapT == GL_CLAMP || tObj->WrapT == GL_CLAMP_TO_EDGE || - tObj->WrapT == GL_CLAMP_TO_BORDER_ARB); + tObj->WrapT == GL_CLAMP_TO_BORDER); ASSERT(img->Format != GL_COLOR_INDEX); /* XXX lots of opportunity for optimization in this loop */ @@ -1854,22 +2160,22 @@ sample_linear_rect(GLcontext *ctx, GLuint texUnit, /* NOTE: we DO NOT use [0, 1] texture coordinates! */ if (tObj->WrapS == GL_CLAMP) { - fcol = CLAMP(s[i], 0.0F, width); + fcol = CLAMP(texcoords[i][0], 0.0F, width); } else if (tObj->WrapS == GL_CLAMP_TO_EDGE) { - fcol = CLAMP(s[i], 0.5F, width - 0.5F); + fcol = CLAMP(texcoords[i][0], 0.5F, width - 0.5F); } else { - fcol = CLAMP(s[i], -0.5F, width + 0.5F); + fcol = CLAMP(texcoords[i][0], -0.5F, width + 0.5F); } if (tObj->WrapT == GL_CLAMP) { - frow = CLAMP(t[i], 0.0F, height); + frow = CLAMP(texcoords[i][1], 0.0F, height); } else if (tObj->WrapT == GL_CLAMP_TO_EDGE) { - frow = CLAMP(t[i], 0.5F, height - 0.5F); + frow = CLAMP(texcoords[i][1], 0.5F, height - 0.5F); } else { - frow = CLAMP(t[i], -0.5F, height + 0.5F); + frow = CLAMP(texcoords[i][1], -0.5F, height + 0.5F); } /* compute integer rows/columns */ @@ -1897,92 +2203,456 @@ sample_linear_rect(GLcontext *ctx, GLuint texUnit, w11 = a * b ; /* compute weighted average of samples */ - rgba[i][0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]; - rgba[i][1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]; - rgba[i][2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]; - rgba[i][3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]; + rgba[i][0] = + (GLchan) (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]); + rgba[i][1] = + (GLchan) (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]); + rgba[i][2] = + (GLchan) (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]); + rgba[i][3] = + (GLchan) (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]); } } - static void sample_lambda_rect( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]) { - const GLfloat minMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit]; - GLuint i; + GLuint minStart, minEnd, magStart, magEnd; - { + /* We only need lambda to decide between minification and magnification. + * There is no mipmapping with rectangular textures. + */ + compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], + n, lambda, &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + if (tObj->MinFilter == GL_NEAREST) { + sample_nearest_rect( ctx, texUnit, tObj, minEnd - minStart, + texcoords + minStart, NULL, rgba + minStart); + } + else { + sample_linear_rect( ctx, texUnit, tObj, minEnd - minStart, + texcoords + minStart, NULL, rgba + minStart); + } + } + if (magStart < magEnd) { + if (tObj->MagFilter == GL_NEAREST) { + sample_nearest_rect( ctx, texUnit, tObj, magEnd - magStart, + texcoords + magStart, NULL, rgba + magStart); + } + else { + sample_linear_rect( ctx, texUnit, tObj, magEnd - magStart, + texcoords + magStart, NULL, rgba + magStart); + } + } +} + + + +/* + * Sample a shadow/depth texture. + */ +static void +sample_depth_texture( GLcontext *ctx, GLuint unit, + const struct gl_texture_object *tObj, GLuint n, + GLfloat texcoords[][4], const GLfloat lambda[], + GLchan texel[][4] ) +{ + const GLint baseLevel = tObj->BaseLevel; + const struct gl_texture_image *texImage = tObj->Image[baseLevel]; + const GLuint width = texImage->Width; + const GLuint height = texImage->Height; + GLchan ambient; + GLenum function; + GLchan result; + + (void) unit; + + ASSERT(tObj->Image[tObj->BaseLevel]->Format == GL_DEPTH_COMPONENT); + ASSERT(tObj->Target == GL_TEXTURE_1D || + tObj->Target == GL_TEXTURE_2D || + tObj->Target == GL_TEXTURE_RECTANGLE_NV); + + UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient); + + /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */ + + /* XXX this could be precomputed and saved in the texture object */ + if (tObj->CompareFlag) { + /* GL_SGIX_shadow */ + if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { + function = GL_LEQUAL; + } + else { + ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX); + function = GL_GEQUAL; + } + } + else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { + /* GL_ARB_shadow */ + function = tObj->CompareFunc; + } + else { + function = GL_NONE; /* pass depth through as grayscale */ + } + + if (tObj->MagFilter == GL_NEAREST) { + GLuint i; for (i = 0; i < n; i++) { - GLfloat coord[4]; - coord[0] = s[i]; - coord[1] = t[i]; - coord[2] = u[i]; - coord[3] = 1.0; - if (lambda[i] > minMagThresh) { - /* minification */ - switch (tObj->MinFilter) { - case GL_NEAREST: - sample_nearest_rect(ctx, texUnit, tObj, 1, - s + i, t + i, u + i, lambda + i, - rgba + i ); - break; - case GL_LINEAR: - sample_linear_rect(ctx, texUnit, tObj, 1, - s + i, t + i, u + i, lambda + i, - rgba + i ); - break; - default: - _mesa_problem(NULL, "Bad min filter in sample_lambda_rect"); - return; + GLfloat depthSample; + GLint col, row; + /* XXX fix for texture rectangle! */ + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0], width, col); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1], height, row); + depthSample = *((const GLfloat *) texImage->Data + row * width + col); + + switch (function) { + case GL_LEQUAL: + result = (texcoords[i][2] <= depthSample) ? CHAN_MAX : ambient; + break; + case GL_GEQUAL: + result = (texcoords[i][2] >= depthSample) ? CHAN_MAX : ambient; + break; + case GL_LESS: + result = (texcoords[i][2] < depthSample) ? CHAN_MAX : ambient; + break; + case GL_GREATER: + result = (texcoords[i][2] > depthSample) ? CHAN_MAX : ambient; + break; + case GL_EQUAL: + result = (texcoords[i][2] == depthSample) ? CHAN_MAX : ambient; + break; + case GL_NOTEQUAL: + result = (texcoords[i][2] != depthSample) ? CHAN_MAX : ambient; + break; + case GL_ALWAYS: + result = CHAN_MAX; + break; + case GL_NEVER: + result = ambient; + break; + case GL_NONE: + CLAMPED_FLOAT_TO_CHAN(result, depthSample); + break; + default: + _mesa_problem(ctx, "Bad compare func in sample_depth_texture"); + return; + } + + switch (tObj->DepthMode) { + case GL_LUMINANCE: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = CHAN_MAX; + break; + case GL_INTENSITY: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = result; + break; + case GL_ALPHA: + texel[i][RCOMP] = 0; + texel[i][GCOMP] = 0; + texel[i][BCOMP] = 0; + texel[i][ACOMP] = result; + break; + default: + _mesa_problem(ctx, "Bad depth texture mode"); + } + } + } + else { + GLuint i; + ASSERT(tObj->MagFilter == GL_LINEAR); + for (i = 0; i < n; i++) { + GLfloat depth00, depth01, depth10, depth11; + GLint i0, i1, j0, j1; + GLfloat u, v; + GLuint useBorderTexel; + + /* XXX fix for texture rectangle! */ + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0], u, width, i0, i1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1], v, height,j0, j1); + + useBorderTexel = 0; + if (texImage->Border) { + i0 += texImage->Border; + i1 += texImage->Border; + j0 += texImage->Border; + j1 += texImage->Border; + } + else { + if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT; + if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT; + if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT; + if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT; + } + + /* get four depth samples from the texture */ + if (useBorderTexel & (I0BIT | J0BIT)) { + depth00 = 1.0; + } + else { + depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0); + } + if (useBorderTexel & (I1BIT | J0BIT)) { + depth10 = 1.0; + } + else { + depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1); + } + if (useBorderTexel & (I0BIT | J1BIT)) { + depth01 = 1.0; + } + else { + depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0); + } + if (useBorderTexel & (I1BIT | J1BIT)) { + depth11 = 1.0; + } + else { + depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1); + } + + if (0) { + /* compute a single weighted depth sample and do one comparison */ + const GLfloat a = FRAC(u + 1.0F); + const GLfloat b = FRAC(v + 1.0F); + const GLfloat w00 = (1.0F - a) * (1.0F - b); + const GLfloat w10 = ( a) * (1.0F - b); + const GLfloat w01 = (1.0F - a) * ( b); + const GLfloat w11 = ( a) * ( b); + const GLfloat depthSample = w00 * depth00 + w10 * depth10 + + w01 * depth01 + w11 * depth11; + if ((depthSample <= texcoords[i][2] && function == GL_LEQUAL) || + (depthSample >= texcoords[i][2] && function == GL_GEQUAL)) { + result = ambient; + } + else { + result = CHAN_MAX; } } else { - /* magnification */ - switch (tObj->MagFilter) { - case GL_NEAREST: - sample_nearest_rect(ctx, texUnit, tObj, 1, - s + i, t + i, u + i, lambda + i, - rgba + i ); - break; - case GL_LINEAR: - sample_linear_rect(ctx, texUnit, tObj, 1, - s + i, t + i, u + i, lambda + i, - rgba + i ); - break; - default: - _mesa_problem(NULL, "Bad mag filter in sample_lambda_rect"); - return; + /* Do four depth/R comparisons and compute a weighted result. + * If this touches on somebody's I.P., I'll remove this code + * upon request. + */ + const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F; + GLfloat luminance = CHAN_MAXF; + + switch (function) { + case GL_LEQUAL: + if (depth00 <= texcoords[i][2]) luminance -= d; + if (depth01 <= texcoords[i][2]) luminance -= d; + if (depth10 <= texcoords[i][2]) luminance -= d; + if (depth11 <= texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; + break; + case GL_GEQUAL: + if (depth00 >= texcoords[i][2]) luminance -= d; + if (depth01 >= texcoords[i][2]) luminance -= d; + if (depth10 >= texcoords[i][2]) luminance -= d; + if (depth11 >= texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; + break; + case GL_LESS: + if (depth00 < texcoords[i][2]) luminance -= d; + if (depth01 < texcoords[i][2]) luminance -= d; + if (depth10 < texcoords[i][2]) luminance -= d; + if (depth11 < texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; + break; + case GL_GREATER: + if (depth00 > texcoords[i][2]) luminance -= d; + if (depth01 > texcoords[i][2]) luminance -= d; + if (depth10 > texcoords[i][2]) luminance -= d; + if (depth11 > texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; + break; + case GL_EQUAL: + if (depth00 == texcoords[i][2]) luminance -= d; + if (depth01 == texcoords[i][2]) luminance -= d; + if (depth10 == texcoords[i][2]) luminance -= d; + if (depth11 == texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; + break; + case GL_NOTEQUAL: + if (depth00 != texcoords[i][2]) luminance -= d; + if (depth01 != texcoords[i][2]) luminance -= d; + if (depth10 != texcoords[i][2]) luminance -= d; + if (depth11 != texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; + break; + case GL_ALWAYS: + result = 0; + break; + case GL_NEVER: + result = CHAN_MAX; + break; + case GL_NONE: + /* ordinary bilinear filtering */ + { + const GLfloat a = FRAC(u + 1.0F); + const GLfloat b = FRAC(v + 1.0F); + const GLfloat w00 = (1.0F - a) * (1.0F - b); + const GLfloat w10 = ( a) * (1.0F - b); + const GLfloat w01 = (1.0F - a) * ( b); + const GLfloat w11 = ( a) * ( b); + const GLfloat depthSample = w00 * depth00 + w10 * depth10 + + w01 * depth01 + w11 * depth11; + CLAMPED_FLOAT_TO_CHAN(result, depthSample); + } + break; + default: + _mesa_problem(ctx, "Bad compare func in sample_depth_texture"); + return; } } - } - } + switch (tObj->DepthMode) { + case GL_LUMINANCE: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = CHAN_MAX; + break; + case GL_INTENSITY: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = result; + break; + case GL_ALPHA: + texel[i][RCOMP] = 0; + texel[i][GCOMP] = 0; + texel[i][BCOMP] = 0; + texel[i][ACOMP] = result; + break; + default: + _mesa_problem(ctx, "Bad depth texture mode"); + } + } /* for */ + } /* if filter */ } +#if 0 +/* + * Experimental depth texture sampling function. + */ +static void +sample_depth_texture2(const GLcontext *ctx, + const struct gl_texture_unit *texUnit, + GLuint n, GLfloat texcoords[][4], + GLchan texel[][4]) +{ + const struct gl_texture_object *texObj = texUnit->_Current; + const GLint baseLevel = texObj->BaseLevel; + const struct gl_texture_image *texImage = texObj->Image[baseLevel]; + const GLuint width = texImage->Width; + const GLuint height = texImage->Height; + GLchan ambient; + GLboolean lequal, gequal; + + if (texObj->Target != GL_TEXTURE_2D) { + _mesa_problem(ctx, "only 2-D depth textures supported at this time"); + return; + } + + if (texObj->MinFilter != texObj->MagFilter) { + _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); + return; + } + + /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if + * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object + * isn't a depth texture. + */ + if (texImage->Format != GL_DEPTH_COMPONENT) { + _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture"); + return; + } + UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient); + + if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { + lequal = GL_TRUE; + gequal = GL_FALSE; + } + else { + lequal = GL_FALSE; + gequal = GL_TRUE; + } + + { + GLuint i; + for (i = 0; i < n; i++) { + const GLint K = 3; + GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count; + GLfloat w; + GLchan lum; + COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, texcoords[i][0], + width, col); + COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1], + height, row); + + imin = col - K; + imax = col + K; + jmin = row - K; + jmax = row + K; + + if (imin < 0) imin = 0; + if (imax >= width) imax = width - 1; + if (jmin < 0) jmin = 0; + if (jmax >= height) jmax = height - 1; + + samples = (imax - imin + 1) * (jmax - jmin + 1); + count = 0; + for (jj = jmin; jj <= jmax; jj++) { + for (ii = imin; ii <= imax; ii++) { + GLfloat depthSample = *((const GLfloat *) texImage->Data + + jj * width + ii); + if ((depthSample <= r[i] && lequal) || + (depthSample >= r[i] && gequal)) { + count++; + } + } + } + + w = (GLfloat) count / (GLfloat) samples; + w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient); + lum = (GLint) w; + + texel[i][RCOMP] = lum; + texel[i][GCOMP] = lum; + texel[i][BCOMP] = lum; + texel[i][ACOMP] = CHAN_MAX; + } + } +} +#endif + + +/** + * We use this function when a texture object is in an "incomplete" state. + */ static void null_sample_func( GLcontext *ctx, GLuint texUnit, const struct gl_texture_object *tObj, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat u[], const GLfloat lambda[], + GLfloat texcoords[][4], const GLfloat lambda[], GLchan rgba[][4]) { } -/**********************************************************************/ -/* Texture Sampling Setup */ -/**********************************************************************/ - - -/* +/** * Setup the texture sampling function for this texture object. */ void @@ -1991,11 +2661,12 @@ _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, { SWcontext *swrast = SWRAST_CONTEXT(ctx); - if (!t->Complete) { - swrast->TextureSample[texUnit] = null_sample_func; + if (!t->Complete) { + swrast->TextureSample[texUnit] = null_sample_func; } else { - GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter); + const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter); + const GLenum format = t->Image[t->BaseLevel]->Format; if (needLambda) { /* Compute min/mag filter threshold */ @@ -2011,27 +2682,33 @@ _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, switch (t->Target) { case GL_TEXTURE_1D: - if (needLambda) { + if (format == GL_DEPTH_COMPONENT) { + swrast->TextureSample[texUnit] = sample_depth_texture; + } + else if (needLambda) { swrast->TextureSample[texUnit] = sample_lambda_1d; } - else if (t->MinFilter==GL_LINEAR) { + else if (t->MinFilter == GL_LINEAR) { swrast->TextureSample[texUnit] = sample_linear_1d; } else { - ASSERT(t->MinFilter==GL_NEAREST); + ASSERT(t->MinFilter == GL_NEAREST); swrast->TextureSample[texUnit] = sample_nearest_1d; } break; case GL_TEXTURE_2D: - if (needLambda) { + if (format == GL_DEPTH_COMPONENT) { + swrast->TextureSample[texUnit] = sample_depth_texture; + } + else if (needLambda) { swrast->TextureSample[texUnit] = sample_lambda_2d; } - else if (t->MinFilter==GL_LINEAR) { + else if (t->MinFilter == GL_LINEAR) { swrast->TextureSample[texUnit] = sample_linear_2d; } else { GLint baseLevel = t->BaseLevel; - ASSERT(t->MinFilter==GL_NEAREST); + ASSERT(t->MinFilter == GL_NEAREST); if (t->WrapS == GL_REPEAT && t->WrapT == GL_REPEAT && t->Image[baseLevel]->Border == 0 && @@ -2052,23 +2729,23 @@ _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, if (needLambda) { swrast->TextureSample[texUnit] = sample_lambda_3d; } - else if (t->MinFilter==GL_LINEAR) { + else if (t->MinFilter == GL_LINEAR) { swrast->TextureSample[texUnit] = sample_linear_3d; } else { - ASSERT(t->MinFilter==GL_NEAREST); + ASSERT(t->MinFilter == GL_NEAREST); swrast->TextureSample[texUnit] = sample_nearest_3d; } break; - case GL_TEXTURE_CUBE_MAP_ARB: + case GL_TEXTURE_CUBE_MAP: if (needLambda) { swrast->TextureSample[texUnit] = sample_lambda_cube; } - else if (t->MinFilter==GL_LINEAR) { + else if (t->MinFilter == GL_LINEAR) { swrast->TextureSample[texUnit] = sample_linear_cube; } else { - ASSERT(t->MinFilter==GL_NEAREST); + ASSERT(t->MinFilter == GL_NEAREST); swrast->TextureSample[texUnit] = sample_nearest_cube; } break; @@ -2085,7 +2762,7 @@ _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, } break; default: - _mesa_problem(NULL, "invalid dimensions in _mesa_set_texture_sampler"); + _mesa_problem(ctx, "invalid target in _swrast_choose_texture_sample_func"); } } } @@ -2094,70 +2771,131 @@ _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) ) #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) ) + +/** + * Do texture application for GL_ARB/EXT_texture_env_combine. + * This function also supports GL_{EXT,ARB}_texture_env_dot3 and + * GL_ATI_texture_env_combine3 + * + * \param ctx rendering context + * \param textureUnit the texture unit to apply + * \param n number of fragments to process (span width) + * \param primary_rgba incoming fragment color array + * \param texelBuffer pointer to texel colors for all texture units + * + * \param rgba incoming colors, which get modified here + */ static INLINE void -texture_combine(const GLcontext *ctx, - const struct gl_texture_unit *textureUnit, - GLuint n, - CONST GLchan (*primary_rgba)[4], - CONST GLchan (*texel)[4], - GLchan (*rgba)[4]) +texture_combine( const GLcontext *ctx, GLuint unit, GLuint n, + CONST GLchan (*primary_rgba)[4], + CONST GLchan *texelBuffer, + GLchan (*rgba)[4] ) { + const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]); const GLchan (*argRGB [3])[4]; const GLchan (*argA [3])[4]; - GLuint i, j; const GLuint RGBshift = textureUnit->CombineScaleShiftRGB; const GLuint Ashift = textureUnit->CombineScaleShiftA; #if CHAN_TYPE == GL_FLOAT const GLchan RGBmult = (GLfloat) (1 << RGBshift); const GLchan Amult = (GLfloat) (1 << Ashift); + static const GLchan one[4] = { 1.0, 1.0, 1.0, 1.0 }; + static const GLchan zero[4] = { 0.0, 0.0, 0.0, 0.0 }; #else const GLint half = (CHAN_MAX + 1) / 2; + static const GLchan one[4] = { CHAN_MAX, CHAN_MAX, CHAN_MAX, CHAN_MAX }; + static const GLchan zero[4] = { 0, 0, 0, 0 }; #endif + GLuint i, j; + GLuint numColorArgs; + GLuint numAlphaArgs; + /* GLchan ccolor[3][4]; */ DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4); /* mac 32k limitation */ CHECKARRAY(ccolor, return); /* mac 32k limitation */ ASSERT(ctx->Extensions.EXT_texture_env_combine || ctx->Extensions.ARB_texture_env_combine); + ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine); + + + /* + printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n", + textureUnit->CombineModeRGB, + textureUnit->CombineModeA, + textureUnit->CombineSourceRGB[0], + textureUnit->CombineSourceA[0], + textureUnit->CombineSourceRGB[1], + textureUnit->CombineSourceA[1]); + */ /* * Do operand setup for up to 3 operands. Loop over the terms. */ - for (j = 0; j < 3; j++) { - switch (textureUnit->CombineSourceA[j]) { - case GL_TEXTURE: - argA[j] = texel; - break; - case GL_PRIMARY_COLOR_EXT: - argA[j] = primary_rgba; - break; - case GL_PREVIOUS_EXT: - argA[j] = (const GLchan (*)[4]) rgba; - break; - case GL_CONSTANT_EXT: - { - GLchan alpha, (*c)[4] = ccolor[j]; - UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]); - for (i = 0; i < n; i++) - c[i][ACOMP] = alpha; - argA[j] = (const GLchan (*)[4]) ccolor[j]; - } - break; - default: - _mesa_problem(ctx, "invalid combine source"); - } + switch (textureUnit->CombineModeRGB) { + case GL_REPLACE: + numColorArgs = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + numColorArgs = 2; + break; + case GL_INTERPOLATE: + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + case GL_MODULATE_SUBTRACT_ATI: + numColorArgs = 3; + break; + default: + numColorArgs = 0; + ASSERT(0); + break; + } + + switch (textureUnit->CombineModeA) { + case GL_REPLACE: + numAlphaArgs = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + numAlphaArgs = 2; + break; + case GL_INTERPOLATE: + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + case GL_MODULATE_SUBTRACT_ATI: + numAlphaArgs = 3; + break; + default: + numAlphaArgs = 0; + ASSERT(0); + break; + } + + for (j = 0; j < numColorArgs; j++) { + const GLenum srcRGB = textureUnit->CombineSourceRGB[j]; - switch (textureUnit->CombineSourceRGB[j]) { + + switch (srcRGB) { case GL_TEXTURE: - argRGB[j] = texel; + argRGB[j] = (const GLchan (*)[4]) + (texelBuffer + unit * (n * 4 * sizeof(GLchan))); break; - case GL_PRIMARY_COLOR_EXT: + case GL_PRIMARY_COLOR: argRGB[j] = primary_rgba; break; - case GL_PREVIOUS_EXT: + case GL_PREVIOUS: argRGB[j] = (const GLchan (*)[4]) rgba; break; - case GL_CONSTANT_EXT: + case GL_CONSTANT: { GLchan (*c)[4] = ccolor[j]; GLchan red, green, blue, alpha; @@ -2174,8 +2912,24 @@ texture_combine(const GLcontext *ctx, argRGB[j] = (const GLchan (*)[4]) ccolor[j]; } break; + /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources. + */ + case GL_ZERO: + argRGB[j] = & zero; + break; + case GL_ONE: + argRGB[j] = & one; + break; default: - _mesa_problem(ctx, "invalid combine source"); + /* ARB_texture_env_crossbar source */ + { + const GLuint srcUnit = srcRGB - GL_TEXTURE0; + ASSERT(srcUnit < ctx->Const.MaxTextureUnits); + if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled) + return; + argRGB[j] = (const GLchan (*)[4]) + (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan))); + } } if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) { @@ -2208,6 +2962,51 @@ texture_combine(const GLcontext *ctx, } } } + } + + + for (j = 0; j < numAlphaArgs; j++) { + const GLenum srcA = textureUnit->CombineSourceA[j]; + + switch (srcA) { + case GL_TEXTURE: + argA[j] = (const GLchan (*)[4]) + (texelBuffer + unit * (n * 4 * sizeof(GLchan))); + break; + case GL_PRIMARY_COLOR: + argA[j] = primary_rgba; + break; + case GL_PREVIOUS: + argA[j] = (const GLchan (*)[4]) rgba; + break; + case GL_CONSTANT: + { + GLchan alpha, (*c)[4] = ccolor[j]; + UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]); + for (i = 0; i < n; i++) + c[i][ACOMP] = alpha; + argA[j] = (const GLchan (*)[4]) ccolor[j]; + } + break; + /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources. + */ + case GL_ZERO: + argA[j] = & zero; + break; + case GL_ONE: + argA[j] = & one; + break; + default: + /* ARB_texture_env_crossbar source */ + { + const GLuint srcUnit = srcA - GL_TEXTURE0; + ASSERT(srcUnit < ctx->Const.MaxTextureUnits); + if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled) + return; + argA[j] = (const GLchan (*)[4]) + (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan))); + } + } if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) { const GLchan (*src)[4] = argA[j]; @@ -2217,17 +3016,6 @@ texture_combine(const GLcontext *ctx, dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP]; } } - - if (textureUnit->CombineModeRGB == GL_REPLACE && - textureUnit->CombineModeA == GL_REPLACE) { - break; /* done, we need only arg0 */ - } - - if (j == 1 && - textureUnit->CombineModeRGB != GL_INTERPOLATE_EXT && - textureUnit->CombineModeA != GL_INTERPOLATE_EXT) { - break; /* arg0 and arg1 are done. we don't need arg2. */ - } } /* @@ -2305,7 +3093,7 @@ texture_combine(const GLcontext *ctx, } } break; - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: { const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; @@ -2328,7 +3116,7 @@ texture_combine(const GLcontext *ctx, } } break; - case GL_INTERPOLATE_EXT: + case GL_INTERPOLATE: { const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; @@ -2361,7 +3149,7 @@ texture_combine(const GLcontext *ctx, } } break; - case GL_SUBTRACT_ARB: + case GL_SUBTRACT: { const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; @@ -2407,8 +3195,8 @@ texture_combine(const GLcontext *ctx, } } break; - case GL_DOT3_RGB_ARB: - case GL_DOT3_RGBA_ARB: + case GL_DOT3_RGB: + case GL_DOT3_RGBA: { /* DO scale the result by 1 2 or 4 */ const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; @@ -2418,8 +3206,8 @@ texture_combine(const GLcontext *ctx, GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) + (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) + (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F)) - * 4.0F; - dot = CLAMP(dot, 0.0, CHAN_MAXF) * RGBmult; + * 4.0F * RGBmult; + dot = CLAMP(dot, 0.0, CHAN_MAXF); #else GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half, (GLint)arg1[i][RCOMP] - half) + @@ -2427,12 +3215,100 @@ texture_combine(const GLcontext *ctx, (GLint)arg1[i][GCOMP] - half) + S_PROD((GLint)arg0[i][BCOMP] - half, (GLint)arg1[i][BCOMP] - half)) >> 6; - dot = CLAMP(dot, 0, CHAN_MAX) << RGBshift; + dot <<= RGBshift; + dot = CLAMP(dot, 0, CHAN_MAX); #endif rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot; } } break; + case GL_MODULATE_ADD_ATI: + { + const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; + const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; + const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2]; +#if CHAN_TYPE != GL_FLOAT + const GLint shift = CHAN_BITS - RGBshift; +#endif + for (i = 0; i < n; i++) { +#if CHAN_TYPE == GL_FLOAT + rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP]) * RGBmult; + rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP]) * RGBmult; + rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP]) * RGBmult; +#else + GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP]) + + ((GLuint) arg1[i][RCOMP] << CHAN_BITS)) >> shift; + GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP]) + + ((GLuint) arg1[i][GCOMP] << CHAN_BITS)) >> shift; + GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP]) + + ((GLuint) arg1[i][BCOMP] << CHAN_BITS)) >> shift; + rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX); + rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX); + rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX); +#endif + } + } + break; + case GL_MODULATE_SIGNED_ADD_ATI: + { + const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; + const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; + const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2]; +#if CHAN_TYPE != GL_FLOAT + const GLint shift = CHAN_BITS - RGBshift; +#endif + for (i = 0; i < n; i++) { +#if CHAN_TYPE == GL_FLOAT + rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP] - 0.5) * RGBmult; + rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP] - 0.5) * RGBmult; + rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP] - 0.5) * RGBmult; +#else + GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP]) + + (((GLint) arg1[i][RCOMP] - half) << CHAN_BITS)) + >> shift; + GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP]) + + (((GLint) arg1[i][GCOMP] - half) << CHAN_BITS)) + >> shift; + GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP]) + + (((GLint) arg1[i][BCOMP] - half) << CHAN_BITS)) + >> shift; + rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); + rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); + rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); +#endif + } + } + break; + case GL_MODULATE_SUBTRACT_ATI: + { + const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; + const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; + const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2]; +#if CHAN_TYPE != GL_FLOAT + const GLint shift = CHAN_BITS - RGBshift; +#endif + for (i = 0; i < n; i++) { +#if CHAN_TYPE == GL_FLOAT + rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) - arg1[i][RCOMP]) * RGBmult; + rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) - arg1[i][GCOMP]) * RGBmult; + rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) - arg1[i][BCOMP]) * RGBmult; +#else + GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP]) + - ((GLint) arg1[i][RCOMP] << CHAN_BITS)) + >> shift; + GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP]) + - ((GLint) arg1[i][GCOMP] << CHAN_BITS)) + >> shift; + GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP]) + - ((GLint) arg1[i][BCOMP] << CHAN_BITS)) + >> shift; + rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); + rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); + rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); +#endif + } + } + break; default: _mesa_problem(ctx, "invalid combine mode"); } @@ -2489,7 +3365,7 @@ texture_combine(const GLcontext *ctx, } } break; - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: { const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; @@ -2504,7 +3380,7 @@ texture_combine(const GLcontext *ctx, } } break; - case GL_INTERPOLATE_EXT: + case GL_INTERPOLATE: { const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; @@ -2526,7 +3402,7 @@ texture_combine(const GLcontext *ctx, } } break; - case GL_SUBTRACT_ARB: + case GL_SUBTRACT: { const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; @@ -2540,7 +3416,66 @@ texture_combine(const GLcontext *ctx, } } break; - + case GL_MODULATE_ADD_ATI: + { + const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; + const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; + const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2]; +#if CHAN_TYPE != GL_FLOAT + const GLint shift = CHAN_BITS - Ashift; +#endif + for (i = 0; i < n; i++) { +#if CHAN_TYPE == GL_FLOAT + rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP]) * Amult; +#else + GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP]) + + ((GLuint) arg1[i][ACOMP] << CHAN_BITS)) + >> shift; + rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); +#endif + } + } + break; + case GL_MODULATE_SIGNED_ADD_ATI: + { + const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; + const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; + const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2]; +#if CHAN_TYPE != GL_FLOAT + const GLint shift = CHAN_BITS - Ashift; +#endif + for (i = 0; i < n; i++) { +#if CHAN_TYPE == GL_FLOAT + rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP] - 0.5F) * Amult; +#else + GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP]) + + (((GLint) arg1[i][ACOMP] - half) << CHAN_BITS)) + >> shift; + rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); +#endif + } + } + break; + case GL_MODULATE_SUBTRACT_ATI: + { + const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; + const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; + const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2]; +#if CHAN_TYPE != GL_FLOAT + const GLint shift = CHAN_BITS - Ashift; +#endif + for (i = 0; i < n; i++) { +#if CHAN_TYPE == GL_FLOAT + rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) - arg1[i][ACOMP]) * Amult; +#else + GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP]) + - ((GLint) arg1[i][ACOMP] << CHAN_BITS)) + >> shift; + rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); +#endif + } + } + break; default: _mesa_problem(ctx, "invalid combine mode"); } @@ -2551,7 +3486,7 @@ texture_combine(const GLcontext *ctx, * GL_DOT3. */ if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT || - textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) { + textureUnit->CombineModeRGB == GL_DOT3_RGBA) { for (i = 0; i < n; i++) { rgba[i][ACOMP] = rgba[i][RCOMP]; } @@ -2561,14 +3496,23 @@ texture_combine(const GLcontext *ctx, #undef PROD +/** + * Implement NVIDIA's GL_NV_texture_env_combine4 extension when + * texUnit->EnvMode == GL_COMBINE4_NV. + */ +static INLINE void +texture_combine4( const GLcontext *ctx, GLuint unit, GLuint n, + CONST GLchan (*primary_rgba)[4], + CONST GLchan *texelBuffer, + GLchan (*rgba)[4] ) +{ +} -/**********************************************************************/ -/* Texture Application */ -/**********************************************************************/ -/* - * Combine incoming fragment color with texel color to produce output color. +/** + * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND, + * MODULATE, or DECAL) to an array of fragments. * Input: textureUnit - pointer to texture unit to apply * format - base internal texture format * n - number of fragments @@ -2578,7 +3522,7 @@ texture_combine(const GLcontext *ctx, * according to the texture environment mode. */ static void -apply_texture( const GLcontext *ctx, +texture_apply( const GLcontext *ctx, const struct gl_texture_unit *texUnit, GLuint n, CONST GLchan primary_rgba[][4], CONST GLchan texel[][4], @@ -2597,8 +3541,9 @@ apply_texture( const GLcontext *ctx, format = texUnit->_Current->Image[baseLevel]->Format; - if (format==GL_COLOR_INDEX || format==GL_DEPTH_COMPONENT) { - format = GL_RGBA; /* XXXX a hack! */ + if (format == GL_COLOR_INDEX || format == GL_DEPTH_COMPONENT + || format == GL_YCBCR_MESA) { + format = GL_RGBA; /* a bit of a hack */ } switch (texUnit->EnvMode) { @@ -2657,7 +3602,7 @@ apply_texture( const GLcontext *ctx, } break; default: - _mesa_problem(ctx, "Bad format (GL_REPLACE) in apply_texture"); + _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply"); return; } break; @@ -2723,7 +3668,7 @@ apply_texture( const GLcontext *ctx, } break; default: - _mesa_problem(ctx, "Bad format (GL_MODULATE) in apply_texture"); + _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply"); return; } break; @@ -2756,7 +3701,7 @@ apply_texture( const GLcontext *ctx, } break; default: - _mesa_problem(ctx, "Bad format (GL_DECAL) in apply_texture"); + _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply"); return; } break; @@ -2826,7 +3771,7 @@ apply_texture( const GLcontext *ctx, } break; default: - _mesa_problem(ctx, "Bad format (GL_BLEND) in apply_texture"); + _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply"); return; } break; @@ -2903,351 +3848,109 @@ apply_texture( const GLcontext *ctx, } break; default: - _mesa_problem(ctx, "Bad format (GL_ADD) in apply_texture"); + _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply"); return; } break; - case GL_COMBINE_EXT: - texture_combine(ctx, texUnit, n, primary_rgba, texel, rgba); - break; - default: - _mesa_problem(ctx, "Bad env mode in apply_texture"); + _mesa_problem(ctx, "Bad env mode in texture_apply"); return; } } -/* - * Sample a shadow/depth texture. - * Input: ctx - context - * texUnit - the texture unit - * n - number of samples - * s,t,r - array [n] of texture coordinates - * In/Out: rgba - array [n] of texel colors. +/** + * Apply texture mapping to a span of fragments. */ -static void -sample_depth_texture(const GLcontext *ctx, - const struct gl_texture_unit *texUnit, - GLuint n, - const GLfloat s[], const GLfloat t[], const GLfloat r[], - GLchan texel[][4]) +void +_swrast_texture_span( GLcontext *ctx, struct sw_span *span ) { - const struct gl_texture_object *texObj = texUnit->_Current; - const GLint baseLevel = texObj->BaseLevel; - const struct gl_texture_image *texImage = texObj->Image[baseLevel]; - const GLuint width = texImage->Width; - const GLuint height = texImage->Height; - const GLchan ambient = texObj->ShadowAmbient; - GLboolean lequal, gequal; + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLchan primary_rgba[MAX_WIDTH][4]; + GLuint unit; - if (texObj->Target != GL_TEXTURE_2D) { - _mesa_problem(ctx, "only 2-D depth textures supported at this time"); - return; - } + ASSERT(span->end < MAX_WIDTH); + ASSERT(span->arrayMask & SPAN_TEXTURE); - if (texObj->MinFilter != texObj->MagFilter) { - _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); - return; - } - - /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if - * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object - * isn't a depth texture. + /* + * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR) */ - if (texImage->Format != GL_DEPTH_COMPONENT) { - _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture"); - return; - } - - if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { - lequal = GL_TRUE; - gequal = GL_FALSE; - } - else { - lequal = GL_FALSE; - gequal = GL_TRUE; - } + if (swrast->_AnyTextureCombine) + MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan)); - if (texObj->MagFilter == GL_NEAREST) { - GLuint i; - for (i = 0; i < n; i++) { - GLfloat depthSample; - GLint col, row; - COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col); - COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row); - depthSample = *((const GLfloat *) texImage->Data + row * width + col); - if ((r[i] <= depthSample && lequal) || - (r[i] >= depthSample && gequal)) { - texel[i][RCOMP] = CHAN_MAX; - texel[i][GCOMP] = CHAN_MAX; - texel[i][BCOMP] = CHAN_MAX; - texel[i][ACOMP] = CHAN_MAX; - } - else { - texel[i][RCOMP] = ambient; - texel[i][GCOMP] = ambient; - texel[i][BCOMP] = ambient; - texel[i][ACOMP] = CHAN_MAX; - } - } - } - else { - GLuint i; - ASSERT(texObj->MagFilter == GL_LINEAR); - for (i = 0; i < n; i++) { - GLfloat depth00, depth01, depth10, depth11; - GLint i0, i1, j0, j1; - GLfloat u, v; - GLuint useBorderTexel; - - COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapS, s[i], u, width, i0, i1); - COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapT, t[i], v, height,j0, j1); - - useBorderTexel = 0; - if (texImage->Border) { - i0 += texImage->Border; - i1 += texImage->Border; - j0 += texImage->Border; - j1 += texImage->Border; - } - else { - if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT; - if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT; - if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT; - if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT; - } - - /* get four depth samples from the texture */ - if (useBorderTexel & (I0BIT | J0BIT)) { - depth00 = 1.0; - } - else { - depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0); - } - if (useBorderTexel & (I1BIT | J0BIT)) { - depth10 = 1.0; - } - else { - depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1); - } - if (useBorderTexel & (I0BIT | J1BIT)) { - depth01 = 1.0; - } - else { - depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0); - } - if (useBorderTexel & (I1BIT | J1BIT)) { - depth11 = 1.0; - } - else { - depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1); - } - - if (0) { - /* compute a single weighted depth sample and do one comparison */ - const GLfloat a = FRAC(u + 1.0F); - const GLfloat b = FRAC(v + 1.0F); - const GLfloat w00 = (1.0F - a) * (1.0F - b); - const GLfloat w10 = ( a) * (1.0F - b); - const GLfloat w01 = (1.0F - a) * ( b); - const GLfloat w11 = ( a) * ( b); - const GLfloat depthSample = w00 * depth00 + w10 * depth10 - + w01 * depth01 + w11 * depth11; - if ((depthSample <= r[i] && lequal) || - (depthSample >= r[i] && gequal)) { - texel[i][RCOMP] = ambient; - texel[i][GCOMP] = ambient; - texel[i][BCOMP] = ambient; - texel[i][ACOMP] = CHAN_MAX; - } - else { - texel[i][RCOMP] = CHAN_MAX; - texel[i][GCOMP] = CHAN_MAX; - texel[i][BCOMP] = CHAN_MAX; - texel[i][ACOMP] = CHAN_MAX; - } - } - else { - /* Do four depth/R comparisons and compute a weighted result. - * If this touches on somebody's I.P., I'll remove this code - * upon request. - */ - const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F; - GLfloat luminance = CHAN_MAXF; - GLchan lum; - if (lequal) { - if (depth00 <= r[i]) luminance -= d; - if (depth01 <= r[i]) luminance -= d; - if (depth10 <= r[i]) luminance -= d; - if (depth11 <= r[i]) luminance -= d; - } - else { - if (depth00 >= r[i]) luminance -= d; - if (depth01 >= r[i]) luminance -= d; - if (depth10 >= r[i]) luminance -= d; - if (depth11 >= r[i]) luminance -= d; - } - lum = (GLchan) luminance; - texel[i][RCOMP] = lum; - texel[i][GCOMP] = lum; - texel[i][BCOMP] = lum; - texel[i][ACOMP] = CHAN_MAX; - } - } - } -} - - -#if 0 -/* - * Experimental depth texture sampling function. - */ -static void -sample_depth_texture2(const GLcontext *ctx, - const struct gl_texture_unit *texUnit, - GLuint n, - const GLfloat s[], const GLfloat t[], const GLfloat r[], - GLchan texel[][4]) -{ - const struct gl_texture_object *texObj = texUnit->_Current; - const GLint baseLevel = texObj->BaseLevel; - const struct gl_texture_image *texImage = texObj->Image[baseLevel]; - const GLuint width = texImage->Width; - const GLuint height = texImage->Height; - const GLchan ambient = texObj->ShadowAmbient; - GLboolean lequal, gequal; - - if (texObj->Dimensions != 2) { - _mesa_problem(ctx, "only 2-D depth textures supported at this time"); - return; - } - - if (texObj->MinFilter != texObj->MagFilter) { - _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); - return; - } - - /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if - * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object - * isn't a depth texture. + /* + * Must do all texture sampling before combining in order to + * accomodate GL_ARB_texture_env_crossbar. */ - if (texImage->Format != GL_DEPTH_COMPONENT) { - _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture"); - return; - } - - if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { - lequal = GL_TRUE; - gequal = GL_FALSE; - } - else { - lequal = GL_FALSE; - gequal = GL_TRUE; - } - - { - GLuint i; - for (i = 0; i < n; i++) { - const GLint K = 3; - GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count; - GLfloat w; - GLchan lum; - COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col); - COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row); - - imin = col - K; - imax = col + K; - jmin = row - K; - jmax = row + K; - - if (imin < 0) imin = 0; - if (imax >= width) imax = width - 1; - if (jmin < 0) jmin = 0; - if (jmax >= height) jmax = height - 1; - - samples = (imax - imin + 1) * (jmax - jmin + 1); - count = 0; - for (jj = jmin; jj <= jmax; jj++) { - for (ii = imin; ii <= imax; ii++) { - GLfloat depthSample = *((const GLfloat *) texImage->Data - + jj * width + ii); - if ((depthSample <= r[i] && lequal) || - (depthSample >= r[i] && gequal)) { - count++; - } - } - } - - w = (GLfloat) count / (GLfloat) samples; - w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient); - lum = (GLint) w; - - texel[i][RCOMP] = lum; - texel[i][GCOMP] = lum; - texel[i][BCOMP] = lum; - texel[i][ACOMP] = CHAN_MAX; - } - } -} -#endif - - -/* - * Apply a unit of texture mapping to the incoming fragments. - */ -void -_swrast_texture_fragments( GLcontext *ctx, GLuint texUnit, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat r[], GLfloat lambda[], - CONST GLchan primary_rgba[][4], GLchan rgba[][4] ) -{ - const GLuint mask = TEXTURE0_ANY << (texUnit * NUM_TEXTURE_TARGETS); - - if (ctx->Texture._ReallyEnabled & mask) { - const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit]; - - if (textureUnit->_Current) { /* XXX need this? */ - GLchan texel[PB_SIZE][4]; - - if (lambda) { - if (textureUnit->LodBias != 0.0F) { + for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { + if (ctx->Texture.Unit[unit]._ReallyEnabled) { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + const struct gl_texture_object *curObj = texUnit->_Current; + GLfloat *lambda = span->array->lambda[unit]; + GLchan (*texels)[4] = (GLchan (*)[4]) + (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan))); + + /* adjust texture lod (lambda) */ + if (span->arrayMask | SPAN_LAMBDA) { + if (texUnit->LodBias != 0.0F) { /* apply LOD bias, but don't clamp yet */ GLuint i; - for (i=0;i<n;i++) { - lambda[i] += textureUnit->LodBias; + for (i = 0; i < span->end; i++) { + lambda[i] += texUnit->LodBias; } } - if (textureUnit->_Current->MinLod != -1000.0 || - textureUnit->_Current->MaxLod != 1000.0) { + if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) { /* apply LOD clamping to lambda */ - const GLfloat min = textureUnit->_Current->MinLod; - const GLfloat max = textureUnit->_Current->MaxLod; + const GLfloat min = curObj->MinLod; + const GLfloat max = curObj->MaxLod; GLuint i; - for (i=0;i<n;i++) { + for (i = 0; i < span->end; i++) { GLfloat l = lambda[i]; lambda[i] = CLAMP(l, min, max); } } } - /* Sample the texture. */ - if (textureUnit->_Current->CompareFlag) { - /* depth texture */ - sample_depth_texture(ctx, textureUnit, n, s, t, r, texel); + /* Sample the texture (span->end fragments) */ + swrast->TextureSample[unit]( ctx, unit, texUnit->_Current, + span->end, span->array->texcoords[unit], + lambda, texels ); + } + } + + /* + * OK, now apply the texture (aka texture combine/blend). + * We modify the span->color.rgba values. + */ + for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { + if (ctx->Texture.Unit[unit]._ReallyEnabled) { + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + if (texUnit->EnvMode == GL_COMBINE) { + /* GL_ARB/EXT_texture_env_combine */ + texture_combine( ctx, unit, span->end, + (CONST GLchan (*)[4]) primary_rgba, + swrast->TexelBuffer, + span->array->rgba ); + } + else if (texUnit->EnvMode == GL_COMBINE4_NV) { + /* GL_NV_texture_env_combine4 */ + texture_combine4( ctx, unit, span->end, + (CONST GLchan (*)[4]) primary_rgba, + swrast->TexelBuffer, + span->array->rgba ); } else { - /* color texture */ - SWRAST_CONTEXT(ctx)->TextureSample[texUnit]( ctx, texUnit, - textureUnit->_Current, - n, s, t, r, - lambda, texel ); - } - apply_texture( ctx, textureUnit, n, primary_rgba, - (const GLchan (*)[4]) texel, rgba ); + /* conventional texture blend */ + const GLchan (*texels)[4] = (const GLchan (*)[4]) + (swrast->TexelBuffer + unit * + (span->end * 4 * sizeof(GLchan))); + texture_apply( ctx, texUnit, span->end, + (CONST GLchan (*)[4]) primary_rgba, texels, + span->array->rgba ); + } } } } diff --git a/xc/extras/Mesa/src/swrast/s_texture.h b/xc/extras/Mesa/src/swrast/s_texture.h index c1b792094..0157071f1 100644 --- a/xc/extras/Mesa/src/swrast/s_texture.h +++ b/xc/extras/Mesa/src/swrast/s_texture.h @@ -1,10 +1,9 @@ -/* $Id: s_texture.h,v 1.1.1.1 2002/10/22 13:06:51 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -40,10 +39,6 @@ _swrast_choose_texture_sample_func( GLcontext *ctx, extern void -_swrast_texture_fragments( GLcontext *ctx, GLuint texSet, GLuint n, - const GLfloat s[], const GLfloat t[], - const GLfloat r[], GLfloat lambda[], - CONST GLchan primary_rgba[][4], GLchan rgba[][4] ); - +_swrast_texture_span( GLcontext *ctx, struct sw_span *span ); #endif diff --git a/xc/extras/Mesa/src/swrast/s_triangle.c b/xc/extras/Mesa/src/swrast/s_triangle.c index ad9e77926..a4efb679f 100644 --- a/xc/extras/Mesa/src/swrast/s_triangle.c +++ b/xc/extras/Mesa/src/swrast/s_triangle.c @@ -1,10 +1,9 @@ -/* $Id: s_triangle.c,v 1.1.1.1 2002/10/22 13:06:48 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.2 + * Version: 5.0 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -34,8 +33,8 @@ #include "glheader.h" #include "context.h" #include "colormac.h" +#include "imports.h" #include "macros.h" -#include "mem.h" #include "mmath.h" #include "texformat.h" #include "teximage.h" @@ -47,10 +46,11 @@ #include "s_feedback.h" #include "s_span.h" #include "s_triangle.h" -#include "s_trispan.h" - +/* + * Just used for feedback mode. + */ GLboolean _mesa_cull_triangle( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, @@ -81,18 +81,12 @@ static void flat_ci_triangle( GLcontext *ctx, #define INTERP_Z 1 #define INTERP_FOG 1 -#define RENDER_SPAN( span ) \ - GLdepth zSpan[MAX_WIDTH]; \ - GLfloat fogSpan[MAX_WIDTH]; \ - GLuint i; \ - for (i = 0; i < span.count; i++) { \ - zSpan[i] = FixedToDepth(span.z); \ - span.z += span.zStep; \ - fogSpan[i] = span.fog; \ - span.fog += span.fogStep; \ - } \ - _mesa_write_monoindex_span(ctx, span.count, span.x, span.y, \ - zSpan, fogSpan, v2->index, NULL, GL_POLYGON ); +#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); #include "s_tritemp.h" } @@ -111,21 +105,7 @@ static void smooth_ci_triangle( GLcontext *ctx, #define INTERP_FOG 1 #define INTERP_INDEX 1 -#define RENDER_SPAN( span ) \ - GLdepth zSpan[MAX_WIDTH]; \ - GLfloat fogSpan[MAX_WIDTH]; \ - GLuint indexSpan[MAX_WIDTH]; \ - GLuint i; \ - for (i = 0; i < span.count; i++) { \ - zSpan[i] = FixedToDepth(span.z); \ - span.z += span.zStep; \ - indexSpan[i] = FixedToInt(span.index); \ - span.index += span.indexStep; \ - fogSpan[i] = span.fog; \ - span.fog += span.fogStep; \ - } \ - _mesa_write_index_span(ctx, span.count, span.x, span.y, \ - zSpan, fogSpan, indexSpan, NULL, GL_POLYGON); +#define RENDER_SPAN( span ) _mesa_write_index_span(ctx, &span); #include "s_tritemp.h" } @@ -144,23 +124,22 @@ static void flat_rgba_triangle( GLcontext *ctx, #define INTERP_FOG 1 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define RENDER_SPAN( span ) \ - GLdepth zSpan[MAX_WIDTH]; \ - GLfloat fogSpan[MAX_WIDTH]; \ - GLuint i; \ - for (i = 0; i < span.count; i++) { \ - zSpan[i] = FixedToDepth(span.z); \ - span.z += span.zStep; \ - fogSpan[i] = span.fog; \ - span.fog += span.fogStep; \ - } \ - _mesa_write_monocolor_span(ctx, span.count, span.x, span.y, zSpan, \ - fogSpan, v2->color, NULL, GL_POLYGON ); +#define SETUP_CODE \ + ASSERT(ctx->Texture._EnabledUnits == 0); \ + 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); #include "s_tritemp.h" - - ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ - ASSERT(ctx->Light.ShadeModel==GL_FLAT); } @@ -180,33 +159,17 @@ static void smooth_rgba_triangle( GLcontext *ctx, #define INTERP_RGB 1 #define INTERP_ALPHA 1 -#define RENDER_SPAN( span ) \ - GLdepth zSpan[MAX_WIDTH]; \ - GLchan rgbaSpan[MAX_WIDTH][4]; \ - GLfloat fogSpan[MAX_WIDTH]; \ - GLuint i; \ - for (i = 0; i < span.count; i++) { \ - rgbaSpan[i][RCOMP] = FixedToChan(span.red); \ - rgbaSpan[i][GCOMP] = FixedToChan(span.green); \ - rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \ - rgbaSpan[i][ACOMP] = FixedToChan(span.alpha); \ - span.red += span.redStep; \ - span.green += span.greenStep; \ - span.blue += span.blueStep; \ - span.alpha += span.alphaStep; \ - zSpan[i] = FixedToDepth(span.z); \ - span.z += span.zStep; \ - fogSpan[i] = span.fog; \ - span.fog += span.fogStep; \ - } \ - _mesa_write_rgba_span(ctx, span.count, span.x, span.y, \ - (CONST GLdepth *) zSpan, \ - fogSpan, rgbaSpan, NULL, GL_POLYGON); +#define SETUP_CODE \ + { \ + /* texturing must be off */ \ + ASSERT(ctx->Texture._EnabledUnits == 0); \ + ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); \ + } + +#define RENDER_SPAN( span ) _mesa_write_rgba_span(ctx, &span); #include "s_tritemp.h" - ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ - ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); } @@ -228,7 +191,7 @@ static void simple_textured_triangle( GLcontext *ctx, #define SETUP_CODE \ SWcontext *swrast = SWRAST_CONTEXT(ctx); \ struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ - GLint b = obj->BaseLevel; \ + 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; \ @@ -241,23 +204,23 @@ static void simple_textured_triangle( GLcontext *ctx, } #define RENDER_SPAN( span ) \ - GLchan rgbSpan[MAX_WIDTH][3]; \ GLuint i; \ span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ span.intTex[1] -= FIXED_HALF; \ - for (i = 0; i < span.count; i++) { \ + 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 */ \ - rgbSpan[i][RCOMP] = texture[pos]; \ - rgbSpan[i][GCOMP] = texture[pos+1]; \ - rgbSpan[i][BCOMP] = texture[pos+2]; \ + span.array->rgb[i][RCOMP] = texture[pos]; \ + span.array->rgb[i][GCOMP] = texture[pos+1]; \ + span.array->rgb[i][BCOMP] = texture[pos+2]; \ span.intTex[0] += span.intTexStep[0]; \ span.intTex[1] += span.intTexStep[1]; \ } \ - (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \ - (CONST GLchan (*)[3]) rgbSpan, NULL ); + (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ + (CONST GLchan (*)[3]) span.array->rgb,\ + NULL ); #include "s_tritemp.h" } @@ -284,46 +247,45 @@ static void simple_z_textured_triangle( GLcontext *ctx, #define SETUP_CODE \ SWcontext *swrast = SWRAST_CONTEXT(ctx); \ struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ - 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; \ + 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; \ - GLint smask = obj->Image[b]->Width - 1; \ - GLint tmask = obj->Image[b]->Height - 1; \ + const GLint smask = obj->Image[b]->Width - 1; \ + const GLint tmask = obj->Image[b]->Height - 1; \ if (!texture) { \ /* this shouldn't happen */ \ return; \ } #define RENDER_SPAN( span ) \ - GLchan rgbSpan[MAX_WIDTH][3]; \ - GLubyte mask[MAX_WIDTH]; \ GLuint i; \ span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ span.intTex[1] -= FIXED_HALF; \ - for (i = 0; i < span.count; i++) { \ + 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 */ \ - rgbSpan[i][RCOMP] = texture[pos]; \ - rgbSpan[i][GCOMP] = texture[pos+1]; \ - rgbSpan[i][BCOMP] = texture[pos+2]; \ + span.array->rgb[i][RCOMP] = texture[pos]; \ + span.array->rgb[i][GCOMP] = texture[pos+1]; \ + span.array->rgb[i][BCOMP] = texture[pos+2]; \ zRow[i] = z; \ - mask[i] = 1; \ + span.array->mask[i] = 1; \ } \ else { \ - mask[i] = 0; \ + span.array->mask[i] = 0; \ } \ span.intTex[0] += span.intTexStep[0]; \ span.intTex[1] += span.intTexStep[1]; \ span.z += span.zStep; \ } \ - (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \ - (CONST GLchan (*)[3]) rgbSpan, mask ); + (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ + (CONST GLchan (*)[3]) span.array->rgb,\ + span.array->mask ); #include "s_tritemp.h" } @@ -341,7 +303,6 @@ struct affine_info const GLchan *texture; GLfixed er, eg, eb, ea; GLint tbytesline, tsize; - GLint fixedToDepthShift; }; @@ -349,8 +310,8 @@ struct affine_info * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD * texture env modes. */ -static void -affine_span(GLcontext *ctx, struct triangle_span *span, +static INLINE void +affine_span(GLcontext *ctx, struct sw_span *span, struct affine_info *info) { GLchan sample[4]; /* the filtered texture sample */ @@ -388,7 +349,7 @@ affine_span(GLcontext *ctx, struct triangle_span *span, sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) + \ tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT -#define MODULATE \ +#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); \ @@ -440,17 +401,13 @@ affine_span(GLcontext *ctx, struct triangle_span *span, #define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00) #define SPAN_NEAREST(DO_TEX,COMP) \ - for (i = 0; i < span->count; i++) { \ + 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; \ - zspan[i] = FixedToDepth(span->z); \ - fogspan[i] = span->fog; \ DO_TEX; \ - span->fog += span->fogStep; \ - span->z += span->zStep; \ span->red += span->redStep; \ span->green += span->greenStep; \ span->blue += span->blueStep; \ @@ -461,7 +418,7 @@ affine_span(GLcontext *ctx, struct triangle_span *span, } #define SPAN_LINEAR(DO_TEX,COMP) \ - for (i = 0; i < span->count; i++) { \ + 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; \ @@ -484,11 +441,7 @@ affine_span(GLcontext *ctx, struct triangle_span *span, tex01 -= info->tbytesline; \ tex11 -= info->tbytesline; \ } \ - zspan[i] = FixedToDepth(span->z); \ - fogspan[i] = span->fog; \ DO_TEX; \ - span->fog += span->fogStep; \ - span->z += span->zStep; \ span->red += span->redStep; \ span->green += span->greenStep; \ span->blue += span->blueStep; \ @@ -498,14 +451,9 @@ affine_span(GLcontext *ctx, struct triangle_span *span, dest += 4; \ } -#define FixedToDepth(F) ((F) >> fixedToDepthShift) GLuint i; - GLdepth zspan[MAX_WIDTH]; - GLfloat fogspan[MAX_WIDTH]; - GLchan rgba[MAX_WIDTH][4]; - GLchan *dest = rgba[0]; - const GLint fixedToDepthShift = info->fixedToDepthShift; + GLchan *dest = span->array->rgba[0]; span->intTex[0] -= FIXED_HALF; span->intTex[1] -= FIXED_HALF; @@ -528,7 +476,8 @@ affine_span(GLcontext *ctx, struct triangle_span *span, SPAN_NEAREST(NEAREST_RGB;ADD,3); break; default: - abort(); + _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR"); + return; } break; case GL_RGBA: @@ -549,7 +498,8 @@ affine_span(GLcontext *ctx, struct triangle_span *span, SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); break; default: - abort(); + _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR"); + return; } break; } @@ -575,7 +525,8 @@ affine_span(GLcontext *ctx, struct triangle_span *span, SPAN_LINEAR(LINEAR_RGB;ADD,3); break; default: - abort(); + _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR"); + return; } break; case GL_RGBA: @@ -596,17 +547,19 @@ affine_span(GLcontext *ctx, struct triangle_span *span, SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); break; default: - abort(); - } break; + _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR"); + return; + } + break; } break; } - _mesa_write_rgba_span(ctx, span->count, span->x, span->y, - zspan, fogspan, rgba, NULL, GL_POLYGON); + span->interpMask &= ~SPAN_RGBA; + ASSERT(span->arrayMask & SPAN_RGBA); + _mesa_write_rgba_span(ctx, span); #undef SPAN_NEAREST #undef SPAN_LINEAR -#undef FixedToDepth } @@ -632,10 +585,9 @@ static void affine_textured_triangle( GLcontext *ctx, struct affine_info info; \ struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ struct gl_texture_object *obj = unit->Current2D; \ - GLint b = obj->BaseLevel; \ - GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ - GLfloat theight = (GLfloat) obj->Image[b]->Height; \ - info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\ + const GLint b = obj->BaseLevel; \ + const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ + const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ info.texture = (const GLchan *) obj->Image[b]->Data; \ info.twidth_log2 = obj->Image[b]->WidthLog2; \ info.smask = obj->Image[b]->Width - 1; \ @@ -643,6 +595,7 @@ static void affine_textured_triangle( GLcontext *ctx, 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) */ \ @@ -695,12 +648,11 @@ struct persp_info const GLchan *texture; GLfixed er, eg, eb, ea; /* texture env color */ GLint tbytesline, tsize; - GLint fixedToDepthShift; }; -static void -fast_persp_span(GLcontext *ctx, struct triangle_span *span, +static INLINE void +fast_persp_span(GLcontext *ctx, struct sw_span *span, struct persp_info *info) { GLchan sample[4]; /* the filtered texture sample */ @@ -711,7 +663,7 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). */ #define SPAN_NEAREST(DO_TEX,COMP) \ - for (i = 0; i < span->count; i++) { \ + 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); \ @@ -720,11 +672,7 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, GLint t = IFLOOR(t_tmp) & info->tmask; \ GLint pos = (t << info->twidth_log2) + s; \ const GLchan *tex00 = info->texture + COMP * pos; \ - zspan[i] = FixedToDepth(span->z); \ - fogspan[i] = span->fog; \ DO_TEX; \ - span->fog += span->fogStep; \ - span->z += span->zStep; \ span->red += span->redStep; \ span->green += span->greenStep; \ span->blue += span->blueStep; \ @@ -736,7 +684,7 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, } #define SPAN_LINEAR(DO_TEX,COMP) \ - for (i = 0; i < span->count; i++) { \ + 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); \ @@ -764,11 +712,7 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, tex01 -= info->tbytesline; \ tex11 -= info->tbytesline; \ } \ - zspan[i] = FixedToDepth(span->z); \ - fogspan[i] = span->fog; \ DO_TEX; \ - span->fog += span->fogStep; \ - span->z += span->zStep; \ span->red += span->redStep; \ span->green += span->greenStep; \ span->blue += span->blueStep; \ @@ -779,23 +723,17 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, dest += 4; \ } -#define FixedToDepth(F) ((F) >> fixedToDepthShift) - GLuint i; - GLdepth zspan[MAX_WIDTH]; GLfloat tex_coord[3], tex_step[3]; - GLfloat fogspan[MAX_WIDTH]; - GLchan rgba[MAX_WIDTH][4]; - GLchan *dest = rgba[0]; - const GLint fixedToDepthShift = info->fixedToDepthShift; - - 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); + GLchan *dest = span->array->rgba[0]; + + tex_coord[0] = span->tex[0][0] * (info->smask + 1); + tex_step[0] = span->texStepX[0][0] * (info->smask + 1); + tex_coord[1] = span->tex[0][1] * (info->tmask + 1); + tex_step[1] = span->texStepX[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]; + tex_coord[2] = span->tex[0][3]; + tex_step[2] = span->texStepX[0][3]; switch (info->filter) { case GL_NEAREST: @@ -816,7 +754,8 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, SPAN_NEAREST(NEAREST_RGB;ADD,3); break; default: - abort(); + _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR"); + return; } break; case GL_RGBA: @@ -837,7 +776,8 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); break; default: - abort(); + _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR"); + return; } break; } @@ -861,7 +801,8 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, SPAN_LINEAR(LINEAR_RGB;ADD,3); break; default: - abort(); + _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR"); + return; } break; case GL_RGBA: @@ -882,25 +823,19 @@ fast_persp_span(GLcontext *ctx, struct triangle_span *span, SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); break; default: - abort(); + _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR"); + return; } break; } break; } - /* This does not seem to be necessary, but I don't know !! */ - /* span->tex[0][0] = tex_coord[0] / (info->smask + 1), - span->tex[0][1] = tex_coord[1] / (info->tmask + 1),*/ - /* span->tex[0][2] only if 3D-texturing, here only 2D */ - /* span->tex[0][3] = tex_coord[2]; */ - _mesa_write_rgba_span(ctx, span->count, span->x, span->y, - zspan, fogspan, rgba, NULL, GL_POLYGON); - + ASSERT(span->arrayMask & SPAN_RGBA); + _mesa_write_rgba_span(ctx, span); #undef SPAN_NEAREST #undef SPAN_LINEAR -#undef FixedToDepth } @@ -924,10 +859,9 @@ static void persp_textured_triangle( GLcontext *ctx, #define SETUP_CODE \ struct persp_info info; \ - struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ - struct gl_texture_object *obj = unit->Current2D; \ - GLint b = obj->BaseLevel; \ - info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\ + const struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ + const struct gl_texture_object *obj = unit->Current2D; \ + const GLint b = obj->BaseLevel; \ info.texture = (const GLchan *) obj->Image[b]->Data; \ info.twidth_log2 = obj->Image[b]->WidthLog2; \ info.smask = obj->Image[b]->Width - 1; \ @@ -969,7 +903,10 @@ static void persp_textured_triangle( GLcontext *ctx, } \ info.tsize = obj->Image[b]->Height * info.tbytesline; -#define RENDER_SPAN( span ) fast_persp_span(ctx, &span, &info); +#define RENDER_SPAN( span ) \ + span.interpMask &= ~SPAN_RGBA; \ + span.arrayMask |= SPAN_RGBA; \ + fast_persp_span(ctx, &span, &info); #include "s_tritemp.h" @@ -978,335 +915,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); -} - @@ -1323,173 +931,27 @@ static void general_textured_triangle( GLcontext *ctx, #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 \ - const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ - const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ - DEFARRAY(GLfloat, sSpan, MAX_WIDTH); /* mac 32k limitation */ \ - DEFARRAY(GLfloat, tSpan, MAX_WIDTH); /* mac 32k limitation */ \ - DEFARRAY(GLfloat, uSpan, MAX_WIDTH); /* mac 32k limitation */ \ - CHECKARRAY(sSpan, return); /* mac 32k limitation */ \ - CHECKARRAY(tSpan, return); /* mac 32k limitation */ \ - CHECKARRAY(uSpan, return); /* mac 32k limitation */ \ - span.texWidth[0] = (GLfloat) texImage->Width; \ - span.texHeight[0] = (GLfloat) texImage->Height; \ - (void) fixedToDepthShift; - -#define RENDER_SPAN( span ) \ - GLdepth zSpan[MAX_WIDTH]; \ - GLfloat fogSpan[MAX_WIDTH]; \ - GLchan rgbaSpan[MAX_WIDTH][4]; \ - GLuint i; \ - /* NOTE: we could just call rasterize_span() here instead */ \ - for (i = 0; i < span.count; i++) { \ - GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0; \ - zSpan[i] = FixedToDepth(span.z); \ - span.z += span.zStep; \ - fogSpan[i] = span.fog; \ - span.fog += span.fogStep; \ - rgbaSpan[i][RCOMP] = FixedToChan(span.red); \ - rgbaSpan[i][GCOMP] = FixedToChan(span.green); \ - rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \ - rgbaSpan[i][ACOMP] = FixedToChan(span.alpha); \ - span.red += span.redStep; \ - span.green += span.greenStep; \ - span.blue += span.blueStep; \ - span.alpha += span.alphaStep; \ - sSpan[i] = (GLfloat) (span.tex[0][0] * invQ); \ - tSpan[i] = (GLfloat) (span.tex[0][1] * invQ); \ - uSpan[i] = (GLfloat) (span.tex[0][2] * invQ); \ - span.tex[0][0] += span.texStep[0][0]; \ - span.tex[0][1] += span.texStep[0][1]; \ - span.tex[0][2] += span.texStep[0][2]; \ - span.tex[0][3] += span.texStep[0][3]; \ - } \ - _mesa_write_texture_span(ctx, span.count, span.x, span.y, \ - zSpan, fogSpan, sSpan, tSpan, uSpan, \ - NULL, rgbaSpan, NULL, NULL, GL_POLYGON ); - -#define CLEANUP_CODE \ - UNDEFARRAY(sSpan); /* mac 32k limitation */ \ - UNDEFARRAY(tSpan); \ - UNDEFARRAY(uSpan); - -#include "s_tritemp.h" -} - - -/* - * Render a smooth-shaded, textured, RGBA triangle with separate specular - * color interpolation. - * Interpolate texcoords with perspective correction, w/out mipmapping. - */ -static void general_textured_spec_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_SPEC 1 #define INTERP_ALPHA 1 #define INTERP_TEX 1 -#define SETUP_CODE \ - const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ - const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ - span.texWidth[0] = (GLfloat) texImage->Width; \ - span.texHeight[0] = (GLfloat) texImage->Height; \ - (void) fixedToDepthShift; - -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); - -#include "s_tritemp.h" -} - - -/* - * Render a smooth-shaded, textured, RGBA triangle. - * Interpolate S,T,R with perspective correction and compute lambda for - * each fragment. Lambda is used to determine whether to use the - * minification or magnification filter. If minification and using - * mipmaps, lambda is also used to select the texture level of detail. - */ -static void lambda_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 INTERP_LAMBDA 1 - -#define SETUP_CODE \ - const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ - const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ - span.texWidth[0] = (GLfloat) texImage->Width; \ - span.texHeight[0] = (GLfloat) texImage->Height; \ - (void) fixedToDepthShift; - -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); +#define RENDER_SPAN( span ) _mesa_write_texture_span(ctx, &span); #include "s_tritemp.h" } -/* - * Render a smooth-shaded, textured, RGBA triangle with separate specular - * interpolation. - * Interpolate S,T,R with perspective correction and compute lambda for - * each fragment. Lambda is used to determine whether to use the - * minification or magnification filter. If minification and using - * mipmaps, lambda is also used to select the texture level of detail. - */ -static void lambda_textured_spec_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_SPEC 1 -#define INTERP_ALPHA 1 -#define INTERP_TEX 1 -#define INTERP_LAMBDA 1 - -#define SETUP_CODE \ - const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ - const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ - span.texWidth[0] = (GLfloat) texImage->Width; \ - span.texHeight[0] = (GLfloat) texImage->Height; \ - (void) fixedToDepthShift; - -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); - -#include "s_tritemp.h" -} - /* * This is the big one! - * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates - * with lambda (LOD). + * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates. * Yup, it's slow. */ static void -lambda_multitextured_triangle( GLcontext *ctx, - const SWvertex *v0, - const SWvertex *v1, - const SWvertex *v2 ) +multitextured_triangle( GLcontext *ctx, + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) { #define INTERP_Z 1 @@ -1499,23 +961,8 @@ lambda_multitextured_triangle( GLcontext *ctx, #define INTERP_ALPHA 1 #define INTERP_SPEC 1 #define INTERP_MULTITEX 1 -#define INTERP_LAMBDA 1 -#define SETUP_CODE \ - GLuint u; \ - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ - if (ctx->Texture.Unit[u]._ReallyEnabled) { \ - const struct gl_texture_object *texObj; \ - const struct gl_texture_image *texImage; \ - texObj = ctx->Texture.Unit[u]._Current; \ - texImage = texObj->Image[texObj->BaseLevel]; \ - span.texWidth[u] = (GLfloat) texImage->Width; \ - span.texHeight[u] = (GLfloat) texImage->Height; \ - } \ - } \ - (void) fixedToDepthShift; - -#define RENDER_SPAN( span ) rasterize_span(ctx, &span); +#define RENDER_SPAN( span ) _mesa_write_texture_span(ctx, &span); #include "s_tritemp.h" @@ -1537,7 +984,7 @@ static void occlusion_zless_triangle( GLcontext *ctx, #define RENDER_SPAN( span ) \ GLuint i; \ - for (i = 0; i < span.count; i++) { \ + for (i = 0; i < span.end; i++) { \ GLdepth z = FixedToDepth(span.z); \ if (z < zRow[i]) { \ ctx->OcclusionResult = GL_TRUE; \ @@ -1616,13 +1063,13 @@ void _swrast_add_spec_terms_triangle( GLcontext *ctx, #ifdef DEBUG /* record the current triangle function name */ -static const char *triFuncName = NULL; +const char *_mesa_triFuncName = NULL; -#define USE(triFunc) \ -do { \ - triFuncName = #triFunc; \ - /*printf("%s\n", triFuncName);*/ \ - swrast->Triangle = triFunc; \ +#define USE(triFunc) \ +do { \ + _mesa_triFuncName = #triFunc; \ + /*printf("%s\n", _mesa_triFuncName);*/ \ + swrast->Triangle = triFunc; \ } while (0) #else @@ -1678,7 +1125,7 @@ _swrast_choose_triangle( GLcontext *ctx ) } } - if (ctx->Texture._ReallyEnabled) { + if (ctx->Texture._EnabledUnits) { /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ const struct gl_texture_object *texObj2D; const struct gl_texture_image *texImg; @@ -1692,10 +1139,12 @@ _swrast_choose_triangle( GLcontext *ctx ) envMode = ctx->Texture.Unit[0].EnvMode; /* First see if we can used an optimized 2-D texture function */ - if (ctx->Texture._ReallyEnabled==TEXTURE0_2D + if (ctx->Texture._EnabledUnits == 1 + && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT && texObj2D->WrapS==GL_REPEAT && texObj2D->WrapT==GL_REPEAT && texImg->Border==0 + && texImg->Width == texImg->RowStride && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) && minFilter == magFilter && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR @@ -1733,38 +1182,17 @@ _swrast_choose_triangle( GLcontext *ctx ) } } else { - /* More complicated textures (mipmap, multi-tex, sep specular) */ - GLboolean needLambda; - /* if mag filter != min filter we need to compute lambda */ - const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; - if (obj && obj->MinFilter != obj->MagFilter) - needLambda = GL_TRUE; - else - needLambda = GL_FALSE; - if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { - USE(lambda_multitextured_triangle); - } - else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { - /* separate specular color interpolation */ - if (needLambda) { - USE(lambda_textured_spec_triangle); - } - else { - USE(general_textured_spec_triangle); - } + /* general case textured triangles */ + if (ctx->Texture._EnabledUnits > 1) { + USE(multitextured_triangle); } else { - if (needLambda) { - USE(lambda_textured_triangle); - } - else { - USE(general_textured_triangle); - } + USE(general_textured_triangle); } } } else { - ASSERT(!ctx->Texture._ReallyEnabled); + ASSERT(!ctx->Texture._EnabledUnits); if (ctx->Light.ShadeModel==GL_SMOOTH) { /* smooth shaded, no texturing, stippled or some raster ops */ if (rgbmode) { diff --git a/xc/extras/Mesa/src/swrast/s_trispan.h b/xc/extras/Mesa/src/swrast/s_trispan.h index 9a85132fe..15207e863 100644 --- a/xc/extras/Mesa/src/swrast/s_trispan.h +++ b/xc/extras/Mesa/src/swrast/s_trispan.h @@ -1,4 +1,3 @@ -/* $Id: s_trispan.h,v 1.1.1.1 2002/10/22 13:06:42 alanh Exp $ */ /* * Mesa 3-D graphics library @@ -29,65 +28,4 @@ #define S_TRISPAN_H -/* - * The triangle_span structure is used by the triangle template code in - * s_tritemp.h. It describes how colors, Z, texcoords, etc are to be - * interpolated across each scanline of triangle. - * With this structure it's easy to hand-off span rasterization to a - * subroutine instead of doing it all inline like we used to do. - * It also cleans up the local variable namespace a great deal. - * - * It would be interesting to experiment with multiprocessor rasterization - * with this structure. The triangle rasterizer could simply emit a - * stream of these structures which would be consumed by one or more - * span-processing threads which could run in parallel. - */ - - -/* When the triangle_span struct is initialized, these flags indicates - * which values are needed for rendering the triangle. - */ -#define SPAN_RGBA 0x001 -#define SPAN_SPEC 0x002 -#define SPAN_INDEX 0x004 -#define SPAN_Z 0x008 -#define SPAN_FOG 0x010 -#define SPAN_TEXTURE 0x020 -#define SPAN_INT_TEXTURE 0x040 -#define SPAN_LAMBDA 0x080 -#define SPAN_FLAT 0x100 /* flat shading? */ - - -struct triangle_span { - GLint x, y; - GLuint count; - GLuint activeMask; /* OR of the SPAN_* flags */ -#if CHAN_TYPE == GL_FLOAT - GLfloat red, redStep; - GLfloat green, greenStep; - GLfloat blue, blueStep; - GLfloat alpha, alphaStep; - GLfloat specRed, specRedStep; - GLfloat specGreen, specGreenStep; - GLfloat specBlue, specBlueStep; -#else - GLfixed red, redStep; - GLfixed green, greenStep; - GLfixed blue, blueStep; - GLfixed alpha, alphaStep; - GLfixed specRed, specRedStep; - GLfixed specGreen, specGreenStep; - GLfixed specBlue, specBlueStep; -#endif - GLfixed index, indexStep; - GLfixed z, zStep; - GLfloat fog, fogStep; - GLfloat tex[MAX_TEXTURE_UNITS][4], texStep[MAX_TEXTURE_UNITS][4]; - GLfixed intTex[2], intTexStep[2]; - /* Needed for texture lambda (LOD) computation */ - GLfloat rho[MAX_TEXTURE_UNITS]; - GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS]; -}; - - #endif /* S_TRISPAN_H */ diff --git a/xc/extras/Mesa/src/swrast/s_tritemp.h b/xc/extras/Mesa/src/swrast/s_tritemp.h index 41306fc03..2feeb8b13 100644 --- a/xc/extras/Mesa/src/swrast/s_tritemp.h +++ b/xc/extras/Mesa/src/swrast/s_tritemp.h @@ -1,3 +1,4 @@ + /* * Mesa 3-D graphics library * Version: 3.5 @@ -21,7 +22,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $XFree86: xc/extras/Mesa/src/swrast/s_tritemp.h,v 1.3 2002/09/09 21:07:37 dawes Exp $ */ +/* $XFree86: xc/extras/Mesa/src/swrast/s_tritemp.h,v 1.2 2002/02/27 21:07:54 tsi Exp $ */ /* * Triangle Rasterizer Template @@ -41,8 +42,6 @@ * INTERP_TEX - if defined, interpolate set 0 float STRQ texcoords * NOTE: OpenGL STRQ = Mesa STUV (R was taken for red) * INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords - * INTERP_LAMBDA - if defined, compute lambda value (for mipmapping) - * a lambda value for every texture unit * INTERP_FLOAT_RGBA - if defined, interpolate RGBA with floating point * INTERP_FLOAT_SPEC - if defined, interpolate specular with floating point * @@ -115,10 +114,12 @@ GLfloat oneOverArea; const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */ float bf = SWRAST_CONTEXT(ctx)->_backface_sign; - const GLint snapMask = ~((FIXED_ONE / 16) - 1); /* for x/y coord snapping */ + const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */ GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy; - struct triangle_span span; + struct sw_span span; + + INIT_SPAN(span, GL_POLYGON, 0, 0, 0); #ifdef INTERP_Z (void) fixedToDepthShift; @@ -127,14 +128,8 @@ /* printf("%s()\n", __FUNCTION__); printf(" %g, %g, %g\n", v0->win[0], v0->win[1], v0->win[2]); - printf(" %d, %d, %d, %d\n", - v0->color[0], v0->color[1], v0->color[2], v0->color[3]); printf(" %g, %g, %g\n", v1->win[0], v1->win[1], v1->win[2]); - printf(" %d, %d, %d, %d\n", - v1->color[0], v1->color[1], v1->color[2], v1->color[3]); printf(" %g, %g, %g\n", v2->win[0], v2->win[1], v2->win[2]); - printf(" %d, %d, %d, %d\n", - v2->color[0], v2->color[1], v2->color[2], v2->color[3]); */ /* Compute fixed point x,y coords w/ half-pixel offsets and snapping. @@ -210,7 +205,7 @@ if (area * bf < 0.0) return; - if (area == 0.0F || IS_INF_OR_NAN(area)) + if (IS_INF_OR_NAN(area) || area == 0.0F) return; oneOverArea = 1.0F / area; @@ -219,6 +214,7 @@ #ifndef DO_OCCLUSION_TEST ctx->OcclusionResult = GL_TRUE; #endif + span.facing = ctx->_Facing; /* for 2-sided stencil test */ /* Edge setup. For a triangle strip these could be reused... */ { @@ -319,20 +315,16 @@ GLfloat dtdx, dtdy; #endif #ifdef INTERP_TEX - GLfloat dsdy; - GLfloat dtdy; - GLfloat dudy; - GLfloat dvdy; + GLfloat dsdx, dsdy; + GLfloat dtdx, dtdy; + GLfloat dudx, dudy; + GLfloat dvdx, dvdy; #endif #ifdef INTERP_MULTITEX - GLfloat dsdy[MAX_TEXTURE_UNITS]; - GLfloat dtdy[MAX_TEXTURE_UNITS]; - GLfloat dudy[MAX_TEXTURE_UNITS]; - GLfloat dvdy[MAX_TEXTURE_UNITS]; -#endif - -#if defined(INTERP_LAMBDA) && !defined(INTERP_TEX) && !defined(INTERP_MULTITEX) -#error "Mipmapping without texturing doesn't make sense." + GLfloat dsdx[MAX_TEXTURE_UNITS], dsdy[MAX_TEXTURE_UNITS]; + GLfloat dtdx[MAX_TEXTURE_UNITS], dtdy[MAX_TEXTURE_UNITS]; + GLfloat dudx[MAX_TEXTURE_UNITS], dudy[MAX_TEXTURE_UNITS]; + GLfloat dvdx[MAX_TEXTURE_UNITS], dvdy[MAX_TEXTURE_UNITS]; #endif /* @@ -344,11 +336,10 @@ scan_from_left_to_right = (oneOverArea < 0.0F); - span.activeMask = 0; /* compute d?/dx and d?/dy derivatives */ #ifdef INTERP_Z - span.activeMask |= SPAN_Z; + span.interpMask |= SPAN_Z; { GLfloat eMaj_dz, eBot_dz; eMaj_dz = vMax->win[2] - vMin->win[2]; @@ -369,7 +360,7 @@ } #endif #ifdef INTERP_FOG - span.activeMask |= SPAN_FOG; + span.interpMask |= SPAN_FOG; { const GLfloat eMaj_dfog = vMax->fog - vMin->fog; const GLfloat eBot_dfog = vMid->fog - vMin->fog; @@ -378,7 +369,7 @@ } #endif #ifdef INTERP_RGB - span.activeMask |= SPAN_RGBA; + span.interpMask |= SPAN_RGBA; if (ctx->Light.ShadeModel == GL_SMOOTH) { GLfloat eMaj_dr, eBot_dr; GLfloat eMaj_dg, eBot_dg; @@ -419,7 +410,7 @@ } else { ASSERT (ctx->Light.ShadeModel == GL_FLAT); - span.activeMask |= SPAN_FLAT; + span.interpMask |= SPAN_FLAT; drdx = drdy = 0.0F; dgdx = dgdy = 0.0F; dbdx = dbdy = 0.0F; @@ -433,7 +424,7 @@ } #endif #ifdef INTERP_FLOAT_RGBA - span.activeMask |= SPAN_RGBA; + span.interpMask |= SPAN_RGBA; if (ctx->Light.ShadeModel == GL_SMOOTH) { GLfloat eMaj_dr, eBot_dr; GLfloat eMaj_dg, eBot_dg; @@ -468,7 +459,7 @@ } #endif #ifdef INTERP_SPEC - span.activeMask |= SPAN_SPEC; + span.interpMask |= SPAN_SPEC; if (ctx->Light.ShadeModel == GL_SMOOTH) { GLfloat eMaj_dsr, eBot_dsr; GLfloat eMaj_dsg, eBot_dsg; @@ -505,7 +496,7 @@ } #endif #ifdef INTERP_FLOAT_SPEC - span.activeMask |= SPAN_SPEC; + span.interpMask |= SPAN_SPEC; if (ctx->Light.ShadeModel == GL_SMOOTH) { GLfloat eMaj_dsr, eBot_dsr; GLfloat eMaj_dsg, eBot_dsg; @@ -533,7 +524,7 @@ } #endif #ifdef INTERP_INDEX - span.activeMask |= SPAN_INDEX; + span.interpMask |= SPAN_INDEX; if (ctx->Light.ShadeModel == GL_SMOOTH) { GLfloat eMaj_di, eBot_di; eMaj_di = (GLfloat) ((GLint) vMax->index - (GLint) vMin->index); @@ -543,13 +534,13 @@ didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx); } else { - span.activeMask |= SPAN_FLAT; + span.interpMask |= SPAN_FLAT; didx = didy = 0.0F; span.indexStep = 0; } #endif #ifdef INTERP_INT_TEX - span.activeMask |= SPAN_INT_TEXTURE; + span.interpMask |= SPAN_INT_TEXTURE; { GLfloat eMaj_ds, eBot_ds; eMaj_ds = (vMax->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE; @@ -569,7 +560,7 @@ #endif #ifdef INTERP_TEX - span.activeMask |= SPAN_TEXTURE; + span.interpMask |= SPAN_TEXTURE; { GLfloat wMax = vMax->win[3]; GLfloat wMin = vMin->win[3]; @@ -581,46 +572,35 @@ eMaj_ds = vMax->texcoord[0][0] * wMax - vMin->texcoord[0][0] * wMin; eBot_ds = vMid->texcoord[0][0] * wMid - vMin->texcoord[0][0] * wMin; - span.texStep[0][0] = oneOverArea * (eMaj_ds * eBot.dy - - eMaj.dy * eBot_ds); + dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds); dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx); + span.texStepX[0][0] = dsdx; + span.texStepY[0][0] = dsdy; eMaj_dt = vMax->texcoord[0][1] * wMax - vMin->texcoord[0][1] * wMin; eBot_dt = vMid->texcoord[0][1] * wMid - vMin->texcoord[0][1] * wMin; - span.texStep[0][1] = oneOverArea * (eMaj_dt * eBot.dy - - eMaj.dy * eBot_dt); + dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt); dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx); + span.texStepX[0][1] = dtdx; + span.texStepY[0][1] = dtdy; eMaj_du = vMax->texcoord[0][2] * wMax - vMin->texcoord[0][2] * wMin; eBot_du = vMid->texcoord[0][2] * wMid - vMin->texcoord[0][2] * wMin; - span.texStep[0][2] = oneOverArea * (eMaj_du * eBot.dy - - eMaj.dy * eBot_du); + dudx = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du); dudy = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx); + span.texStepX[0][2] = dudx; + span.texStepY[0][2] = dudy; eMaj_dv = vMax->texcoord[0][3] * wMax - vMin->texcoord[0][3] * wMin; eBot_dv = vMid->texcoord[0][3] * wMid - vMin->texcoord[0][3] * wMin; - span.texStep[0][3] = oneOverArea * (eMaj_dv * eBot.dy - - eMaj.dy * eBot_dv); + dvdx = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv); dvdy = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx); + span.texStepX[0][3] = dvdx; + span.texStepY[0][3] = dvdy; } -# ifdef INTERP_LAMBDA - { - GLfloat dudx = span.texStep[0][0] * span.texWidth[0]; - GLfloat dudy = dsdy * span.texWidth[0]; - GLfloat dvdx = span.texStep[0][1] * span.texHeight[0]; - GLfloat dvdy = dtdy * span.texHeight[0]; - GLfloat r1 = dudx * dudx + dudy * dudy; - GLfloat r2 = dvdx * dvdx + dvdy * dvdy; - span.rho[0] = r1 + r2; /* was rho2 = MAX2(r1,r2) */ - span.activeMask |= SPAN_LAMBDA; - } -# endif #endif #ifdef INTERP_MULTITEX - span.activeMask |= SPAN_TEXTURE; -# ifdef INTERP_LAMBDA - span.activeMask |= SPAN_LAMBDA; -# endif + span.interpMask |= SPAN_TEXTURE; { GLfloat wMax = vMax->win[3]; GLfloat wMin = vMin->win[3]; @@ -636,44 +616,37 @@ - vMin->texcoord[u][0] * wMin; eBot_ds = vMid->texcoord[u][0] * wMid - vMin->texcoord[u][0] * wMin; - span.texStep[u][0] = oneOverArea * (eMaj_ds * eBot.dy - - eMaj.dy * eBot_ds); + dsdx[u] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds); dsdy[u] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx); + span.texStepX[u][0] = dsdx[u]; + span.texStepY[u][0] = dsdy[u]; eMaj_dt = vMax->texcoord[u][1] * wMax - vMin->texcoord[u][1] * wMin; eBot_dt = vMid->texcoord[u][1] * wMid - vMin->texcoord[u][1] * wMin; - span.texStep[u][1] = oneOverArea * (eMaj_dt * eBot.dy - - eMaj.dy * eBot_dt); + dtdx[u] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt); dtdy[u] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx); + span.texStepX[u][1] = dtdx[u]; + span.texStepY[u][1] = dtdy[u]; eMaj_du = vMax->texcoord[u][2] * wMax - vMin->texcoord[u][2] * wMin; eBot_du = vMid->texcoord[u][2] * wMid - vMin->texcoord[u][2] * wMin; - span.texStep[u][2] = oneOverArea * (eMaj_du * eBot.dy - - eMaj.dy * eBot_du); + dudx[u] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du); dudy[u] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx); + span.texStepX[u][2] = dudx[u]; + span.texStepY[u][2] = dudy[u]; eMaj_dv = vMax->texcoord[u][3] * wMax - vMin->texcoord[u][3] * wMin; eBot_dv = vMid->texcoord[u][3] * wMid - vMin->texcoord[u][3] * wMin; - span.texStep[u][3] = oneOverArea * (eMaj_dv * eBot.dy - - eMaj.dy * eBot_dv); + dvdx[u] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv); dvdy[u] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx); -# ifdef INTERP_LAMBDA - { - GLfloat dudx = span.texStep[u][0] * span.texWidth[u]; - GLfloat dudy = dsdy[u] * span.texWidth[u]; - GLfloat dvdx = span.texStep[u][1] * span.texHeight[u]; - GLfloat dvdy = dtdy[u] * span.texHeight[u]; - GLfloat r1 = dudx * dudx + dudy * dudy; - GLfloat r2 = dvdx * dvdx + dvdy * dvdy; - span.rho[u] = r1 + r2; /* was rho2 = MAX2(r1,r2) */ - } -# endif + span.texStepX[u][3] = dvdx[u]; + span.texStepY[u][3] = dvdy[u]; } } } @@ -1033,21 +1006,21 @@ GLfloat invW = vLower->win[3]; GLfloat s0, t0, u0, v0; s0 = vLower->texcoord[0][0] * invW; - sLeft = s0 + (span.texStep[0][0] * adjx + dsdy * adjy) + sLeft = s0 + (span.texStepX[0][0] * adjx + dsdy * adjy) * (1.0F/FIXED_SCALE); - dsOuter = dsdy + dxOuter * span.texStep[0][0]; + dsOuter = dsdy + dxOuter * span.texStepX[0][0]; t0 = vLower->texcoord[0][1] * invW; - tLeft = t0 + (span.texStep[0][1] * adjx + dtdy * adjy) + tLeft = t0 + (span.texStepX[0][1] * adjx + dtdy * adjy) * (1.0F/FIXED_SCALE); - dtOuter = dtdy + dxOuter * span.texStep[0][1]; + dtOuter = dtdy + dxOuter * span.texStepX[0][1]; u0 = vLower->texcoord[0][2] * invW; - uLeft = u0 + (span.texStep[0][2] * adjx + dudy * adjy) + uLeft = u0 + (span.texStepX[0][2] * adjx + dudy * adjy) * (1.0F/FIXED_SCALE); - duOuter = dudy + dxOuter * span.texStep[0][2]; + duOuter = dudy + dxOuter * span.texStepX[0][2]; v0 = vLower->texcoord[0][3] * invW; - vLeft = v0 + (span.texStep[0][3] * adjx + dvdy * adjy) + vLeft = v0 + (span.texStepX[0][3] * adjx + dvdy * adjy) * (1.0F/FIXED_SCALE); - dvOuter = dvdy + dxOuter * span.texStep[0][3]; + dvOuter = dvdy + dxOuter * span.texStepX[0][3]; } #endif #ifdef INTERP_MULTITEX @@ -1058,21 +1031,21 @@ GLfloat invW = vLower->win[3]; GLfloat s0, t0, u0, v0; s0 = vLower->texcoord[u][0] * invW; - sLeft[u] = s0 + (span.texStep[u][0] * adjx + dsdy[u] + sLeft[u] = s0 + (span.texStepX[u][0] * adjx + dsdy[u] * adjy) * (1.0F/FIXED_SCALE); - dsOuter[u] = dsdy[u] + dxOuter * span.texStep[u][0]; + dsOuter[u] = dsdy[u] + dxOuter * span.texStepX[u][0]; t0 = vLower->texcoord[u][1] * invW; - tLeft[u] = t0 + (span.texStep[u][1] * adjx + dtdy[u] + tLeft[u] = t0 + (span.texStepX[u][1] * adjx + dtdy[u] * adjy) * (1.0F/FIXED_SCALE); - dtOuter[u] = dtdy[u] + dxOuter * span.texStep[u][1]; + dtOuter[u] = dtdy[u] + dxOuter * span.texStepX[u][1]; u0 = vLower->texcoord[u][2] * invW; - uLeft[u] = u0 + (span.texStep[u][2] * adjx + dudy[u] + uLeft[u] = u0 + (span.texStepX[u][2] * adjx + dudy[u] * adjy) * (1.0F/FIXED_SCALE); - duOuter[u] = dudy[u] + dxOuter * span.texStep[u][2]; + duOuter[u] = dudy[u] + dxOuter * span.texStepX[u][2]; v0 = vLower->texcoord[u][3] * invW; - vLeft[u] = v0 + (span.texStep[u][3] * adjx + dvdy[u] + vLeft[u] = v0 + (span.texStepX[u][3] * adjx + dvdy[u] * adjy) * (1.0F/FIXED_SCALE); - dvOuter[u] = dvdy[u] + dxOuter * span.texStep[u][3]; + dvOuter[u] = dvdy[u] + dxOuter * span.texStepX[u][3]; } } } @@ -1125,20 +1098,20 @@ fdtInner = fdtOuter + span.intTexStep[1]; #endif #ifdef INTERP_TEX - dsInner = dsOuter + span.texStep[0][0]; - dtInner = dtOuter + span.texStep[0][1]; - duInner = duOuter + span.texStep[0][2]; - dvInner = dvOuter + span.texStep[0][3]; + dsInner = dsOuter + span.texStepX[0][0]; + dtInner = dtOuter + span.texStepX[0][1]; + duInner = duOuter + span.texStepX[0][2]; + dvInner = dvOuter + span.texStepX[0][3]; #endif #ifdef INTERP_MULTITEX { GLuint u; for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { if (ctx->Texture.Unit[u]._ReallyEnabled) { - dsInner[u] = dsOuter[u] + span.texStep[u][0]; - dtInner[u] = dtOuter[u] + span.texStep[u][1]; - duInner[u] = duOuter[u] + span.texStep[u][2]; - dvInner[u] = dvOuter[u] + span.texStep[u][3]; + dsInner[u] = dsOuter[u] + span.texStepX[u][0]; + dtInner[u] = dtOuter[u] + span.texStepX[u][1]; + duInner[u] = duOuter[u] + span.texStepX[u][2]; + dvInner[u] = dvOuter[u] + span.texStepX[u][3]; } } } @@ -1148,11 +1121,13 @@ /* initialize the span interpolants to the leftmost value */ /* ff = fixed-pt fragment */ const GLint right = FixedToInt(fxRightEdge); + span.x = FixedToInt(fxLeftEdge); + if (right <= span.x) - span.count = 0; + span.end = 0; else - span.count = right - span.x; + span.end = right - span.x; #ifdef INTERP_Z span.z = fz; @@ -1266,7 +1241,7 @@ #endif /* This is where we actually generate fragments */ - if (span.count > 0) { + if (span.end > 0) { RENDER_SPAN( span ); } @@ -1276,7 +1251,7 @@ * pixel-center x coordinate so that it stays * on or inside the major edge. */ - span.y++; + (span.y)++; lines--; fxLeftEdge += fdxLeftEdge; @@ -1419,7 +1394,6 @@ #undef INTERP_INT_TEX #undef INTERP_TEX #undef INTERP_MULTITEX -#undef INTERP_LAMBDA #undef INTERP_FLOAT_RGBA #undef INTERP_FLOAT_SPEC diff --git a/xc/extras/Mesa/src/swrast/s_zoom.c b/xc/extras/Mesa/src/swrast/s_zoom.c index b56128147..0d1f08458 100644 --- a/xc/extras/Mesa/src/swrast/s_zoom.c +++ b/xc/extras/Mesa/src/swrast/s_zoom.c @@ -1,8 +1,7 @@ -/* $Id: s_zoom.c,v 1.1.1.1 2002/10/22 13:06:58 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 4.0.3 + * Version: 4.1 * * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. * @@ -26,6 +25,8 @@ #include "glheader.h" #include "macros.h" +#include "imports.h" +#include "colormac.h" #include "s_context.h" #include "s_span.h" @@ -33,342 +34,229 @@ #include "s_zoom.h" - /* - * Write a span of pixels to the frame buffer while applying a pixel zoom. - * This is only used by glDrawPixels and glCopyPixels. - * Input: n - number of pixels in input row - * x, y - destination of the span - * z - depth values for the span - * red, green, blue, alpha - array of colors - * y0 - location of first row in the image we're drawing. + * Helper function called from _mesa_write_zoomed_rgba/rgb/index_span(). */ -void -_mesa_write_zoomed_rgba_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, const GLdepth z[], - const GLfloat *fog, - CONST GLchan rgba[][4], GLint y0 ) +static void +zoom_span( GLcontext *ctx, const struct sw_span *span, + const GLvoid *src, GLint y0, GLenum format ) { - GLint m; - GLint r0, r1, row, r; - GLint i, j, skipcol; - GLchan zrgba[MAX_WIDTH][4]; /* zoomed pixel colors */ - GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */ - GLfloat zfog[MAX_WIDTH]; /* zoomed fog values */ - GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH ); - const GLuint *srcRGBA32 = (const GLuint *) rgba; - GLuint *dstRGBA32 = (GLuint *) zrgba; - - /* compute width of output row */ - m = (GLint) ABSF( n * ctx->Pixel.ZoomX ); - if (m==0) { + GLint r0, r1, row; + GLint c0, c1, skipCol; + GLint i, j; + const GLuint maxWidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH ); + GLchan rgbaSave[MAX_WIDTH][4]; + GLuint indexSave[MAX_WIDTH]; + const GLchan (*rgba)[4] = (const GLchan (*)[4]) src; + const GLchan (*rgb)[3] = (const GLchan (*)[3]) src; + const GLuint *indexes = (const GLuint *) src; + struct sw_span zoomed; + struct span_arrays zoomed_arrays; /* this is big! */ + + /* no pixel arrays! */ + ASSERT((span->arrayMask & SPAN_XY) == 0); + ASSERT(span->primitive == GL_BITMAP); + + INIT_SPAN(zoomed, GL_BITMAP, 0, 0, 0); + zoomed.array = &zoomed_arrays; + + if (format == GL_RGBA || format == GL_RGB) { + zoomed.z = span->z; + zoomed.zStep = span->z; + zoomed.fog = span->fog; + zoomed.fogStep = span->fogStep; + zoomed.interpMask = span->interpMask & ~SPAN_RGBA; + zoomed.arrayMask |= SPAN_RGBA; + } + else if (format == GL_COLOR_INDEX) { + zoomed.z = span->z; + zoomed.zStep = span->z; + zoomed.fog = span->fog; + zoomed.fogStep = span->fogStep; + zoomed.interpMask = span->interpMask & ~SPAN_INDEX; + zoomed.arrayMask |= SPAN_INDEX; + } + + /* + * Compute which columns to draw: [c0, c1) + */ + c0 = (GLint) span->x; + c1 = (GLint) (span->x + span->end * ctx->Pixel.ZoomX); + if (c0 == c1) { return; } - if (ctx->Pixel.ZoomX<0.0) { - /* adjust x coordinate for left/right mirroring */ - x = x - m; + else if (c1 < c0) { + /* swap */ + GLint ctmp = c1; + c1 = c0; + c0 = ctmp; } - - /* compute which rows to draw */ - row = y-y0; + if (c0 < 0) { + zoomed.x = 0; + zoomed.start = 0; + zoomed.end = c1; + skipCol = -c0; + } + else { + zoomed.x = c0; + zoomed.start = 0; + zoomed.end = c1 - c0; + skipCol = 0; + } + if (zoomed.end > maxWidth) + zoomed.end = maxWidth; + + /* + * Compute which rows to draw: [r0, r1) + */ + row = span->y - y0; r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); - if (r0==r1) { + if (r0 == r1) { return; } - else if (r1<r0) { + else if (r1 < r0) { + /* swap */ GLint rtmp = r1; r1 = r0; r0 = rtmp; } - /* return early if r0...r1 is above or below window */ - if (r0<0 && r1<0) { - /* below window */ + ASSERT(r0 < r1); + ASSERT(c0 < c1); + + /* + * Trivial clip rejection testing. + */ + if (r1 < 0) /* below window */ return; - } - if (r0 >= (GLint) ctx->DrawBuffer->Height && - r1 >= (GLint) ctx->DrawBuffer->Height) { - /* above window */ + if (r0 >= (GLint) ctx->DrawBuffer->Height) /* above window */ return; - } - - /* check if left edge is outside window */ - skipcol = 0; - if (x<0) { - skipcol = -x; - m += x; - } - /* make sure span isn't too long or short */ - if (m>maxwidth) { - m = maxwidth; - } - else if (m<=0) { + if (c1 < 0) /* left of window */ + return; + if (c0 >= (GLint) ctx->DrawBuffer->Width) /* right of window */ return; - } - - assert( m <= MAX_WIDTH ); /* zoom the span horizontally */ - if (ctx->Pixel.ZoomX==-1.0F) { - /* n==m */ - for (j=0;j<m;j++) { - i = n - (j+skipcol) - 1; - dstRGBA32[j] = srcRGBA32[i]; - zdepth[j] = z[i]; + if (format == GL_RGBA) { + if (ctx->Pixel.ZoomX == -1.0F) { + /* common case */ + for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { + i = span->end - (j + skipCol) - 1; + COPY_CHAN4(zoomed.array->rgba[j], rgba[i]); + } } - if (fog && ctx->Fog.Enabled) { - for (j=0;j<m;j++) { - i = n - (j+skipcol) - 1; - zfog[j] = fog[i]; - } + else { + /* general solution */ + const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; + for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { + i = (GLint) ((j + skipCol) * xscale); + if (i < 0) + i = span->end + i - 1; + COPY_CHAN4(zoomed.array->rgba[j], rgba[i]); + } } } - else { - GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; - for (j=0;j<m;j++) { - i = (GLint) ((j+skipcol) * xscale); - if (i<0) i = n + i - 1; - dstRGBA32[j] = srcRGBA32[i]; - zdepth[j] = z[i]; + else if (format == GL_RGB) { + if (ctx->Pixel.ZoomX == -1.0F) { + /* common case */ + for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { + i = span->end - (j + skipCol) - 1; + zoomed.array->rgba[j][0] = rgb[i][0]; + zoomed.array->rgba[j][1] = rgb[i][1]; + zoomed.array->rgba[j][2] = rgb[i][2]; + zoomed.array->rgba[j][3] = CHAN_MAX; + } } - if (fog && ctx->Fog.Enabled) { - for (j=0;j<m;j++) { - i = (GLint) ((j+skipcol) * xscale); - if (i<0) i = n + i - 1; - zfog[j] = fog[i]; - } + else { + /* general solution */ + const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; + for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { + i = (GLint) ((j + skipCol) * xscale); + if (i < 0) + i = span->end + i - 1; + zoomed.array->rgba[j][0] = rgb[i][0]; + zoomed.array->rgba[j][1] = rgb[i][1]; + zoomed.array->rgba[j][2] = rgb[i][2]; + zoomed.array->rgba[j][3] = CHAN_MAX; + } } } - - /* write the span */ - for (r=r0; r<r1; r++) { - _mesa_write_rgba_span( ctx, m, x+skipcol, r, zdepth, - (fog ? zfog : 0), zrgba, NULL, GL_BITMAP ); - } -} - - - -void -_mesa_write_zoomed_rgb_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, const GLdepth z[], - const GLfloat *fog, - CONST GLchan rgb[][3], GLint y0 ) -{ - GLint m; - GLint r0, r1, row, r; - GLint i, j, skipcol; - GLchan zrgba[MAX_WIDTH][4]; /* zoomed pixel colors */ - GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */ - GLfloat zfog[MAX_WIDTH]; /* zoomed fog values */ - GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH ); - - /* compute width of output row */ - m = (GLint) ABSF( n * ctx->Pixel.ZoomX ); - if (m==0) { - return; - } - if (ctx->Pixel.ZoomX<0.0) { - /* adjust x coordinate for left/right mirroring */ - x = x - m; - } - - /* compute which rows to draw */ - row = y-y0; - r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); - r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); - if (r0==r1) { - return; - } - else if (r1<r0) { - GLint rtmp = r1; - r1 = r0; - r0 = rtmp; - } - - /* return early if r0...r1 is above or below window */ - if (r0<0 && r1<0) { - /* below window */ - return; - } - if (r0 >= (GLint) ctx->DrawBuffer->Height && - r1 >= (GLint) ctx->DrawBuffer->Height) { - /* above window */ - return; - } - - /* check if left edge is outside window */ - skipcol = 0; - if (x<0) { - skipcol = -x; - m += x; - } - /* make sure span isn't too long or short */ - if (m>maxwidth) { - m = maxwidth; - } - else if (m<=0) { - return; + else if (format == GL_COLOR_INDEX) { + if (ctx->Pixel.ZoomX == -1.0F) { + /* common case */ + for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { + i = span->end - (j + skipCol) - 1; + zoomed.array->index[j] = indexes[i]; + } + } + else { + /* general solution */ + const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; + for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { + i = (GLint) ((j + skipCol) * xscale); + if (i < 0) + i = span->end + i - 1; + zoomed.array->index[j] = indexes[i]; + } + } } - assert( m <= MAX_WIDTH ); - - /* zoom the span horizontally */ - if (ctx->Pixel.ZoomX==-1.0F) { - /* n==m */ - for (j=0;j<m;j++) { - i = n - (j+skipcol) - 1; - zrgba[j][0] = rgb[i][0]; - zrgba[j][1] = rgb[i][1]; - zrgba[j][2] = rgb[i][2]; - zrgba[j][3] = CHAN_MAX; - zdepth[j] = z[i]; + /* write the span in rows [r0, r1) */ + if (format == GL_RGBA || format == GL_RGB) { + /* Writing the span may modify the colors, so make a backup now if we're + * going to call _mesa_write_zoomed_span() more than once. + */ + if (r1 - r0 > 1) { + MEMCPY(rgbaSave, zoomed.array->rgba, zoomed.end * 4 * sizeof(GLchan)); } - if (fog && ctx->Fog.Enabled) { - for (j=0;j<m;j++) { - i = n - (j+skipcol) - 1; - zfog[j] = fog[i]; - } + for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) { + _mesa_write_rgba_span(ctx, &zoomed); + if (r1 - r0 > 1) { + /* restore the colors */ + MEMCPY(zoomed.array->rgba, rgbaSave, zoomed.end*4 * sizeof(GLchan)); + } } } - else { - GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; - for (j=0;j<m;j++) { - i = (GLint) ((j+skipcol) * xscale); - if (i<0) i = n + i - 1; - zrgba[j][0] = rgb[i][0]; - zrgba[j][1] = rgb[i][1]; - zrgba[j][2] = rgb[i][2]; - zrgba[j][3] = CHAN_MAX; - zdepth[j] = z[i]; + else if (format == GL_COLOR_INDEX) { + if (r1 - r0 > 1) { + MEMCPY(indexSave, zoomed.array->index, zoomed.end * sizeof(GLuint)); } - if (fog && ctx->Fog.Enabled) { - for (j=0;j<m;j++) { - i = (GLint) ((j+skipcol) * xscale); - if (i<0) i = n + i - 1; - zfog[j] = fog[i]; - } + for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) { + _mesa_write_index_span(ctx, &zoomed); + if (r1 - r0 > 1) { + /* restore the colors */ + MEMCPY(zoomed.array->index, indexSave, zoomed.end * sizeof(GLuint)); + } } } - - /* write the span */ - for (r=r0; r<r1; r++) { - _mesa_write_rgba_span( ctx, m, x+skipcol, r, zdepth, - (fog ? zfog : 0), zrgba, NULL, GL_BITMAP ); - } } - -/* - * As above, but write CI pixels. - */ void -_mesa_write_zoomed_index_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, const GLdepth z[], - const GLfloat *fog, - const GLuint indexes[], GLint y0 ) +_mesa_write_zoomed_rgba_span( GLcontext *ctx, const struct sw_span *span, + CONST GLchan rgba[][4], GLint y0 ) { - GLint m; - GLint r0, r1, row, r; - GLint i, j, skipcol; - GLuint zindexes[MAX_WIDTH]; /* zoomed color indexes */ - GLdepth zdepth[MAX_WIDTH]; /* zoomed depth values */ - GLfloat zfog[MAX_WIDTH]; /* zoomed fog values */ - GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH ); - - /* compute width of output row */ - m = (GLint) ABSF( n * ctx->Pixel.ZoomX ); - if (m==0) { - return; - } - if (ctx->Pixel.ZoomX<0.0) { - /* adjust x coordinate for left/right mirroring */ - x = x - m; - } - - /* compute which rows to draw */ - row = y-y0; - r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); - r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); - if (r0==r1) { - return; - } - else if (r1<r0) { - GLint rtmp = r1; - r1 = r0; - r0 = rtmp; - } - - /* return early if r0...r1 is above or below window */ - if (r0<0 && r1<0) { - /* below window */ - return; - } - if (r0 >= (GLint) ctx->DrawBuffer->Height && - r1 >= (GLint) ctx->DrawBuffer->Height) { - /* above window */ - return; - } + zoom_span(ctx, span, (const GLvoid *) rgba, y0, GL_RGBA); +} - /* check if left edge is outside window */ - skipcol = 0; - if (x<0) { - skipcol = -x; - m += x; - } - /* make sure span isn't too long or short */ - if (m>maxwidth) { - m = maxwidth; - } - else if (m<=0) { - return; - } - assert( m <= MAX_WIDTH ); +void +_mesa_write_zoomed_rgb_span( GLcontext *ctx, const struct sw_span *span, + CONST GLchan rgb[][3], GLint y0 ) +{ + zoom_span(ctx, span, (const GLvoid *) rgb, y0, GL_RGB); +} - /* zoom the span horizontally */ - if (ctx->Pixel.ZoomX==-1.0F) { - /* n==m */ - for (j=0;j<m;j++) { - i = n - (j+skipcol) - 1; - zindexes[j] = indexes[i]; - zdepth[j] = z[i]; - } - if (fog && ctx->Fog.Enabled) { - for (j=0;j<m;j++) { - i = n - (j+skipcol) - 1; - zfog[j] = fog[i]; - } - } - } - else { - GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; - for (j=0;j<m;j++) { - i = (GLint) ((j+skipcol) * xscale); - if (i<0) i = n + i - 1; - zindexes[j] = indexes[i]; - zdepth[j] = z[i]; - } - if (fog && ctx->Fog.Enabled) { - for (j=0;j<m;j++) { - i = (GLint) ((j+skipcol) * xscale); - if (i<0) i = n + i - 1; - zfog[j] = fog[i]; - } - } - } - /* write the span */ - for (r=r0; r<r1; r++) { - _mesa_write_index_span( ctx, m, x+skipcol, r, zdepth, - (fog ? zfog : 0), zindexes, NULL, GL_BITMAP ); - } +void +_mesa_write_zoomed_index_span( GLcontext *ctx, const struct sw_span *span, + GLint y0 ) +{ + zoom_span(ctx, span, (const GLvoid *) span->array->index, y0, GL_COLOR_INDEX); } - /* * As above, but write stencil values. */ @@ -431,7 +319,7 @@ _mesa_write_zoomed_stencil_span( GLcontext *ctx, return; } - assert( m <= MAX_WIDTH ); + ASSERT( m <= MAX_WIDTH ); /* zoom the span horizontally */ if (ctx->Pixel.ZoomX==-1.0F) { diff --git a/xc/extras/Mesa/src/swrast/s_zoom.h b/xc/extras/Mesa/src/swrast/s_zoom.h index a55223607..bdc7013e0 100644 --- a/xc/extras/Mesa/src/swrast/s_zoom.h +++ b/xc/extras/Mesa/src/swrast/s_zoom.h @@ -1,10 +1,9 @@ -/* $Id: s_zoom.h,v 1.1.1.1 2002/10/22 13:06:58 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -24,39 +23,26 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #ifndef S_ZOOM_H #define S_ZOOM_H - #include "mtypes.h" - +#include "swrast.h" extern void -_mesa_write_zoomed_rgba_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, const GLdepth z[], - const GLfloat *fog, - CONST GLchan rgba[][4], GLint y0 ); - +_mesa_write_zoomed_rgba_span( GLcontext *ctx, const struct sw_span *span, + CONST GLchan rgb[][4], GLint y0 ); extern void -_mesa_write_zoomed_rgb_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, const GLdepth z[], - const GLfloat *fog, +_mesa_write_zoomed_rgb_span( GLcontext *ctx, const struct sw_span *span, CONST GLchan rgb[][3], GLint y0 ); - extern void -_mesa_write_zoomed_index_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, const GLdepth z[], - const GLfloat *fog, - const GLuint indexes[], GLint y0 ); - +_mesa_write_zoomed_index_span( GLcontext *ctx, const struct sw_span *span, + GLint y0 ); extern void -_mesa_write_zoomed_stencil_span( GLcontext *ctx, - GLuint n, GLint x, GLint y, +_mesa_write_zoomed_stencil_span( GLcontext *ctx, GLuint n, GLint x, GLint y, const GLstencil stencil[], GLint y0 ); - #endif diff --git a/xc/extras/Mesa/src/swrast/swrast.h b/xc/extras/Mesa/src/swrast/swrast.h index 7149be8fb..76e9ca24d 100644 --- a/xc/extras/Mesa/src/swrast/swrast.h +++ b/xc/extras/Mesa/src/swrast/swrast.h @@ -1,10 +1,9 @@ -/* $Id: swrast.h,v 1.1.1.1 2002/10/22 13:06:46 alanh Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * 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"), @@ -23,8 +22,12 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Authors: - * Keith Whitwell <keithw@valinux.com> + */ + +/** + * \file swrast/swrast.h + * \brief Defines basic structures for sw_rasterizer. + * \author Keith Whitwell <keith@tungstengraphics.com> */ #ifndef SWRAST_H @@ -32,9 +35,11 @@ #include "mtypes.h" - - -/* The software rasterizer now uses this format for vertices. Thus a +/** + * \struct SWvertex + * \brief Data-structure to handle vertices in the software rasterizer. + * + * The software rasterizer now uses this format for vertices. Thus a * 'RasterSetup' stage or other translation is required between the * tnl module and the swrast rasterization functions. This serves to * isolate the swrast module from the internals of the tnl module, and @@ -57,6 +62,8 @@ * primitives unaccelerated), hook in swrast_setup instead. */ typedef struct { + /** win[0], win[1] are the screen-coords of SWvertex. win[2] is the + * z-coord. what is win[3]? */ GLfloat win[4]; GLfloat texcoord[MAX_TEXTURE_UNITS][4]; GLchan color[4]; @@ -67,6 +74,154 @@ typedef struct { } SWvertex; +/** + * \struct sw_span + * \brief Contains data for either a horizontal line or a set of + * pixels that are passed through a pipeline of functions before being + * drawn. + * + * The sw_span structure describes the colors, Z, fogcoord, texcoords, + * etc for either a horizontal run or a set of independent pixels. We + * can either specify a base/step to indicate interpolated values, or + * fill in arrays of values. The interpMask and arrayMask bitfields + * indicate which are active. + * + * With this structure it's easy to hand-off span rasterization to + * subroutines instead of doing it all inline in the triangle functions + * like we used to do. + * It also cleans up the local variable namespace a great deal. + * + * It would be interesting to experiment with multiprocessor rasterization + * with this structure. The triangle rasterizer could simply emit a + * stream of these structures which would be consumed by one or more + * span-processing threads which could run in parallel. + */ + + +/** + * \defgroup SpanFlags SPAN_XXX-flags + * Bitmasks to indicate which span_arrays need to be computed + * (sw_span::interpMask) or have already been filled + * (sw_span::arrayMask) + */ +/*@{*/ +#define SPAN_RGBA 0x001 +#define SPAN_SPEC 0x002 +#define SPAN_INDEX 0x004 +#define SPAN_Z 0x008 +#define SPAN_FOG 0x010 +#define SPAN_TEXTURE 0x020 +#define SPAN_INT_TEXTURE 0x040 +#define SPAN_LAMBDA 0x080 +#define SPAN_COVERAGE 0x100 +#define SPAN_FLAT 0x200 /**< flat shading? */ +/** sw_span::arrayMask only - for span_arrays::x, span_arrays::y */ +#define SPAN_XY 0x400 +#define SPAN_MASK 0x800 /**< sw_span::arrayMask only */ +/*@}*/ + + +/** + * \struct span_arrays + * \brief Arrays of fragment values. + * + * These will either be computed from the x/xStep values above or + * filled in by glDraw/CopyPixels, etc. + */ +struct span_arrays { + GLchan rgb[MAX_WIDTH][3]; + GLchan rgba[MAX_WIDTH][4]; + GLuint index[MAX_WIDTH]; + GLchan spec[MAX_WIDTH][4]; /* specular color */ + GLint x[MAX_WIDTH]; /**< X/Y used for point/line rendering only */ + GLint y[MAX_WIDTH]; /**< X/Y used for point/line rendering only */ + GLdepth z[MAX_WIDTH]; + GLfloat fog[MAX_WIDTH]; + GLfloat texcoords[MAX_TEXTURE_UNITS][MAX_WIDTH][4]; + GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; + GLfloat coverage[MAX_WIDTH]; + + /** This mask indicates if fragment is alive or culled */ + GLubyte mask[MAX_WIDTH]; +}; + + +struct sw_span { + GLint x, y; + + /** Only need to process pixels between start <= i < end */ + /** At this time, start is always zero. */ + GLuint start, end; + + /** This flag indicates that mask[] array is effectively filled with ones */ + GLboolean writeAll; + + /** either GL_POLYGON, GL_LINE, GL_POLYGON, GL_BITMAP */ + GLenum primitive; + + /** 0 = front-facing span, 1 = back-facing span (for two-sided stencil) */ + GLuint facing; + + /** + * This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates + * which of the x/xStep variables are relevant. + */ + GLuint interpMask; + +#if CHAN_TYPE == GL_FLOAT + GLfloat red, redStep; + GLfloat green, greenStep; + GLfloat blue, blueStep; + GLfloat alpha, alphaStep; + GLfloat specRed, specRedStep; + GLfloat specGreen, specGreenStep; + GLfloat specBlue, specBlueStep; +#else /* CHAN_TYPE == GL_UNSIGNED_BYTE or GL_UNSIGNED SHORT */ + GLfixed red, redStep; + GLfixed green, greenStep; + GLfixed blue, blueStep; + GLfixed alpha, alphaStep; + GLfixed specRed, specRedStep; + GLfixed specGreen, specGreenStep; + GLfixed specBlue, specBlueStep; +#endif + GLfixed index, indexStep; + GLfixed z, zStep; + GLfloat fog, fogStep; + GLfloat tex[MAX_TEXTURE_UNITS][4]; + GLfloat texStepX[MAX_TEXTURE_UNITS][4]; + GLfloat texStepY[MAX_TEXTURE_UNITS][4]; + GLfixed intTex[2], intTexStep[2]; + + /** + * This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates + * which of the fragment arrays in the span_arrays struct are relevant. + */ + GLuint arrayMask; + + /** + * We store the arrays of fragment values in a separate struct so + * that we can allocate sw_span structs on the stack without using + * a lot of memory. The span_arrays struct is about 400KB while the + * sw_span struct is only about 512 bytes. + */ + struct span_arrays *array; +}; + + +#define INIT_SPAN(S, PRIMITIVE, END, INTERP_MASK, ARRAY_MASK) \ +do { \ + (S).primitive = (PRIMITIVE); \ + (S).interpMask = (INTERP_MASK); \ + (S).arrayMask = (ARRAY_MASK); \ + (S).start = 0; \ + (S).end = (END); \ + (S).facing = 0; \ + (S).array = SWRAST_CONTEXT(ctx)->SpanArrays; \ +} while (0) + + + struct swrast_device_driver; @@ -75,6 +230,12 @@ struct swrast_device_driver; extern void _swrast_alloc_buffers( GLframebuffer *buffer ); +extern void +_swrast_use_read_buffer( GLcontext *ctx ); + +extern void +_swrast_use_draw_buffer( GLcontext *ctx ); + extern GLboolean _swrast_CreateContext( GLcontext *ctx ); @@ -125,6 +286,10 @@ _swrast_Accum( GLcontext *ctx, GLenum op, GLint width, GLint height ); +extern void +_swrast_DrawBuffer( GLcontext *ctx, GLenum mode ); + + /* Reset the stipple counter */ extern void @@ -153,6 +318,14 @@ _swrast_Quad( GLcontext *ctx, extern void _swrast_flush( GLcontext *ctx ); +extern void +_swrast_render_primitive( GLcontext *ctx, GLenum mode ); + +extern void +_swrast_render_start( GLcontext *ctx ); + +extern void +_swrast_render_finish( GLcontext *ctx ); /* Tell the software rasterizer about core state changes. */ @@ -177,19 +350,19 @@ _swrast_print_vertex( GLcontext *ctx, const SWvertex *v ); * Imaging fallbacks (a better solution should be found, perhaps * moving all the imaging fallback code to a new module) */ -void +extern void _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height); -void +extern void _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width); -void +extern void _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -void +extern void _swrast_CopyColorTable( GLcontext *ctx, GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); @@ -201,48 +374,51 @@ _swrast_CopyColorTable( GLcontext *ctx, */ extern void _swrast_copy_teximage1d(GLcontext *ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLint border); + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLint border); extern void _swrast_copy_teximage2d(GLcontext *ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border); + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border); extern void _swrast_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLint x, GLint y, GLsizei width); + GLint xoffset, GLint x, GLint y, GLsizei width); extern void _swrast_copy_texsubimage2d(GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint x, GLint y, GLsizei width, GLsizei height); + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height); extern void _swrast_copy_texsubimage3d(GLcontext *ctx, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height); + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height); -/* The driver interface for the software rasterizer. Unless otherwise - * noted, all functions are mandatory. +/* The driver interface for the software rasterizer. + * Unless otherwise noted, all functions are mandatory. */ struct swrast_device_driver { - void (*SetReadBuffer)( GLcontext *ctx, GLframebuffer *colorBuffer, - GLenum buffer ); + void (*SetBuffer)( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit); /* - * Specifies the current buffer for span/pixel reading. - * colorBuffer will be one of: - * GL_FRONT_LEFT - this buffer always exists - * GL_BACK_LEFT - when double buffering - * GL_FRONT_RIGHT - when using stereo - * GL_BACK_RIGHT - when using stereo and double buffering + * Specifies the current buffer for span/pixel writing/reading. + * buffer indicates which window to write to / read from. Normally, + * this'll be the buffer currently bound to the context, but it doesn't + * have to be! + * bufferBit indicates which color buffer, one of: + * FRONT_LEFT_BIT - this buffer always exists + * BACK_LEFT_BIT - when double buffering + * FRONT_RIGHT_BIT - when using stereo + * BACK_RIGHT_BIT - when using stereo and double buffering + * AUXn_BIT - if aux buffers are implemented */ |