/* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, * 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 NON-INFRINGEMENT. IN NO EVENT SHALL * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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. */ #if HAVE_RGBA #define VERT_SET_IND(v, c) (void)c #define VERT_COPY_IND(v0, v1) #define VERT_SAVE_IND(idx) #define VERT_RESTORE_IND(idx) #if HAVE_BACK_COLORS #define VERT_SET_RGBA(v, c) #endif #else #define VERT_SET_RGBA(v, c) (void)c #define VERT_COPY_RGBA(v0, v1) #define VERT_SAVE_RGBA(idx) #define VERT_RESTORE_RGBA(idx) #if HAVE_BACK_COLORS #define VERT_SET_IND(v, c) #endif #endif #if !HAVE_SPEC #define VERT_SET_SPEC(v, c) (void)c #define VERT_COPY_SPEC(v0, v1) #define VERT_SAVE_SPEC(idx) #define VERT_RESTORE_SPEC(idx) #if HAVE_BACK_COLORS #define VERT_COPY_SPEC1(v) #endif #else #if HAVE_BACK_COLORS #define VERT_SET_SPEC(v, c) #endif #endif #if !HAVE_BACK_COLORS #define VERT_COPY_SPEC1(v) #define VERT_COPY_IND1(v) #define VERT_COPY_RGBA1(v) #endif #ifndef INSANE_VERTICES #define VERT_SET_Z(v, val) VERT_Z(v) = val #define VERT_Z_ADD(v, val) VERT_Z(v) += val #endif #if DO_TRI static void TAG(triangle)(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; VERTEX *v[3]; GLfloat offset; GLfloat z[3]; GLenum mode = GL_FILL; GLuint facing; LOCAL_VARS(3); #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__); #endif #ifdef PERFORMANCE_MEASURE if (VIA_PERFORMANCE) P_M; #endif v[0] = (VERTEX *)GET_VERTEX(e0); v[1] = (VERTEX *)GET_VERTEX(e1); v[2] = (VERTEX *)GET_VERTEX(e2); if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED) { GLfloat ex = VERT_X(v[0]) - VERT_X(v[2]); GLfloat ey = VERT_Y(v[0]) - VERT_Y(v[2]); GLfloat fx = VERT_X(v[1]) - VERT_X(v[2]); GLfloat fy = VERT_Y(v[1]) - VERT_Y(v[2]); GLfloat cc = ex * fy - ey * fx; if (DO_TWOSIDE || DO_UNFILLED) { facing = AREA_IS_CCW(cc) ^ ctx->Polygon._FrontBit; if (DO_UNFILLED) { if (facing) { mode = ctx->Polygon.BackMode; if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode != GL_FRONT) { return; } } else { mode = ctx->Polygon.FrontMode; if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode != GL_BACK) { return; } } } if (DO_TWOSIDE && facing == 1) { if (HAVE_RGBA) { if (HAVE_BACK_COLORS) { if (!DO_FLAT) { VERT_SAVE_RGBA(0); VERT_SAVE_RGBA(1); VERT_COPY_RGBA1(v[0]); VERT_COPY_RGBA1(v[1]); } VERT_SAVE_RGBA(2); VERT_COPY_RGBA1(v[2]); if (HAVE_SPEC) { if (!DO_FLAT) { VERT_SAVE_SPEC(0); VERT_SAVE_SPEC(1); VERT_COPY_SPEC1(v[0]); VERT_COPY_SPEC1(v[1]); } VERT_SAVE_SPEC(2); VERT_COPY_SPEC1(v[2]); } } else { GLfloat (*vbcolor)[4] = VB->ColorPtr[1]->data; ASSERT(VB->ColorPtr[1]->stride == 4*sizeof(GLfloat)); (void)vbcolor; if (!DO_FLAT) { VERT_SAVE_RGBA(0); VERT_SAVE_RGBA(1); VERT_SET_RGBA(v[0], vbcolor[e0]); VERT_SET_RGBA(v[1], vbcolor[e1]); } VERT_SAVE_RGBA(2); VERT_SET_RGBA(v[2], vbcolor[e2]); if (HAVE_SPEC && VB->SecondaryColorPtr[1]) { GLfloat (*vbspec)[4] = VB->SecondaryColorPtr[1]->data; if (!DO_FLAT) { VERT_SAVE_SPEC(0); VERT_SAVE_SPEC(1); VERT_SET_SPEC(v[0], vbspec[e0]); VERT_SET_SPEC(v[1], vbspec[e1]); } VERT_SAVE_SPEC(2); VERT_SET_SPEC(v[2], vbspec[e2]); } } } else { GLfloat *vbindex = (GLfloat*) VB->IndexPtr[1]->data; if (!DO_FLAT) { VERT_SAVE_IND( 0 ); VERT_SAVE_IND( 1 ); VERT_SET_IND(v[0], vbindex[e0]); VERT_SET_IND(v[1], vbindex[e1]); } VERT_SAVE_IND( 2 ); VERT_SET_IND(v[2], vbindex[e2]); } } } if (DO_OFFSET) { offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE; z[0] = VERT_Z(v[0]); z[1] = VERT_Z(v[1]); z[2] = VERT_Z(v[2]); if (cc * cc > 1e-16) { GLfloat ic = 1.0 / cc; 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 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; } offset *= ctx->MRD; } } if (DO_FLAT) { if (HAVE_RGBA) { VERT_SAVE_RGBA(0); VERT_SAVE_RGBA(1); VERT_COPY_RGBA(v[0], v[2]); VERT_COPY_RGBA(v[1], v[2]); if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { VERT_SAVE_SPEC(0); VERT_SAVE_SPEC(1); VERT_COPY_SPEC(v[0], v[2]); VERT_COPY_SPEC(v[1], v[2]); } } else { VERT_SAVE_IND(0); VERT_SAVE_IND(1); VERT_COPY_IND(v[0], v[2]); VERT_COPY_IND(v[1], v[2]); } } if (mode == GL_POINT) { if (DO_OFFSET && ctx->Polygon.OffsetPoint) { VERT_Z_ADD(v[0], offset); VERT_Z_ADD(v[1], offset); VERT_Z_ADD(v[2], offset); } UNFILLED_TRI(ctx, GL_POINT, e0, e1, e2); } else if (mode == GL_LINE) { if (DO_OFFSET && ctx->Polygon.OffsetLine) { VERT_Z_ADD(v[0], offset); VERT_Z_ADD(v[1], offset); VERT_Z_ADD(v[2], offset); } UNFILLED_TRI(ctx, GL_LINE, e0, e1, e2); } else { if (DO_OFFSET && ctx->Polygon.OffsetFill) { VERT_Z_ADD(v[0], offset); VERT_Z_ADD(v[1], offset); VERT_Z_ADD(v[2], offset); } if (DO_UNFILLED) RASTERIZE(GL_TRIANGLES); TRI(v[0], v[1], v[2]); } if (DO_OFFSET) { VERT_SET_Z(v[0], z[0]); VERT_SET_Z(v[1], z[1]); VERT_SET_Z(v[2], z[2]); } if (DO_TWOSIDE && facing == 1) { if (HAVE_RGBA) { if (!DO_FLAT) { VERT_RESTORE_RGBA(0); VERT_RESTORE_RGBA(1); } VERT_RESTORE_RGBA(2); if (HAVE_SPEC) { if (!DO_FLAT) { VERT_RESTORE_SPEC(0); VERT_RESTORE_SPEC(1); } VERT_RESTORE_SPEC(2); } } else { if (!DO_FLAT) { VERT_RESTORE_IND( 0 ); VERT_RESTORE_IND( 1 ); } VERT_RESTORE_IND( 2 ); } } if (DO_FLAT) { if (HAVE_RGBA) { VERT_RESTORE_RGBA(0); VERT_RESTORE_RGBA(1); if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { VERT_RESTORE_SPEC(0); VERT_RESTORE_SPEC(1); } } else { VERT_RESTORE_IND(0); VERT_RESTORE_IND(1); } } SET_PRIMITIVE_RENDERED #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__); #endif } #endif #if DO_QUAD #if DO_FULL_QUAD static void TAG(quad)(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2, GLuint e3) { struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; VERTEX *v[4]; GLfloat offset; GLfloat z[4]; GLenum mode = GL_FILL; GLuint facing; LOCAL_VARS(4); #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__); #endif #ifdef PERFORMANCE_MEASURE if (VIA_PERFORMANCE) P_M; #endif v[0] = (VERTEX *)GET_VERTEX(e0); v[1] = (VERTEX *)GET_VERTEX(e1); v[2] = (VERTEX *)GET_VERTEX(e2); v[3] = (VERTEX *)GET_VERTEX(e3); if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED) { GLfloat ex = VERT_X(v[2]) - VERT_X(v[0]); GLfloat ey = VERT_Y(v[2]) - VERT_Y(v[0]); GLfloat fx = VERT_X(v[3]) - VERT_X(v[1]); GLfloat fy = VERT_Y(v[3]) - VERT_Y(v[1]); GLfloat cc = ex * fy - ey * fx; if (DO_TWOSIDE || DO_UNFILLED) { facing = AREA_IS_CCW(cc) ^ ctx->Polygon._FrontBit; if (DO_UNFILLED) { if (facing) { mode = ctx->Polygon.BackMode; if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode != GL_FRONT) { return; } } else { mode = ctx->Polygon.FrontMode; if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode != GL_BACK) { return; } } } if (DO_TWOSIDE && facing == 1) { if (HAVE_RGBA) { GLfloat (*vbcolor)[4] = VB->ColorPtr[1]->data; (void)vbcolor; if (HAVE_BACK_COLORS) { if (!DO_FLAT) { VERT_SAVE_RGBA(0); VERT_SAVE_RGBA(1); VERT_SAVE_RGBA(2); VERT_COPY_RGBA1(v[0]); VERT_COPY_RGBA1(v[1]); VERT_COPY_RGBA1(v[2]); } VERT_SAVE_RGBA(3); VERT_COPY_RGBA1(v[3]); if (HAVE_SPEC) { if (!DO_FLAT) { VERT_SAVE_SPEC(0); VERT_SAVE_SPEC(1); VERT_SAVE_SPEC(2); VERT_COPY_SPEC1(v[0]); VERT_COPY_SPEC1(v[1]); VERT_COPY_SPEC1(v[2]); } VERT_SAVE_SPEC(3); VERT_COPY_SPEC1(v[3]); } } else { if (!DO_FLAT) { VERT_SAVE_RGBA(0); VERT_SAVE_RGBA(1); VERT_SAVE_RGBA(2); VERT_SET_RGBA(v[0], vbcolor[e0]); VERT_SET_RGBA(v[1], vbcolor[e1]); VERT_SET_RGBA(v[2], vbcolor[e2]); } VERT_SAVE_RGBA(3); VERT_SET_RGBA(v[3], vbcolor[e3]); if (HAVE_SPEC && VB->SecondaryColorPtr[1]) { GLfloat (*vbspec)[4] = VB->SecondaryColorPtr[1]->data; ASSERT(VB->SecondaryColorPtr[1]->stride==4*sizeof(GLfloat)); if (!DO_FLAT) { VERT_SAVE_SPEC(0); VERT_SAVE_SPEC(1); VERT_SAVE_SPEC(2); VERT_SET_SPEC(v[0], vbspec[e0]); VERT_SET_SPEC(v[1], vbspec[e1]); VERT_SET_SPEC(v[2], vbspec[e2]); } VERT_SAVE_SPEC(3); VERT_SET_SPEC(v[3], vbspec[e3]); } } } else { GLfloat *vbindex = (GLfloat*) VB->IndexPtr[1]->data; if (!DO_FLAT) { VERT_SAVE_IND( 0 ); VERT_SAVE_IND( 1 ); VERT_SAVE_IND( 2 ); VERT_SET_IND(v[0], vbindex[e0]); VERT_SET_IND(v[1], vbindex[e1]); VERT_SET_IND(v[2], vbindex[e2]); } VERT_SAVE_IND( 3 ); VERT_SET_IND(v[3], vbindex[e3]); } } } if (DO_OFFSET) { offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE; z[0] = VERT_Z(v[0]); z[1] = VERT_Z(v[1]); z[2] = VERT_Z(v[2]); z[3] = VERT_Z(v[3]); if (cc * cc > 1e-16) { GLfloat ez = z[2] - z[0]; GLfloat fz = z[3] - z[1]; 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; } offset *= ctx->MRD; } } if (DO_FLAT) { if (HAVE_RGBA) { VERT_SAVE_RGBA(0); VERT_SAVE_RGBA(1); VERT_SAVE_RGBA(2); VERT_COPY_RGBA(v[0], v[3]); VERT_COPY_RGBA(v[1], v[3]); VERT_COPY_RGBA(v[2], v[3]); if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { VERT_SAVE_SPEC(0); VERT_SAVE_SPEC(1); VERT_SAVE_SPEC(2); VERT_COPY_SPEC(v[0], v[3]); VERT_COPY_SPEC(v[1], v[3]); VERT_COPY_SPEC(v[2], v[3]); } } else { VERT_SAVE_IND(0); VERT_SAVE_IND(1); VERT_SAVE_IND(2); VERT_COPY_IND(v[0], v[3]); VERT_COPY_IND(v[1], v[3]); VERT_COPY_IND(v[2], v[3]); } } if (mode == GL_POINT) { if (( DO_OFFSET) && ctx->Polygon.OffsetPoint) { VERT_Z_ADD(v[0], offset); VERT_Z_ADD(v[1], offset); VERT_Z_ADD(v[2], offset); VERT_Z_ADD(v[3], offset); } UNFILLED_QUAD(ctx, GL_POINT, e0, e1, e2, e3); } else if (mode == GL_LINE) { if (DO_OFFSET && ctx->Polygon.OffsetLine) { VERT_Z_ADD(v[0], offset); VERT_Z_ADD(v[1], offset); VERT_Z_ADD(v[2], offset); VERT_Z_ADD(v[3], offset); } UNFILLED_QUAD(ctx, GL_LINE, e0, e1, e2, e3); } else { if (DO_OFFSET && ctx->Polygon.OffsetFill) { VERT_Z_ADD(v[0], offset); VERT_Z_ADD(v[1], offset); VERT_Z_ADD(v[2], offset); VERT_Z_ADD(v[3], offset); } RASTERIZE(GL_TRIANGLES); QUAD((v[0]), (v[1]), (v[2]), (v[3])); } if (DO_OFFSET) { VERT_SET_Z(v[0], z[0]); VERT_SET_Z(v[1], z[1]); VERT_SET_Z(v[2], z[2]); VERT_SET_Z(v[3], z[3]); } if (DO_TWOSIDE && facing == 1) { if (HAVE_RGBA) { if (!DO_FLAT) { VERT_RESTORE_RGBA(0); VERT_RESTORE_RGBA(1); VERT_RESTORE_RGBA(2); } VERT_RESTORE_RGBA(3); if (HAVE_SPEC) { if (!DO_FLAT) { VERT_RESTORE_SPEC(0); VERT_RESTORE_SPEC(1); VERT_RESTORE_SPEC(2); } VERT_RESTORE_SPEC(3); } } else { if (!DO_FLAT) { VERT_RESTORE_IND( 0 ); VERT_RESTORE_IND( 1 ); VERT_RESTORE_IND( 2 ); } VERT_RESTORE_IND( 3 ); } } if (DO_FLAT) { if (HAVE_RGBA) { VERT_RESTORE_RGBA(0); VERT_RESTORE_RGBA(1); VERT_RESTORE_RGBA(2); if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { VERT_RESTORE_SPEC(0); VERT_RESTORE_SPEC(1); VERT_RESTORE_SPEC(2); } } else { VERT_RESTORE_IND(0); VERT_RESTORE_IND(1); VERT_RESTORE_IND(2); } } #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__); #endif } #else static void TAG(quad)(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2, GLuint e3) { #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__); #endif #ifdef PERFORMANCE_MEASURE if (VIA_PERFORMANCE) P_M; #endif if (DO_UNFILLED) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; GLubyte ef1 = VB->EdgeFlag[e1]; GLubyte ef3 = VB->EdgeFlag[e3]; VB->EdgeFlag[e1] = 0; TAG(triangle)(ctx, e0, e1, e3); VB->EdgeFlag[e1] = ef1; VB->EdgeFlag[e3] = 0; TAG(triangle)(ctx, e1, e2, e3); VB->EdgeFlag[e3] = ef3; } else { TAG(triangle)(ctx, e0, e1, e3); TAG(triangle)(ctx, e1, e2, e3); } #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__); #endif } #endif #endif #if DO_LINE static void TAG(line)(GLcontext *ctx, GLuint e0, GLuint e1) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; VERTEX *v[2]; LOCAL_VARS(2); #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__); #endif #ifdef PERFORMANCE_MEASURE if (VIA_PERFORMANCE) P_M; #endif v[0] = (VERTEX *)GET_VERTEX(e0); v[1] = (VERTEX *)GET_VERTEX(e1); if (DO_FLAT) { if (HAVE_RGBA) { VERT_SAVE_RGBA( 0 ); VERT_COPY_RGBA( v[0], v[1] ); if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { VERT_SAVE_SPEC(0); VERT_COPY_SPEC(v[0], v[1]); } } else { VERT_SAVE_IND(0); VERT_COPY_IND(v[0], v[1]); } } LINE(v[0], v[1]); if (DO_FLAT) { if (HAVE_RGBA) { VERT_RESTORE_RGBA(0); if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { VERT_RESTORE_SPEC(0); } } else { VERT_RESTORE_IND(0); } } SET_PRIMITIVE_RENDERED #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__); #endif } #endif #if DO_POINTS static void TAG(points)(GLcontext *ctx, GLuint first, GLuint last) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; int i; LOCAL_VARS(1); #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__); #endif #ifdef PERFORMANCE_MEASURE if (VIA_PERFORMANCE) P_M; #endif if (VB->Elts == 0) { for (i = first; i < last; i++) { if (VB->ClipMask[i] == 0) { VERTEX *v = (VERTEX *)GET_VERTEX(i); POINT(v); SET_PRIMITIVE_RENDERED } } } else { for (i = first; i < last; i++) { GLuint e = VB->Elts[i]; if (VB->ClipMask[e] == 0) { VERTEX *v = (VERTEX *)GET_VERTEX(e); POINT(v); SET_PRIMITIVE_RENDERED } } } #ifdef DEBUG if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__); #endif } #endif static void TAG(init)(void) { #if DO_QUAD TAB[IND].quad = TAG(quad); #endif #if DO_TRI TAB[IND].triangle = TAG(triangle); #endif #if DO_LINE TAB[IND].line = TAG(line); #endif #if DO_POINTS TAB[IND].points = TAG(points); #endif } #undef IND #undef TAG #if HAVE_RGBA #undef VERT_SET_IND #undef VERT_COPY_IND #undef VERT_SAVE_IND #undef VERT_RESTORE_IND #if HAVE_BACK_COLORS #undef VERT_SET_RGBA #endif #else #undef VERT_SET_RGBA #undef VERT_COPY_RGBA #undef VERT_SAVE_RGBA #undef VERT_RESTORE_RGBA #if HAVE_BACK_COLORS #undef VERT_SET_IND #endif #endif #if !HAVE_SPEC #undef VERT_SET_SPEC #undef VERT_COPY_SPEC #undef VERT_SAVE_SPEC #undef VERT_RESTORE_SPEC #if HAVE_BACK_COLORS #undef VERT_COPY_SPEC1 #endif #else #if HAVE_BACK_COLORS #undef VERT_SET_SPEC #endif #endif #if !HAVE_BACK_COLORS #undef VERT_COPY_SPEC1 #undef VERT_COPY_IND1 #undef VERT_COPY_RGBA1 #endif #ifndef INSANE_VERTICES #undef VERT_SET_Z #undef VERT_Z_ADD #endif