/* -*- mode: c; c-basic-offset: 3 -*- * * Copyright 2000 VA Linux Systems Inc., Fremont, California. * * 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 (including the next * paragraph) 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 * VA LINUX SYSTEMS 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. */ /* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_tritmp.h,v 1.2 2001/08/18 02:51:07 dawes Exp $ */ /* * Original rewrite: * Gareth Hughes , 29 Sep - 1 Oct 2000 * * Authors: * Gareth Hughes * Keith Whitwell * */ static __inline void TAG(triangle)( GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2, GLuint pv ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); struct vertex_buffer *VB = ctx->VB; tdfxVertexPtr fxverts = TDFX_DRIVER_DATA(VB)->verts; tdfxVertex *v[3]; #if (IND & TDFX_OFFSET_BIT) GLfloat offset; GLfloat z[3]; #endif #if (IND & (TDFX_TWOSIDE_BIT | TDFX_FLAT_BIT)) GLuint c[3]; #endif v[0] = &fxverts[e0]; v[1] = &fxverts[e1]; v[2] = &fxverts[e2]; #if (IND & (TDFX_TWOSIDE_BIT | TDFX_FLAT_BIT)) c[0] = v[0]->ui[4]; c[1] = v[1]->ui[4]; c[2] = v[2]->ui[4]; #endif #if (IND & (TDFX_TWOSIDE_BIT | TDFX_OFFSET_BIT)) { GLfloat ex = v[0]->v.x - v[2]->v.x; GLfloat ey = v[0]->v.y - v[2]->v.y; GLfloat fx = v[1]->v.x - v[2]->v.x; GLfloat fy = v[1]->v.y - v[2]->v.y; GLfloat cc = ex*fy - ey*fx; #if (IND & TDFX_TWOSIDE_BIT) { GLuint facing = ( cc < 0.0 ) ^ ctx->Polygon.FrontBit; GLubyte (*vbcolor)[4] = VB->Color[facing]->data; if (IND & TDFX_FLAT_BIT) { TDFX_COLOR( (char *)&v[0]->ui[4], vbcolor[pv] ); v[2]->ui[4] = v[1]->ui[4] = v[0]->ui[4]; } else { TDFX_COLOR( (char *)&v[0]->ui[4], vbcolor[e0] ); TDFX_COLOR( (char *)&v[1]->ui[4], vbcolor[e1] ); TDFX_COLOR( (char *)&v[2]->ui[4], vbcolor[e2] ); } } #endif #if (IND & TDFX_OFFSET_BIT) { offset = ctx->Polygon.OffsetUnits; z[0] = v[0]->v.z; z[1] = v[1]->v.z; z[2] = v[2]->v.z; if (cc * cc > 1e-16) { GLfloat ez = z[0] - z[2]; GLfloat fz = z[1] - z[2]; GLfloat a = ey*fz - ez*fy; GLfloat b = ez*fx - ex*fz; GLfloat ic = 1.0 / cc; GLfloat ac = a * ic; GLfloat bc = b * ic; if ( ac < 0.0f ) ac = -ac; if ( bc < 0.0f ) bc = -bc; offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor; } v[0]->v.z += offset; v[1]->v.z += offset; v[2]->v.z += offset; } #endif } #elif (IND & TDFX_FLAT_BIT) { GLuint color = fxverts[pv].ui[4]; v[0]->ui[4] = color; v[1]->ui[4] = color; v[2]->ui[4] = color; } #endif #if (IND & TDFX_CLIPRECT_BIT) BEGIN_CLIP_LOOP_LOCKED( fxMesa ); fxMesa->Glide.grDrawTriangle( v[0], v[1], v[2] ); END_CLIP_LOOP_LOCKED( fxMesa ); #else fxMesa->Glide.grDrawTriangle( v[0], v[1], v[2] ); #endif #if (IND & TDFX_OFFSET_BIT) v[0]->v.z = z[0]; v[1]->v.z = z[1]; v[2]->v.z = z[2]; #endif #if (IND & (TDFX_FLAT_BIT | TDFX_TWOSIDE_BIT)) v[0]->ui[4] = c[0]; v[1]->ui[4] = c[1]; v[2]->ui[4] = c[2]; #endif } static __inline void TAG(quad)( GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2, GLuint e3, GLuint pv ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); struct vertex_buffer *VB = ctx->VB; tdfxVertexPtr fxverts = TDFX_DRIVER_DATA(VB)->verts; tdfxVertex *v[4]; #if (IND & TDFX_OFFSET_BIT) GLfloat offset; GLfloat z[4]; #endif #if (IND & (TDFX_TWOSIDE_BIT | TDFX_FLAT_BIT)) GLuint c[4]; #endif v[0] = &fxverts[e0]; v[1] = &fxverts[e1]; v[2] = &fxverts[e2]; v[3] = &fxverts[e3]; /* fprintf(stderr, "%s\n", __FUNCTION__); */ #if (IND & (TDFX_TWOSIDE_BIT | TDFX_FLAT_BIT)) c[0] = v[0]->ui[4]; c[1] = v[1]->ui[4]; c[2] = v[2]->ui[4]; c[3] = v[3]->ui[4]; #endif #if (IND & (TDFX_TWOSIDE_BIT | TDFX_OFFSET_BIT)) { GLfloat ex = v[0]->v.x - v[2]->v.x; GLfloat ey = v[0]->v.y - v[2]->v.y; GLfloat fx = v[1]->v.x - v[2]->v.x; GLfloat fy = v[1]->v.y - v[2]->v.y; GLfloat cc = ex*fy - ey*fx; #if (IND & TDFX_TWOSIDE_BIT) { GLuint facing = ( cc < 0.0 ) ^ ctx->Polygon.FrontBit; GLubyte (*vbcolor)[4] = VB->Color[facing]->data; if (IND & TDFX_FLAT_BIT) { TDFX_COLOR( (char *)&v[0]->ui[4], vbcolor[pv] ); v[3]->ui[4] = v[2]->ui[4] = v[1]->ui[4] = v[0]->ui[4]; } else { TDFX_COLOR( (char *)&v[0]->ui[4], vbcolor[e0] ); TDFX_COLOR( (char *)&v[1]->ui[4], vbcolor[e1] ); TDFX_COLOR( (char *)&v[2]->ui[4], vbcolor[e2] ); TDFX_COLOR( (char *)&v[3]->ui[4], vbcolor[e3] ); } } #endif #if (IND & TDFX_OFFSET_BIT) { offset = ctx->Polygon.OffsetUnits; z[0] = v[0]->v.z; z[1] = v[1]->v.z; z[2] = v[2]->v.z; z[3] = v[3]->v.z; if (cc * cc > 1e-16) { GLfloat ez = z[0] - z[2]; GLfloat fz = z[1] - z[2]; GLfloat a = ey*fz - ez*fy; GLfloat b = ez*fx - ex*fz; GLfloat ic = 1.0 / cc; GLfloat ac = a * ic; GLfloat bc = b * ic; if ( ac < 0.0f ) ac = -ac; if ( bc < 0.0f ) bc = -bc; offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor; } v[0]->v.z += offset; v[1]->v.z += offset; v[2]->v.z += offset; v[3]->v.z += offset; } #endif } #elif (IND & TDFX_FLAT_BIT) { GLuint color = fxverts[pv].ui[4]; v[0]->ui[4] = color; v[1]->ui[4] = color; v[2]->ui[4] = color; v[3]->ui[4] = color; } #endif /* Marginally faster to call grDrawTriangle twice * than calling grDrawVertexArray. */ #if (IND & TDFX_CLIPRECT_BIT) BEGIN_CLIP_LOOP_LOCKED( fxMesa ); /* grDrawVertexArray( GR_TRIANGLE_FAN, 4, v ); */ fxMesa->Glide.grDrawTriangle( v[0], v[1], v[3] ); fxMesa->Glide.grDrawTriangle( v[1], v[2], v[3] ); END_CLIP_LOOP_LOCKED( fxMesa ); #else /* grDrawVertexArray( GR_TRIANGLE_FAN, 4, v ); */ fxMesa->Glide.grDrawTriangle( v[0], v[1], v[3] ); fxMesa->Glide.grDrawTriangle( v[1], v[2], v[3] ); #endif #if (IND & TDFX_OFFSET_BIT) v[0]->v.z = z[0]; v[1]->v.z = z[1]; v[2]->v.z = z[2]; v[3]->v.z = z[3]; #endif #if (IND & (TDFX_FLAT_BIT | TDFX_TWOSIDE_BIT)) v[0]->ui[4] = c[0]; v[1]->ui[4] = c[1]; v[2]->ui[4] = c[2]; v[3]->ui[4] = c[3]; #endif } static __inline void TAG(line)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint pv ) { tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); tdfxVertexPtr fxVB = TDFX_DRIVER_DATA(ctx->VB)->verts; float width = ctx->Line.Width; GLfloat z0, z1; GLuint c0, c1; tdfxVertex *vert0 = &fxVB[v0]; tdfxVertex *vert1 = &fxVB[v1]; if ( IND & TDFX_TWOSIDE_BIT ) { GLubyte (*vbcolor)[4] = ctx->VB->ColorPtr->data; if ( IND & TDFX_FLAT_BIT ) { TDFX_COLOR( (char *)&vert0->v.color,vbcolor[pv] ); *(int *)&vert1->v.color = *(int *)&vert0->v.color; } else { TDFX_COLOR( (char *)&vert0->v.color,vbcolor[v0] ); TDFX_COLOR( (char *)&vert1->v.color,vbcolor[v1] ); } } else if ( IND & TDFX_FLAT_BIT ) { c0 = *(GLuint *) &(vert0->v.color); c1 = *(GLuint *) &(vert1->v.color); *(int *)&vert0->v.color = *(int *)&vert1->v.color = *(int *)&fxVB[pv].v.color; } if ( IND & TDFX_OFFSET_BIT ) { GLfloat offset = ctx->LineZoffset; z0 = vert0->v.z; z1 = vert1->v.z; vert0->v.z += offset; vert1->v.z += offset; } if (IND & TDFX_CLIPRECT_BIT) { BEGIN_CLIP_LOOP_LOCKED( fxMesa ); tdfx_draw_line( fxMesa, &fxVB[v0], &fxVB[v1], width ); END_CLIP_LOOP_LOCKED( fxMesa ); } else tdfx_draw_line( fxMesa, &fxVB[v0], &fxVB[v1], width ); if ( IND & TDFX_OFFSET_BIT ) { vert0->v.z = z0; vert1->v.z = z1; } if ( (IND & TDFX_FLAT_BIT) && !(IND & TDFX_TWOSIDE_BIT) ) { *(GLuint *) &(vert0->v.color) = c0; *(GLuint *) &(vert1->v.color) = c1; } } static __inline void TAG(points)( GLcontext *ctx, GLuint first, GLuint last ) { tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); struct vertex_buffer *VB = ctx->VB; tdfxVertexPtr fxVB = TDFX_DRIVER_DATA(VB)->verts; GLfloat sz = ctx->Point.Size; int i; for ( i = first ; i < last ; i++ ) { if ( VB->ClipMask[i] == 0 ) { if ( IND & (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT) ) { tdfxVertex tmp0 = fxVB[i]; if ( IND & TDFX_TWOSIDE_BIT ) { GLubyte (*vbcolor)[4] = VB->ColorPtr->data; TDFX_COLOR( (char *)&tmp0.v.color, vbcolor[i] ); } if ( IND & TDFX_OFFSET_BIT ) { GLfloat offset = ctx->PointZoffset; tmp0.v.z += offset; } if (IND & TDFX_CLIPRECT_BIT) { BEGIN_CLIP_LOOP_LOCKED( fxMesa ); tdfx_draw_point( fxMesa, &tmp0, sz ); END_CLIP_LOOP_LOCKED( fxMesa ); } else tdfx_draw_point( fxMesa, &tmp0, sz ); } else if (IND & TDFX_CLIPRECT_BIT) { BEGIN_CLIP_LOOP_LOCKED( fxMesa ); tdfx_draw_point( fxMesa, &fxVB[i], sz ); END_CLIP_LOOP_LOCKED( fxMesa ); } else tdfx_draw_point( fxMesa, &fxVB[i], sz ); } } } /* Accelerate unclipped VB rendering when fxMesa->renderIndex != 0 * * The versions for renderIndex == 0 are further optimized and appear * in tdfx_tris.c */ #if (TYPE == 0) #define RENDER_POINTS( start, count ) TAG(points)( ctx, start, count ) #define RENDER_LINE( i1, i ) TAG(line)( ctx, i1, i, i ) #define RENDER_TRI( i2, i1, i, pv, parity ) \ do { \ if (parity) TAG(triangle)( ctx, i1, i2, i, pv ); \ else TAG(triangle)( ctx, i2, i1, i, pv ); \ } while (0) #define RENDER_QUAD( i3, i2, i1, i, pv ) TAG(quad)( ctx, i3, i2, i1, i, pv ) #define LOCAL_VARS GLcontext *ctx = VB->ctx; #define PRESERVE_TAG #include "render_tmp.h" #endif static void TAG(init)( void ) { rast_tab[IND].triangle = TAG(triangle); rast_tab[IND].quad = TAG(quad); rast_tab[IND].line = TAG(line); rast_tab[IND].points = TAG(points); #if (TYPE == 0) rast_tab[IND].render_tab = TAG(render_tab); #else rast_tab[IND].render_tab = 0; #endif TAG(render_init)(); } #undef IND #undef TAG