-/* $Id: s_aatriangle.c,v 1.7 2001/02/16 18:14:41 keithw Exp $ */
-
/*
* Mesa 3-D graphics library
- * Version: 3.5
- *
- * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- *
+ * 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
*/
-#include "mmath.h"
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "context.h"
+#include "macros.h"
+#include "imports.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[],
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;
static INLINE GLfloat
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
{
- GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
- return z;
+ ASSERT(plane[2] != 0.0F);
+ return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
}
static INLINE GLfloat
solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
{
- GLfloat z = -plane[2] / (plane[3] + plane[0] * x + plane[1] * y);
- return z;
+ 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])
{
- GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2] + 0.5F;
- if (z < 0.0F)
+ 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_MAXF)
- return CHAN_MAXF;
- return (GLchan) (GLint) z;
+ else if (z > CHAN_MAX)
+ return CHAN_MAX;
+ return (GLchan) IROUND_POS(z);
+#endif
}
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 */
- { 0.00, 0.00 },
- { 0.75, 0.00 },
- { 0.00, 0.75 },
- { 0.75, 0.75 },
+ { 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 */
- { 0.25, 0.00 },
- { 0.50, 0.00 },
- { 0.00, 0.25 },
- { 0.25, 0.25 },
- { 0.50, 0.25 },
- { 0.75, 0.25 },
- { 0.00, 0.50 },
- { 0.25, 0.50 },
- { 0.50, 0.50 },
- { 0.75, 0.50 },
- { 0.25, 0.75 },
- { 0.50, 0.75 }
+ { 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];
#ifdef DEBUG
{
const GLfloat area = dx0 * dy1 - dx1 * dy0;
- assert(area >= 0.0);
+ 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 - v0[0];
- const GLfloat fy0 = sy - v0[1];
- const GLfloat fx1 = sx - v1[0];
- const GLfloat fy1 = sy - v1[1];
- const GLfloat fx2 = sx - v2[0];
- const GLfloat fy2 = sy - v2[1];
/* cross product determines if sample is inside or outside each edge */
- GLfloat cross0 = (dx0 * fy0 - dy0 * fx0);
- GLfloat cross1 = (dx1 * fy1 - dy1 * fx1);
- GLfloat cross2 = (dx2 * fy2 - dy2 * fx2);
+ 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 (cross0 == 0.0F)
- cross0 = dx0 + dy0;
- if (cross1 == 0.0F)
- cross1 = dx1 + dy1;
- if (cross2 == 0.0F)
- cross2 = dx2 + dy2;
- if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F) {
- /* point is outside triangle */
+ 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;
compute_coveragei(const GLfloat v0[3], const GLfloat v1[3],
const GLfloat v2[3], GLint winx, GLint winy)
{
- /* NOTE: 15 samples instead of 16.
- * A better sample distribution could be used.
- */
+ /* NOTE: 15 samples instead of 16. */
static const GLfloat samples[15][2] = {
/* start with the four corners */
- { 0.00, 0.00 },
- { 0.75, 0.00 },
- { 0.00, 0.75 },
- { 0.75, 0.75 },
+ { 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 */
- { 0.25, 0.00 },
- { 0.50, 0.00 },
- { 0.00, 0.25 },
- { 0.25, 0.25 },
- { 0.50, 0.25 },
- { 0.75, 0.25 },
- { 0.00, 0.50 },
- { 0.25, 0.50 },
- /*{ 0.50, 0.50 },*/
- { 0.75, 0.50 },
- { 0.25, 0.75 },
- { 0.50, 0.75 }
+ { 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) }
};
const GLfloat x = (GLfloat) winx;
const GLfloat y = (GLfloat) winy;
#ifdef DEBUG
{
const GLfloat area = dx0 * dy1 - dx1 * dy0;
- assert(area >= 0.0);
+ ASSERT(area >= 0.0);
}
#endif
const SWvertex *v2)
{
#define DO_Z
+#define DO_FOG
#define DO_RGBA
#include "s_aatritemp.h"
}
const SWvertex *v2)
{
#define DO_Z
+#define DO_FOG
#define DO_INDEX
#include "s_aatritemp.h"
}
/*
* Compute mipmap level of detail.
+ * XXX we should really include the R coordinate in this computation
+ * in order to do 3-D texture mipmapping.
*/
static INLINE GLfloat
compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
- GLfloat invQ, GLfloat width, GLfloat height)
+ const GLfloat qPlane[4], GLfloat cx, GLfloat cy,
+ GLfloat invQ, GLfloat texWidth, GLfloat texHeight)
{
- GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width;
- GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width;
- GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height;
- GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height;
- GLfloat r1 = dudx * dudx + dudy * dudy;
- GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
- GLfloat rho2 = r1 + r2;
- /* return log base 2 of rho */
- return log(rho2) * 1.442695 * 0.5; /* 1.442695 = 1/log(2) */
+ const GLfloat s = solve_plane(cx, cy, sPlane);
+ const GLfloat t = solve_plane(cx, cy, tPlane);
+ const GLfloat invQ_x1 = solve_plane_recip(cx+1.0F, cy, qPlane);
+ const GLfloat invQ_y1 = solve_plane_recip(cx, cy+1.0F, qPlane);
+ const GLfloat s_x1 = s - sPlane[0] / sPlane[2];
+ const GLfloat s_y1 = s - sPlane[1] / sPlane[2];
+ const GLfloat t_x1 = t - tPlane[0] / tPlane[2];
+ const GLfloat t_y1 = t - tPlane[1] / tPlane[2];
+ GLfloat dsdx = s_x1 * invQ_x1 - s * invQ;
+ GLfloat dsdy = s_y1 * invQ_y1 - s * invQ;
+ GLfloat dtdx = t_x1 * invQ_x1 - t * invQ;
+ GLfloat dtdy = t_y1 * invQ_y1 - t * invQ;
+ GLfloat maxU, maxV, rho, lambda;
+ dsdx = FABSF(dsdx);
+ dsdy = FABSF(dsdy);
+ dtdx = FABSF(dtdx);
+ dtdy = FABSF(dtdy);
+ maxU = MAX2(dsdx, dsdy) * texWidth;
+ maxV = MAX2(dtdx, dtdy) * texHeight;
+ rho = MAX2(maxU, maxV);
+ lambda = LOG2(rho);
+ return lambda;
}
const SWvertex *v2)
{
#define DO_Z
+#define DO_FOG
#define DO_RGBA
-#define DO_TEX
+#define DO_ATTRIBS
#include "s_aatritemp.h"
}
const SWvertex *v2)
{
#define DO_Z
+#define DO_FOG
#define DO_RGBA
-#define DO_TEX
+#define DO_ATTRIBS
#define DO_SPEC
#include "s_aatritemp.h"
}
-static void
-multitex_aa_tri(GLcontext *ctx,
- const SWvertex *v0,
- const SWvertex *v1,
- const SWvertex *v2)
-{
-#define DO_Z
-#define DO_RGBA
-#define DO_MULTITEX
-#include "s_aatritemp.h"
-}
-
-static void
-spec_multitex_aa_tri(GLcontext *ctx,
- const SWvertex *v0,
- const SWvertex *v1,
- const SWvertex *v2)
-{
-#define DO_Z
-#define DO_RGBA
-#define DO_MULTITEX
-#define DO_SPEC
-#include "s_aatritemp.h"
-}
-
/*
- * Examine GL state and set ctx->Driver.TriangleFunc to an
+ * Examine GL state and set swrast->Triangle to an
* appropriate antialiased triangle rasterizer function.
*/
void
-_mesa_set_aa_triangle_function(GLcontext *ctx)
+_swrast_set_aa_triangle_function(GLcontext *ctx)
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
ASSERT(ctx->Polygon.SmoothFlag);
- if (ctx->Texture._ReallyEnabled) {
- if (ctx->_TriangleCaps & DD_SEPERATE_SPECULAR) {
- if (swrast->_MultiTextureEnabled) {
- SWRAST_CONTEXT(ctx)->Triangle = spec_multitex_aa_tri;
- }
- else {
- SWRAST_CONTEXT(ctx)->Triangle = spec_tex_aa_tri;
- }
+ if (ctx->Texture._EnabledCoordUnits != 0
+ || ctx->FragmentProgram._Current) {
+ if (NEED_SECONDARY_COLOR(ctx)) {
+ SWRAST_CONTEXT(ctx)->Triangle = spec_tex_aa_tri;
}
else {
- if (swrast->_MultiTextureEnabled) {
- SWRAST_CONTEXT(ctx)->Triangle = multitex_aa_tri;
- }
- else {
- SWRAST_CONTEXT(ctx)->Triangle = tex_aa_tri;
- }
+ SWRAST_CONTEXT(ctx)->Triangle = tex_aa_tri;
}
}
else if (ctx->Visual.rgbMode) {