From f7025b4baa1ba35ee796785641f04eac5bedb0a6 Mon Sep 17 00:00:00 2001 From: marha Date: Wed, 5 Oct 2011 17:37:34 +0200 Subject: mkfontscale pixman xserver xtrans libX11 libXdmcp libxcb libXmu mesa git update 5 oct 2011 --- mesalib/src/mesa/swrast/s_aaline.c | 984 +++++++++++++-------------- mesalib/src/mesa/swrast/s_aatriangle.c | 624 ++++++++--------- mesalib/src/mesa/swrast/s_blit.c | 2 +- mesalib/src/mesa/swrast/s_context.c | 11 - mesalib/src/mesa/swrast/s_context.h | 12 +- mesalib/src/mesa/swrast/s_fragprog.c | 2 +- mesalib/src/mesa/swrast/s_logic.c | 438 ++++++------ mesalib/src/mesa/swrast/s_points.c | 1144 ++++++++++++++++---------------- mesalib/src/mesa/swrast/s_span.c | 22 +- mesalib/src/mesa/swrast/s_stencil.c | 2 +- mesalib/src/mesa/swrast/s_texcombine.c | 22 +- mesalib/src/mesa/swrast/s_texfetch.c | 2 +- mesalib/src/mesa/swrast/s_texfilter.c | 52 +- mesalib/src/mesa/swrast/s_texture.c | 7 + mesalib/src/mesa/swrast/s_triangle.c | 8 +- mesalib/src/mesa/swrast/s_zoom.c | 866 ++++++++++++------------ 16 files changed, 2107 insertions(+), 2091 deletions(-) (limited to 'mesalib/src/mesa/swrast') diff --git a/mesalib/src/mesa/swrast/s_aaline.c b/mesalib/src/mesa/swrast/s_aaline.c index be817f326..d4b1805d9 100644 --- a/mesalib/src/mesa/swrast/s_aaline.c +++ b/mesalib/src/mesa/swrast/s_aaline.c @@ -1,492 +1,492 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.3 - * - * Copyright (C) 1999-2007 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 "main/glheader.h" -#include "main/imports.h" -#include "main/macros.h" -#include "main/mtypes.h" -#include "swrast/s_aaline.h" -#include "swrast/s_context.h" -#include "swrast/s_span.h" -#include "swrast/swrast.h" - - -#define SUB_PIXEL 4 - - -/* - * Info about the AA line we're rendering - */ -struct LineInfo -{ - GLfloat x0, y0; /* start */ - GLfloat x1, y1; /* end */ - GLfloat dx, dy; /* direction vector */ - GLfloat len; /* length */ - GLfloat halfWidth; /* half of line width */ - GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */ - /* for coverage computation */ - GLfloat qx0, qy0; /* quad vertices */ - GLfloat qx1, qy1; - GLfloat qx2, qy2; - GLfloat qx3, qy3; - GLfloat ex0, ey0; /* quad edge vectors */ - GLfloat ex1, ey1; - GLfloat ex2, ey2; - GLfloat ex3, ey3; - - /* DO_Z */ - GLfloat zPlane[4]; - /* DO_RGBA - always enabled */ - GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; - /* DO_ATTRIBS */ - GLfloat wPlane[4]; - GLfloat attrPlane[FRAG_ATTRIB_MAX][4][4]; - GLfloat lambda[FRAG_ATTRIB_MAX]; - GLfloat texWidth[FRAG_ATTRIB_MAX]; - GLfloat texHeight[FRAG_ATTRIB_MAX]; - - SWspan span; -}; - - - -/* - * Compute the equation of a plane used to interpolate line fragment data - * such as color, Z, texture coords, etc. - * Input: (x0, y0) and (x1,y1) are the endpoints of the line. - * z0, and z1 are the end point values to interpolate. - * Output: plane - the plane equation. - * - * Note: we don't really have enough parameters to specify a plane. - * We take the endpoints of the line and compute a plane such that - * the cross product of the line vector and the plane normal is - * parallel to the projection plane. - */ -static void -compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, - GLfloat z0, GLfloat z1, GLfloat plane[4]) -{ -#if 0 - /* original */ - const GLfloat px = x1 - x0; - const GLfloat py = y1 - y0; - const GLfloat pz = z1 - z0; - const GLfloat qx = -py; - const GLfloat qy = px; - const GLfloat qz = 0; - const GLfloat a = py * qz - pz * qy; - const GLfloat b = pz * qx - px * qz; - const GLfloat c = px * qy - py * qx; - const GLfloat d = -(a * x0 + b * y0 + c * z0); - plane[0] = a; - plane[1] = b; - plane[2] = c; - plane[3] = d; -#else - /* simplified */ - const GLfloat px = x1 - x0; - const GLfloat py = y1 - y0; - const GLfloat pz = z0 - z1; - const GLfloat a = pz * px; - const GLfloat b = pz * py; - const GLfloat c = px * px + py * py; - const GLfloat d = -(a * x0 + b * y0 + c * z0); - if (a == 0.0 && b == 0.0 && c == 0.0 && d == 0.0) { - plane[0] = 0.0; - plane[1] = 0.0; - plane[2] = 1.0; - plane[3] = 0.0; - } - else { - plane[0] = a; - plane[1] = b; - plane[2] = c; - plane[3] = d; - } -#endif -} - - -static INLINE void -constant_plane(GLfloat value, GLfloat plane[4]) -{ - plane[0] = 0.0; - plane[1] = 0.0; - plane[2] = -1.0; - plane[3] = value; -} - - -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; -} - -#define SOLVE_PLANE(X, Y, PLANE) \ - ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2]) - - -/* - * Return 1 / solve_plane(). - */ -static INLINE GLfloat -solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) -{ - const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; - if (denom == 0.0) - return 0.0; - else - return -plane[2] / denom; -} - - -/* - * Solve plane and return clamped GLchan value. - */ -static INLINE GLchan -solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4]) -{ - const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; -#if CHAN_TYPE == GL_FLOAT - return CLAMP(z, 0.0F, CHAN_MAXF); -#else - if (z < 0) - return 0; - else if (z > CHAN_MAX) - return CHAN_MAX; - return (GLchan) IROUND_POS(z); -#endif -} - - -/* - * Compute mipmap level of detail. - */ -static INLINE GLfloat -compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4], - GLfloat invQ, GLfloat width, GLfloat height) -{ - 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) (LOGF(rho2) * 1.442695 * 0.5);/* 1.442695 = 1/log(2) */ -} - - - - -/* - * Fill in the samples[] array with the (x,y) subpixel positions of - * xSamples * ySamples sample positions. - * Note that the four corner samples are put into the first four - * positions of the array. This allows us to optimize for the common - * case of all samples being inside the polygon. - */ -static void -make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2]) -{ - const GLfloat dx = 1.0F / (GLfloat) xSamples; - const GLfloat dy = 1.0F / (GLfloat) ySamples; - GLint x, y; - GLint i; - - i = 4; - for (x = 0; x < xSamples; x++) { - for (y = 0; y < ySamples; y++) { - GLint j; - if (x == 0 && y == 0) { - /* lower left */ - j = 0; - } - else if (x == xSamples - 1 && y == 0) { - /* lower right */ - j = 1; - } - else if (x == 0 && y == ySamples - 1) { - /* upper left */ - j = 2; - } - else if (x == xSamples - 1 && y == ySamples - 1) { - /* upper right */ - j = 3; - } - else { - j = i++; - } - samples[j][0] = x * dx + 0.5F * dx; - samples[j][1] = y * dy + 0.5F * dy; - } - } -} - - - -/* - * Compute how much of the given pixel's area is inside the rectangle - * defined by vertices v0, v1, v2, v3. - * Vertices MUST be specified in counter-clockwise order. - * Return: coverage in [0, 1]. - */ -static GLfloat -compute_coveragef(const struct LineInfo *info, - GLint winx, GLint winy) -{ - static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2]; - static GLboolean haveSamples = GL_FALSE; - const GLfloat x = (GLfloat) winx; - const GLfloat y = (GLfloat) winy; - GLint stop = 4, i; - GLfloat insideCount = SUB_PIXEL * SUB_PIXEL; - - if (!haveSamples) { - make_sample_table(SUB_PIXEL, SUB_PIXEL, samples); - haveSamples = GL_TRUE; - } - -#if 0 /*DEBUG*/ - { - const GLfloat area = dx0 * dy1 - dx1 * dy0; - assert(area >= 0.0); - } -#endif - - for (i = 0; i < stop; i++) { - const GLfloat sx = x + samples[i][0]; - const GLfloat sy = y + samples[i][1]; - const GLfloat fx0 = sx - info->qx0; - const GLfloat fy0 = sy - info->qy0; - const GLfloat fx1 = sx - info->qx1; - const GLfloat fy1 = sy - info->qy1; - const GLfloat fx2 = sx - info->qx2; - const GLfloat fy2 = sy - info->qy2; - const GLfloat fx3 = sx - info->qx3; - const GLfloat fy3 = sy - info->qy3; - /* cross product determines if sample is inside or outside each edge */ - GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0); - GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1); - GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2); - GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3); - /* Check if the sample is exactly on an edge. If so, let cross be a - * positive or negative value depending on the direction of the edge. - */ - if (cross0 == 0.0F) - cross0 = info->ex0 + info->ey0; - if (cross1 == 0.0F) - cross1 = info->ex1 + info->ey1; - if (cross2 == 0.0F) - cross2 = info->ex2 + info->ey2; - if (cross3 == 0.0F) - cross3 = info->ex3 + info->ey3; - if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) { - /* point is outside quadrilateral */ - insideCount -= 1.0F; - stop = SUB_PIXEL * SUB_PIXEL; - } - } - if (stop == 4) - return 1.0F; - else - return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL)); -} - - -typedef void (*plot_func)(struct gl_context *ctx, struct LineInfo *line, - int ix, int iy); - - - -/* - * Draw an AA line segment (called many times per line when stippling) - */ -static void -segment(struct gl_context *ctx, - struct LineInfo *line, - plot_func plot, - GLfloat t0, GLfloat t1) -{ - const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx; - const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy; - /* compute the actual segment's endpoints */ - const GLfloat x0 = line->x0 + t0 * line->dx; - const GLfloat y0 = line->y0 + t0 * line->dy; - const GLfloat x1 = line->x0 + t1 * line->dx; - const GLfloat y1 = line->y0 + t1 * line->dy; - - /* compute vertices of the line-aligned quadrilateral */ - line->qx0 = x0 - line->yAdj; - line->qy0 = y0 + line->xAdj; - line->qx1 = x0 + line->yAdj; - line->qy1 = y0 - line->xAdj; - line->qx2 = x1 + line->yAdj; - line->qy2 = y1 - line->xAdj; - line->qx3 = x1 - line->yAdj; - line->qy3 = y1 + line->xAdj; - /* compute the quad's edge vectors (for coverage calc) */ - line->ex0 = line->qx1 - line->qx0; - line->ey0 = line->qy1 - line->qy0; - line->ex1 = line->qx2 - line->qx1; - line->ey1 = line->qy2 - line->qy1; - line->ex2 = line->qx3 - line->qx2; - line->ey2 = line->qy3 - line->qy2; - line->ex3 = line->qx0 - line->qx3; - line->ey3 = line->qy0 - line->qy3; - - if (absDx > absDy) { - /* X-major line */ - GLfloat dydx = line->dy / line->dx; - GLfloat xLeft, xRight, yBot, yTop; - GLint ix, ixRight; - if (x0 < x1) { - xLeft = x0 - line->halfWidth; - xRight = x1 + line->halfWidth; - if (line->dy >= 0.0) { - yBot = y0 - 3.0F * line->halfWidth; - yTop = y0 + line->halfWidth; - } - else { - yBot = y0 - line->halfWidth; - yTop = y0 + 3.0F * line->halfWidth; - } - } - else { - xLeft = x1 - line->halfWidth; - xRight = x0 + line->halfWidth; - if (line->dy <= 0.0) { - yBot = y1 - 3.0F * line->halfWidth; - yTop = y1 + line->halfWidth; - } - else { - yBot = y1 - line->halfWidth; - yTop = y1 + 3.0F * line->halfWidth; - } - } - - /* scan along the line, left-to-right */ - ixRight = (GLint) (xRight + 1.0F); - - /*printf("avg span height: %g\n", yTop - yBot);*/ - for (ix = (GLint) xLeft; ix < ixRight; ix++) { - const GLint iyBot = (GLint) yBot; - const GLint iyTop = (GLint) (yTop + 1.0F); - GLint iy; - /* scan across the line, bottom-to-top */ - for (iy = iyBot; iy < iyTop; iy++) { - (*plot)(ctx, line, ix, iy); - } - yBot += dydx; - yTop += dydx; - } - } - else { - /* Y-major line */ - GLfloat dxdy = line->dx / line->dy; - GLfloat yBot, yTop, xLeft, xRight; - GLint iy, iyTop; - if (y0 < y1) { - yBot = y0 - line->halfWidth; - yTop = y1 + line->halfWidth; - if (line->dx >= 0.0) { - xLeft = x0 - 3.0F * line->halfWidth; - xRight = x0 + line->halfWidth; - } - else { - xLeft = x0 - line->halfWidth; - xRight = x0 + 3.0F * line->halfWidth; - } - } - else { - yBot = y1 - line->halfWidth; - yTop = y0 + line->halfWidth; - if (line->dx <= 0.0) { - xLeft = x1 - 3.0F * line->halfWidth; - xRight = x1 + line->halfWidth; - } - else { - xLeft = x1 - line->halfWidth; - xRight = x1 + 3.0F * line->halfWidth; - } - } - - /* scan along the line, bottom-to-top */ - iyTop = (GLint) (yTop + 1.0F); - - /*printf("avg span width: %g\n", xRight - xLeft);*/ - for (iy = (GLint) yBot; iy < iyTop; iy++) { - const GLint ixLeft = (GLint) xLeft; - const GLint ixRight = (GLint) (xRight + 1.0F); - GLint ix; - /* scan across the line, left-to-right */ - for (ix = ixLeft; ix < ixRight; ix++) { - (*plot)(ctx, line, ix, iy); - } - xLeft += dxdy; - xRight += dxdy; - } - } -} - - -#define NAME(x) aa_rgba_##x -#define DO_Z -#include "s_aalinetemp.h" - - -#define NAME(x) aa_general_rgba_##x -#define DO_Z -#define DO_ATTRIBS -#include "s_aalinetemp.h" - - - -void -_swrast_choose_aa_line_function(struct gl_context *ctx) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - - ASSERT(ctx->Line.SmoothFlag); - - if (ctx->Texture._EnabledCoordUnits != 0 - || ctx->FragmentProgram._Current - || (ctx->Light.Enabled && - ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - || ctx->Fog.ColorSumEnabled - || swrast->_FogEnabled) { - swrast->Line = aa_general_rgba_line; - } - else { - swrast->Line = aa_rgba_line; - } -} +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 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 "main/glheader.h" +#include "main/imports.h" +#include "main/macros.h" +#include "main/mtypes.h" +#include "swrast/s_aaline.h" +#include "swrast/s_context.h" +#include "swrast/s_span.h" +#include "swrast/swrast.h" + + +#define SUB_PIXEL 4 + + +/* + * Info about the AA line we're rendering + */ +struct LineInfo +{ + GLfloat x0, y0; /* start */ + GLfloat x1, y1; /* end */ + GLfloat dx, dy; /* direction vector */ + GLfloat len; /* length */ + GLfloat halfWidth; /* half of line width */ + GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */ + /* for coverage computation */ + GLfloat qx0, qy0; /* quad vertices */ + GLfloat qx1, qy1; + GLfloat qx2, qy2; + GLfloat qx3, qy3; + GLfloat ex0, ey0; /* quad edge vectors */ + GLfloat ex1, ey1; + GLfloat ex2, ey2; + GLfloat ex3, ey3; + + /* DO_Z */ + GLfloat zPlane[4]; + /* DO_RGBA - always enabled */ + GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; + /* DO_ATTRIBS */ + GLfloat wPlane[4]; + GLfloat attrPlane[FRAG_ATTRIB_MAX][4][4]; + GLfloat lambda[FRAG_ATTRIB_MAX]; + GLfloat texWidth[FRAG_ATTRIB_MAX]; + GLfloat texHeight[FRAG_ATTRIB_MAX]; + + SWspan span; +}; + + + +/* + * Compute the equation of a plane used to interpolate line fragment data + * such as color, Z, texture coords, etc. + * Input: (x0, y0) and (x1,y1) are the endpoints of the line. + * z0, and z1 are the end point values to interpolate. + * Output: plane - the plane equation. + * + * Note: we don't really have enough parameters to specify a plane. + * We take the endpoints of the line and compute a plane such that + * the cross product of the line vector and the plane normal is + * parallel to the projection plane. + */ +static void +compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, + GLfloat z0, GLfloat z1, GLfloat plane[4]) +{ +#if 0 + /* original */ + const GLfloat px = x1 - x0; + const GLfloat py = y1 - y0; + const GLfloat pz = z1 - z0; + const GLfloat qx = -py; + const GLfloat qy = px; + const GLfloat qz = 0; + const GLfloat a = py * qz - pz * qy; + const GLfloat b = pz * qx - px * qz; + const GLfloat c = px * qy - py * qx; + const GLfloat d = -(a * x0 + b * y0 + c * z0); + plane[0] = a; + plane[1] = b; + plane[2] = c; + plane[3] = d; +#else + /* simplified */ + const GLfloat px = x1 - x0; + const GLfloat py = y1 - y0; + const GLfloat pz = z0 - z1; + const GLfloat a = pz * px; + const GLfloat b = pz * py; + const GLfloat c = px * px + py * py; + const GLfloat d = -(a * x0 + b * y0 + c * z0); + if (a == 0.0 && b == 0.0 && c == 0.0 && d == 0.0) { + plane[0] = 0.0; + plane[1] = 0.0; + plane[2] = 1.0; + plane[3] = 0.0; + } + else { + plane[0] = a; + plane[1] = b; + plane[2] = c; + plane[3] = d; + } +#endif +} + + +static inline void +constant_plane(GLfloat value, GLfloat plane[4]) +{ + plane[0] = 0.0; + plane[1] = 0.0; + plane[2] = -1.0; + plane[3] = value; +} + + +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; +} + +#define SOLVE_PLANE(X, Y, PLANE) \ + ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2]) + + +/* + * Return 1 / solve_plane(). + */ +static inline GLfloat +solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) +{ + const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; + if (denom == 0.0) + return 0.0; + else + return -plane[2] / denom; +} + + +/* + * Solve plane and return clamped GLchan value. + */ +static inline GLchan +solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4]) +{ + const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; +#if CHAN_TYPE == GL_FLOAT + return CLAMP(z, 0.0F, CHAN_MAXF); +#else + if (z < 0) + return 0; + else if (z > CHAN_MAX) + return CHAN_MAX; + return (GLchan) IROUND_POS(z); +#endif +} + + +/* + * Compute mipmap level of detail. + */ +static inline GLfloat +compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4], + GLfloat invQ, GLfloat width, GLfloat height) +{ + 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) (LOGF(rho2) * 1.442695 * 0.5);/* 1.442695 = 1/log(2) */ +} + + + + +/* + * Fill in the samples[] array with the (x,y) subpixel positions of + * xSamples * ySamples sample positions. + * Note that the four corner samples are put into the first four + * positions of the array. This allows us to optimize for the common + * case of all samples being inside the polygon. + */ +static void +make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2]) +{ + const GLfloat dx = 1.0F / (GLfloat) xSamples; + const GLfloat dy = 1.0F / (GLfloat) ySamples; + GLint x, y; + GLint i; + + i = 4; + for (x = 0; x < xSamples; x++) { + for (y = 0; y < ySamples; y++) { + GLint j; + if (x == 0 && y == 0) { + /* lower left */ + j = 0; + } + else if (x == xSamples - 1 && y == 0) { + /* lower right */ + j = 1; + } + else if (x == 0 && y == ySamples - 1) { + /* upper left */ + j = 2; + } + else if (x == xSamples - 1 && y == ySamples - 1) { + /* upper right */ + j = 3; + } + else { + j = i++; + } + samples[j][0] = x * dx + 0.5F * dx; + samples[j][1] = y * dy + 0.5F * dy; + } + } +} + + + +/* + * Compute how much of the given pixel's area is inside the rectangle + * defined by vertices v0, v1, v2, v3. + * Vertices MUST be specified in counter-clockwise order. + * Return: coverage in [0, 1]. + */ +static GLfloat +compute_coveragef(const struct LineInfo *info, + GLint winx, GLint winy) +{ + static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2]; + static GLboolean haveSamples = GL_FALSE; + const GLfloat x = (GLfloat) winx; + const GLfloat y = (GLfloat) winy; + GLint stop = 4, i; + GLfloat insideCount = SUB_PIXEL * SUB_PIXEL; + + if (!haveSamples) { + make_sample_table(SUB_PIXEL, SUB_PIXEL, samples); + haveSamples = GL_TRUE; + } + +#if 0 /*DEBUG*/ + { + const GLfloat area = dx0 * dy1 - dx1 * dy0; + assert(area >= 0.0); + } +#endif + + for (i = 0; i < stop; i++) { + const GLfloat sx = x + samples[i][0]; + const GLfloat sy = y + samples[i][1]; + const GLfloat fx0 = sx - info->qx0; + const GLfloat fy0 = sy - info->qy0; + const GLfloat fx1 = sx - info->qx1; + const GLfloat fy1 = sy - info->qy1; + const GLfloat fx2 = sx - info->qx2; + const GLfloat fy2 = sy - info->qy2; + const GLfloat fx3 = sx - info->qx3; + const GLfloat fy3 = sy - info->qy3; + /* cross product determines if sample is inside or outside each edge */ + GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0); + GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1); + GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2); + GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3); + /* Check if the sample is exactly on an edge. If so, let cross be a + * positive or negative value depending on the direction of the edge. + */ + if (cross0 == 0.0F) + cross0 = info->ex0 + info->ey0; + if (cross1 == 0.0F) + cross1 = info->ex1 + info->ey1; + if (cross2 == 0.0F) + cross2 = info->ex2 + info->ey2; + if (cross3 == 0.0F) + cross3 = info->ex3 + info->ey3; + if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) { + /* point is outside quadrilateral */ + insideCount -= 1.0F; + stop = SUB_PIXEL * SUB_PIXEL; + } + } + if (stop == 4) + return 1.0F; + else + return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL)); +} + + +typedef void (*plot_func)(struct gl_context *ctx, struct LineInfo *line, + int ix, int iy); + + + +/* + * Draw an AA line segment (called many times per line when stippling) + */ +static void +segment(struct gl_context *ctx, + struct LineInfo *line, + plot_func plot, + GLfloat t0, GLfloat t1) +{ + const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx; + const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy; + /* compute the actual segment's endpoints */ + const GLfloat x0 = line->x0 + t0 * line->dx; + const GLfloat y0 = line->y0 + t0 * line->dy; + const GLfloat x1 = line->x0 + t1 * line->dx; + const GLfloat y1 = line->y0 + t1 * line->dy; + + /* compute vertices of the line-aligned quadrilateral */ + line->qx0 = x0 - line->yAdj; + line->qy0 = y0 + line->xAdj; + line->qx1 = x0 + line->yAdj; + line->qy1 = y0 - line->xAdj; + line->qx2 = x1 + line->yAdj; + line->qy2 = y1 - line->xAdj; + line->qx3 = x1 - line->yAdj; + line->qy3 = y1 + line->xAdj; + /* compute the quad's edge vectors (for coverage calc) */ + line->ex0 = line->qx1 - line->qx0; + line->ey0 = line->qy1 - line->qy0; + line->ex1 = line->qx2 - line->qx1; + line->ey1 = line->qy2 - line->qy1; + line->ex2 = line->qx3 - line->qx2; + line->ey2 = line->qy3 - line->qy2; + line->ex3 = line->qx0 - line->qx3; + line->ey3 = line->qy0 - line->qy3; + + if (absDx > absDy) { + /* X-major line */ + GLfloat dydx = line->dy / line->dx; + GLfloat xLeft, xRight, yBot, yTop; + GLint ix, ixRight; + if (x0 < x1) { + xLeft = x0 - line->halfWidth; + xRight = x1 + line->halfWidth; + if (line->dy >= 0.0) { + yBot = y0 - 3.0F * line->halfWidth; + yTop = y0 + line->halfWidth; + } + else { + yBot = y0 - line->halfWidth; + yTop = y0 + 3.0F * line->halfWidth; + } + } + else { + xLeft = x1 - line->halfWidth; + xRight = x0 + line->halfWidth; + if (line->dy <= 0.0) { + yBot = y1 - 3.0F * line->halfWidth; + yTop = y1 + line->halfWidth; + } + else { + yBot = y1 - line->halfWidth; + yTop = y1 + 3.0F * line->halfWidth; + } + } + + /* scan along the line, left-to-right */ + ixRight = (GLint) (xRight + 1.0F); + + /*printf("avg span height: %g\n", yTop - yBot);*/ + for (ix = (GLint) xLeft; ix < ixRight; ix++) { + const GLint iyBot = (GLint) yBot; + const GLint iyTop = (GLint) (yTop + 1.0F); + GLint iy; + /* scan across the line, bottom-to-top */ + for (iy = iyBot; iy < iyTop; iy++) { + (*plot)(ctx, line, ix, iy); + } + yBot += dydx; + yTop += dydx; + } + } + else { + /* Y-major line */ + GLfloat dxdy = line->dx / line->dy; + GLfloat yBot, yTop, xLeft, xRight; + GLint iy, iyTop; + if (y0 < y1) { + yBot = y0 - line->halfWidth; + yTop = y1 + line->halfWidth; + if (line->dx >= 0.0) { + xLeft = x0 - 3.0F * line->halfWidth; + xRight = x0 + line->halfWidth; + } + else { + xLeft = x0 - line->halfWidth; + xRight = x0 + 3.0F * line->halfWidth; + } + } + else { + yBot = y1 - line->halfWidth; + yTop = y0 + line->halfWidth; + if (line->dx <= 0.0) { + xLeft = x1 - 3.0F * line->halfWidth; + xRight = x1 + line->halfWidth; + } + else { + xLeft = x1 - line->halfWidth; + xRight = x1 + 3.0F * line->halfWidth; + } + } + + /* scan along the line, bottom-to-top */ + iyTop = (GLint) (yTop + 1.0F); + + /*printf("avg span width: %g\n", xRight - xLeft);*/ + for (iy = (GLint) yBot; iy < iyTop; iy++) { + const GLint ixLeft = (GLint) xLeft; + const GLint ixRight = (GLint) (xRight + 1.0F); + GLint ix; + /* scan across the line, left-to-right */ + for (ix = ixLeft; ix < ixRight; ix++) { + (*plot)(ctx, line, ix, iy); + } + xLeft += dxdy; + xRight += dxdy; + } + } +} + + +#define NAME(x) aa_rgba_##x +#define DO_Z +#include "s_aalinetemp.h" + + +#define NAME(x) aa_general_rgba_##x +#define DO_Z +#define DO_ATTRIBS +#include "s_aalinetemp.h" + + + +void +_swrast_choose_aa_line_function(struct gl_context *ctx) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + ASSERT(ctx->Line.SmoothFlag); + + if (ctx->Texture._EnabledCoordUnits != 0 + || ctx->FragmentProgram._Current + || (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) + || ctx->Fog.ColorSumEnabled + || swrast->_FogEnabled) { + swrast->Line = aa_general_rgba_line; + } + else { + swrast->Line = aa_rgba_line; + } +} diff --git a/mesalib/src/mesa/swrast/s_aatriangle.c b/mesalib/src/mesa/swrast/s_aatriangle.c index ad068d0c0..c68fdf63b 100644 --- a/mesalib/src/mesa/swrast/s_aatriangle.c +++ b/mesalib/src/mesa/swrast/s_aatriangle.c @@ -1,312 +1,312 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.3 - * - * Copyright (C) 1999-2007 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. - */ - - -/* - * Antialiased Triangle rasterizers - */ - - -#include "main/glheader.h" -#include "main/context.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/state.h" -#include "s_aatriangle.h" -#include "s_context.h" -#include "s_span.h" - - -/* - * 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[], - GLfloat z0, GLfloat z1, GLfloat z2, GLfloat plane[4]) -{ - const GLfloat px = v1[0] - v0[0]; - const GLfloat py = v1[1] - v0[1]; - const GLfloat pz = z1 - z0; - - const GLfloat qx = v2[0] - v0[0]; - 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; - plane[1] = b; - plane[2] = c; - plane[3] = d; -} - - -/* - * Compute coefficients of a plane with a constant Z value. - */ -static INLINE void -constant_plane(GLfloat value, GLfloat plane[4]) -{ - plane[0] = 0.0; - plane[1] = 0.0; - plane[2] = -1.0; - plane[3] = value; -} - -#define CONSTANT_PLANE(VALUE, PLANE) \ -do { \ - PLANE[0] = 0.0F; \ - PLANE[1] = 0.0F; \ - PLANE[2] = -1.0F; \ - PLANE[3] = VALUE; \ -} while (0) - - - -/* - * Solve plane equation for Z at (X,Y). - */ -static INLINE GLfloat -solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4]) -{ - ASSERT(plane[2] != 0.0F); - return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; -} - - -#define SOLVE_PLANE(X, Y, PLANE) \ - ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2]) - - -/* - * Return 1 / solve_plane(). - */ -static INLINE GLfloat -solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) -{ - const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; - if (denom == 0.0F) - return 0.0F; - else - return -plane[2] / denom; -} - - -/* - * Solve plane and return clamped GLchan value. - */ -static INLINE GLchan -solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4]) -{ - const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; -#if CHAN_TYPE == GL_FLOAT - return CLAMP(z, 0.0F, CHAN_MAXF); -#else - if (z < 0) - return 0; - else if (z > CHAN_MAX) - return CHAN_MAX; - return (GLchan) IROUND_POS(z); -#endif -} - - -static INLINE GLfloat -plane_dx(const GLfloat plane[4]) -{ - return -plane[0] / plane[2]; -} - -static INLINE GLfloat -plane_dy(const GLfloat plane[4]) -{ - return -plane[1] / plane[2]; -} - - - -/* - * Compute how much (area) of the given pixel is inside the triangle. - * Vertices MUST be specified in counter-clockwise order. - * Return: coverage in [0, 1]. - */ -static GLfloat -compute_coveragef(const GLfloat v0[3], const GLfloat v1[3], - const GLfloat v2[3], GLint winx, GLint winy) -{ - /* Given a position [0,3]x[0,3] return the sub-pixel sample position. - * Contributed by Ray Tice. - * - * Jitter sample positions - - * - average should be .5 in x & y for each column - * - each of the 16 rows and columns should be used once - * - the rectangle formed by the first four points - * should contain the other points - * - the distrubition should be fairly even in any given direction - * - * The pattern drawn below isn't optimal, but it's better than a regular - * grid. In the drawing, the center of each subpixel is surrounded by - * four dots. The "x" marks the jittered position relative to the - * subpixel center. - */ -#define POS(a, b) (0.5+a*4+b)/16 - static const GLfloat samples[16][2] = { - /* start with the four corners */ - { POS(0, 2), POS(0, 0) }, - { POS(3, 3), POS(0, 2) }, - { POS(0, 0), POS(3, 1) }, - { POS(3, 1), POS(3, 3) }, - /* continue with interior samples */ - { POS(1, 1), POS(0, 1) }, - { POS(2, 0), POS(0, 3) }, - { POS(0, 3), POS(1, 3) }, - { POS(1, 2), POS(1, 0) }, - { POS(2, 3), POS(1, 2) }, - { POS(3, 2), POS(1, 1) }, - { POS(0, 1), POS(2, 2) }, - { POS(1, 0), POS(2, 1) }, - { POS(2, 1), POS(2, 3) }, - { POS(3, 0), POS(2, 0) }, - { POS(1, 3), POS(3, 0) }, - { POS(2, 2), POS(3, 2) } - }; - - const GLfloat x = (GLfloat) winx; - const GLfloat y = (GLfloat) winy; - const GLfloat dx0 = v1[0] - v0[0]; - const GLfloat dy0 = v1[1] - v0[1]; - const GLfloat dx1 = v2[0] - v1[0]; - const GLfloat dy1 = v2[1] - v1[1]; - const GLfloat dx2 = v0[0] - v2[0]; - const GLfloat dy2 = v0[1] - v2[1]; - GLint stop = 4, i; - GLfloat insideCount = 16.0F; - - ASSERT(dx0 * dy1 - dx1 * dy0 >= 0.0); /* area >= 0.0 */ - - for (i = 0; i < stop; i++) { - const GLfloat sx = x + samples[i][0]; - const GLfloat sy = y + samples[i][1]; - /* cross product determines if sample is inside or outside each edge */ - GLfloat cross = (dx0 * (sy - v0[1]) - dy0 * (sx - v0[0])); - /* Check if the sample is exactly on an edge. If so, let cross be a - * positive or negative value depending on the direction of the edge. - */ - if (cross == 0.0F) - cross = dx0 + dy0; - if (cross < 0.0F) { - /* sample point is outside first edge */ - insideCount -= 1.0F; - stop = 16; - } - else { - /* sample point is inside first edge */ - cross = (dx1 * (sy - v1[1]) - dy1 * (sx - v1[0])); - if (cross == 0.0F) - cross = dx1 + dy1; - if (cross < 0.0F) { - /* sample point is outside second edge */ - insideCount -= 1.0F; - stop = 16; - } - else { - /* sample point is inside first and second edges */ - cross = (dx2 * (sy - v2[1]) - dy2 * (sx - v2[0])); - if (cross == 0.0F) - cross = dx2 + dy2; - if (cross < 0.0F) { - /* sample point is outside third edge */ - insideCount -= 1.0F; - stop = 16; - } - } - } - } - if (stop == 4) - return 1.0F; - else - return insideCount * (1.0F / 16.0F); -} - - - -static void -rgba_aa_tri(struct gl_context *ctx, - const SWvertex *v0, - const SWvertex *v1, - const SWvertex *v2) -{ -#define DO_Z -#include "s_aatritemp.h" -} - - -static void -general_aa_tri(struct gl_context *ctx, - const SWvertex *v0, - const SWvertex *v1, - const SWvertex *v2) -{ -#define DO_Z -#define DO_ATTRIBS -#include "s_aatritemp.h" -} - - - -/* - * Examine GL state and set swrast->Triangle to an - * appropriate antialiased triangle rasterizer function. - */ -void -_swrast_set_aa_triangle_function(struct gl_context *ctx) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - - ASSERT(ctx->Polygon.SmoothFlag); - - if (ctx->Texture._EnabledCoordUnits != 0 - || ctx->FragmentProgram._Current - || swrast->_FogEnabled - || _mesa_need_secondary_color(ctx)) { - SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri; - } - else { - SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri; - } - - ASSERT(SWRAST_CONTEXT(ctx)->Triangle); -} +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 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. + */ + + +/* + * Antialiased Triangle rasterizers + */ + + +#include "main/glheader.h" +#include "main/context.h" +#include "main/colormac.h" +#include "main/macros.h" +#include "main/imports.h" +#include "main/state.h" +#include "s_aatriangle.h" +#include "s_context.h" +#include "s_span.h" + + +/* + * 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[], + GLfloat z0, GLfloat z1, GLfloat z2, GLfloat plane[4]) +{ + const GLfloat px = v1[0] - v0[0]; + const GLfloat py = v1[1] - v0[1]; + const GLfloat pz = z1 - z0; + + const GLfloat qx = v2[0] - v0[0]; + 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; + plane[1] = b; + plane[2] = c; + plane[3] = d; +} + + +/* + * Compute coefficients of a plane with a constant Z value. + */ +static inline void +constant_plane(GLfloat value, GLfloat plane[4]) +{ + plane[0] = 0.0; + plane[1] = 0.0; + plane[2] = -1.0; + plane[3] = value; +} + +#define CONSTANT_PLANE(VALUE, PLANE) \ +do { \ + PLANE[0] = 0.0F; \ + PLANE[1] = 0.0F; \ + PLANE[2] = -1.0F; \ + PLANE[3] = VALUE; \ +} while (0) + + + +/* + * Solve plane equation for Z at (X,Y). + */ +static inline GLfloat +solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4]) +{ + ASSERT(plane[2] != 0.0F); + return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; +} + + +#define SOLVE_PLANE(X, Y, PLANE) \ + ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2]) + + +/* + * Return 1 / solve_plane(). + */ +static inline GLfloat +solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) +{ + const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; + if (denom == 0.0F) + return 0.0F; + else + return -plane[2] / denom; +} + + +/* + * Solve plane and return clamped GLchan value. + */ +static inline GLchan +solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4]) +{ + const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; +#if CHAN_TYPE == GL_FLOAT + return CLAMP(z, 0.0F, CHAN_MAXF); +#else + if (z < 0) + return 0; + else if (z > CHAN_MAX) + return CHAN_MAX; + return (GLchan) IROUND_POS(z); +#endif +} + + +static inline GLfloat +plane_dx(const GLfloat plane[4]) +{ + return -plane[0] / plane[2]; +} + +static inline GLfloat +plane_dy(const GLfloat plane[4]) +{ + return -plane[1] / plane[2]; +} + + + +/* + * Compute how much (area) of the given pixel is inside the triangle. + * Vertices MUST be specified in counter-clockwise order. + * Return: coverage in [0, 1]. + */ +static GLfloat +compute_coveragef(const GLfloat v0[3], const GLfloat v1[3], + const GLfloat v2[3], GLint winx, GLint winy) +{ + /* Given a position [0,3]x[0,3] return the sub-pixel sample position. + * Contributed by Ray Tice. + * + * Jitter sample positions - + * - average should be .5 in x & y for each column + * - each of the 16 rows and columns should be used once + * - the rectangle formed by the first four points + * should contain the other points + * - the distrubition should be fairly even in any given direction + * + * The pattern drawn below isn't optimal, but it's better than a regular + * grid. In the drawing, the center of each subpixel is surrounded by + * four dots. The "x" marks the jittered position relative to the + * subpixel center. + */ +#define POS(a, b) (0.5+a*4+b)/16 + static const GLfloat samples[16][2] = { + /* start with the four corners */ + { POS(0, 2), POS(0, 0) }, + { POS(3, 3), POS(0, 2) }, + { POS(0, 0), POS(3, 1) }, + { POS(3, 1), POS(3, 3) }, + /* continue with interior samples */ + { POS(1, 1), POS(0, 1) }, + { POS(2, 0), POS(0, 3) }, + { POS(0, 3), POS(1, 3) }, + { POS(1, 2), POS(1, 0) }, + { POS(2, 3), POS(1, 2) }, + { POS(3, 2), POS(1, 1) }, + { POS(0, 1), POS(2, 2) }, + { POS(1, 0), POS(2, 1) }, + { POS(2, 1), POS(2, 3) }, + { POS(3, 0), POS(2, 0) }, + { POS(1, 3), POS(3, 0) }, + { POS(2, 2), POS(3, 2) } + }; + + const GLfloat x = (GLfloat) winx; + const GLfloat y = (GLfloat) winy; + const GLfloat dx0 = v1[0] - v0[0]; + const GLfloat dy0 = v1[1] - v0[1]; + const GLfloat dx1 = v2[0] - v1[0]; + const GLfloat dy1 = v2[1] - v1[1]; + const GLfloat dx2 = v0[0] - v2[0]; + const GLfloat dy2 = v0[1] - v2[1]; + GLint stop = 4, i; + GLfloat insideCount = 16.0F; + + ASSERT(dx0 * dy1 - dx1 * dy0 >= 0.0); /* area >= 0.0 */ + + for (i = 0; i < stop; i++) { + const GLfloat sx = x + samples[i][0]; + const GLfloat sy = y + samples[i][1]; + /* cross product determines if sample is inside or outside each edge */ + GLfloat cross = (dx0 * (sy - v0[1]) - dy0 * (sx - v0[0])); + /* Check if the sample is exactly on an edge. If so, let cross be a + * positive or negative value depending on the direction of the edge. + */ + if (cross == 0.0F) + cross = dx0 + dy0; + if (cross < 0.0F) { + /* sample point is outside first edge */ + insideCount -= 1.0F; + stop = 16; + } + else { + /* sample point is inside first edge */ + cross = (dx1 * (sy - v1[1]) - dy1 * (sx - v1[0])); + if (cross == 0.0F) + cross = dx1 + dy1; + if (cross < 0.0F) { + /* sample point is outside second edge */ + insideCount -= 1.0F; + stop = 16; + } + else { + /* sample point is inside first and second edges */ + cross = (dx2 * (sy - v2[1]) - dy2 * (sx - v2[0])); + if (cross == 0.0F) + cross = dx2 + dy2; + if (cross < 0.0F) { + /* sample point is outside third edge */ + insideCount -= 1.0F; + stop = 16; + } + } + } + } + if (stop == 4) + return 1.0F; + else + return insideCount * (1.0F / 16.0F); +} + + + +static void +rgba_aa_tri(struct gl_context *ctx, + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2) +{ +#define DO_Z +#include "s_aatritemp.h" +} + + +static void +general_aa_tri(struct gl_context *ctx, + const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2) +{ +#define DO_Z +#define DO_ATTRIBS +#include "s_aatritemp.h" +} + + + +/* + * Examine GL state and set swrast->Triangle to an + * appropriate antialiased triangle rasterizer function. + */ +void +_swrast_set_aa_triangle_function(struct gl_context *ctx) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + ASSERT(ctx->Polygon.SmoothFlag); + + if (ctx->Texture._EnabledCoordUnits != 0 + || ctx->FragmentProgram._Current + || swrast->_FogEnabled + || _mesa_need_secondary_color(ctx)) { + SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri; + } + else { + SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri; + } + + ASSERT(SWRAST_CONTEXT(ctx)->Triangle); +} diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index 7f53f19eb..f094be898 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -243,7 +243,7 @@ blit_nearest(struct gl_context *ctx, #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) ) -static INLINE GLfloat +static inline GLfloat lerp_2d(GLfloat a, GLfloat b, GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11) { diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c index a4acac233..5287671d7 100644 --- a/mesalib/src/mesa/swrast/s_context.c +++ b/mesalib/src/mesa/swrast/s_context.c @@ -780,17 +780,6 @@ _swrast_CreateContext( struct gl_context *ctx ) swrast->PointSpan.facing = 0; swrast->PointSpan.array = swrast->SpanArrays; - /* TexelBuffer is also global and normally shared by all SWspan instances; - * when running with multiple threads, create one per thread. - */ - swrast->TexelBuffer = (GLfloat *) MALLOC(ctx->Const.MaxTextureImageUnits * maxThreads * - MAX_WIDTH * 4 * sizeof(GLfloat)); - if (!swrast->TexelBuffer) { - FREE(swrast->SpanArrays); - FREE(swrast); - return GL_FALSE; - } - init_program_native_limits(&ctx->Const.VertexProgram); init_program_native_limits(&ctx->Const.GeometryProgram); init_program_native_limits(&ctx->Const.FragmentProgram); diff --git a/mesalib/src/mesa/swrast/s_context.h b/mesalib/src/mesa/swrast/s_context.h index 1e0bfc0f9..12ad688b0 100644 --- a/mesalib/src/mesa/swrast/s_context.h +++ b/mesalib/src/mesa/swrast/s_context.h @@ -163,14 +163,14 @@ struct swrast_texture_image /** cast wrapper */ -static INLINE struct swrast_texture_image * +static inline struct swrast_texture_image * swrast_texture_image(struct gl_texture_image *img) { return (struct swrast_texture_image *) img; } /** cast wrapper */ -static INLINE const struct swrast_texture_image * +static inline const struct swrast_texture_image * swrast_texture_image_const(const struct gl_texture_image *img) { return (const struct swrast_texture_image *) img; @@ -308,14 +308,14 @@ _swrast_update_texture_samplers(struct gl_context *ctx); /** Return SWcontext for the given struct gl_context */ -static INLINE SWcontext * +static inline SWcontext * SWRAST_CONTEXT(struct gl_context *ctx) { return (SWcontext *) ctx->swrast_context; } /** const version of above */ -static INLINE const SWcontext * +static inline const SWcontext * CONST_SWRAST_CONTEXT(const struct gl_context *ctx) { return (const SWcontext *) ctx->swrast_context; @@ -327,7 +327,7 @@ CONST_SWRAST_CONTEXT(const struct gl_context *ctx) * For drivers that rely on swrast for fallback rendering, this is the * driver's opportunity to map renderbuffers and textures. */ -static INLINE void +static inline void swrast_render_start(struct gl_context *ctx) { SWcontext *swrast = SWRAST_CONTEXT(ctx); @@ -337,7 +337,7 @@ swrast_render_start(struct gl_context *ctx) /** Called after framebuffer reading/writing */ -static INLINE void +static inline void swrast_render_finish(struct gl_context *ctx) { SWcontext *swrast = SWRAST_CONTEXT(ctx); diff --git a/mesalib/src/mesa/swrast/s_fragprog.c b/mesalib/src/mesa/swrast/s_fragprog.c index 9513b1c46..7f205a200 100644 --- a/mesalib/src/mesa/swrast/s_fragprog.c +++ b/mesalib/src/mesa/swrast/s_fragprog.c @@ -35,7 +35,7 @@ * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel' * and return results in 'colorOut'. */ -static INLINE void +static inline void swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle) { if (swizzle == SWIZZLE_NOOP) { diff --git a/mesalib/src/mesa/swrast/s_logic.c b/mesalib/src/mesa/swrast/s_logic.c index 2f0c0ea7c..80ee46c24 100644 --- a/mesalib/src/mesa/swrast/s_logic.c +++ b/mesalib/src/mesa/swrast/s_logic.c @@ -1,219 +1,219 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.2 - * - * Copyright (C) 1999-2006 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 "main/glheader.h" -#include "main/context.h" -#include "main/imports.h" -#include "main/macros.h" - -#include "s_context.h" -#include "s_logic.h" -#include "s_span.h" - - -/** - * We do all logic ops on 4-byte GLuints. - * Depending on bytes per pixel, the mask array elements correspond to - * 1, 2 or 4 GLuints. - */ -#define LOGIC_OP_LOOP(MODE, MASKSTRIDE) \ -do { \ - GLuint i; \ - switch (MODE) { \ - case GL_CLEAR: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = 0; \ - } \ - } \ - break; \ - case GL_SET: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~0; \ - } \ - } \ - break; \ - case GL_COPY: \ - /* do nothing */ \ - break; \ - case GL_COPY_INVERTED: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~src[i]; \ - } \ - } \ - break; \ - case GL_NOOP: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = dest[i]; \ - } \ - } \ - break; \ - case GL_INVERT: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~dest[i]; \ - } \ - } \ - break; \ - case GL_AND: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] &= dest[i]; \ - } \ - } \ - break; \ - case GL_NAND: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~(src[i] & dest[i]); \ - } \ - } \ - break; \ - case GL_OR: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] |= dest[i]; \ - } \ - } \ - break; \ - case GL_NOR: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~(src[i] | dest[i]); \ - } \ - } \ - break; \ - case GL_XOR: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] ^= dest[i]; \ - } \ - } \ - break; \ - case GL_EQUIV: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~(src[i] ^ dest[i]); \ - } \ - } \ - break; \ - case GL_AND_REVERSE: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = src[i] & ~dest[i]; \ - } \ - } \ - break; \ - case GL_AND_INVERTED: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~src[i] & dest[i]; \ - } \ - } \ - break; \ - case GL_OR_REVERSE: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = src[i] | ~dest[i]; \ - } \ - } \ - break; \ - case GL_OR_INVERTED: \ - for (i = 0; i < n; i++) { \ - if (mask[i / MASKSTRIDE]) { \ - src[i] = ~src[i] | dest[i]; \ - } \ - } \ - break; \ - default: \ - _mesa_problem(ctx, "bad logicop mode");\ - } \ -} while (0) - - - -static INLINE void -logicop_uint1(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[], - const GLubyte mask[]) -{ - LOGIC_OP_LOOP(ctx->Color.LogicOp, 1); -} - - -static INLINE void -logicop_uint2(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[], - const GLubyte mask[]) -{ - LOGIC_OP_LOOP(ctx->Color.LogicOp, 2); -} - - -static INLINE void -logicop_uint4(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[], - const GLubyte mask[]) -{ - LOGIC_OP_LOOP(ctx->Color.LogicOp, 4); -} - - - -/** - * Apply the current logic operator to a span of RGBA pixels. - * We can handle horizontal runs of pixels (spans) or arrays of x/y - * pixel coordinates. - */ -void -_swrast_logicop_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb, - SWspan *span) -{ - void *rbPixels; - - ASSERT(span->end < MAX_WIDTH); - ASSERT(span->arrayMask & SPAN_RGBA); - ASSERT(rb->DataType == span->array->ChanType); - - rbPixels = _swrast_get_dest_rgba(ctx, rb, span); - - if (span->array->ChanType == GL_UNSIGNED_BYTE) { - /* treat 4*GLubyte as GLuint */ - logicop_uint1(ctx, span->end, - (GLuint *) span->array->rgba8, - (const GLuint *) rbPixels, span->array->mask); - } - else if (span->array->ChanType == GL_UNSIGNED_SHORT) { - /* treat 2*GLushort as GLuint */ - logicop_uint2(ctx, 2 * span->end, - (GLuint *) span->array->rgba16, - (const GLuint *) rbPixels, span->array->mask); - } - else { - logicop_uint4(ctx, 4 * span->end, - (GLuint *) span->array->attribs[FRAG_ATTRIB_COL0], - (const GLuint *) rbPixels, span->array->mask); - } -} +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 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 "main/glheader.h" +#include "main/context.h" +#include "main/imports.h" +#include "main/macros.h" + +#include "s_context.h" +#include "s_logic.h" +#include "s_span.h" + + +/** + * We do all logic ops on 4-byte GLuints. + * Depending on bytes per pixel, the mask array elements correspond to + * 1, 2 or 4 GLuints. + */ +#define LOGIC_OP_LOOP(MODE, MASKSTRIDE) \ +do { \ + GLuint i; \ + switch (MODE) { \ + case GL_CLEAR: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = 0; \ + } \ + } \ + break; \ + case GL_SET: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~0; \ + } \ + } \ + break; \ + case GL_COPY: \ + /* do nothing */ \ + break; \ + case GL_COPY_INVERTED: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~src[i]; \ + } \ + } \ + break; \ + case GL_NOOP: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = dest[i]; \ + } \ + } \ + break; \ + case GL_INVERT: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~dest[i]; \ + } \ + } \ + break; \ + case GL_AND: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] &= dest[i]; \ + } \ + } \ + break; \ + case GL_NAND: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~(src[i] & dest[i]); \ + } \ + } \ + break; \ + case GL_OR: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] |= dest[i]; \ + } \ + } \ + break; \ + case GL_NOR: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~(src[i] | dest[i]); \ + } \ + } \ + break; \ + case GL_XOR: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] ^= dest[i]; \ + } \ + } \ + break; \ + case GL_EQUIV: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~(src[i] ^ dest[i]); \ + } \ + } \ + break; \ + case GL_AND_REVERSE: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = src[i] & ~dest[i]; \ + } \ + } \ + break; \ + case GL_AND_INVERTED: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~src[i] & dest[i]; \ + } \ + } \ + break; \ + case GL_OR_REVERSE: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = src[i] | ~dest[i]; \ + } \ + } \ + break; \ + case GL_OR_INVERTED: \ + for (i = 0; i < n; i++) { \ + if (mask[i / MASKSTRIDE]) { \ + src[i] = ~src[i] | dest[i]; \ + } \ + } \ + break; \ + default: \ + _mesa_problem(ctx, "bad logicop mode");\ + } \ +} while (0) + + + +static inline void +logicop_uint1(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[], + const GLubyte mask[]) +{ + LOGIC_OP_LOOP(ctx->Color.LogicOp, 1); +} + + +static inline void +logicop_uint2(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[], + const GLubyte mask[]) +{ + LOGIC_OP_LOOP(ctx->Color.LogicOp, 2); +} + + +static inline void +logicop_uint4(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[], + const GLubyte mask[]) +{ + LOGIC_OP_LOOP(ctx->Color.LogicOp, 4); +} + + + +/** + * Apply the current logic operator to a span of RGBA pixels. + * We can handle horizontal runs of pixels (spans) or arrays of x/y + * pixel coordinates. + */ +void +_swrast_logicop_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb, + SWspan *span) +{ + void *rbPixels; + + ASSERT(span->end < MAX_WIDTH); + ASSERT(span->arrayMask & SPAN_RGBA); + ASSERT(rb->DataType == span->array->ChanType); + + rbPixels = _swrast_get_dest_rgba(ctx, rb, span); + + if (span->array->ChanType == GL_UNSIGNED_BYTE) { + /* treat 4*GLubyte as GLuint */ + logicop_uint1(ctx, span->end, + (GLuint *) span->array->rgba8, + (const GLuint *) rbPixels, span->array->mask); + } + else if (span->array->ChanType == GL_UNSIGNED_SHORT) { + /* treat 2*GLushort as GLuint */ + logicop_uint2(ctx, 2 * span->end, + (GLuint *) span->array->rgba16, + (const GLuint *) rbPixels, span->array->mask); + } + else { + logicop_uint4(ctx, 4 * span->end, + (GLuint *) span->array->attribs[FRAG_ATTRIB_COL0], + (const GLuint *) rbPixels, span->array->mask); + } +} diff --git a/mesalib/src/mesa/swrast/s_points.c b/mesalib/src/mesa/swrast/s_points.c index a46be8f58..11b7ef7b1 100644 --- a/mesalib/src/mesa/swrast/s_points.c +++ b/mesalib/src/mesa/swrast/s_points.c @@ -1,572 +1,572 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 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 "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "s_context.h" -#include "s_feedback.h" -#include "s_points.h" -#include "s_span.h" - - -/** - * Used to cull points with invalid coords - */ -#define CULL_INVALID(V) \ - do { \ - float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0] \ - + (V)->attrib[FRAG_ATTRIB_WPOS][1]; \ - if (IS_INF_OR_NAN(tmp)) \ - return; \ - } while(0) - - - -/** - * Get/compute the point size. - * The size may come from a vertex shader, or computed with attentuation - * or just the glPointSize value. - * Must also clamp to user-defined range and implmentation limits. - */ -static INLINE GLfloat -get_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed) -{ - GLfloat size; - - if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) { - /* use vertex's point size */ - size = vert->pointSize; - } - else { - /* use constant point size */ - size = ctx->Point.Size; - } - /* always clamp to user-specified limits */ - size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize); - /* clamp to implementation limits */ - if (smoothed) - size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA); - else - size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize); - - return size; -} - - -/** - * Draw a point sprite - */ -static void -sprite_point(struct gl_context *ctx, const SWvertex *vert) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - SWspan span; - GLfloat size; - GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1]; - GLuint numTcoords = 0; - GLfloat t0, dtdy; - - CULL_INVALID(vert); - - /* z coord */ - if (ctx->DrawBuffer->Visual.depthBits <= 16) - span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); - else - span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); - span.zStep = 0; - - size = get_size(ctx, vert, GL_FALSE); - - /* span init */ - INIT_SPAN(span, GL_POINT); - span.interpMask = SPAN_Z | SPAN_RGBA; - - span.facing = swrast->PointLineFacing; - - span.red = ChanToFixed(vert->color[0]); - span.green = ChanToFixed(vert->color[1]); - span.blue = ChanToFixed(vert->color[2]); - span.alpha = ChanToFixed(vert->color[3]); - span.redStep = 0; - span.greenStep = 0; - span.blueStep = 0; - span.alphaStep = 0; - - /* need these for fragment programs */ - span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; - span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; - span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; - - { - GLfloat s, r, dsdx; - - /* texcoord / pointcoord interpolants */ - s = 0.0F; - dsdx = 1.0F / size; - if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) { - dtdy = 1.0F / size; - t0 = 0.5F * dtdy; - } - else { - /* GL_UPPER_LEFT */ - dtdy = -1.0F / size; - t0 = 1.0F + 0.5F * dtdy; - } - - ATTRIB_LOOP_BEGIN - if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) { - /* a texcoord attribute */ - const GLuint u = attr - FRAG_ATTRIB_TEX0; - ASSERT(u < Elements(ctx->Point.CoordReplace)); - if (ctx->Point.CoordReplace[u]) { - tCoords[numTcoords++] = attr; - - if (ctx->Point.SpriteRMode == GL_ZERO) - r = 0.0F; - else if (ctx->Point.SpriteRMode == GL_S) - r = vert->attrib[attr][0]; - else /* GL_R */ - r = vert->attrib[attr][2]; - - span.attrStart[attr][0] = s; - span.attrStart[attr][1] = 0.0; /* overwritten below */ - span.attrStart[attr][2] = r; - span.attrStart[attr][3] = 1.0; - - span.attrStepX[attr][0] = dsdx; - span.attrStepX[attr][1] = 0.0; - span.attrStepX[attr][2] = 0.0; - span.attrStepX[attr][3] = 0.0; - - span.attrStepY[attr][0] = 0.0; - span.attrStepY[attr][1] = dtdy; - span.attrStepY[attr][2] = 0.0; - span.attrStepY[attr][3] = 0.0; - - continue; - } - } - else if (attr == FRAG_ATTRIB_PNTC) { - /* GLSL gl_PointCoord.xy (.zw undefined) */ - span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0; - span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */ - span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx; - span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0; - span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0; - span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy; - tCoords[numTcoords++] = FRAG_ATTRIB_PNTC; - continue; - } - /* use vertex's texcoord/attrib */ - COPY_4V(span.attrStart[attr], vert->attrib[attr]); - ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); - ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); - ATTRIB_LOOP_END; - } - - /* compute pos, bounds and render */ - { - const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; - const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; - GLint iSize = (GLint) (size + 0.5F); - GLint xmin, xmax, ymin, ymax, iy; - GLint iRadius; - GLfloat tcoord = t0; - - iSize = MAX2(1, iSize); - iRadius = iSize / 2; - - if (iSize & 1) { - /* odd size */ - xmin = (GLint) (x - iRadius); - xmax = (GLint) (x + iRadius); - ymin = (GLint) (y - iRadius); - ymax = (GLint) (y + iRadius); - } - else { - /* even size */ - /* 0.501 factor allows conformance to pass */ - xmin = (GLint) (x + 0.501) - iRadius; - xmax = xmin + iSize - 1; - ymin = (GLint) (y + 0.501) - iRadius; - ymax = ymin + iSize - 1; - } - - /* render spans */ - for (iy = ymin; iy <= ymax; iy++) { - GLuint i; - /* setup texcoord T for this row */ - for (i = 0; i < numTcoords; i++) { - span.attrStart[tCoords[i]][1] = tcoord; - } - - /* these might get changed by span clipping */ - span.x = xmin; - span.y = iy; - span.end = xmax - xmin + 1; - - _swrast_write_rgba_span(ctx, &span); - - tcoord += dtdy; - } - } -} - - -/** - * Draw smooth/antialiased point. RGB or CI mode. - */ -static void -smooth_point(struct gl_context *ctx, const SWvertex *vert) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - SWspan span; - GLfloat size, alphaAtten; - - CULL_INVALID(vert); - - /* z coord */ - if (ctx->DrawBuffer->Visual.depthBits <= 16) - span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); - else - span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); - span.zStep = 0; - - size = get_size(ctx, vert, GL_TRUE); - - /* alpha attenuation / fade factor */ - if (ctx->Multisample._Enabled) { - if (vert->pointSize >= ctx->Point.Threshold) { - alphaAtten = 1.0F; - } - else { - GLfloat dsize = vert->pointSize / ctx->Point.Threshold; - alphaAtten = dsize * dsize; - } - } - else { - alphaAtten = 1.0; - } - (void) alphaAtten; /* not used */ - - /* span init */ - INIT_SPAN(span, GL_POINT); - span.interpMask = SPAN_Z | SPAN_RGBA; - span.arrayMask = SPAN_COVERAGE | SPAN_MASK; - - span.facing = swrast->PointLineFacing; - - span.red = ChanToFixed(vert->color[0]); - span.green = ChanToFixed(vert->color[1]); - span.blue = ChanToFixed(vert->color[2]); - span.alpha = ChanToFixed(vert->color[3]); - span.redStep = 0; - span.greenStep = 0; - span.blueStep = 0; - span.alphaStep = 0; - - /* need these for fragment programs */ - span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; - span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; - span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; - - ATTRIB_LOOP_BEGIN - COPY_4V(span.attrStart[attr], vert->attrib[attr]); - ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); - ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); - ATTRIB_LOOP_END - - /* compute pos, bounds and render */ - { - const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; - const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; - const GLfloat radius = 0.5F * size; - const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ - const GLfloat rmax = radius + 0.7071F; - const GLfloat rmin2 = MAX2(0.0F, rmin * rmin); - const GLfloat rmax2 = rmax * rmax; - const GLfloat cscale = 1.0F / (rmax2 - rmin2); - const GLint xmin = (GLint) (x - radius); - const GLint xmax = (GLint) (x + radius); - const GLint ymin = (GLint) (y - radius); - const GLint ymax = (GLint) (y + radius); - GLint ix, iy; - - for (iy = ymin; iy <= ymax; iy++) { - - /* these might get changed by span clipping */ - span.x = xmin; - span.y = iy; - span.end = xmax - xmin + 1; - - /* compute coverage for each pixel in span */ - for (ix = xmin; ix <= xmax; ix++) { - const GLfloat dx = ix - x + 0.5F; - const GLfloat dy = iy - y + 0.5F; - const GLfloat dist2 = dx * dx + dy * dy; - GLfloat coverage; - - if (dist2 < rmax2) { - if (dist2 >= rmin2) { - /* compute partial coverage */ - coverage = 1.0F - (dist2 - rmin2) * cscale; - } - else { - /* full coverage */ - coverage = 1.0F; - } - span.array->mask[ix - xmin] = 1; - } - else { - /* zero coverage - fragment outside the radius */ - coverage = 0.0; - span.array->mask[ix - xmin] = 0; - } - span.array->coverage[ix - xmin] = coverage; - } - - /* render span */ - _swrast_write_rgba_span(ctx, &span); - - } - } -} - - -/** - * Draw large (size >= 1) non-AA point. RGB or CI mode. - */ -static void -large_point(struct gl_context *ctx, const SWvertex *vert) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - SWspan span; - GLfloat size; - - CULL_INVALID(vert); - - /* z coord */ - if (ctx->DrawBuffer->Visual.depthBits <= 16) - span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); - else - span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); - span.zStep = 0; - - size = get_size(ctx, vert, GL_FALSE); - - /* span init */ - INIT_SPAN(span, GL_POINT); - span.arrayMask = SPAN_XY; - span.facing = swrast->PointLineFacing; - - span.interpMask = SPAN_Z | SPAN_RGBA; - span.red = ChanToFixed(vert->color[0]); - span.green = ChanToFixed(vert->color[1]); - span.blue = ChanToFixed(vert->color[2]); - span.alpha = ChanToFixed(vert->color[3]); - span.redStep = 0; - span.greenStep = 0; - span.blueStep = 0; - span.alphaStep = 0; - - /* need these for fragment programs */ - span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; - span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; - span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; - - ATTRIB_LOOP_BEGIN - COPY_4V(span.attrStart[attr], vert->attrib[attr]); - ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); - ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); - ATTRIB_LOOP_END - - /* compute pos, bounds and render */ - { - const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; - const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; - GLint iSize = (GLint) (size + 0.5F); - GLint xmin, xmax, ymin, ymax, ix, iy; - GLint iRadius; - - iSize = MAX2(1, iSize); - iRadius = iSize / 2; - - if (iSize & 1) { - /* odd size */ - xmin = (GLint) (x - iRadius); - xmax = (GLint) (x + iRadius); - ymin = (GLint) (y - iRadius); - ymax = (GLint) (y + iRadius); - } - else { - /* even size */ - /* 0.501 factor allows conformance to pass */ - xmin = (GLint) (x + 0.501) - iRadius; - xmax = xmin + iSize - 1; - ymin = (GLint) (y + 0.501) - iRadius; - ymax = ymin + iSize - 1; - } - - /* generate fragments */ - span.end = 0; - for (iy = ymin; iy <= ymax; iy++) { - for (ix = xmin; ix <= xmax; ix++) { - span.array->x[span.end] = ix; - span.array->y[span.end] = iy; - span.end++; - } - } - assert(span.end <= MAX_WIDTH); - _swrast_write_rgba_span(ctx, &span); - } -} - - -/** - * Draw size=1, single-pixel point - */ -static void -pixel_point(struct gl_context *ctx, const SWvertex *vert) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - /* - * Note that unlike the other functions, we put single-pixel points - * into a special span array in order to render as many points as - * possible with a single _swrast_write_rgba_span() call. - */ - SWspan *span = &(swrast->PointSpan); - GLuint count; - - CULL_INVALID(vert); - - /* Span init */ - span->interpMask = 0; - span->arrayMask = SPAN_XY | SPAN_Z; - span->arrayMask |= SPAN_RGBA; - /*span->arrayMask |= SPAN_LAMBDA;*/ - span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */ - - /* need these for fragment programs */ - span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; - span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; - span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; - - /* check if we need to flush */ - if (span->end >= MAX_WIDTH || - (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) || - span->facing != swrast->PointLineFacing) { - if (span->end > 0) { - _swrast_write_rgba_span(ctx, span); - span->end = 0; - } - } - - count = span->end; - - span->facing = swrast->PointLineFacing; - - /* fragment attributes */ - span->array->rgba[count][RCOMP] = vert->color[0]; - span->array->rgba[count][GCOMP] = vert->color[1]; - span->array->rgba[count][BCOMP] = vert->color[2]; - span->array->rgba[count][ACOMP] = vert->color[3]; - - ATTRIB_LOOP_BEGIN - COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]); - ATTRIB_LOOP_END - - /* fragment position */ - span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0]; - span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1]; - span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); - - span->end = count + 1; - ASSERT(span->end <= MAX_WIDTH); -} - - -/** - * Add specular color to primary color, draw point, restore original - * primary color. - */ -void -_swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0) -{ - SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */ - GLfloat rSum, gSum, bSum; - GLchan cSave[4]; - - /* save */ - COPY_CHAN4(cSave, ncv0->color); - /* sum */ - rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0]; - gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1]; - bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2]; - UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum); - UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum); - UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum); - /* draw */ - SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0); - /* restore */ - COPY_CHAN4(ncv0->color, cSave); -} - - -/** - * Examine current state to determine which point drawing function to use. - */ -void -_swrast_choose_point(struct gl_context *ctx) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - const GLfloat size = CLAMP(ctx->Point.Size, - ctx->Point.MinSize, - ctx->Point.MaxSize); - - if (ctx->RenderMode == GL_RENDER) { - if (ctx->Point.PointSprite) { - swrast->Point = sprite_point; - } - else if (ctx->Point.SmoothFlag) { - swrast->Point = smooth_point; - } - else if (size > 1.0 || - ctx->Point._Attenuated || - ctx->VertexProgram.PointSizeEnabled) { - swrast->Point = large_point; - } - else { - swrast->Point = pixel_point; - } - } - else if (ctx->RenderMode == GL_FEEDBACK) { - swrast->Point = _swrast_feedback_point; - } - else { - /* GL_SELECT mode */ - swrast->Point = _swrast_select_point; - } -} +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 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 "main/glheader.h" +#include "main/colormac.h" +#include "main/macros.h" +#include "s_context.h" +#include "s_feedback.h" +#include "s_points.h" +#include "s_span.h" + + +/** + * Used to cull points with invalid coords + */ +#define CULL_INVALID(V) \ + do { \ + float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0] \ + + (V)->attrib[FRAG_ATTRIB_WPOS][1]; \ + if (IS_INF_OR_NAN(tmp)) \ + return; \ + } while(0) + + + +/** + * Get/compute the point size. + * The size may come from a vertex shader, or computed with attentuation + * or just the glPointSize value. + * Must also clamp to user-defined range and implmentation limits. + */ +static inline GLfloat +get_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed) +{ + GLfloat size; + + if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) { + /* use vertex's point size */ + size = vert->pointSize; + } + else { + /* use constant point size */ + size = ctx->Point.Size; + } + /* always clamp to user-specified limits */ + size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize); + /* clamp to implementation limits */ + if (smoothed) + size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA); + else + size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize); + + return size; +} + + +/** + * Draw a point sprite + */ +static void +sprite_point(struct gl_context *ctx, const SWvertex *vert) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + SWspan span; + GLfloat size; + GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1]; + GLuint numTcoords = 0; + GLfloat t0, dtdy; + + CULL_INVALID(vert); + + /* z coord */ + if (ctx->DrawBuffer->Visual.depthBits <= 16) + span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); + else + span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); + span.zStep = 0; + + size = get_size(ctx, vert, GL_FALSE); + + /* span init */ + INIT_SPAN(span, GL_POINT); + span.interpMask = SPAN_Z | SPAN_RGBA; + + span.facing = swrast->PointLineFacing; + + span.red = ChanToFixed(vert->color[0]); + span.green = ChanToFixed(vert->color[1]); + span.blue = ChanToFixed(vert->color[2]); + span.alpha = ChanToFixed(vert->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + + /* need these for fragment programs */ + span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; + span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; + span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; + + { + GLfloat s, r, dsdx; + + /* texcoord / pointcoord interpolants */ + s = 0.0F; + dsdx = 1.0F / size; + if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) { + dtdy = 1.0F / size; + t0 = 0.5F * dtdy; + } + else { + /* GL_UPPER_LEFT */ + dtdy = -1.0F / size; + t0 = 1.0F + 0.5F * dtdy; + } + + ATTRIB_LOOP_BEGIN + if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) { + /* a texcoord attribute */ + const GLuint u = attr - FRAG_ATTRIB_TEX0; + ASSERT(u < Elements(ctx->Point.CoordReplace)); + if (ctx->Point.CoordReplace[u]) { + tCoords[numTcoords++] = attr; + + if (ctx->Point.SpriteRMode == GL_ZERO) + r = 0.0F; + else if (ctx->Point.SpriteRMode == GL_S) + r = vert->attrib[attr][0]; + else /* GL_R */ + r = vert->attrib[attr][2]; + + span.attrStart[attr][0] = s; + span.attrStart[attr][1] = 0.0; /* overwritten below */ + span.attrStart[attr][2] = r; + span.attrStart[attr][3] = 1.0; + + span.attrStepX[attr][0] = dsdx; + span.attrStepX[attr][1] = 0.0; + span.attrStepX[attr][2] = 0.0; + span.attrStepX[attr][3] = 0.0; + + span.attrStepY[attr][0] = 0.0; + span.attrStepY[attr][1] = dtdy; + span.attrStepY[attr][2] = 0.0; + span.attrStepY[attr][3] = 0.0; + + continue; + } + } + else if (attr == FRAG_ATTRIB_PNTC) { + /* GLSL gl_PointCoord.xy (.zw undefined) */ + span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0; + span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */ + span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx; + span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0; + span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0; + span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy; + tCoords[numTcoords++] = FRAG_ATTRIB_PNTC; + continue; + } + /* use vertex's texcoord/attrib */ + COPY_4V(span.attrStart[attr], vert->attrib[attr]); + ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); + ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); + ATTRIB_LOOP_END; + } + + /* compute pos, bounds and render */ + { + const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; + const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; + GLint iSize = (GLint) (size + 0.5F); + GLint xmin, xmax, ymin, ymax, iy; + GLint iRadius; + GLfloat tcoord = t0; + + iSize = MAX2(1, iSize); + iRadius = iSize / 2; + + if (iSize & 1) { + /* odd size */ + xmin = (GLint) (x - iRadius); + xmax = (GLint) (x + iRadius); + ymin = (GLint) (y - iRadius); + ymax = (GLint) (y + iRadius); + } + else { + /* even size */ + /* 0.501 factor allows conformance to pass */ + xmin = (GLint) (x + 0.501) - iRadius; + xmax = xmin + iSize - 1; + ymin = (GLint) (y + 0.501) - iRadius; + ymax = ymin + iSize - 1; + } + + /* render spans */ + for (iy = ymin; iy <= ymax; iy++) { + GLuint i; + /* setup texcoord T for this row */ + for (i = 0; i < numTcoords; i++) { + span.attrStart[tCoords[i]][1] = tcoord; + } + + /* these might get changed by span clipping */ + span.x = xmin; + span.y = iy; + span.end = xmax - xmin + 1; + + _swrast_write_rgba_span(ctx, &span); + + tcoord += dtdy; + } + } +} + + +/** + * Draw smooth/antialiased point. RGB or CI mode. + */ +static void +smooth_point(struct gl_context *ctx, const SWvertex *vert) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + SWspan span; + GLfloat size, alphaAtten; + + CULL_INVALID(vert); + + /* z coord */ + if (ctx->DrawBuffer->Visual.depthBits <= 16) + span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); + else + span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); + span.zStep = 0; + + size = get_size(ctx, vert, GL_TRUE); + + /* alpha attenuation / fade factor */ + if (ctx->Multisample._Enabled) { + if (vert->pointSize >= ctx->Point.Threshold) { + alphaAtten = 1.0F; + } + else { + GLfloat dsize = vert->pointSize / ctx->Point.Threshold; + alphaAtten = dsize * dsize; + } + } + else { + alphaAtten = 1.0; + } + (void) alphaAtten; /* not used */ + + /* span init */ + INIT_SPAN(span, GL_POINT); + span.interpMask = SPAN_Z | SPAN_RGBA; + span.arrayMask = SPAN_COVERAGE | SPAN_MASK; + + span.facing = swrast->PointLineFacing; + + span.red = ChanToFixed(vert->color[0]); + span.green = ChanToFixed(vert->color[1]); + span.blue = ChanToFixed(vert->color[2]); + span.alpha = ChanToFixed(vert->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + + /* need these for fragment programs */ + span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; + span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; + span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; + + ATTRIB_LOOP_BEGIN + COPY_4V(span.attrStart[attr], vert->attrib[attr]); + ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); + ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); + ATTRIB_LOOP_END + + /* compute pos, bounds and render */ + { + const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; + const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; + const GLfloat radius = 0.5F * size; + const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ + const GLfloat rmax = radius + 0.7071F; + const GLfloat rmin2 = MAX2(0.0F, rmin * rmin); + const GLfloat rmax2 = rmax * rmax; + const GLfloat cscale = 1.0F / (rmax2 - rmin2); + const GLint xmin = (GLint) (x - radius); + const GLint xmax = (GLint) (x + radius); + const GLint ymin = (GLint) (y - radius); + const GLint ymax = (GLint) (y + radius); + GLint ix, iy; + + for (iy = ymin; iy <= ymax; iy++) { + + /* these might get changed by span clipping */ + span.x = xmin; + span.y = iy; + span.end = xmax - xmin + 1; + + /* compute coverage for each pixel in span */ + for (ix = xmin; ix <= xmax; ix++) { + const GLfloat dx = ix - x + 0.5F; + const GLfloat dy = iy - y + 0.5F; + const GLfloat dist2 = dx * dx + dy * dy; + GLfloat coverage; + + if (dist2 < rmax2) { + if (dist2 >= rmin2) { + /* compute partial coverage */ + coverage = 1.0F - (dist2 - rmin2) * cscale; + } + else { + /* full coverage */ + coverage = 1.0F; + } + span.array->mask[ix - xmin] = 1; + } + else { + /* zero coverage - fragment outside the radius */ + coverage = 0.0; + span.array->mask[ix - xmin] = 0; + } + span.array->coverage[ix - xmin] = coverage; + } + + /* render span */ + _swrast_write_rgba_span(ctx, &span); + + } + } +} + + +/** + * Draw large (size >= 1) non-AA point. RGB or CI mode. + */ +static void +large_point(struct gl_context *ctx, const SWvertex *vert) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + SWspan span; + GLfloat size; + + CULL_INVALID(vert); + + /* z coord */ + if (ctx->DrawBuffer->Visual.depthBits <= 16) + span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); + else + span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); + span.zStep = 0; + + size = get_size(ctx, vert, GL_FALSE); + + /* span init */ + INIT_SPAN(span, GL_POINT); + span.arrayMask = SPAN_XY; + span.facing = swrast->PointLineFacing; + + span.interpMask = SPAN_Z | SPAN_RGBA; + span.red = ChanToFixed(vert->color[0]); + span.green = ChanToFixed(vert->color[1]); + span.blue = ChanToFixed(vert->color[2]); + span.alpha = ChanToFixed(vert->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + + /* need these for fragment programs */ + span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; + span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; + span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; + + ATTRIB_LOOP_BEGIN + COPY_4V(span.attrStart[attr], vert->attrib[attr]); + ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); + ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); + ATTRIB_LOOP_END + + /* compute pos, bounds and render */ + { + const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; + const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; + GLint iSize = (GLint) (size + 0.5F); + GLint xmin, xmax, ymin, ymax, ix, iy; + GLint iRadius; + + iSize = MAX2(1, iSize); + iRadius = iSize / 2; + + if (iSize & 1) { + /* odd size */ + xmin = (GLint) (x - iRadius); + xmax = (GLint) (x + iRadius); + ymin = (GLint) (y - iRadius); + ymax = (GLint) (y + iRadius); + } + else { + /* even size */ + /* 0.501 factor allows conformance to pass */ + xmin = (GLint) (x + 0.501) - iRadius; + xmax = xmin + iSize - 1; + ymin = (GLint) (y + 0.501) - iRadius; + ymax = ymin + iSize - 1; + } + + /* generate fragments */ + span.end = 0; + for (iy = ymin; iy <= ymax; iy++) { + for (ix = xmin; ix <= xmax; ix++) { + span.array->x[span.end] = ix; + span.array->y[span.end] = iy; + span.end++; + } + } + assert(span.end <= MAX_WIDTH); + _swrast_write_rgba_span(ctx, &span); + } +} + + +/** + * Draw size=1, single-pixel point + */ +static void +pixel_point(struct gl_context *ctx, const SWvertex *vert) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + /* + * Note that unlike the other functions, we put single-pixel points + * into a special span array in order to render as many points as + * possible with a single _swrast_write_rgba_span() call. + */ + SWspan *span = &(swrast->PointSpan); + GLuint count; + + CULL_INVALID(vert); + + /* Span init */ + span->interpMask = 0; + span->arrayMask = SPAN_XY | SPAN_Z; + span->arrayMask |= SPAN_RGBA; + /*span->arrayMask |= SPAN_LAMBDA;*/ + span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */ + + /* need these for fragment programs */ + span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; + span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; + span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; + + /* check if we need to flush */ + if (span->end >= MAX_WIDTH || + (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) || + span->facing != swrast->PointLineFacing) { + if (span->end > 0) { + _swrast_write_rgba_span(ctx, span); + span->end = 0; + } + } + + count = span->end; + + span->facing = swrast->PointLineFacing; + + /* fragment attributes */ + span->array->rgba[count][RCOMP] = vert->color[0]; + span->array->rgba[count][GCOMP] = vert->color[1]; + span->array->rgba[count][BCOMP] = vert->color[2]; + span->array->rgba[count][ACOMP] = vert->color[3]; + + ATTRIB_LOOP_BEGIN + COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]); + ATTRIB_LOOP_END + + /* fragment position */ + span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0]; + span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1]; + span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); + + span->end = count + 1; + ASSERT(span->end <= MAX_WIDTH); +} + + +/** + * Add specular color to primary color, draw point, restore original + * primary color. + */ +void +_swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0) +{ + SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */ + GLfloat rSum, gSum, bSum; + GLchan cSave[4]; + + /* save */ + COPY_CHAN4(cSave, ncv0->color); + /* sum */ + rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0]; + gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1]; + bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2]; + UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum); + UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum); + UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum); + /* draw */ + SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0); + /* restore */ + COPY_CHAN4(ncv0->color, cSave); +} + + +/** + * Examine current state to determine which point drawing function to use. + */ +void +_swrast_choose_point(struct gl_context *ctx) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLfloat size = CLAMP(ctx->Point.Size, + ctx->Point.MinSize, + ctx->Point.MaxSize); + + if (ctx->RenderMode == GL_RENDER) { + if (ctx->Point.PointSprite) { + swrast->Point = sprite_point; + } + else if (ctx->Point.SmoothFlag) { + swrast->Point = smooth_point; + } + else if (size > 1.0 || + ctx->Point._Attenuated || + ctx->VertexProgram.PointSizeEnabled) { + swrast->Point = large_point; + } + else { + swrast->Point = pixel_point; + } + } + else if (ctx->RenderMode == GL_FEEDBACK) { + swrast->Point = _swrast_feedback_point; + } + else { + /* GL_SELECT mode */ + swrast->Point = _swrast_select_point; + } +} diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c index 4631ff3d5..1aa20f9d7 100644 --- a/mesalib/src/mesa/swrast/s_span.c +++ b/mesalib/src/mesa/swrast/s_span.c @@ -162,7 +162,7 @@ _swrast_span_default_attribs(struct gl_context *ctx, SWspan *span) * Perspective correction will be done. The point/line/triangle function * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]! */ -static INLINE void +static inline void interpolate_active_attribs(struct gl_context *ctx, SWspan *span, GLbitfield attrMask) { const SWcontext *swrast = SWRAST_CONTEXT(ctx); @@ -209,7 +209,7 @@ interpolate_active_attribs(struct gl_context *ctx, SWspan *span, GLbitfield attr * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16) * color array. */ -static INLINE void +static inline void interpolate_int_colors(struct gl_context *ctx, SWspan *span) { #if CHAN_BITS != 32 @@ -309,7 +309,7 @@ interpolate_int_colors(struct gl_context *ctx, SWspan *span) /** * Populate the FRAG_ATTRIB_COL0 array. */ -static INLINE void +static inline void interpolate_float_colors(SWspan *span) { GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; @@ -611,7 +611,7 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span) /** * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array. */ -static INLINE void +static inline void interpolate_wpos(struct gl_context *ctx, SWspan *span) { GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS]; @@ -645,7 +645,7 @@ interpolate_wpos(struct gl_context *ctx, SWspan *span) /** * Apply the current polygon stipple pattern to a span of pixels. */ -static INLINE void +static inline void stipple_polygon_span(struct gl_context *ctx, SWspan *span) { GLubyte *mask = span->array->mask; @@ -690,7 +690,7 @@ stipple_polygon_span(struct gl_context *ctx, SWspan *span) * Return: GL_TRUE some pixels still visible * GL_FALSE nothing visible */ -static INLINE GLuint +static inline GLuint clip_span( struct gl_context *ctx, SWspan *span ) { const GLint xmin = ctx->DrawBuffer->_Xmin; @@ -817,7 +817,7 @@ clip_span( struct gl_context *ctx, SWspan *span ) * Only called during fixed-function operation. * Result is float color array (FRAG_ATTRIB_COL0). */ -static INLINE void +static inline void add_specular(struct gl_context *ctx, SWspan *span) { const SWcontext *swrast = SWRAST_CONTEXT(ctx); @@ -866,7 +866,7 @@ add_specular(struct gl_context *ctx, SWspan *span) /** * Apply antialiasing coverage value to alpha values. */ -static INLINE void +static inline void apply_aa_coverage(SWspan *span) { const GLfloat *coverage = span->array->coverage; @@ -900,7 +900,7 @@ apply_aa_coverage(SWspan *span) /** * Clamp span's float colors to [0,1] */ -static INLINE void +static inline void clamp_colors(SWspan *span) { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; @@ -921,7 +921,7 @@ clamp_colors(SWspan *span) * program that writes to gl_FragData[1] or higher. * \param output which fragment program color output is being processed */ -static INLINE void +static inline void convert_color_type(SWspan *span, GLenum newType, GLuint output) { GLvoid *src, *dst; @@ -961,7 +961,7 @@ convert_color_type(SWspan *span, GLenum newType, GLuint output) /** * Apply fragment shader, fragment program or normal texturing to span. */ -static INLINE void +static inline void shade_texture_span(struct gl_context *ctx, SWspan *span) { if (ctx->FragmentProgram._Current || diff --git a/mesalib/src/mesa/swrast/s_stencil.c b/mesalib/src/mesa/swrast/s_stencil.c index fa5093a34..e713e2393 100644 --- a/mesalib/src/mesa/swrast/s_stencil.c +++ b/mesalib/src/mesa/swrast/s_stencil.c @@ -391,7 +391,7 @@ do_stencil_test( struct gl_context *ctx, GLuint face, GLuint n, GLstencil stenci * Compute the zpass/zfail masks by comparing the pre- and post-depth test * masks. */ -static INLINE void +static inline void compute_pass_fail_masks(GLuint n, const GLubyte origMask[], const GLubyte newMask[], GLubyte passMask[], GLubyte failMask[]) diff --git a/mesalib/src/mesa/swrast/s_texcombine.c b/mesalib/src/mesa/swrast/s_texcombine.c index 80b9dff3c..c67c356c1 100644 --- a/mesalib/src/mesa/swrast/s_texcombine.c +++ b/mesalib/src/mesa/swrast/s_texcombine.c @@ -45,7 +45,7 @@ typedef float (*float4_array)[4]; /** * Return array of texels for given unit. */ -static INLINE float4_array +static inline float4_array get_texel_array(SWcontext *swrast, GLuint unit) { #ifdef _OPENMP @@ -590,6 +590,26 @@ _swrast_texture_span( struct gl_context *ctx, SWspan *span ) float4_array primary_rgba; GLuint unit; + if (!swrast->TexelBuffer) { +#ifdef _OPENMP + const GLint maxThreads = omp_get_max_threads(); +#else + const GLint maxThreads = 1; +#endif + + /* TexelBuffer is also global and normally shared by all SWspan + * instances; when running with multiple threads, create one per + * thread. + */ + swrast->TexelBuffer = + (GLfloat *) MALLOC(ctx->Const.MaxTextureImageUnits * maxThreads * + MAX_WIDTH * 4 * sizeof(GLfloat)); + if (!swrast->TexelBuffer) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine"); + return; + } + } + primary_rgba = (float4_array) malloc(span->end * 4 * sizeof(GLfloat)); if (!primary_rgba) { diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index ed17b4bda..73b5af319 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -51,7 +51,7 @@ * linear RGB value in [0, 1]. * Implemented with a 256-entry lookup table. */ -static INLINE GLfloat +static inline GLfloat nonlinear_to_linear(GLubyte cs8) { static GLfloat table[256]; diff --git a/mesalib/src/mesa/swrast/s_texfilter.c b/mesalib/src/mesa/swrast/s_texfilter.c index dd3761986..ca9133b21 100644 --- a/mesalib/src/mesa/swrast/s_texfilter.c +++ b/mesalib/src/mesa/swrast/s_texfilter.c @@ -57,7 +57,7 @@ * optimization! If we find that's not true on some systems, convert * to a macro. */ -static INLINE GLfloat +static inline GLfloat lerp_2d(GLfloat a, GLfloat b, GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11) { @@ -71,7 +71,7 @@ lerp_2d(GLfloat a, GLfloat b, * Do 3D/trilinear interpolation of float values. * \sa lerp_2d */ -static INLINE GLfloat +static inline GLfloat lerp_3d(GLfloat a, GLfloat b, GLfloat c, GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110, GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111) @@ -89,7 +89,7 @@ lerp_3d(GLfloat a, GLfloat b, GLfloat c, /** * Do linear interpolation of colors. */ -static INLINE void +static inline void lerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4]) { result[0] = LERP(t, a[0], b[0]); @@ -102,7 +102,7 @@ lerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4]) /** * Do bilinear interpolation of colors. */ -static INLINE void +static inline void lerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b, const GLfloat t00[4], const GLfloat t10[4], const GLfloat t01[4], const GLfloat t11[4]) @@ -117,7 +117,7 @@ lerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b, /** * Do trilinear interpolation of colors. */ -static INLINE void +static inline void lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c, const GLfloat t000[4], const GLfloat t100[4], const GLfloat t010[4], const GLfloat t110[4], @@ -153,7 +153,7 @@ lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c, * i0, i1 = returns two nearest texel indexes * weight = returns blend factor between texels */ -static INLINE void +static inline void linear_texel_locations(GLenum wrapMode, const struct gl_texture_image *img, GLint size, GLfloat s, @@ -281,7 +281,7 @@ linear_texel_locations(GLenum wrapMode, /** * Used to compute texel location for nearest sampling. */ -static INLINE GLint +static inline GLint nearest_texel_location(GLenum wrapMode, const struct gl_texture_image *img, GLint size, GLfloat s) @@ -406,7 +406,7 @@ nearest_texel_location(GLenum wrapMode, /* Power of two image sizes only */ -static INLINE void +static inline void linear_repeat_texel_location(GLuint size, GLfloat s, GLint *i0, GLint *i1, GLfloat *weight) { @@ -420,7 +420,7 @@ linear_repeat_texel_location(GLuint size, GLfloat s, /** * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode. */ -static INLINE GLint +static inline GLint clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max) { switch (wrapMode) { @@ -440,7 +440,7 @@ clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max) /** * As above, but GL_LINEAR filtering. */ -static INLINE void +static inline void clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max, GLint *i0out, GLint *i1out, GLfloat *weight) { @@ -481,7 +481,7 @@ clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max, /** * Compute slice/image to use for 1D or 2D array texture. */ -static INLINE GLint +static inline GLint tex_array_slice(GLfloat coord, GLsizei size) { GLint slice = IFLOOR(coord + 0.5f); @@ -494,7 +494,7 @@ tex_array_slice(GLfloat coord, GLsizei size) * Compute nearest integer texcoords for given texobj and coordinate. * NOTE: only used for depth texture sampling. */ -static INLINE void +static inline void nearest_texcoord(const struct gl_texture_object *texObj, GLuint level, const GLfloat texcoord[4], @@ -541,7 +541,7 @@ nearest_texcoord(const struct gl_texture_object *texObj, * Compute linear integer texcoords for given texobj and coordinate. * NOTE: only used for depth texture sampling. */ -static INLINE void +static inline void linear_texcoord(const struct gl_texture_object *texObj, GLuint level, const GLfloat texcoord[4], @@ -598,7 +598,7 @@ linear_texcoord(const struct gl_texture_object *texObj, * For linear interpolation between mipmap levels N and N+1, this function * computes N. */ -static INLINE GLint +static inline GLint linear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) { if (lambda < 0.0F) @@ -613,7 +613,7 @@ linear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) /** * Compute the nearest mipmap level to take texels from. */ -static INLINE GLint +static inline GLint nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) { GLfloat l; @@ -649,7 +649,7 @@ nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) * 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 +static inline void compute_min_mag_ranges(const struct gl_texture_object *tObj, GLuint n, const GLfloat lambda[], GLuint *minStart, GLuint *minEnd, @@ -758,7 +758,7 @@ compute_min_mag_ranges(const struct gl_texture_object *tObj, * the base texture format. Ex: if the texture base format it GL_ALPHA, * we return (0,0,0,BorderAlpha). */ -static INLINE void +static inline void get_border_color(const struct gl_texture_object *tObj, const struct gl_texture_image *img, GLfloat rgba[4]) @@ -798,7 +798,7 @@ get_border_color(const struct gl_texture_object *tObj, /** * Return the texture sample for coordinate (s) using GL_NEAREST filter. */ -static INLINE void +static inline void sample_1d_nearest(struct gl_context *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, @@ -823,7 +823,7 @@ sample_1d_nearest(struct gl_context *ctx, /** * Return the texture sample for coordinate (s) using GL_LINEAR filter. */ -static INLINE void +static inline void sample_1d_linear(struct gl_context *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, @@ -1057,7 +1057,7 @@ sample_lambda_1d( struct gl_context *ctx, /** * Return the texture sample for coordinate (s,t) using GL_NEAREST filter. */ -static INLINE void +static inline void sample_2d_nearest(struct gl_context *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, @@ -1091,7 +1091,7 @@ sample_2d_nearest(struct gl_context *ctx, * Return the texture sample for coordinate (s,t) using GL_LINEAR filter. * New sampling code contributed by Lynn Quam . */ -static INLINE void +static inline void sample_2d_linear(struct gl_context *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, @@ -1156,7 +1156,7 @@ sample_2d_linear(struct gl_context *ctx, * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT. * We don't have to worry about the texture border. */ -static INLINE void +static inline void sample_2d_linear_repeat(struct gl_context *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, @@ -1760,7 +1760,7 @@ sample_2d_footprint(struct gl_context *ctx, * Returns the index of the specified texture object in the * gl_context texture unit array. */ -static INLINE GLuint +static inline GLuint texture_unit_index(const struct gl_context *ctx, const struct gl_texture_object *tObj) { @@ -1941,7 +1941,7 @@ sample_lambda_2d_aniso(struct gl_context *ctx, /** * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter. */ -static INLINE void +static inline void sample_3d_nearest(struct gl_context *ctx, const struct gl_texture_object *tObj, const struct gl_texture_image *img, @@ -3282,7 +3282,7 @@ sample_lambda_1d_array(struct gl_context *ctx, /** * Compare texcoord against depth sample. Return 1.0 or the ambient value. */ -static INLINE GLfloat +static inline GLfloat shadow_compare(GLenum function, GLfloat coord, GLfloat depthSample, GLfloat ambient) { @@ -3315,7 +3315,7 @@ shadow_compare(GLenum function, GLfloat coord, GLfloat depthSample, /** * Compare texcoord against four depth samples. */ -static INLINE GLfloat +static inline GLfloat shadow_compare4(GLenum function, GLfloat coord, GLfloat depth00, GLfloat depth01, GLfloat depth10, GLfloat depth11, diff --git a/mesalib/src/mesa/swrast/s_texture.c b/mesalib/src/mesa/swrast/s_texture.c index aa073753f..36b429cfa 100644 --- a/mesalib/src/mesa/swrast/s_texture.c +++ b/mesalib/src/mesa/swrast/s_texture.c @@ -177,6 +177,13 @@ _swrast_map_teximage(struct gl_context *ctx, 1); assert(slice < texImage->Depth); map += slice * sliceSize; + } else if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { + GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat, + texImage->Width, + 1, + 1); + assert(slice < texImage->Height); + map += slice * sliceSize; } /* apply x/y offset to map address */ diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c index 77bd2a359..839c4fd08 100644 --- a/mesalib/src/mesa/swrast/s_triangle.c +++ b/mesalib/src/mesa/swrast/s_triangle.c @@ -237,13 +237,13 @@ struct affine_info }; -static INLINE GLint +static inline GLint ilerp(GLint t, GLint a, GLint b) { return a + ((t * (b - a)) >> FIXED_SHIFT); } -static INLINE GLint +static inline GLint ilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11) { const GLint temp0 = ilerp(ia, v00, v10); @@ -256,7 +256,7 @@ ilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11) * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD * texture env modes. */ -static INLINE void +static inline void affine_span(struct gl_context *ctx, SWspan *span, struct affine_info *info) { @@ -591,7 +591,7 @@ struct persp_info }; -static INLINE void +static inline void fast_persp_span(struct gl_context *ctx, SWspan *span, struct persp_info *info) { diff --git a/mesalib/src/mesa/swrast/s_zoom.c b/mesalib/src/mesa/swrast/s_zoom.c index 3b99bf754..3fb784847 100644 --- a/mesalib/src/mesa/swrast/s_zoom.c +++ b/mesalib/src/mesa/swrast/s_zoom.c @@ -1,433 +1,433 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2008 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 "main/glheader.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/colormac.h" - -#include "s_context.h" -#include "s_span.h" -#include "s_stencil.h" -#include "s_zoom.h" - - -/** - * Compute the bounds of the region resulting from zooming a pixel span. - * The resulting region will be entirely inside the window/scissor bounds - * so no additional clipping is needed. - * \param imageX, imageY position of the mage being drawn (gl WindowPos) - * \param spanX, spanY position of span being drawing - * \param width number of pixels in span - * \param x0, x1 returned X bounds of zoomed region [x0, x1) - * \param y0, y1 returned Y bounds of zoomed region [y0, y1) - * \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped - */ -static GLboolean -compute_zoomed_bounds(struct gl_context *ctx, GLint imageX, GLint imageY, - GLint spanX, GLint spanY, GLint width, - GLint *x0, GLint *x1, GLint *y0, GLint *y1) -{ - const struct gl_framebuffer *fb = ctx->DrawBuffer; - GLint c0, c1, r0, r1; - - ASSERT(spanX >= imageX); - ASSERT(spanY >= imageY); - - /* - * Compute destination columns: [c0, c1) - */ - c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX); - c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX); - if (c1 < c0) { - /* swap */ - GLint tmp = c1; - c1 = c0; - c0 = tmp; - } - c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax); - c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax); - if (c0 == c1) { - return GL_FALSE; /* no width */ - } - - /* - * Compute destination rows: [r0, r1) - */ - r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY); - r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY); - if (r1 < r0) { - /* swap */ - GLint tmp = r1; - r1 = r0; - r0 = tmp; - } - r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax); - r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax); - if (r0 == r1) { - return GL_FALSE; /* no height */ - } - - *x0 = c0; - *x1 = c1; - *y0 = r0; - *y1 = r1; - - return GL_TRUE; -} - - -/** - * Convert a zoomed x image coordinate back to an unzoomed x coord. - * 'zx' is screen position of a pixel in the zoomed image, who's left edge - * is at 'imageX'. - * return corresponding x coord in the original, unzoomed image. - * This can use this for unzooming X or Y values. - */ -static INLINE GLint -unzoom_x(GLfloat zoomX, GLint imageX, GLint zx) -{ - /* - zx = imageX + (x - imageX) * zoomX; - zx - imageX = (x - imageX) * zoomX; - (zx - imageX) / zoomX = x - imageX; - */ - GLint x; - if (zoomX < 0.0) - zx++; - x = imageX + (GLint) ((zx - imageX) / zoomX); - return x; -} - - - -/** - * Helper function called from _swrast_write_zoomed_rgba/rgb/ - * index/depth_span(). - */ -static void -zoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span, - const GLvoid *src, GLenum format ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - SWspan zoomed; - GLint x0, x1, y0, y1; - GLint zoomedWidth; - - if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end, - &x0, &x1, &y0, &y1)) { - return; /* totally clipped */ - } - - if (!swrast->ZoomedArrays) { - /* allocate on demand */ - swrast->ZoomedArrays = (SWspanarrays *) CALLOC(sizeof(SWspanarrays)); - if (!swrast->ZoomedArrays) - return; - } - - zoomedWidth = x1 - x0; - ASSERT(zoomedWidth > 0); - ASSERT(zoomedWidth <= MAX_WIDTH); - - /* no pixel arrays! must be horizontal spans. */ - ASSERT((span->arrayMask & SPAN_XY) == 0); - ASSERT(span->primitive == GL_BITMAP); - - INIT_SPAN(zoomed, GL_BITMAP); - zoomed.x = x0; - zoomed.end = zoomedWidth; - zoomed.array = swrast->ZoomedArrays; - zoomed.array->ChanType = span->array->ChanType; - if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) - zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8; - else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) - zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16; - else - zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[FRAG_ATTRIB_COL0]; - - COPY_4V(zoomed.attrStart[FRAG_ATTRIB_WPOS], span->attrStart[FRAG_ATTRIB_WPOS]); - COPY_4V(zoomed.attrStepX[FRAG_ATTRIB_WPOS], span->attrStepX[FRAG_ATTRIB_WPOS]); - COPY_4V(zoomed.attrStepY[FRAG_ATTRIB_WPOS], span->attrStepY[FRAG_ATTRIB_WPOS]); - - zoomed.attrStart[FRAG_ATTRIB_FOGC][0] = span->attrStart[FRAG_ATTRIB_FOGC][0]; - zoomed.attrStepX[FRAG_ATTRIB_FOGC][0] = span->attrStepX[FRAG_ATTRIB_FOGC][0]; - zoomed.attrStepY[FRAG_ATTRIB_FOGC][0] = span->attrStepY[FRAG_ATTRIB_FOGC][0]; - - if (format == GL_RGBA || format == GL_RGB) { - /* copy Z info */ - zoomed.z = span->z; - zoomed.zStep = span->zStep; - /* we'll generate an array of colorss */ - zoomed.interpMask = span->interpMask & ~SPAN_RGBA; - zoomed.arrayMask |= SPAN_RGBA; - zoomed.arrayAttribs |= FRAG_BIT_COL0; /* we'll produce these values */ - ASSERT(span->arrayMask & SPAN_RGBA); - } - else if (format == GL_DEPTH_COMPONENT) { - /* Copy color info */ - zoomed.red = span->red; - zoomed.green = span->green; - zoomed.blue = span->blue; - zoomed.alpha = span->alpha; - zoomed.redStep = span->redStep; - zoomed.greenStep = span->greenStep; - zoomed.blueStep = span->blueStep; - zoomed.alphaStep = span->alphaStep; - /* we'll generate an array of depth values */ - zoomed.interpMask = span->interpMask & ~SPAN_Z; - zoomed.arrayMask |= SPAN_Z; - ASSERT(span->arrayMask & SPAN_Z); - } - else { - _mesa_problem(ctx, "Bad format in zoom_span"); - return; - } - - /* zoom the span horizontally */ - if (format == GL_RGBA) { - if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) { - const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src; - GLint i; - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; - ASSERT(j >= 0); - ASSERT(j < (GLint) span->end); - COPY_4UBV(zoomed.array->rgba8[i], rgba[j]); - } - } - else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) { - const GLushort (*rgba)[4] = (const GLushort (*)[4]) src; - GLint i; - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; - ASSERT(j >= 0); - ASSERT(j < (GLint) span->end); - COPY_4V(zoomed.array->rgba16[i], rgba[j]); - } - } - else { - const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src; - GLint i; - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; - ASSERT(j >= 0); - ASSERT(j < span->end); - COPY_4V(zoomed.array->attribs[FRAG_ATTRIB_COL0][i], rgba[j]); - } - } - } - else if (format == GL_RGB) { - if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) { - const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src; - GLint i; - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; - ASSERT(j >= 0); - ASSERT(j < (GLint) span->end); - zoomed.array->rgba8[i][0] = rgb[j][0]; - zoomed.array->rgba8[i][1] = rgb[j][1]; - zoomed.array->rgba8[i][2] = rgb[j][2]; - zoomed.array->rgba8[i][3] = 0xff; - } - } - else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) { - const GLushort (*rgb)[3] = (const GLushort (*)[3]) src; - GLint i; - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; - ASSERT(j >= 0); - ASSERT(j < (GLint) span->end); - zoomed.array->rgba16[i][0] = rgb[j][0]; - zoomed.array->rgba16[i][1] = rgb[j][1]; - zoomed.array->rgba16[i][2] = rgb[j][2]; - zoomed.array->rgba16[i][3] = 0xffff; - } - } - else { - const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src; - GLint i; - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; - ASSERT(j >= 0); - ASSERT(j < span->end); - zoomed.array->attribs[FRAG_ATTRIB_COL0][i][0] = rgb[j][0]; - zoomed.array->attribs[FRAG_ATTRIB_COL0][i][1] = rgb[j][1]; - zoomed.array->attribs[FRAG_ATTRIB_COL0][i][2] = rgb[j][2]; - zoomed.array->attribs[FRAG_ATTRIB_COL0][i][3] = 1.0F; - } - } - } - else if (format == GL_DEPTH_COMPONENT) { - const GLuint *zValues = (const GLuint *) src; - GLint i; - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; - ASSERT(j >= 0); - ASSERT(j < (GLint) span->end); - zoomed.array->z[i] = zValues[j]; - } - /* Now, fall into the RGB path below */ - format = GL_RGBA; - } - - /* 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 _swrast_write_zoomed_span() more than once. - * Also, clipping may change the span end value, so store it as well. - */ - const GLint end = zoomed.end; /* save */ - GLuint rgbaSave[MAX_WIDTH][4]; - const GLint pixelSize = - (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) : - ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort) - : 4 * sizeof(GLfloat)); - if (y1 - y0 > 1) { - memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize); - } - for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) { - _swrast_write_rgba_span(ctx, &zoomed); - zoomed.end = end; /* restore */ - if (y1 - y0 > 1) { - /* restore the colors */ - memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize); - } - } - } -} - - -void -_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY, - const SWspan *span, const GLvoid *rgba) -{ - zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA); -} - - -void -_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY, - const SWspan *span, const GLvoid *rgb) -{ - zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB); -} - - -void -_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY, - const SWspan *span) -{ - zoom_span(ctx, imgX, imgY, span, - (const GLvoid *) span->array->z, GL_DEPTH_COMPONENT); -} - - -/** - * Zoom/write stencil values. - * No per-fragment operations are applied. - */ -void -_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY, - GLint width, GLint spanX, GLint spanY, - const GLstencil stencil[]) -{ - GLstencil zoomedVals[MAX_WIDTH]; - GLint x0, x1, y0, y1, y; - GLint i, zoomedWidth; - - if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width, - &x0, &x1, &y0, &y1)) { - return; /* totally clipped */ - } - - zoomedWidth = x1 - x0; - ASSERT(zoomedWidth > 0); - ASSERT(zoomedWidth <= MAX_WIDTH); - - /* zoom the span horizontally */ - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX; - ASSERT(j >= 0); - ASSERT(j < width); - zoomedVals[i] = stencil[j]; - } - - /* write the zoomed spans */ - for (y = y0; y < y1; y++) { - _swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals); - } -} - - -/** - * Zoom/write z values (16 or 32-bit). - * No per-fragment operations are applied. - */ -void -_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY, - GLint width, GLint spanX, GLint spanY, - const GLvoid *z) -{ - struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer; - GLushort zoomedVals16[MAX_WIDTH]; - GLuint zoomedVals32[MAX_WIDTH]; - GLint x0, x1, y0, y1, y; - GLint i, zoomedWidth; - - if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width, - &x0, &x1, &y0, &y1)) { - return; /* totally clipped */ - } - - zoomedWidth = x1 - x0; - ASSERT(zoomedWidth > 0); - ASSERT(zoomedWidth <= MAX_WIDTH); - - /* zoom the span horizontally */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX; - ASSERT(j >= 0); - ASSERT(j < width); - zoomedVals16[i] = ((GLushort *) z)[j]; - } - z = zoomedVals16; - } - else { - ASSERT(rb->DataType == GL_UNSIGNED_INT); - for (i = 0; i < zoomedWidth; i++) { - GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX; - ASSERT(j >= 0); - ASSERT(j < width); - zoomedVals32[i] = ((GLuint *) z)[j]; - } - z = zoomedVals32; - } - - /* write the zoomed spans */ - for (y = y0; y < y1; y++) { - rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL); - } -} +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 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 "main/glheader.h" +#include "main/macros.h" +#include "main/imports.h" +#include "main/colormac.h" + +#include "s_context.h" +#include "s_span.h" +#include "s_stencil.h" +#include "s_zoom.h" + + +/** + * Compute the bounds of the region resulting from zooming a pixel span. + * The resulting region will be entirely inside the window/scissor bounds + * so no additional clipping is needed. + * \param imageX, imageY position of the mage being drawn (gl WindowPos) + * \param spanX, spanY position of span being drawing + * \param width number of pixels in span + * \param x0, x1 returned X bounds of zoomed region [x0, x1) + * \param y0, y1 returned Y bounds of zoomed region [y0, y1) + * \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped + */ +static GLboolean +compute_zoomed_bounds(struct gl_context *ctx, GLint imageX, GLint imageY, + GLint spanX, GLint spanY, GLint width, + GLint *x0, GLint *x1, GLint *y0, GLint *y1) +{ + const struct gl_framebuffer *fb = ctx->DrawBuffer; + GLint c0, c1, r0, r1; + + ASSERT(spanX >= imageX); + ASSERT(spanY >= imageY); + + /* + * Compute destination columns: [c0, c1) + */ + c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX); + c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX); + if (c1 < c0) { + /* swap */ + GLint tmp = c1; + c1 = c0; + c0 = tmp; + } + c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax); + c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax); + if (c0 == c1) { + return GL_FALSE; /* no width */ + } + + /* + * Compute destination rows: [r0, r1) + */ + r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY); + r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY); + if (r1 < r0) { + /* swap */ + GLint tmp = r1; + r1 = r0; + r0 = tmp; + } + r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax); + r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax); + if (r0 == r1) { + return GL_FALSE; /* no height */ + } + + *x0 = c0; + *x1 = c1; + *y0 = r0; + *y1 = r1; + + return GL_TRUE; +} + + +/** + * Convert a zoomed x image coordinate back to an unzoomed x coord. + * 'zx' is screen position of a pixel in the zoomed image, who's left edge + * is at 'imageX'. + * return corresponding x coord in the original, unzoomed image. + * This can use this for unzooming X or Y values. + */ +static inline GLint +unzoom_x(GLfloat zoomX, GLint imageX, GLint zx) +{ + /* + zx = imageX + (x - imageX) * zoomX; + zx - imageX = (x - imageX) * zoomX; + (zx - imageX) / zoomX = x - imageX; + */ + GLint x; + if (zoomX < 0.0) + zx++; + x = imageX + (GLint) ((zx - imageX) / zoomX); + return x; +} + + + +/** + * Helper function called from _swrast_write_zoomed_rgba/rgb/ + * index/depth_span(). + */ +static void +zoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span, + const GLvoid *src, GLenum format ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + SWspan zoomed; + GLint x0, x1, y0, y1; + GLint zoomedWidth; + + if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end, + &x0, &x1, &y0, &y1)) { + return; /* totally clipped */ + } + + if (!swrast->ZoomedArrays) { + /* allocate on demand */ + swrast->ZoomedArrays = (SWspanarrays *) CALLOC(sizeof(SWspanarrays)); + if (!swrast->ZoomedArrays) + return; + } + + zoomedWidth = x1 - x0; + ASSERT(zoomedWidth > 0); + ASSERT(zoomedWidth <= MAX_WIDTH); + + /* no pixel arrays! must be horizontal spans. */ + ASSERT((span->arrayMask & SPAN_XY) == 0); + ASSERT(span->primitive == GL_BITMAP); + + INIT_SPAN(zoomed, GL_BITMAP); + zoomed.x = x0; + zoomed.end = zoomedWidth; + zoomed.array = swrast->ZoomedArrays; + zoomed.array->ChanType = span->array->ChanType; + if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) + zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8; + else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) + zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16; + else + zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[FRAG_ATTRIB_COL0]; + + COPY_4V(zoomed.attrStart[FRAG_ATTRIB_WPOS], span->attrStart[FRAG_ATTRIB_WPOS]); + COPY_4V(zoomed.attrStepX[FRAG_ATTRIB_WPOS], span->attrStepX[FRAG_ATTRIB_WPOS]); + COPY_4V(zoomed.attrStepY[FRAG_ATTRIB_WPOS], span->attrStepY[FRAG_ATTRIB_WPOS]); + + zoomed.attrStart[FRAG_ATTRIB_FOGC][0] = span->attrStart[FRAG_ATTRIB_FOGC][0]; + zoomed.attrStepX[FRAG_ATTRIB_FOGC][0] = span->attrStepX[FRAG_ATTRIB_FOGC][0]; + zoomed.attrStepY[FRAG_ATTRIB_FOGC][0] = span->attrStepY[FRAG_ATTRIB_FOGC][0]; + + if (format == GL_RGBA || format == GL_RGB) { + /* copy Z info */ + zoomed.z = span->z; + zoomed.zStep = span->zStep; + /* we'll generate an array of colorss */ + zoomed.interpMask = span->interpMask & ~SPAN_RGBA; + zoomed.arrayMask |= SPAN_RGBA; + zoomed.arrayAttribs |= FRAG_BIT_COL0; /* we'll produce these values */ + ASSERT(span->arrayMask & SPAN_RGBA); + } + else if (format == GL_DEPTH_COMPONENT) { + /* Copy color info */ + zoomed.red = span->red; + zoomed.green = span->green; + zoomed.blue = span->blue; + zoomed.alpha = span->alpha; + zoomed.redStep = span->redStep; + zoomed.greenStep = span->greenStep; + zoomed.blueStep = span->blueStep; + zoomed.alphaStep = span->alphaStep; + /* we'll generate an array of depth values */ + zoomed.interpMask = span->interpMask & ~SPAN_Z; + zoomed.arrayMask |= SPAN_Z; + ASSERT(span->arrayMask & SPAN_Z); + } + else { + _mesa_problem(ctx, "Bad format in zoom_span"); + return; + } + + /* zoom the span horizontally */ + if (format == GL_RGBA) { + if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) { + const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src; + GLint i; + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; + ASSERT(j >= 0); + ASSERT(j < (GLint) span->end); + COPY_4UBV(zoomed.array->rgba8[i], rgba[j]); + } + } + else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) { + const GLushort (*rgba)[4] = (const GLushort (*)[4]) src; + GLint i; + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; + ASSERT(j >= 0); + ASSERT(j < (GLint) span->end); + COPY_4V(zoomed.array->rgba16[i], rgba[j]); + } + } + else { + const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src; + GLint i; + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; + ASSERT(j >= 0); + ASSERT(j < span->end); + COPY_4V(zoomed.array->attribs[FRAG_ATTRIB_COL0][i], rgba[j]); + } + } + } + else if (format == GL_RGB) { + if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) { + const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src; + GLint i; + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; + ASSERT(j >= 0); + ASSERT(j < (GLint) span->end); + zoomed.array->rgba8[i][0] = rgb[j][0]; + zoomed.array->rgba8[i][1] = rgb[j][1]; + zoomed.array->rgba8[i][2] = rgb[j][2]; + zoomed.array->rgba8[i][3] = 0xff; + } + } + else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) { + const GLushort (*rgb)[3] = (const GLushort (*)[3]) src; + GLint i; + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; + ASSERT(j >= 0); + ASSERT(j < (GLint) span->end); + zoomed.array->rgba16[i][0] = rgb[j][0]; + zoomed.array->rgba16[i][1] = rgb[j][1]; + zoomed.array->rgba16[i][2] = rgb[j][2]; + zoomed.array->rgba16[i][3] = 0xffff; + } + } + else { + const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src; + GLint i; + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; + ASSERT(j >= 0); + ASSERT(j < span->end); + zoomed.array->attribs[FRAG_ATTRIB_COL0][i][0] = rgb[j][0]; + zoomed.array->attribs[FRAG_ATTRIB_COL0][i][1] = rgb[j][1]; + zoomed.array->attribs[FRAG_ATTRIB_COL0][i][2] = rgb[j][2]; + zoomed.array->attribs[FRAG_ATTRIB_COL0][i][3] = 1.0F; + } + } + } + else if (format == GL_DEPTH_COMPONENT) { + const GLuint *zValues = (const GLuint *) src; + GLint i; + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x; + ASSERT(j >= 0); + ASSERT(j < (GLint) span->end); + zoomed.array->z[i] = zValues[j]; + } + /* Now, fall into the RGB path below */ + format = GL_RGBA; + } + + /* 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 _swrast_write_zoomed_span() more than once. + * Also, clipping may change the span end value, so store it as well. + */ + const GLint end = zoomed.end; /* save */ + GLuint rgbaSave[MAX_WIDTH][4]; + const GLint pixelSize = + (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) : + ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort) + : 4 * sizeof(GLfloat)); + if (y1 - y0 > 1) { + memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize); + } + for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) { + _swrast_write_rgba_span(ctx, &zoomed); + zoomed.end = end; /* restore */ + if (y1 - y0 > 1) { + /* restore the colors */ + memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize); + } + } + } +} + + +void +_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY, + const SWspan *span, const GLvoid *rgba) +{ + zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA); +} + + +void +_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY, + const SWspan *span, const GLvoid *rgb) +{ + zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB); +} + + +void +_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY, + const SWspan *span) +{ + zoom_span(ctx, imgX, imgY, span, + (const GLvoid *) span->array->z, GL_DEPTH_COMPONENT); +} + + +/** + * Zoom/write stencil values. + * No per-fragment operations are applied. + */ +void +_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY, + GLint width, GLint spanX, GLint spanY, + const GLstencil stencil[]) +{ + GLstencil zoomedVals[MAX_WIDTH]; + GLint x0, x1, y0, y1, y; + GLint i, zoomedWidth; + + if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width, + &x0, &x1, &y0, &y1)) { + return; /* totally clipped */ + } + + zoomedWidth = x1 - x0; + ASSERT(zoomedWidth > 0); + ASSERT(zoomedWidth <= MAX_WIDTH); + + /* zoom the span horizontally */ + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX; + ASSERT(j >= 0); + ASSERT(j < width); + zoomedVals[i] = stencil[j]; + } + + /* write the zoomed spans */ + for (y = y0; y < y1; y++) { + _swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals); + } +} + + +/** + * Zoom/write z values (16 or 32-bit). + * No per-fragment operations are applied. + */ +void +_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY, + GLint width, GLint spanX, GLint spanY, + const GLvoid *z) +{ + struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer; + GLushort zoomedVals16[MAX_WIDTH]; + GLuint zoomedVals32[MAX_WIDTH]; + GLint x0, x1, y0, y1, y; + GLint i, zoomedWidth; + + if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width, + &x0, &x1, &y0, &y1)) { + return; /* totally clipped */ + } + + zoomedWidth = x1 - x0; + ASSERT(zoomedWidth > 0); + ASSERT(zoomedWidth <= MAX_WIDTH); + + /* zoom the span horizontally */ + if (rb->DataType == GL_UNSIGNED_SHORT) { + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX; + ASSERT(j >= 0); + ASSERT(j < width); + zoomedVals16[i] = ((GLushort *) z)[j]; + } + z = zoomedVals16; + } + else { + ASSERT(rb->DataType == GL_UNSIGNED_INT); + for (i = 0; i < zoomedWidth; i++) { + GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX; + ASSERT(j >= 0); + ASSERT(j < width); + zoomedVals32[i] = ((GLuint *) z)[j]; + } + z = zoomedVals32; + } + + /* write the zoomed spans */ + for (y = y0; y < y1; y++) { + rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL); + } +} -- cgit v1.2.3