diff options
Diffstat (limited to 'mesalib/src/mesa/swrast')
-rw-r--r-- | mesalib/src/mesa/swrast/s_aaline.c | 984 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_aatriangle.c | 624 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_blit.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_context.c | 11 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_context.h | 12 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_fragprog.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_logic.c | 438 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_points.c | 1144 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_span.c | 22 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_stencil.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_texcombine.c | 22 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_texfetch.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_texfilter.c | 52 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_texture.c | 7 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_triangle.c | 8 | ||||
-rw-r--r-- | mesalib/src/mesa/swrast/s_zoom.c | 866 |
16 files changed, 2107 insertions, 2091 deletions
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 <quam@ai.sri.com>. */ -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); + } +} |