瀏覽代碼

New implementation of antialiased lines. Mesa should now pass the remaining

GL conformance tests for AA lines (but not tried yet).
TODO: improve code sharing with the AA triangle code.
tags/mesa_3_5
Brian Paul 26 年之前
父節點
當前提交
7798374e47
共有 3 個文件被更改,包括 871 次插入 和 0 次删除
  1. 509
    0
      src/mesa/swrast/s_aaline.c
  2. 40
    0
      src/mesa/swrast/s_aaline.h
  3. 322
    0
      src/mesa/swrast/s_aalinetemp.h

+ 509
- 0
src/mesa/swrast/s_aaline.c 查看文件

@@ -0,0 +1,509 @@
/* $Id: s_aaline.c,v 1.1 2000/11/05 23:15:16 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#include "glheader.h"
#include "swrast/s_aaline.h"
#include "swrast/s_pb.h"
#include "swrast/s_context.h"
#include "swrast/swrast.h"
#include "types.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_FOG */
GLfloat fPlane[4];
/* DO_RGBA */
GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
/* DO_INDEX */
GLfloat iPlane[4];
/* DO_SPEC */
GLfloat srPlane[4], sgPlane[4], sbPlane[4];
/* DO_TEX or DO_MULTITEX */
GLfloat sPlane[MAX_TEXTURE_UNITS][4];
GLfloat tPlane[MAX_TEXTURE_UNITS][4];
GLfloat uPlane[MAX_TEXTURE_UNITS][4];
GLfloat vPlane[MAX_TEXTURE_UNITS][4];
GLfloat lambda[MAX_TEXTURE_UNITS];
GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS];
};



/*
* 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);
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])
{
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])
{
GLfloat z = -plane[2] / (plane[3] + plane[0] * x + plane[1] * y);
return z;
}


/*
* 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)
return 0;
else if (z > CHAN_MAXF)
return CHAN_MAXF;
return (GLchan) (GLint) z;
}


/*
* 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 */
return log(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;
samples[j][1] = y * 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)(GLcontext *ctx, const struct LineInfo *line,
struct pixel_buffer *pb, int ix, int iy);


/*
* Draw an AA line segment (called many times per line when stippling)
*/
static void
segment(GLcontext *ctx,
struct LineInfo *line,
plot_func plot,
struct pixel_buffer *pb,
GLfloat t0, GLfloat t1)
{
const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx;
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.0 * line->halfWidth;
yTop = y0 + line->halfWidth;
}
else {
yBot = y0 - line->halfWidth;
yTop = y0 + 3.0 * line->halfWidth;
}
}
else {
xLeft = x1 - line->halfWidth;
xRight = x0 + line->halfWidth;
if (line->dy <= 0.0) {
yBot = y1 - 3.0 * line->halfWidth;
yTop = y1 + line->halfWidth;
}
else {
yBot = y1 - line->halfWidth;
yTop = y1 + 3.0 * 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, pb, 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.0 * line->halfWidth;
xRight = x0 + line->halfWidth;
}
else {
xLeft = x0 - line->halfWidth;
xRight = x0 + 3.0 * line->halfWidth;
}
}
else {
yBot = y1 - line->halfWidth;
yTop = y0 + line->halfWidth;
if (line->dx <= 0.0) {
xLeft = x1 - 3.0 * line->halfWidth;
xRight = x1 + line->halfWidth;
}
else {
xLeft = x1 - line->halfWidth;
xRight = x1 + 3.0 * 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, pb, ix, iy);
}
xLeft += dxdy;
xRight += dxdy;
}
}
}


#define NAME(x) aa_ci_##x
#define DO_Z
#define DO_FOG
#define DO_INDEX
#include "s_aalinetemp.h"


#define NAME(x) aa_rgba_##x
#define DO_Z
#define DO_FOG
#define DO_RGBA
#include "s_aalinetemp.h"


#define NAME(x) aa_tex_rgba_##x
#define DO_Z
#define DO_FOG
#define DO_RGBA
#define DO_TEX
#include "s_aalinetemp.h"


#define NAME(x) aa_multitex_rgba_##x
#define DO_Z
#define DO_RGBA
#define DO_MULTITEX
#define DO_SPEC
#include "s_aalinetemp.h"



void
_swrast_choose_aa_line_function(GLcontext *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);

ASSERT(ctx->Line.SmoothFlag);

if (ctx->Visual.RGBAflag) {
/* RGBA */
if (ctx->Texture._ReallyEnabled) {
if (ctx->Texture._MultiTextureEnabled
|| ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR
|| ctx->Fog.ColorSumEnabled)
/* Multitextured! */
swrast->Line = aa_multitex_rgba_line;
else
swrast->Line = aa_tex_rgba_line;
}
else {
swrast->Line = aa_rgba_line;
}
}
else {
/* Color Index */
swrast->Line = aa_ci_line;
}
}


+ 40
- 0
src/mesa/swrast/s_aaline.h 查看文件

@@ -0,0 +1,40 @@
/* $Id: s_aaline.h,v 1.1 2000/11/05 23:15:16 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#ifndef S_AALINE_H
#define S_AALINE_H


#include "types.h"
#include "swrast.h"


extern void
_swrast_choose_aa_line_function(GLcontext *ctx);


#endif

+ 322
- 0
src/mesa/swrast/s_aalinetemp.h 查看文件

@@ -0,0 +1,322 @@
/* $Id: s_aalinetemp.h,v 1.1 2000/11/05 23:15:16 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2000 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 line template.
*/


/*
* Function to render each fragment in the AA line.
*/
static void
NAME(plot)(GLcontext *ctx, const struct LineInfo *line,
struct pixel_buffer *pb, int ix, int iy)
{
const GLfloat fx = (GLfloat) ix;
const GLfloat fy = (GLfloat) iy;
const GLfloat coverage = compute_coveragef(line, ix, iy);
GLdepth z;
GLfloat fog;
GLchan red, green, blue, alpha;
GLint frac, indx, index;
GLchan specRed, specGreen, specBlue;
GLfloat tex[MAX_TEXTURE_UNITS][4], lambda[MAX_TEXTURE_UNITS];

if (coverage == 0.0)
return;

/*
* Compute Z, color, texture coords, fog for the fragment by
* solving the plane equations at (ix,iy).
*/
#ifdef DO_Z
z = (GLdepth) solve_plane(fx, fy, line->zPlane);
#else
z = 0.0;
#endif
#ifdef DO_FOG
fog = solve_plane(fx, fy, line->fPlane);
#else
fog = 0.0;
#endif
#ifdef DO_RGBA
red = solve_plane_chan(fx, fy, line->rPlane);
green = solve_plane_chan(fx, fy, line->gPlane);
blue = solve_plane_chan(fx, fy, line->bPlane);
alpha = (GLchan) (solve_plane_chan(fx, fy, line->aPlane) * coverage);;
#else
(void) red;
(void) green;
(void) blue;
(void) alpha;
#endif
#ifdef DO_INDEX
frac = (GLint) (15.0 * coverage);
indx = (GLint) solve_plane(fx, fy, line->iPlane);
index = (indx & ~0xf) | frac;
#else
(void) frac;
(void) indx;
(void) index;
#endif
#ifdef DO_SPEC
specRed = solve_plane_chan(fx, fy, line->srPlane);
specGreen = solve_plane_chan(fx, fy, line->sgPlane);
specBlue = solve_plane_chan(fx, fy, line->sbPlane);
#else
(void) specRed;
(void) specGreen;
(void) specBlue;
#endif
#ifdef DO_TEX
{
GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[0]);
tex[0][0] = solve_plane(fx, fy, line->sPlane[0]) * invQ;
tex[0][1] = solve_plane(fx, fy, line->tPlane[0]) * invQ;
tex[0][2] = solve_plane(fx, fy, line->uPlane[0]) * invQ;
lambda[0] = compute_lambda(line->sPlane[0], line->tPlane[0], invQ,
line->texWidth[0], line->texHeight[0]);
}
#elif defined(DO_MULTITEX)
{
GLuint unit;
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
GLfloat invQ = solve_plane_recip(fx, fy, line->vPlane[unit]);
tex[unit][0] = solve_plane(fx, fy, line->sPlane[unit]) * invQ;
tex[unit][1] = solve_plane(fx, fy, line->tPlane[unit]) * invQ;
tex[unit][2] = solve_plane(fx, fy, line->uPlane[unit]) * invQ;
lambda[unit] = compute_lambda(line->sPlane[unit],
line->tPlane[unit], invQ,
line->texWidth[unit], line->texHeight[unit]);
}
}
}
#else
(void) tex[0][0];
(void) lambda[0];
#endif


#if defined(DO_MULTITEX)
#if defined(DO_SPEC)
PB_WRITE_MULTITEX_SPEC_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha,
specRed, specGreen, specBlue, tex);
#else
PB_WRITE_MULTITEX_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha, texcoords);
#endif
#elif defined(DO_TEX)
PB_WRITE_TEX_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha,
tex[0][0], tex[0][1], tex[0][2]);
#elif defined(DO_RGBA)
PB_WRITE_RGBA_PIXEL(pb, ix, iy, z, fog, red, green, blue, alpha);
#elif defined(DO_INDEX)
PB_WRITE_CI_PIXEL(pb, ix, iy, z, fog, index);
#endif

PB_CHECK_FLUSH(ctx, pb);
}



/*
* Line setup
*/
static void
NAME(line)(GLcontext *ctx, SWvertex *v0, SWvertex *v1)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct pixel_buffer *pb = SWRAST_CONTEXT(ctx)->PB;
GLfloat tStart, tEnd; /* segment start, end along line length */
GLboolean inSegment;
GLint iLen, i;

/* Init the LineInfo struct */
struct LineInfo line;
line.x0 = v0->win[0];
line.y0 = v0->win[1];
line.x1 = v1->win[0];
line.y1 = v1->win[1];
line.dx = line.x1 - line.x0;
line.dy = line.y1 - line.y0;
line.len = sqrt(line.dx * line.dx + line.dy * line.dy);
line.halfWidth = 0.5F * ctx->Line.Width;
line.xAdj = line.dx / line.len * line.halfWidth;
line.yAdj = line.dy / line.len * line.halfWidth;

#ifdef DO_Z
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->win[2], v1->win[2], line.zPlane);
#endif
#ifdef DO_FOG
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->fog, v1->fog, line.fPlane);
#endif
#ifdef DO_RGBA
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[RCOMP], v1->color[RCOMP], line.rPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[GCOMP], v1->color[GCOMP], line.gPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[BCOMP], v1->color[BCOMP], line.bPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[ACOMP], v1->color[ACOMP], line.aPlane);
}
else {
constant_plane(v0->color[RCOMP], line.rPlane);
constant_plane(v0->color[GCOMP], line.gPlane);
constant_plane(v0->color[BCOMP], line.bPlane);
constant_plane(v0->color[ACOMP], line.aPlane);
}
#endif
#ifdef DO_SPEC
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->specular[RCOMP], v1->specular[RCOMP], line.srPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->specular[GCOMP], v1->specular[GCOMP], line.sgPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->specular[BCOMP], v1->specular[BCOMP], line.sbPlane);
}
else {
constant_plane(v0->specular[RCOMP], line.srPlane);
constant_plane(v0->specular[GCOMP], line.sgPlane);
constant_plane(v0->specular[BCOMP], line.sbPlane);
}
#endif
#ifdef DO_INDEX
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->index, v1->index, line.iPlane);
}
else {
constant_plane(v0->index, line.iPlane);
}
#endif
#ifdef DO_TEX
{
const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
const GLfloat invW0 = v0->win[3];
const GLfloat invW1 = v1->win[3];
const GLfloat s0 = v0->texcoord[0][0] * invW0;
const GLfloat s1 = v1->texcoord[0][0] * invW1;
const GLfloat t0 = v0->texcoord[0][1] * invW0;
const GLfloat t1 = v1->texcoord[0][1] * invW0;
const GLfloat r0 = v0->texcoord[0][2] * invW0;
const GLfloat r1 = v1->texcoord[0][2] * invW0;
const GLfloat q0 = v0->texcoord[0][3] * invW0;
const GLfloat q1 = v1->texcoord[0][3] * invW0;
compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[0]);
compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[0]);
compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[0]);
compute_plane(line.x0, line.y0, line.x1, line.y1, q0, q1, line.vPlane[0]);
line.texWidth[0] = (GLfloat) texImage->Width;
line.texHeight[0] = (GLfloat) texImage->Height;
}
#elif defined(DO_MULITEX)
{
GLuint u;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u].ReallyEnabled) {
const struct gl_texture_object *obj = ctx->Texture.Unit[u].Current;
const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];
const GLfloat invW0 = v0->win[3];
const GLfloat invW1 = v1->win[3];
GLfloat (*texCoord)[4] = VB->TexCoordPtr[u]->data;
const GLfloat s0 = v0->texcoord[u][0] * invW0;
const GLfloat s1 = v1->texcoord[u][0] * invW1;
const GLfloat t0 = v0->texcoord[u][1] * invW0;
const GLfloat t1 = v1->texcoord[u][1] * invW0;
const GLfloat r0 = v0->texcoord[u][2] * invW0;
const GLfloat r1 = v1->texcoord[u][2] * invW0;
const GLfloat q0 = v0->texcoord[u][3] * invW0;
const GLfloat q1 = v1->texcoord[u][3] * invW0;
compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[u]);
compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[u]);
compute_plane(line.x0, line.y0, line.x1, line.y1, u0, u1, line.uPlane[u]);
compute_plane(line.x0, line.y0, line.x1, line.y1, v0, v1, line.vPlane[u]);
line.texWidth[u] = (GLfloat) texImage->Width;
line.texHeight[u] = (GLfloat) texImage->Height;
}
}
}
#endif

tStart = tEnd = 0.0;
inSegment = GL_FALSE;
iLen = (GLint) line.len;

if (ctx->Line.StippleFlag) {
for (i = 0; i < iLen; i++) {
const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
if ((1 << bit) & ctx->Line.StipplePattern) {
/* stipple bit is on */
const GLfloat t = (GLfloat) i / (GLfloat) line.len;
if (!inSegment) {
/* start new segment */
inSegment = GL_TRUE;
tStart = t;
}
else {
/* still in the segment, extend it */
tEnd = t;
}
}
else {
/* stipple bit is off */
if (inSegment && (tEnd > tStart)) {
/* draw the segment */
segment(ctx, &line, NAME(plot), pb, tStart, tEnd);
inSegment = GL_FALSE;
}
else {
/* still between segments, do nothing */
}
}
swrast->StippleCounter++;
}
}
else {
/* non-stippled */
segment(ctx, &line, NAME(plot), pb, 0.0, 1.0);
}
}




#undef DO_Z
#undef DO_FOG
#undef DO_RGBA
#undef DO_INDEX
#undef DO_SPEC
#undef DO_TEX
#undef DO_MULTITEX
#undef NAME

Loading…
取消
儲存