#include "glheader.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "s_aatriangle.h"
#include "s_context.h"
#include "s_span.h"
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;
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 * v0[0] + b * v0[1] + c * z0);
plane[0] = a;
plane[1] = b;
plane[2] = c;
plane[3] = d;
}
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)
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])
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;
}
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 GLfloat
compute_coveragef(const GLfloat v0[3], const GLfloat v1[3],
const GLfloat v2[3], GLint winx, GLint winy)
{
#define POS(a, b) (0.5+a*4+b)/16
static const GLfloat samples[16][2] = {
{ POS(0, 2), POS(0, 0) },
{ POS(3, 3), POS(0, 2) },
{ POS(0, 0), POS(3, 1) },
{ POS(3, 1), POS(3, 3) },
{ 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;
#ifdef 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 - 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];
GLfloat cross0 = (dx0 * fy0 - dy0 * fx0);
GLfloat cross1 = (dx1 * fy1 - dy1 * fx1);
GLfloat cross2 = (dx2 * fy2 - dy2 * fx2);
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) {
insideCount -= 1.0F;
stop = 16;
}
}
if (stop == 4)
return 1.0F;
else
return insideCount * (1.0F / 16.0F);
}
static GLint
compute_coveragei(const GLfloat v0[3], const GLfloat v1[3],
const GLfloat v2[3], GLint winx, GLint winy)
{
static const GLfloat samples[15][2] = {
{ POS(0, 2), POS(0, 0) },
{ POS(3, 3), POS(0, 2) },
{ POS(0, 0), POS(3, 1) },
{ POS(3, 1), POS(3, 3) },
{ 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;
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;
GLint insideCount = 15;
#ifdef 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 - 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];
GLfloat cross0 = (dx0 * fy0 - dy0 * fx0);
GLfloat cross1 = (dx1 * fy1 - dy1 * fx1);
GLfloat cross2 = (dx2 * fy2 - dy2 * fx2);
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) {
insideCount--;
stop = 15;
}
}
if (stop == 4)
return 15;
else
return insideCount;
}
static void
rgba_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#include "s_aatritemp.h"
}
static void
index_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_INDEX
#include "s_aatritemp.h"
}
static INLINE GLfloat
compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
const GLfloat qPlane[4], GLfloat cx, GLfloat cy,
GLfloat invQ, GLfloat texWidth, GLfloat texHeight)
{
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;
}
static void
tex_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_TEX
#include "s_aatritemp.h"
}
static void
spec_tex_aa_tri(GLcontext *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_TEX
#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_FOG
#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_FOG
#define DO_RGBA
#define DO_MULTITEX
#define DO_SPEC
#include "s_aatritemp.h"
}
void
_mesa_set_aa_triangle_function(GLcontext *ctx)
{
ASSERT(ctx->Polygon.SmoothFlag);
if (ctx->Texture._EnabledUnits != 0) {
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
if (ctx->Texture._EnabledUnits > 1) {
SWRAST_CONTEXT(ctx)->Triangle = spec_multitex_aa_tri;
}
else {
SWRAST_CONTEXT(ctx)->Triangle = spec_tex_aa_tri;
}
}
else {
if (ctx->Texture._EnabledUnits > 1) {
SWRAST_CONTEXT(ctx)->Triangle = multitex_aa_tri;
}
else {
SWRAST_CONTEXT(ctx)->Triangle = tex_aa_tri;
}
}
}
else if (ctx->Visual.rgbMode) {
SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri;
}
else {
SWRAST_CONTEXT(ctx)->Triangle = index_aa_tri;
}
ASSERT(SWRAST_CONTEXT(ctx)->Triangle);
}