Add unfilled rendering and code for feedback (not yet integrated)

This commit is contained in:
Keith Whitwell 2003-02-03 21:33:02 +00:00
parent cd9df92c9d
commit 75ccd62be8
3 changed files with 967 additions and 46 deletions

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.1.2.20 2003/01/28 18:28:54 keithw Exp $
# $Id: Makefile,v 1.1.2.21 2003/02/03 21:33:02 keithw Exp $
# Mesa 3-D graphics library
# Version: 5.0
@ -51,11 +51,10 @@ DRIVER_SOURCES = server/radeon_dri.c \
SUBSET_DRIVER_SOURCES = \
radeon_subset_bitmap.c \
radeon_subset_readpix.c \
radeon_subset_feedback.c \
radeon_subset_vtx.c
FULL_DRIVER_SOURCES = \
radeon_subset_bitmap.c \
radeon_subset_readpix.c \
radeon_lighting.c \
radeon_userclip.c \
radeon_texgen.c \

View file

@ -0,0 +1,799 @@
/* $Id: radeon_subset_feedback.c,v 1.1.2.1 2003/02/03 21:33:02 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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 "imports.h"
#include "context.h"
#include "mmath.h"
#include "mtypes.h"
#include "enums.h"
#include "glapi.h"
#include "feedback.h"
#include "radeon_context.h"
typedef struct {
struct { GLfloat x, y, z, w; } pos, eyePos, clipPos, winPos;
struct { GLfloat s, t; } texCoord;
struct { GLfloat r, g, b, a; } color;
} vertex;
static struct {
GLuint vCount;
vertex vBuffer[4];
GLboolean lineReset;
GLboolean partialLineLoop;
} vb;
/**********************************************************************/
/***** Vertex Transformation and Clipping *****/
/**********************************************************************/
/*
* Transform a point (column vector) by a matrix: Q = M * P
*/
#define TRANSFORM_POINT( Q, M, P ) \
Q.x = M[0] * P.x + M[4] * P.y + M[8] * P.z + M[12] * P.w; \
Q.y = M[1] * P.x + M[5] * P.y + M[9] * P.z + M[13] * P.w; \
Q.z = M[2] * P.x + M[6] * P.y + M[10] * P.z + M[14] * P.w; \
Q.w = M[3] * P.x + M[7] * P.y + M[11] * P.z + M[15] * P.w;
/*
* clip coord to window coord mapping
*/
#define MAP_POINT( Q, P, VP ) \
Q.x = (GLfloat) (((P.x / P.w) + 1.0) * VP.Width / 2.0 + VP.X); \
Q.y = (GLfloat) (((P.y / P.w) + 1.0) * VP.Height / 2.0 + VP.Y); \
Q.z = (GLfloat) (((P.z / P.w) + 1.0) * (VP.Far - VP.Near) / 2.0 + VP.Near);\
Q.w = (GLfloat) P.w;
/*
* Linear interpolation:
*/
#define INTERPOLATE(T, A, B) ((A) + ((B) - (A)) * (T))
/*
* Interpolate vertex position, color, texcoords, etc.
*/
static void
interpolate_vertex(GLfloat t, const vertex *v0, const vertex *v1,
vertex *vOut)
{
vOut->eyePos.x = INTERPOLATE(t, v0->eyePos.x, v1->eyePos.x);
vOut->eyePos.y = INTERPOLATE(t, v0->eyePos.y, v1->eyePos.y);
vOut->eyePos.z = INTERPOLATE(t, v0->eyePos.z, v1->eyePos.z);
vOut->eyePos.w = INTERPOLATE(t, v0->eyePos.w, v1->eyePos.w);
vOut->clipPos.x = INTERPOLATE(t, v0->clipPos.x, v1->clipPos.x);
vOut->clipPos.y = INTERPOLATE(t, v0->clipPos.y, v1->clipPos.y);
vOut->clipPos.z = INTERPOLATE(t, v0->clipPos.z, v1->clipPos.z);
vOut->clipPos.w = INTERPOLATE(t, v0->clipPos.w, v1->clipPos.w);
vOut->color.r = INTERPOLATE(t, v0->color.r, v1->color.r);
vOut->color.g = INTERPOLATE(t, v0->color.g, v1->color.g);
vOut->color.b = INTERPOLATE(t, v0->color.b, v1->color.b);
vOut->color.a = INTERPOLATE(t, v0->color.a, v1->color.a);
vOut->texCoord.s = INTERPOLATE(t, v0->texCoord.s, v1->texCoord.s);
vOut->texCoord.t = INTERPOLATE(t, v0->texCoord.t, v1->texCoord.t);
}
/* clip bit codes */
#define CLIP_LEFT 1
#define CLIP_RIGHT 2
#define CLIP_BOTTOM 4
#define CLIP_TOP 8
#define CLIP_NEAR 16
#define CLIP_FAR 32
/*
* Apply view volume clip testing to a point.
* Return: 0 - visible
* non-zero - clip code mask (or of above CLIP_ bits)
*/
static GLuint
clip_point(const vertex *v)
{
GLuint mask = 0;
if (v->clipPos.x > v->clipPos.w) mask |= CLIP_RIGHT;
if (v->clipPos.x < -v->clipPos.w) mask |= CLIP_LEFT;
if (v->clipPos.y > v->clipPos.w) mask |= CLIP_TOP;
if (v->clipPos.y < -v->clipPos.w) mask |= CLIP_BOTTOM;
if (v->clipPos.z > v->clipPos.w) mask |= CLIP_FAR;
if (v->clipPos.z < -v->clipPos.w) mask |= CLIP_NEAR;
return mask;
}
/*
* Apply clipping to a line segment.
* Input: v0, v1 - incoming vertices
* Output: v0out, v1out - result/clipped vertices
* Return: GL_TRUE: visible
* GL_FALSE: totally clipped
*/
static GLboolean
clip_line(const vertex *v0in, const vertex *v1in,
vertex *v0new, vertex *v1new)
{
vertex v0, v1, vNew;
GLfloat dx, dy, dz, dw, t;
GLuint code0, code1;
code0 = clip_point(v0in);
code1 = clip_point(v1in);
if (code0 & code1)
return GL_FALSE; /* totally clipped */
*v0new = *v0in;
*v1new = *v1in;
if (code0 == 0 && code1 == 0)
return GL_TRUE; /* no clipping needed */
v0 = *v0in;
v1 = *v1in;
/*
* We use 6 instances of this code to clip agains the 6 planes.
* For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION
* macros apprpriately.
*/
#define GENERAL_CLIP \
if (OUTSIDE(v0)) { \
if (OUTSIDE(v1)) { \
/* both verts are outside ==> return 0 */ \
return 0; \
} \
else { \
/* v0 is outside, v1 is inside ==> clip */ \
COMPUTE_INTERSECTION( v1, v0, vNew ) \
interpolate_vertex(t, &v1, &v0, &vNew); \
v0 = vNew; \
} \
} \
else { \
if (OUTSIDE(v1)) { \
/* v0 is inside, v1 is outside ==> clip */ \
COMPUTE_INTERSECTION( v0, v1, vNew ) \
interpolate_vertex(t, &v0, &v1, &vNew); \
v1 = vNew; \
} \
/* else both verts are inside ==> do nothing */ \
}
/*** Clip against +X side ***/
#define OUTSIDE(V) (V.clipPos.x > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT.clipPos.x - IN.clipPos.x; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.x - IN.clipPos.w) / (dw-dx);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against -X side ***/
#define OUTSIDE(V) (V.clipPos.x < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT.clipPos.x - IN.clipPos.x; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.x + IN.clipPos.w) / (dw+dx);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against +Y side ***/
#define OUTSIDE(V) (V.clipPos.y > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT.clipPos.y - IN.clipPos.y; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.y - IN.clipPos.w) / (dw-dy);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against -Y side ***/
#define OUTSIDE(V) (V.clipPos.y < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT.clipPos.y - IN.clipPos.y; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.y + IN.clipPos.w) / (dw+dy);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against +Z side ***/
#define OUTSIDE(V) (V.clipPos.z > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT.clipPos.z - IN.clipPos.z; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.z - IN.clipPos.w) / (dw-dz);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against -Z side ***/
#define OUTSIDE(V) (V.clipPos.z < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT.clipPos.z - IN.clipPos.z; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.z + IN.clipPos.w) / (dw+dz);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
#undef GENERAL_CLIP
*v0new = v0;
*v1new = v1;
return GL_TRUE;
}
/*
* Apply clipping to a polygon.
* Input: vIn - array of input vertices
* inCount - number of input vertices
* Output: vOut - new vertices
* Return: number of vertices in vOut
*/
static GLuint
clip_polygon(const vertex *vIn, unsigned int inCount, vertex *vOut)
{
vertex inlist[20], outlist[20];
GLfloat dx, dy, dz, dw, t;
GLuint incount, outcount, previ, curri, result;
const vertex *currVert, *prevVert;
vertex *newVert;
#define GENERAL_CLIP(INCOUNT, INLIST, OUTCOUNT, OUTLIST) \
if (INCOUNT < 3) \
return GL_FALSE; \
previ = INCOUNT - 1; /* let previous = last vertex */ \
prevVert = INLIST + previ; \
OUTCOUNT = 0; \
for (curri = 0; curri < INCOUNT; curri++) { \
currVert = INLIST + curri; \
if (INSIDE(currVert)) { \
if (INSIDE(prevVert)) { \
/* both verts are inside ==> copy current to outlist */ \
OUTLIST[OUTCOUNT] = *currVert; \
OUTCOUNT++; \
} \
else { \
newVert = OUTLIST + OUTCOUNT; \
/* current is inside and previous is outside ==> clip */ \
COMPUTE_INTERSECTION( currVert, prevVert, newVert ) \
OUTCOUNT++; \
/* Output current */ \
OUTLIST[OUTCOUNT] = *currVert; \
OUTCOUNT++; \
} \
} \
else { \
if (INSIDE(prevVert)) { \
newVert = OUTLIST + OUTCOUNT; \
/* current is outside and previous is inside ==> clip */ \
COMPUTE_INTERSECTION( prevVert, currVert, newVert ); \
OUTLIST[OUTCOUNT] = *newVert; \
OUTCOUNT++; \
} \
/* else both verts are outside ==> do nothing */ \
} \
/* let previous = current */ \
previ = curri; \
prevVert = currVert; \
}
/*
* Clip against +X
*/
#define INSIDE(V) (V->clipPos.x <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT->clipPos.x - IN->clipPos.x; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.x - IN->clipPos.w) / (dw - dx); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(inCount, vIn, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -X
*/
#define INSIDE(V) (V->clipPos.x >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT->clipPos.x - IN->clipPos.x; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.x + IN->clipPos.w) / (dw + dx); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, incount, inlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against +Y
*/
#define INSIDE(V) (V->clipPos.y <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT->clipPos.y - IN->clipPos.y; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.y - IN->clipPos.w) / (dw - dy); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(incount, inlist, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -Y
*/
#define INSIDE(V) (V->clipPos.y >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT->clipPos.y - IN->clipPos.y; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.y + IN->clipPos.w) / (dw + dy); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, incount, inlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against +Z
*/
#define INSIDE(V) (V->clipPos.z <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT->clipPos.z - IN->clipPos.z; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.z - IN->clipPos.w) / (dw - dz); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(incount, inlist, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -Z
*/
#define INSIDE(V) (V->clipPos.z >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT->clipPos.z - IN->clipPos.z; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.z + IN->clipPos.w) / (dw + dz); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, result, vOut)
#undef INSIDE
#undef COMPUTE_INTERSECTION
#undef GENERAL_CLIP
return result;
}
/**********************************************************************/
/***** Selection *****/
/**********************************************************************/
static void
select_point(const vertex *v)
{
GET_CURRENT_CONTEXT(ctx);
if (clip_point(v) == 0)
{
vertex c = *v;
MAP_POINT(c.winPos, c.clipPos, ctx->Viewport);
_mesa_update_hitflag(ctx, c.winPos.z);
}
}
static void
select_line(const vertex *v0, const vertex *v1)
{
GET_CURRENT_CONTEXT(ctx);
vertex c0, c1;
if (clip_line(v0, v1, &c0, &c1))
{
MAP_POINT(c0.winPos, c0.clipPos, ctx->Viewport);
MAP_POINT(c1.winPos, c1.clipPos, ctx->Viewport);
_mesa_update_hitflag(ctx, c0.winPos.z);
_mesa_update_hitflag(ctx, c1.winPos.z);
}
}
static void
select_triangle(const vertex *v0,
const vertex *v1,
const vertex *v2)
{
GET_CURRENT_CONTEXT(ctx);
vertex vlist[3], vclipped[8];
GLuint i, n;
vlist[0] = *v0;
vlist[1] = *v1;
vlist[2] = *v2;
n = clip_polygon(vlist, 3, vclipped);
for (i = 0; i < n; i++) {
MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, ctx->Viewport);
_mesa_update_hitflag(ctx, vclipped[i].winPos.z);
}
}
static void
radeon_select_Vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_transform_attrib *t = &(ctx->Transform);
struct gl_polygon_attrib *p = &(ctx->Polygon);
vertex *v = vb.vBuffer + vb.vCount;
/* store the vertex */
v->pos.x = x;
v->pos.y = y;
v->pos.z = z;
v->pos.w = w;
v->color.r = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
v->color.g = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
v->color.b = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
v->color.a = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
v->texCoord.s = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
v->texCoord.t = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];
/* transform to eye space, then clip space */
TRANSFORM_POINT(v->eyePos, ctx->ModelviewMatrixStack.Top->m, v->pos);
TRANSFORM_POINT(v->clipPos, ctx->ProjectionMatrixStack.Top->m, v->eyePos);
switch (ctx->Driver.CurrentExecPrimitive) {
case GL_POINTS:
assert(vb.vCount == 0);
select_point(v);
break;
case GL_LINES:
if (vb.vCount == 0)
{
vb.vCount = 1;
}
else
{
assert(vb.vCount == 1);
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.vCount = 0;
}
break;
case GL_LINE_STRIP:
if (vb.vCount == 0)
{
vb.vCount = 1;
}
else
{
assert(vb.vCount == 1);
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.vBuffer[0] = vb.vBuffer[1];
/* leave vb.vCount at 1 */
}
break;
case GL_LINE_LOOP:
if (vb.vCount == 0)
{
vb.vCount = 1;
vb.partialLineLoop = GL_FALSE;
}
else if (vb.vCount == 1)
{
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.partialLineLoop = GL_TRUE;
vb.vCount = 2;
}
else
{
assert(vb.vCount == 2);
vb.partialLineLoop = GL_FALSE;
select_line(vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount at 2 */
}
break;
case GL_TRIANGLES:
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vCount = 0;
}
break;
case GL_TRIANGLE_STRIP:
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else if (vb.vCount == 2)
{
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vCount = 3;
}
else
{
assert(vb.vCount == 3);
select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
vb.vBuffer[0] = vb.vBuffer[2];
vb.vBuffer[1] = vb.vBuffer[3];
vb.vCount = 2;
}
break;
case GL_TRIANGLE_FAN:
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount = 2 */
}
break;
case GL_QUADS:
if (vb.vCount < 3)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 3);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 2, vb.vBuffer + 3);
vb.vCount = 0;
}
break;
case GL_QUAD_STRIP:
if (vb.vCount < 3)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 3);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
vb.vBuffer[0] = vb.vBuffer[2];
vb.vBuffer[1] = vb.vBuffer[3];
vb.vCount = 2;
}
break;
case GL_POLYGON:
switch (p->FrontMode) {
case GL_POINT:
assert(vb.vCount == 0);
select_point(v);
break;
case GL_LINE:
if (vb.vCount == 0)
{
vb.vCount = 1;
vb.partialLineLoop = GL_FALSE;
}
else if (vb.vCount == 1)
{
select_line(vb.vBuffer + 0, vb.vBuffer + 1);
vb.partialLineLoop = GL_TRUE;
vb.vCount = 2;
}
else
{
assert(vb.vCount == 2);
vb.partialLineLoop = GL_FALSE;
select_line(vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount at 2 */
}
break;
case GL_FILL:
/* draw as a tri-fan */
if (vb.vCount == 0 || vb.vCount == 1)
{
vb.vCount++;
}
else
{
assert(vb.vCount == 2);
select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
vb.vBuffer[1] = vb.vBuffer[2];
/* leave vb.vCount = 2 */
}
break;
default:
; /* impossible */
}
break;
default:
; /* outside begin/end -- no action required */
}
}
static void radeon_select_Vertex2f(GLfloat x, GLfloat y)
{
radeon_select_Vertex4f(x, y, 0.0, 1.0);
}
static void radeon_select_Vertex2fv(const GLfloat * v)
{
radeon_select_Vertex4f(v[0], v[1], 0.0, 1.0);
}
static void radeon_select_Vertex3f(GLfloat x, GLfloat y, GLfloat z)
{
radeon_select_Vertex4f(x, y, z, 1.0);
}
static void radeon_select_Vertex3fv(const GLfloat * v)
{
radeon_select_Vertex4f(v[0], v[1], v[2], 1.0);
}
/* Color
*/
static void radeon_select_Color4f( GLfloat r, GLfloat g,
GLfloat b, GLfloat a )
{
GET_CURRENT_CONTEXT(ctx);
GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
}
static void radeon_select_Color4fv( const GLfloat *v )
{
radeon_select_Color4f( v[0], v[1], v[2], v[3] );
}
static void radeon_select_Color3f( GLfloat r, GLfloat g, GLfloat b )
{
radeon_select_Color4f( r, g, b, 1.0 );
}
static void radeon_select_Color3fv( const GLfloat *v )
{
radeon_select_Color4f( v[0], v[1], v[2], 1.0 );
}
/* TexCoord
*/
static __inline__ void radeon_select_TexCoord2f( GLfloat s, GLfloat t )
{
GET_CURRENT_CONTEXT(ctx);
GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
dest[0] = s;
dest[1] = t;
}
static void radeon_select_TexCoord2fv( const GLfloat *v )
{
radeon_select_TexCoord2f( v[0], v[1] );
}
/* Begin/End
*/
static void radeon_select_Begin(GLenum mode)
{
GET_CURRENT_CONTEXT(ctx);
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
return;
}
if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
return;
}
ctx->Driver.CurrentExecPrimitive = mode;
vb.vCount = 0;
vb.lineReset = GL_TRUE;
vb.partialLineLoop = GL_FALSE;
}
static void radeon_select_End(void)
{
GET_CURRENT_CONTEXT(ctx);
if ( (ctx->Driver.CurrentExecPrimitive == GL_LINE_LOOP ||
(ctx->Driver.CurrentExecPrimitive == GL_POLYGON &&
ctx->Polygon.FrontMode == GL_LINE))
&& vb.vCount == 2 )
{
/* draw the last line segment */
if (vb.partialLineLoop)
select_line(vb.vBuffer + 1, vb.vBuffer + 0);
else
select_line(vb.vBuffer + 2, vb.vBuffer + 0);
}
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
}
void radeon_select_Init( GLcontext *ctx )
{
struct _glapi_table *exec = ctx->Exec;
exec->Color3f = radeon_select_Color3f;
exec->Color3fv = radeon_select_Color3fv;
exec->Color4f = radeon_select_Color4f;
exec->Color4fv = radeon_select_Color4fv;
exec->TexCoord2f = radeon_select_TexCoord2f;
exec->TexCoord2fv = radeon_select_TexCoord2fv;
exec->Vertex2f = radeon_select_Vertex2f;
exec->Vertex2fv = radeon_select_Vertex2fv;
exec->Vertex3f = radeon_select_Vertex3f;
exec->Vertex3fv = radeon_select_Vertex3fv;
exec->Begin = radeon_select_Begin;
exec->End = radeon_select_End;
/* ctx->Driver.FlushVertices = radeonFlushVertices; */
/* ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; */
}

View file

@ -96,24 +96,55 @@ static struct {
static void radeonFlushVertices( GLcontext *, GLuint );
static struct { int start, incr, hwprim; } prims[GL_POLYGON+1] = {
{ 1, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_POINT }, /* GL_POINTS */
{ 2, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE }, /* GL_LINES */
{ 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP }, /* GL_LINE_LOOP */
{ 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP }, /* GL_LINE_STRIP */
{ 3, 3, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST }, /* GL_TRIANGLES */
{ 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP }, /* GL_TRIANGLE_STRIP */
{ 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN }, /* GL_TRIANGLE_FAN */
{ 4, 4, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST }, /* GL_QUADS */
{ 4, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP }, /* GL_QUAD_STRIP */
{ 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN }, /* GL_POLYGON */
static struct { int start, incr, hwprim, lnprim, ptprim; } prims[10] = {
{ 1, 1,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT},
{ 2, 2,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE },
{ 2, 1,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
{ 2, 1,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
{ 3, 3,
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
{ 3, 1,
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
{ 3, 1,
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
{ 4, 4,
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
{ 4, 2,
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
{ 3, 1,
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN,
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
};
static void finish_prim( radeonContextPtr rmesa )
{
GLuint prim_end = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
GLuint hwprim = 0;
/* Too few vertices (eg: 2 vertices for a triangles prim?)
/* Too few vertices? (eg: 2 vertices for a triangles prim?)
*/
if (prim_end < prims[vb.prim].start)
return;
@ -125,8 +156,15 @@ static void finish_prim( radeonContextPtr rmesa )
radeonEmitVertexAOS( rmesa, vb.vertex_size, GET_START(&rmesa->dma.current) );
switch (vb.context->Polygon.FrontMode) {
case GL_LINE: hwprim = prims[vb.prim].lnprim; break;
case GL_POINT: hwprim = prims[vb.prim].ptprim; break;
case GL_FILL: hwprim = prims[vb.prim].hwprim; break;
default: return;
}
radeonEmitVbufPrim( rmesa, vb.vertex_format,
prims[vb.prim].hwprim | rmesa->tcl.tcl_flag,
hwprim | rmesa->tcl.tcl_flag,
prim_end );
rmesa->dma.current.ptr =
@ -154,7 +192,7 @@ static GLuint copy_dma_verts( radeonContextPtr rmesa,
GLcontext *ctx = vb.context;
GLuint nr = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
switch( ctx->Driver.CurrentExecPrimitive )
switch( vb.prim )
{
case GL_POINTS:
return 0;
@ -278,16 +316,28 @@ static void emit_vertex( int v )
vb.stack[0].notify();
}
static void emit_tri( int v0, int v1, int v2 )
{
assert (vb.context->Polygon.FrontMode == GL_LINE);
emit_vertex( v0 ); emit_vertex( v1 );
emit_vertex( v1 ); emit_vertex( v2 );
emit_vertex( v2 ); emit_vertex( v0 );
}
/* Emit a quad (in vb.vertex_store) to dma as two triangles.
*/
static void emit_quad( int v0, int v1, int v2, int v3 )
{
emit_vertex( v0 );
emit_vertex( v1 );
emit_vertex( v3 );
emit_vertex( v1 );
emit_vertex( v2 );
emit_vertex( v3 );
if (vb.context->Polygon.FrontMode == GL_LINE) {
emit_vertex( v0 ); emit_vertex( v1 );
emit_vertex( v1 ); emit_vertex( v2 );
emit_vertex( v2 ); emit_vertex( v3 );
emit_vertex( v3 ); emit_vertex( v0 );
}
else {
emit_vertex( v0 ); emit_vertex( v1 ); emit_vertex( v3 );
emit_vertex( v1 ); emit_vertex( v2 ); emit_vertex( v3 );
}
}
/* Every fourth vertex in a quad primitive, this is called to emit:
@ -306,7 +356,7 @@ static void notify_qstrip1( void );
static void notify_qstrip0( void )
{
pop_notify();
emit_quad( 0, 1, 2, 3 );
emit_quad( 0, 1, 3, 2 );
push_notify( notify_qstrip1, 2, vb.vertex_store );
}
@ -326,6 +376,56 @@ static void notify_lineloop0( void )
emit_vertex(0);
}
/* Need to decompose tristrip & trifan to tris for unfilled line modes
*/
static void notify_tristrip1( void );
static void notify_tristrip2( void );
static void notify_tristrip0( void )
{
pop_notify();
emit_tri( 0, 1, 2 );
push_notify( notify_tristrip1, 1, vb.vertex_store );
}
static void notify_tristrip1( void )
{
pop_notify();
emit_tri( 1, 0, 2 );
push_notify( notify_tristrip2, 1, vb.vertex_store + 1*vb.vertex_size );
}
static void notify_tristrip2( void )
{
pop_notify();
emit_tri( 1, 0, 2 );
push_notify( notify_tristrip0, 1, vb.vertex_store + 2*vb.vertex_size );
}
static void notify_trifan1( void );
static void notify_trifan0( void )
{
pop_notify();
emit_tri( 0, 1, 2 );
push_notify( notify_trifan1, 1, vb.vertex_store + 1*vb.vertex_size );
}
static void notify_trifan1( void )
{
pop_notify();
emit_tri( 0, 2, 1 );
push_notify( notify_trifan0, 1, vb.vertex_store + 2*vb.vertex_size );
}
/* Emit lines in GL_LINE fill mode
*/
static void notify_tri( void )
{
pop_notify();
emit_tri( 0, 1, 2 );
push_notify( notify_tri, 3, vb.vertex_store );
}
void radeonVtxfmtInvalidate( GLcontext *ctx )
@ -431,39 +531,62 @@ static void radeon_Begin( GLenum mode )
vb.prim = ctx->Driver.CurrentExecPrimitive = mode;
se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL] | RADEON_FLAT_SHADE_VTX_LAST;
if (ctx->Line.StippleFlag &&
(ctx->Polygon.FrontMode == GL_LINE ||
mode == GL_LINES ||
mode == GL_LINE_LOOP ||
mode == GL_LINE_STRIP))
RESET_STIPPLE();
switch( mode ) {
case GL_LINES:
if (ctx->Line.StippleFlag)
AUTO_STIPPLE( GL_TRUE );
break;
case GL_LINE_LOOP:
vb.prim = GL_LINE_STRIP;
push_notify( notify_lineloop0, 1, vb.vertex_store );
break;
case GL_TRIANGLES:
if (ctx->Polygon.FrontMode == GL_LINE) {
vb.prim = GL_LINES;
push_notify( notify_tri, 3, vb.vertex_store );
}
break;
case GL_TRIANGLE_STRIP:
if (ctx->Polygon.FrontMode == GL_LINE) {
vb.prim = GL_LINES;
push_notify( notify_tristrip0, 3, vb.vertex_store );
}
break;
case GL_TRIANGLE_FAN:
if (ctx->Polygon.FrontMode == GL_LINE) {
vb.prim = GL_LINES;
push_notify( notify_trifan0, 3, vb.vertex_store );
}
break;
case GL_QUADS:
vb.prim = GL_TRIANGLES;
if (ctx->Polygon.FrontMode == GL_LINE)
vb.prim = GL_LINES;
else
vb.prim = GL_TRIANGLES;
push_notify( notify_quad, 4, vb.vertex_store );
break;
case GL_QUAD_STRIP:
/* Need special treatment only for flat shading -- otherwise the
* tristrip primitive works fine.
*/
if (ctx->_TriangleCaps & DD_FLATSHADE) {
if (ctx->Polygon.FrontMode == GL_LINE) {
push_notify( notify_qstrip0, 4, vb.vertex_store );
}
else if (ctx->_TriangleCaps & DD_FLATSHADE) {
vb.prim = GL_TRIANGLES;
push_notify( notify_qstrip0, 4, vb.vertex_store );
}
break;
case GL_LINES:
if (ctx->Line.StippleFlag) {
RESET_STIPPLE();
AUTO_STIPPLE( GL_TRUE );
}
break;
case GL_LINE_LOOP:
if (ctx->Line.StippleFlag)
RESET_STIPPLE();
vb.prim = GL_LINE_STRIP;
push_notify( notify_lineloop0, 1, vb.vertex_store );
break;
case GL_LINE_STRIP:
if (ctx->Line.StippleFlag)
RESET_STIPPLE();
break;
case GL_POLYGON:
if (ctx->_TriangleCaps & DD_FLATSHADE)
se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST;
if (ctx->Polygon.FrontMode == GL_LINE)
push_notify( notify_lineloop0, 1, vb.vertex_store );
break;
default:
break;
}
@ -618,7 +741,7 @@ void radeonVtxfmtInit( GLcontext *ctx )
exec->Vertex3fv = radeon_Vertex3fv;
exec->Begin = radeon_Begin;
exec->End = radeon_End;
exec->Rectf = _mesa_noop_Rectf; /* is this supported? */
exec->Rectf = _mesa_noop_Rectf;
vb.context = ctx;