diff options
Diffstat (limited to 'src/mesa/tnl')
-rw-r--r-- | src/mesa/tnl/t_array_import.c | 14 | ||||
-rw-r--r-- | src/mesa/tnl/t_context.c | 7 | ||||
-rw-r--r-- | src/mesa/tnl/t_context.h | 17 | ||||
-rw-r--r-- | src/mesa/tnl/t_imm_api.c | 2 | ||||
-rw-r--r-- | src/mesa/tnl/t_imm_exec.c | 13 | ||||
-rw-r--r-- | src/mesa/tnl/t_pipeline.h | 8 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_cliptmp.h | 558 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_render.c | 416 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_rendertmp.h | 86 |
9 files changed, 454 insertions, 667 deletions
diff --git a/src/mesa/tnl/t_array_import.c b/src/mesa/tnl/t_array_import.c index fc2c3d1944..008cc23c64 100644 --- a/src/mesa/tnl/t_array_import.c +++ b/src/mesa/tnl/t_array_import.c @@ -1,4 +1,4 @@ -/* $Id: t_array_import.c,v 1.3 2000/12/28 22:11:05 keithw Exp $ */ +/* $Id: t_array_import.c,v 1.4 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -301,11 +301,6 @@ static void _tnl_upgrade_client_data( GLcontext *ctx, _tnl_import_texcoord( ctx, i, writeable, stride ); } - if ((required & VERT_EDGE) && (VB->EdgeFlagPtr->flags & flags)) { - ASSERT(VB->EdgeFlagPtr == &inputs->EdgeFlag); - _tnl_import_edgeflag( ctx, writeable, stride ); - } - VB->importable_data &= ~required; } @@ -386,11 +381,8 @@ void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count ) } if (inputs & VERT_EDGE) { - if (imports & VERT_EDGE) { - _tnl_import_edgeflag( ctx, 0, 0 ); - tmp->EdgeFlag.count = VB->Count; - } - VB->EdgeFlagPtr = &tmp->EdgeFlag; + _tnl_import_edgeflag( ctx, GL_TRUE, sizeof(GLboolean) ); + VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag.data; } if (inputs & VERT_SPEC_RGB) { diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c index 5b879d8a83..7d04210eb6 100644 --- a/src/mesa/tnl/t_context.c +++ b/src/mesa/tnl/t_context.c @@ -1,4 +1,4 @@ -/* $Id: t_context.c,v 1.7 2000/12/26 05:09:32 keithw Exp $ */ +/* $Id: t_context.c,v 1.8 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -69,6 +69,9 @@ install_driver_callbacks( GLcontext *ctx ) ctx->Driver.MakeCurrent = _tnl_MakeCurrent; ctx->Driver.BeginCallList = _tnl_BeginCallList; ctx->Driver.EndCallList = _tnl_EndCallList; + + ctx->Driver.RenderTabElts = _tnl_render_tab_elts; + ctx->Driver.RenderTabVerts = _tnl_render_tab_verts; } @@ -111,7 +114,7 @@ _tnl_CreateContext( GLcontext *ctx ) /* Set a few default values in the driver struct. */ install_driver_callbacks(ctx); - ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT|FLUSH_STORED_VERTICES; + ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT; ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index 62d260681c..8e3952a412 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -1,4 +1,4 @@ -/* $Id: t_context.h,v 1.8 2000/12/27 22:30:29 keithw Exp $ */ +/* $Id: t_context.h,v 1.9 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -226,6 +226,12 @@ struct vertex_arrays typedef struct gl_material GLmaterial; +typedef void (*interp_func)( GLcontext *ctx, + GLfloat t, GLuint dst, GLuint in, GLuint out, + GLboolean force_boundary ); + +typedef void (*copy_pv_func)( GLcontext *ctx, GLuint dst, GLuint src ); + /* Contains the current state of a running pipeline. */ typedef struct vertex_buffer @@ -251,7 +257,7 @@ typedef struct vertex_buffer GLubyte *ClipMask; /* VERT_CLIP (4) */ GLvector3f *NormalPtr; /* VERT_NORM */ GLfloat *NormalLengthPtr; /* VERT_NORM (optional) */ - GLvector1ub *EdgeFlagPtr; /* VERT_EDGE */ + GLboolean *EdgeFlag; /* VERT_EDGE */ GLvector4f *TexCoordPtr[MAX_TEXTURE_UNITS]; /* VERT_TEX_0..n */ GLvector1ui *IndexPtr[2]; /* VERT_INDEX */ GLvector4ub *ColorPtr[2]; /* VERT_RGBA */ @@ -276,9 +282,10 @@ typedef struct vertex_buffer */ GLuint LastClipped; - void *interpfunc; - /* Two pieces of private data from _tnl_render_stage that have no - * business being in this struct. + interp_func interpfunc; + copy_pv_func copypvfunc; + /* Private data from _tnl_render_stage that has no business being + * in this struct. */ } TNLvertexbuffer; diff --git a/src/mesa/tnl/t_imm_api.c b/src/mesa/tnl/t_imm_api.c index 528f101661..aeca38dd4f 100644 --- a/src/mesa/tnl/t_imm_api.c +++ b/src/mesa/tnl/t_imm_api.c @@ -292,7 +292,7 @@ _tnl_end( GLcontext *ctx ) IM->FlushElt = 0; } - ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; +/* ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; */ } IM->BeginState = state; diff --git a/src/mesa/tnl/t_imm_exec.c b/src/mesa/tnl/t_imm_exec.c index 1549fa53af..4bdce0d18d 100644 --- a/src/mesa/tnl/t_imm_exec.c +++ b/src/mesa/tnl/t_imm_exec.c @@ -1,4 +1,4 @@ -/* $Id: t_imm_exec.c,v 1.4 2000/12/28 22:11:05 keithw Exp $ */ +/* $Id: t_imm_exec.c,v 1.5 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -198,7 +198,7 @@ static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM ) VB->NormalPtr = 0; VB->NormalLengthPtr = 0; VB->FogCoordPtr = 0; - VB->EdgeFlagPtr = 0; + VB->EdgeFlag = 0; VB->IndexPtr[0] = 0; VB->IndexPtr[1] = 0; VB->ColorPtr[0] = 0; @@ -259,10 +259,7 @@ static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM ) } if (inputs & VERT_EDGE) { - tmp->EdgeFlag.data = IM->EdgeFlag + start; - tmp->EdgeFlag.start = IM->EdgeFlag + start; - tmp->EdgeFlag.count = count; - VB->EdgeFlagPtr = &tmp->EdgeFlag; + VB->EdgeFlag = IM->EdgeFlag + start; } if (inputs & VERT_RGBA) { @@ -451,8 +448,8 @@ void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM ) */ _tnl_copy_immediate_vertices( ctx, IM ); -/* if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) */ -/* ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; */ + if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) + ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; } diff --git a/src/mesa/tnl/t_pipeline.h b/src/mesa/tnl/t_pipeline.h index 9d433bde0a..3f64eb8ed9 100644 --- a/src/mesa/tnl/t_pipeline.h +++ b/src/mesa/tnl/t_pipeline.h @@ -1,4 +1,4 @@ -/* $Id: t_pipeline.h,v 1.4 2000/12/26 05:09:33 keithw Exp $ */ +/* $Id: t_pipeline.h,v 1.5 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -62,4 +62,10 @@ extern const struct gl_pipeline_stage _tnl_render_stage; */ extern const struct gl_pipeline_stage *_tnl_default_pipeline[]; + +/* Convenience routines provided by t_vb_render.c: + */ +extern render_func _tnl_render_tab_elts[]; +extern render_func _tnl_render_tab_verts[]; + #endif diff --git a/src/mesa/tnl/t_vb_cliptmp.h b/src/mesa/tnl/t_vb_cliptmp.h index 1aeb014e15..5957f4960c 100644 --- a/src/mesa/tnl/t_vb_cliptmp.h +++ b/src/mesa/tnl/t_vb_cliptmp.h @@ -1,4 +1,4 @@ -/* $Id: t_vb_cliptmp.h,v 1.4 2000/12/28 22:11:05 keithw Exp $ */ +/* $Id: t_vb_cliptmp.h,v 1.5 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -28,340 +28,45 @@ */ -#define INSIDE( J ) !NEGATIVE(J) -#define OUTSIDE( J ) NEGATIVE(J) +#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D - - - -static GLuint TAG(userclip_line)( GLcontext *ctx, - GLuint *i, GLuint *j, - interp_func interp ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLfloat (*coord)[4] = VB->ClipPtr->data; - GLuint ii = *i; - GLuint jj = *j; - GLuint p; - - for (p=0;p<MAX_CLIP_PLANES;p++) { - if (ctx->Transform.ClipEnabled[p]) { - GLfloat a = ctx->Transform._ClipUserPlane[p][0]; - GLfloat b = ctx->Transform._ClipUserPlane[p][1]; - GLfloat c = ctx->Transform._ClipUserPlane[p][2]; - GLfloat d = ctx->Transform._ClipUserPlane[p][3]; - - GLfloat dpI = d*W(ii) + c*Z(ii) + b*Y(ii) + a*X(ii); - GLfloat dpJ = d*W(jj) + c*Z(jj) + b*Y(jj) + a*X(jj); - - GLuint flagI = OUTSIDE( dpI ); - GLuint flagJ = OUTSIDE( dpJ ); - - if (flagI ^ flagJ) { - if (flagJ) { - GLfloat t = dpI / (dpI - dpJ); - VB->ClipMask[jj] |= CLIP_USER_BIT; - jj = interp( ctx, t, ii, jj, GL_FALSE ); - VB->ClipMask[jj] = 0; - } else { - GLfloat t = dpJ / (dpJ - dpI); - VB->ClipMask[ii] |= CLIP_USER_BIT; - ii = interp( ctx, t, jj, ii, GL_FALSE ); - VB->ClipMask[ii] = 0; - } - } - else if (flagI) - return 0; - } - } - - *i = ii; - *j = jj; - return 1; -} - - -static GLuint TAG(userclip_polygon)( GLcontext *ctx, - GLuint n, - GLuint vlist[], - interp_func interp ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLfloat (*coord)[4] = VB->ClipPtr->data; - GLuint vlist2[MAX_CLIPPED_VERTICES]; - GLuint *inlist = vlist, *outlist = vlist2; - GLubyte *clipmask = VB->ClipMask; - GLuint p; - -#define CLIP_DOTPROD(xx) d*W(xx) + c*Z(xx) + b*Y(xx) + a*X(xx) - - /* Can be speeded up to if vertex_stage actually saves the - * UserClipMask, and if it is used in this loop (after computing a - * UserClipOrMask). - */ - for (p=0;p<MAX_CLIP_PLANES;p++) { - if (ctx->Transform.ClipEnabled[p]) { - register float a = ctx->Transform._ClipUserPlane[p][0]; - register float b = ctx->Transform._ClipUserPlane[p][1]; - register float c = ctx->Transform._ClipUserPlane[p][2]; - register float d = ctx->Transform._ClipUserPlane[p][3]; - - /* initialize prev to be last in the input list */ - GLuint idxPrev = inlist[n-1]; - GLfloat dpPrev = CLIP_DOTPROD(idxPrev); - GLuint outcount = 0; - GLuint i; - - for (i = 0 ; i < n ; i++) { - GLuint idx = inlist[i]; - GLfloat dp = CLIP_DOTPROD(idx); - - if (!NEGATIVE(dpPrev)) { - outlist[outcount++] = idxPrev; - clipmask[idxPrev] &= ~CLIP_USER_BIT; - } else { - clipmask[idxPrev] |= CLIP_USER_BIT; - } - - - if (DIFFERENT_SIGNS(dp, dpPrev)) { - GLuint newvert; - if (NEGATIVE(dp)) { - /* Going out of bounds. Avoid division by zero as we - * know dp != dpPrev from DIFFERENT_SIGNS, above. - */ - GLfloat t = dp / (dp - dpPrev); - newvert = interp( ctx, t, idx, idxPrev, GL_TRUE ); - } else { - /* Coming back in. - */ - GLfloat t = dpPrev / (dpPrev - dp); - newvert = interp( ctx, t, idxPrev, idx, GL_FALSE ); - } - clipmask[newvert] = 0; - outlist[outcount++] = newvert; - } - - idxPrev = idx; - dpPrev = dp; - } - - if (outcount < 3) - return 0; - - { - GLuint *tmp; - tmp = inlist; - inlist = outlist; - outlist = tmp; - n = outcount; - } - } /* if */ - } /* for p */ - - if (inlist!=vlist) { - GLuint i; - for (i = 0 ; i < n ; i++) - vlist[i] = inlist[i]; - } - - return n; -} - - -/* This now calls the user clip functions if required. - */ -static void TAG(viewclip_line)( GLcontext *ctx, - GLuint i, GLuint j, - GLubyte mask ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - interp_func interp = (interp_func) VB->interpfunc; - GLfloat (*coord)[4] = VB->ClipPtr->data; - GLuint ii = i, jj = j; - GLuint vlist[2]; - GLuint n; - - VB->LastClipped = VB->FirstClipped; - -/* - * We use 6 instances of this code to clip against the 6 planes. - */ -#define GENERAL_CLIP \ - if (mask & PLANE) { \ - GLfloat dpI = CLIP_DOTPROD( ii ); \ - GLfloat dpJ = CLIP_DOTPROD( jj ); \ - \ - if (DIFFERENT_SIGNS(dpI, dpJ)) { \ - if (NEGATIVE(dpJ)) { \ - GLfloat t = dpI / (dpI - dpJ); \ - VB->ClipMask[jj] |= PLANE; \ - jj = interp( ctx, t, ii, jj, GL_FALSE ); \ - VB->ClipMask[jj] = 0; \ - } else { \ - GLfloat t = dpJ / (dpJ - dpI); \ - VB->ClipMask[ii] |= PLANE; \ - ii = interp( ctx, t, jj, ii, GL_FALSE ); \ - VB->ClipMask[ii] = 0; \ - } \ - } \ - else if (NEGATIVE(dpI)) \ - return; \ - } - -#undef CLIP_DOTPROD -#define PLANE CLIP_RIGHT_BIT -#define CLIP_DOTPROD(K) (- X(K) + W(K)) - - GENERAL_CLIP - -#undef CLIP_DOTPROD -#undef PLANE -#define PLANE CLIP_LEFT_BIT -#define CLIP_DOTPROD(K) (X(K) + W(K)) - - GENERAL_CLIP - -#undef CLIP_DOTPROD -#undef PLANE -#define PLANE CLIP_TOP_BIT -#define CLIP_DOTPROD(K) (- Y(K) + W(K)) - - GENERAL_CLIP - -#undef CLIP_DOTPROD -#undef PLANE -#define PLANE CLIP_BOTTOM_BIT -#define CLIP_DOTPROD(K) (Y(K) + W(K)) - - GENERAL_CLIP - -#undef CLIP_DOTPROD -#undef PLANE -#define PLANE CLIP_FAR_BIT -#define CLIP_DOTPROD(K) (- Z(K) + W(K)) - - if (SIZE >= 3) { - GENERAL_CLIP - } - -#undef CLIP_DOTPROD -#undef PLANE -#define PLANE CLIP_NEAR_BIT -#define CLIP_DOTPROD(K) (Z(K) + W(K)) - - if (SIZE >=3 ) { - GENERAL_CLIP - } - -#undef CLIP_DOTPROD -#undef PLANE -#undef GENERAL_CLIP - - - if (mask & CLIP_USER_BIT) { - if ( TAG(userclip_line)( ctx, &ii, &jj, interp ) == 0 ) - return; - } - - vlist[0] = ii; - vlist[1] = jj; - n = 2; - - /* If necessary, project new vertices. - */ - { - GLuint i, j; - GLfloat (*proj)[4] = VB->ProjectedClipPtr->data; - GLuint start = VB->FirstClipped; - - for (i = 0; i < n; i++) { - j = vlist[i]; - if (j >= start) { - if (SIZE == 4 && W(j) != 0.0F) { - GLfloat wInv = 1.0F / W(j); - proj[j][0] = X(j) * wInv; - proj[j][1] = Y(j) * wInv; - proj[j][2] = Z(j) * wInv; - proj[j][3] = wInv; - } else { - proj[j][0] = X(j); - proj[j][1] = Y(j); - proj[j][2] = Z(j); - proj[j][3] = W(j); - } - } - } - } - - if (ctx->Driver.BuildProjectedVertices) - ctx->Driver.BuildProjectedVertices(ctx, - VB->FirstClipped, - VB->LastClipped, - ~0); - - - /* Render the new line. - */ - ctx->Driver.LineFunc( ctx, ii, jj, j ); -} - -/* We now clip polygon triangles individually. This is necessary to - * avoid artifacts dependent on where the boundary of the VB falls - * within the polygon. As a result, there is an upper bound on the - * number of vertices which may be created, and the test against VB_SIZE - * is redundant. - */ -static void TAG(viewclip_polygon)( GLcontext *ctx, - GLuint n, GLuint vlist[], GLuint pv, - GLubyte mask ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - interp_func interp = (interp_func) VB->interpfunc; - GLfloat (*coord)[4] = VB->ClipPtr->data; - GLuint vlist2[MAX_CLIPPED_VERTICES]; - GLuint *inlist = vlist, *outlist = vlist2; - GLuint i; - GLubyte *clipmask = VB->ClipMask; - - VB->LastClipped = VB->FirstClipped; - - if (mask & CLIP_ALL_BITS) { - -#define GENERAL_CLIP \ +#define POLY_CLIP( PLANE, A, B, C, D ) \ +do { \ if (mask & PLANE) { \ - GLuint idxPrev = inlist[n-1]; \ - GLfloat dpPrev = CLIP_DOTPROD(idxPrev); \ + GLuint idxPrev = inlist[0]; \ + GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \ GLuint outcount = 0; \ GLuint i; \ - \ - mask &= ~PLANE; \ - \ - for (i = 0; i < n; i++) { \ + \ + inlist[n] = inlist[0]; /* prevent rotation of vertices */ \ + for (i = 1; i <= n; i++) { \ GLuint idx = inlist[i]; \ - GLfloat dp = CLIP_DOTPROD(idx); \ + GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \ \ + clipmask[idxPrev] |= PLANE; \ if (!NEGATIVE(dpPrev)) { \ outlist[outcount++] = idxPrev; \ clipmask[idxPrev] &= ~PLANE; \ } \ \ if (DIFFERENT_SIGNS(dp, dpPrev)) { \ - GLuint newvert; \ + GLuint newvert = VB->LastClipped++; \ + VB->ClipMask[newvert] = 0; \ + outlist[outcount++] = newvert; \ if (NEGATIVE(dp)) { \ /* Going out of bounds. Avoid division by zero as we \ * know dp != dpPrev from DIFFERENT_SIGNS, above. \ */ \ GLfloat t = dp / (dp - dpPrev); \ - newvert = interp( ctx, t, idx, idxPrev, GL_TRUE ); \ - } else { \ + LINTERP_SZ( t, coord, newvert, idx, idxPrev, SIZE ); \ + interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \ + } else { \ /* Coming back in. \ */ \ GLfloat t = dpPrev / (dpPrev - dp); \ - newvert = interp( ctx, t, idxPrev, idx, GL_FALSE ); \ + LINTERP_SZ( t, coord, newvert, idxPrev, idx, SIZE ); \ + interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \ } \ - clipmask[newvert] = mask; \ - outlist[outcount++] = newvert; \ } \ \ idxPrev = idx; \ @@ -377,125 +82,184 @@ static void TAG(viewclip_polygon)( GLcontext *ctx, outlist = tmp; \ n = outcount; \ } \ - } - - -#define PLANE CLIP_RIGHT_BIT -#define CLIP_DOTPROD(K) (- X(K) + W(K)) - - GENERAL_CLIP - -#undef CLIP_DOTPROD -#undef PLANE - - -#define PLANE CLIP_LEFT_BIT -#define CLIP_DOTPROD(K) (X(K) + W(K)) - - GENERAL_CLIP + } \ +} while (0) + + +#define LINE_CLIP(PLANE, A, B, C, D ) \ +do { \ + if (mask & PLANE) { \ + GLfloat dpI = CLIP_DOTPROD( ii, A, B, C, D ); \ + GLfloat dpJ = CLIP_DOTPROD( jj, A, B, C, D ); \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLuint newvert = VB->LastClipped++; \ + VB->ClipMask[newvert] = 0; \ + if (NEGATIVE(dpJ)) { \ + GLfloat t = dpI / (dpI - dpJ); \ + VB->ClipMask[jj] |= PLANE; \ + LINTERP_SZ( t, coord, newvert, ii, jj, SIZE ); \ + interp( ctx, t, newvert, ii, jj, GL_FALSE ); \ + jj = newvert; \ + } else { \ + GLfloat t = dpJ / (dpJ - dpI); \ + VB->ClipMask[ii] |= PLANE; \ + LINTERP_SZ( t, coord, newvert, jj, ii, SIZE ); \ + interp( ctx, t, newvert, jj, ii, GL_FALSE ); \ + ii = newvert; \ + } \ + } \ + else if (NEGATIVE(dpI)) \ + return; \ + } \ +} while (0) + + +/* Project if necessary. + */ +static void TAG(build_proj_verts)( GLcontext *ctx ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLfloat (*coord)[4] = VB->ClipPtr->data; + GLfloat (*proj)[4] = VB->ProjectedClipPtr->data; + GLuint last = VB->LastClipped; + GLuint i; -#undef CLIP_DOTPROD -#undef PLANE + for (i = VB->FirstClipped; i < last; i++) { + if (VB->ClipMask[i] == 0) { + if (SIZE == 4 && W(i) != 0.0F) { + GLfloat wInv = 1.0F / W(i); + proj[i][0] = X(i) * wInv; + proj[i][1] = Y(i) * wInv; + proj[i][2] = Z(i) * wInv; + proj[i][3] = wInv; + } else { + proj[i][0] = X(i); + proj[i][1] = Y(i); + proj[i][2] = Z(i); + proj[i][3] = W(i); + } + } + } -#define PLANE CLIP_TOP_BIT -#define CLIP_DOTPROD(K) (- Y(K) + W(K)) + ctx->Driver.BuildProjectedVertices(ctx, + VB->FirstClipped, + VB->LastClipped, + ~0); +} - GENERAL_CLIP +/* Clip a line against the viewport and user clip planes. + */ +static void TAG(clip_line)( GLcontext *ctx, + GLuint i, GLuint j, + GLubyte mask ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + interp_func interp = (interp_func) VB->interpfunc; + GLfloat (*coord)[4] = VB->ClipPtr->data; + GLuint ii = i, jj = j, p; -#undef CLIP_DOTPROD -#undef PLANE + VB->LastClipped = VB->FirstClipped; -#define PLANE CLIP_BOTTOM_BIT -#define CLIP_DOTPROD(K) (Y(K) + W(K)) + if (mask & 0x3f) { + LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); + LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); + LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); + LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); + LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); + LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); + } - GENERAL_CLIP + if (mask & CLIP_USER_BIT) { + for (p=0;p<MAX_CLIP_PLANES;p++) { + if (ctx->Transform.ClipEnabled[p]) { + GLfloat a = ctx->Transform._ClipUserPlane[p][0]; + GLfloat b = ctx->Transform._ClipUserPlane[p][1]; + GLfloat c = ctx->Transform._ClipUserPlane[p][2]; + GLfloat d = ctx->Transform._ClipUserPlane[p][3]; + LINE_CLIP( CLIP_USER_BIT, a, b, c, d ); + } + } + } -#undef CLIP_DOTPROD -#undef PLANE + TAG(build_proj_verts)( ctx ); -#define PLANE CLIP_FAR_BIT -#define CLIP_DOTPROD(K) (- Z(K) + W(K)) + if ((ctx->_TriangleCaps & DD_FLATSHADE) && j != jj) + VB->copypvfunc( ctx, jj, j ); - if (SIZE >= 3) { - GENERAL_CLIP - } + /* Render the new line. + */ + ctx->Driver.LineFunc( ctx, ii, jj ); -#undef CLIP_DOTPROD -#undef PLANE +} -#define PLANE CLIP_NEAR_BIT -#define CLIP_DOTPROD(K) (Z(K) + W(K)) - if (SIZE >=3 ) { - GENERAL_CLIP - } +/* Clip a triangle or quad against the viewport and user clip planes. + */ +static void TAG(clip_polygon)( GLcontext *ctx, + GLuint n, GLuint vlist[], + GLubyte mask ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + interp_func interp = (interp_func) VB->interpfunc; + GLfloat (*coord)[4] = VB->ClipPtr->data; + GLuint pv = vlist[0]; + GLuint vlist2[MAX_CLIPPED_VERTICES]; + GLuint *inlist = vlist, *outlist = vlist2; + GLuint p; + GLubyte *clipmask = VB->ClipMask; -#undef CLIP_DOTPROD -#undef PLANE -#undef GENERAL_CLIP + VB->LastClipped = VB->FirstClipped; - if (inlist != vlist) - for (i = 0 ; i < n ; i++) - vlist[i] = inlist[i]; + if (mask & 0x3f) { + POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); + POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); + POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); + POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); + POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); + POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); } - /* Clip against user clipping planes in clip space. - */ if (mask & CLIP_USER_BIT) { - n = TAG(userclip_polygon)( ctx, n, vlist, interp ); - if (n < 3) return; + for (p=0;p<MAX_CLIP_PLANES;p++) { + if (ctx->Transform.ClipEnabled[p]) { + GLfloat a = ctx->Transform._ClipUserPlane[p][0]; + GLfloat b = ctx->Transform._ClipUserPlane[p][1]; + GLfloat c = ctx->Transform._ClipUserPlane[p][2]; + GLfloat d = ctx->Transform._ClipUserPlane[p][3]; + POLY_CLIP( CLIP_USER_BIT, a, b, c, d ); + } + } } - /* Project if necessary. - */ - { - GLuint i; - GLfloat (*proj)[4] = VB->ProjectedClipPtr->data; - GLuint first = VB->FirstClipped; - - for (i = 0; i < n; i++) { - GLuint j = vlist[i]; - if (j >= first) { - if (SIZE == 4 && W(j) != 0.0F) { - GLfloat wInv = 1.0F / W(j); - proj[j][0] = X(j) * wInv; - proj[j][1] = Y(j) * wInv; - proj[j][2] = Z(j) * wInv; - proj[j][3] = wInv; - } else { - proj[j][0] = X(j); - proj[j][1] = Y(j); - proj[j][2] = Z(j); - proj[j][3] = W(j); - } - } + if (ctx->_TriangleCaps & DD_FLATSHADE) { + if (pv != inlist[0]) { + ASSERT( inlist[0] >= VB->FirstClipped ); + VB->copypvfunc( ctx, inlist[0], pv ); } } - if (ctx->Driver.BuildProjectedVertices) - ctx->Driver.BuildProjectedVertices(ctx, - VB->FirstClipped, - VB->LastClipped, - ~0); + TAG(build_proj_verts)( ctx ); /* Render the new vertices as an unclipped polygon. - * Argh - need to pass in pv... */ { GLuint *tmp = VB->Elts; - VB->Elts = vlist; - render_poly_pv_raw_elts( ctx, 0, n, PRIM_BEGIN|PRIM_END, pv ); + VB->Elts = inlist; + ctx->Driver.RenderTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); VB->Elts = tmp; } } + + #undef W #undef Z #undef Y #undef X #undef SIZE #undef TAG -#undef INSIDE -#undef OUTSIDE +#undef POLY_CLIP +#undef LINE_CLIP diff --git a/src/mesa/tnl/t_vb_render.c b/src/mesa/tnl/t_vb_render.c index b3fef23501..2616d294d3 100644 --- a/src/mesa/tnl/t_vb_render.c +++ b/src/mesa/tnl/t_vb_render.c @@ -1,4 +1,4 @@ -/* $Id: t_vb_render.c,v 1.5 2001/01/03 15:59:31 brianp Exp $ */ +/* $Id: t_vb_render.c,v 1.6 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -22,6 +22,9 @@ * 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. + * + * Author: + * Keith Whitwell <keithw@valinux.com> */ @@ -33,11 +36,16 @@ * and triangle rasterizers via the function pointers: * * context->Driver.BuildProjectedVertices() + * * context->Driver.PointsFunc() * context->Driver.LineFunc() * context->Driver.TriangleFunc() * context->Driver.QuadFunc() * + * context->Driver.RenderTabVerts[] + * context->Driver.RenderTabElts[] + * + * None of these may be null. */ @@ -55,9 +63,6 @@ #include "t_pipeline.h" -typedef GLuint (*interp_func)( GLcontext *ctx, - GLfloat t, GLuint in, GLuint out, - GLboolean force_boundary ); typedef void (*clip_line_func)( GLcontext *ctx, GLuint i, GLuint j, @@ -65,13 +70,8 @@ typedef void (*clip_line_func)( GLcontext *ctx, typedef void (*clip_poly_func)( GLcontext *ctx, GLuint n, GLuint vlist[], - GLuint pv, GLubyte mask ); - + GLubyte mask ); -typedef void (*render_func)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ); @@ -79,33 +79,19 @@ struct render_stage_data { /* Clipping functions for current state. */ - interp_func interp; /* Clip interpolation function */ - GLuint _ClipInputs; /* Inputs referenced by interpfunc */ - + interp_func interp; /* Clip interpolation function */ + copy_pv_func copypv; /* Flatshade fixup function */ + GLuint _ClipInputs; /* Inputs referenced by interpfunc */ }; #define RENDER_STAGE_DATA(stage) ((struct render_stage_data *)stage->private) -static void render_poly_pv_raw_elts( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags, - GLuint pv ); /**********************************************************************/ /* Interpolate between pairs of vertices */ /**********************************************************************/ -#define INTERP_RGBA 0x1 -#define INTERP_TEX 0x2 -#define INTERP_INDEX 0x4 -#define INTERP_SPEC 0x8 -#define INTERP_FOG 0x10 -#define INTERP_EDGE 0x20 -#define MAX_INTERP 0x40 - - #define LINTERP_SZ( t, vec, to, a, b, sz ) \ do { \ switch (sz) { \ @@ -146,8 +132,50 @@ do { \ -static interp_func interp_tab[0x80]; +#define INTERP_RGBA 0x1 +#define INTERP_TEX 0x2 +#define INTERP_INDEX 0x4 +#define INTERP_SPEC 0x8 +#define INTERP_FOG 0x10 +#define INTERP_EDGE 0x20 +#define MAX_INTERP 0x40 + +static interp_func interp_tab[MAX_INTERP]; +static copy_pv_func copy_tab[MAX_INTERP]; + + +#define IND (0) +#define NAME interp_none +#include "t_vb_interptmp.h" + +#define IND (INTERP_FOG) +#define NAME interp_FOG +#include "t_vb_interptmp.h" + +#define IND (INTERP_TEX) +#define NAME interp_TEX +#include "t_vb_interptmp.h" + +#define IND (INTERP_FOG|INTERP_TEX) +#define NAME interp_FOG_TEX +#include "t_vb_interptmp.h" + +#define IND (INTERP_EDGE) +#define NAME interp_EDGE +#include "t_vb_interptmp.h" + +#define IND (INTERP_FOG|INTERP_EDGE) +#define NAME interp_FOG_EDGE +#include "t_vb_interptmp.h" + +#define IND (INTERP_TEX|INTERP_EDGE) +#define NAME interp_TEX_EDGE +#include "t_vb_interptmp.h" + +#define IND (INTERP_FOG|INTERP_TEX|INTERP_EDGE) +#define NAME interp_FOG_TEX_EDGE +#include "t_vb_interptmp.h" #define IND (INTERP_RGBA) #define NAME interp_RGBA @@ -246,15 +274,34 @@ static interp_func interp_tab[0x80]; #include "t_vb_interptmp.h" +#define IND (INTERP_RGBA) +#define NAME copy_RGBA +#include "t_vb_flattmp.h" + +#define IND (INTERP_RGBA|INTERP_SPEC) +#define NAME copy_RGBA_SPEC +#include "t_vb_flattmp.h" + +#define IND (INTERP_INDEX) +#define NAME copy_INDEX +#include "t_vb_flattmp.h" + + + -static GLuint interp_invalid( GLcontext *ctx, - GLfloat t, - GLuint in, GLuint out, - GLboolean boundary ) +static void interp_invalid( GLcontext *ctx, + GLfloat t, + GLuint dst, GLuint in, GLuint out, + GLboolean boundary ) { (void)(ctx && t && in && out && boundary); fprintf(stderr, "Invalid interpolation function in t_vbrender.c\n"); - return in; +} + +static void copy_invalid( GLcontext *ctx, GLuint dst, GLuint src ) +{ + (void)(ctx && dst && src); + fprintf(stderr, "Invalid copy function in t_vbrender.c\n"); } @@ -266,8 +313,19 @@ static void interp_init( void ) * the non-implemented combinations are reachable, but this gives * some safety from crashes. */ - for (i = 0 ; i < Elements(interp_tab) ; i++) + for (i = 0 ; i < Elements(interp_tab) ; i++) { interp_tab[i] = interp_invalid; + copy_tab[i] = copy_invalid; + } + + interp_tab[0] = interp_none; + interp_tab[INTERP_FOG] = interp_FOG; + interp_tab[INTERP_TEX] = interp_TEX; + interp_tab[INTERP_FOG|INTERP_TEX] = interp_FOG_TEX; + interp_tab[INTERP_EDGE] = interp_EDGE; + interp_tab[INTERP_FOG|INTERP_EDGE] = interp_FOG_EDGE; + interp_tab[INTERP_TEX|INTERP_EDGE] = interp_TEX_EDGE; + interp_tab[INTERP_FOG|INTERP_TEX|INTERP_EDGE] = interp_FOG_TEX_EDGE; interp_tab[INTERP_RGBA] = interp_RGBA; interp_tab[INTERP_RGBA|INTERP_SPEC] = interp_RGBA_SPEC; @@ -276,7 +334,8 @@ static void interp_init( void ) interp_tab[INTERP_RGBA|INTERP_TEX] = interp_RGBA_TEX; interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_TEX] = interp_RGBA_SPEC_TEX; interp_tab[INTERP_RGBA|INTERP_FOG|INTERP_TEX] = interp_RGBA_FOG_TEX; - interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX] = interp_RGBA_SPEC_FOG_TEX; + interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX] = + interp_RGBA_SPEC_FOG_TEX; interp_tab[INTERP_INDEX] = interp_INDEX; interp_tab[INTERP_FOG|INTERP_INDEX] = interp_FOG_INDEX; interp_tab[INTERP_TEX|INTERP_INDEX] = interp_TEX_INDEX; @@ -284,15 +343,26 @@ static void interp_init( void ) interp_tab[INTERP_RGBA|INTERP_EDGE] = interp_RGBA_EDGE; interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_EDGE] = interp_RGBA_SPEC_EDGE; interp_tab[INTERP_RGBA|INTERP_FOG|INTERP_EDGE] = interp_RGBA_FOG_EDGE; - interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_EDGE] = interp_RGBA_SPEC_FOG_EDGE; + interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_EDGE] = + interp_RGBA_SPEC_FOG_EDGE; interp_tab[INTERP_RGBA|INTERP_TEX|INTERP_EDGE] = interp_RGBA_TEX_EDGE; - interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_TEX|INTERP_EDGE] = interp_RGBA_SPEC_TEX_EDGE; - interp_tab[INTERP_RGBA|INTERP_FOG|INTERP_TEX|INTERP_EDGE] = interp_RGBA_FOG_TEX_EDGE; - interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX|INTERP_EDGE] = interp_RGBA_SPEC_FOG_TEX_EDGE; + interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_TEX|INTERP_EDGE] = + interp_RGBA_SPEC_TEX_EDGE; + interp_tab[INTERP_RGBA|INTERP_FOG|INTERP_TEX|INTERP_EDGE] = + interp_RGBA_FOG_TEX_EDGE; + interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX|INTERP_EDGE] = + interp_RGBA_SPEC_FOG_TEX_EDGE; interp_tab[INTERP_INDEX|INTERP_EDGE] = interp_INDEX_EDGE; interp_tab[INTERP_FOG|INTERP_INDEX|INTERP_EDGE] = interp_FOG_INDEX_EDGE; interp_tab[INTERP_TEX|INTERP_INDEX|INTERP_EDGE] = interp_TEX_INDEX_EDGE; - interp_tab[INTERP_FOG|INTERP_TEX|INTERP_INDEX|INTERP_EDGE] = interp_FOG_TEX_INDEX_EDGE; + interp_tab[INTERP_FOG|INTERP_TEX|INTERP_INDEX|INTERP_EDGE] = + interp_FOG_TEX_INDEX_EDGE; + + + copy_tab[INTERP_RGBA] = copy_RGBA; + copy_tab[INTERP_RGBA|INTERP_SPEC] = copy_RGBA_SPEC; + copy_tab[INTERP_INDEX] = copy_INDEX; + } @@ -301,12 +371,15 @@ static void interp_init( void ) /**********************************************************************/ -#if 0 -#define NEGATIVE(x) ((*(int *)&x)<0) -#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) +#if defined(USE_IEEE) +#define NEGATIVE(x) ((*(GLuint *)&x) & (1<<31)) +#define DIFFERENT_SIGNS(x,y) (((*(GLuint *)&x)^(*(GLuint *)&y)) & (1<<31)) #else #define NEGATIVE(x) (x < 0) -#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) +#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0) +/* Could just use (x*y<0) except for the flatshading requirements. + * Maybe there's a better way? + */ #endif #define W(i) coord[i][3] @@ -336,176 +409,151 @@ static void interp_init( void ) static clip_poly_func clip_poly_tab[5] = { 0, 0, - viewclip_polygon_2, - viewclip_polygon_3, - viewclip_polygon_4 + clip_polygon_2, + clip_polygon_3, + clip_polygon_4 }; static clip_line_func clip_line_tab[5] = { 0, 0, - viewclip_line_2, - viewclip_line_3, - viewclip_line_4 + clip_line_2, + clip_line_3, + clip_line_4 }; - /**********************************************************************/ -/* Clip and render single primitives */ -/**********************************************************************/ - - - -static INLINE void draw_line(GLcontext *ctx, GLuint v1, GLuint v2 ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLubyte c1 = VB->ClipMask[v1], c2 = VB->ClipMask[v2]; - GLubyte ormask = c1|c2; - if (!ormask) - ctx->Driver.LineFunc( ctx, v1, v2, v2 ); - else if (!(c1 & c2 & 0x3f)) - clip_line_tab[VB->ClipPtr->size]( ctx, v1, v2, ormask ); -} - -static INLINE void draw_triangle(GLcontext *ctx, - GLuint v1, GLuint v2, GLuint v3, - GLuint pv ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLubyte c1 = VB->ClipMask[v1], c2 = VB->ClipMask[v2], c3 = VB->ClipMask[v3]; - GLubyte ormask = c1|c2|c3; - if (!ormask) - ctx->Driver.TriangleFunc( ctx, v1, v2, v3, pv ); - else if (!(c1 & c2 & c3 & 0x3f)) { - GLuint vlist[MAX_CLIPPED_VERTICES]; - ASSIGN_3V(vlist, v1, v2, v3 ); - clip_poly_tab[VB->ClipPtr->size]( ctx, 3, vlist, pv, ormask ); - } -} - - -static INLINE void draw_quad( GLcontext *ctx, - GLuint v1, GLuint v2, GLuint v3, - GLuint v4, GLuint pv ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLubyte c1 = VB->ClipMask[v1], c2 = VB->ClipMask[v2]; - GLubyte c3 = VB->ClipMask[v3], c4 = VB->ClipMask[v4]; - GLubyte ormask = c1|c2|c3|c4; - if (!ormask) - ctx->Driver.QuadFunc( ctx, v1, v2, v3, v4, pv ); - else if (!(c1 & c2 & c3 & c4 & 0x3f)) { - GLuint vlist[MAX_CLIPPED_VERTICES]; - ASSIGN_4V(vlist, v1, v2, v3, v4 ); - clip_poly_tab[VB->ClipPtr->size]( ctx, 4, vlist, pv, ormask ); - } -} - - -/**********************************************************************/ -/* Clip and render whole begin/end objects */ +/* Clip and render whole begin/end objects */ /**********************************************************************/ #define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) -#define EDGEFLAG_GET(idx) VB->EdgeFlagPtr->data[idx] -#define EDGEFLAG_SET(idx, val) VB->EdgeFlagPtr->data[idx] = val +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val -/* Vertices, no clipping. +/* Vertices, with the possibility of clipping. */ #define RENDER_POINTS( start, count ) \ - ctx->Driver.PointsFunc( ctx, start, count-1 ) + ctx->Driver.PointsFunc( ctx, start, count ) -#define RENDER_LINE( i1, i ) \ - ctx->Driver.LineFunc( ctx, i1, i, i ) +#define RENDER_LINE( v1, v2 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte ormask = c1|c2; \ + if (!ormask) \ + LineFunc( ctx, v1, v2 ); \ + else if (!(c1 & c2 & 0x3f)) \ + clip_line_tab[sz]( ctx, v1, v2, ormask ); \ +} while (0) -#define RENDER_TRI( i2, i1, i, pv, parity ) \ +#define RENDER_TRI( v1, v2, v3 ) \ do { \ - if (parity) \ - ctx->Driver.TriangleFunc( ctx, i1, i2, i, pv ); \ - else \ - ctx->Driver.TriangleFunc( ctx, i2, i1, i, pv ); \ + GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \ + GLubyte ormask = c1|c2|c3; \ + if (!ormask) \ + TriangleFunc( ctx, v1, v2, v3 ); \ + else if (!(c1 & c2 & c3 & 0x3f)) { \ + GLuint vlist[MAX_CLIPPED_VERTICES]; \ + ASSIGN_3V(vlist, v3, v1, v2 ); \ + clip_poly_tab[sz]( ctx, 3, vlist, ormask ); \ + } \ } while (0) -#define RENDER_QUAD( i3, i2, i1, i, pv ) \ - ctx->Driver.QuadFunc( ctx, i3, i2, i1, i, pv ); - -#define TAG(x) x##_raw +#define RENDER_QUAD( v1, v2, v3, v4 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte c3 = mask[v3], c4 = mask[v4]; \ + GLubyte ormask = c1|c2|c3|c4; \ + if (!ormask) \ + QuadFunc( ctx, v1, v2, v3, v4 ); \ + else if (!(c1 & c2 & c3 & c4 & 0x3f)) { \ + GLuint vlist[MAX_CLIPPED_VERTICES]; \ + ASSIGN_4V(vlist, v4, v1, v2, v3 ); \ + clip_poly_tab[sz]( ctx, 4, vlist, ormask ); \ + } \ +} while (0) -#define LOCAL_VARS \ - struct vertex_buffer *VB = &(TNL_CONTEXT(ctx)->vb); \ - (void) VB; +#define LOCAL_VARS \ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; \ + const GLuint * const elt = VB->Elts; \ + const GLubyte *mask = VB->ClipMask; \ + const GLuint sz = VB->ClipPtr->size; \ + const line_func LineFunc = ctx->Driver.LineFunc; \ + const triangle_func TriangleFunc = ctx->Driver.TriangleFunc; \ + const quad_func QuadFunc = ctx->Driver.QuadFunc; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; (void) mask; (void) sz; + +#define TAG(x) clip_##x##_verts #define RESET_STIPPLE ctx->Driver.ResetLineStipple( ctx ) #define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE; #define PRESERVE_VB_DEFS #include "t_vb_rendertmp.h" -/* Elts, no clipping. + +/* Elts, with the possibility of clipping. */ #undef ELT #undef TAG -#undef LOCAL_VARS -#define TAG(x) x##_raw_elts #define ELT(x) elt[x] -#define LOCAL_VARS \ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; \ - const GLuint * const elt = VB->Elts; \ - (void) elt; +#define TAG(x) clip_##x##_elts #include "t_vb_rendertmp.h" +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val -/* Vertices, with the possibility of clipping. + +/* Vertices, no clipping. */ -#define RENDER_POINTS( start, count ) \ - ctx->Driver.PointsFunc( ctx, start, count-1 ) +#define RENDER_POINTS( start, count ) \ + ctx->Driver.PointsFunc( ctx, start, count ) -#define RENDER_LINE( i1, i ) \ - draw_line( ctx, i1, i ) +#define RENDER_LINE( v1, v2 ) \ + LineFunc( ctx, v1, v2 ) -#define RENDER_TRI( i2, i1, i, pv, parity) \ -do { \ - GLuint e2=i2, e1=i1; \ - if (parity) { GLuint t=e2; e2=e1; e1=t; } \ - draw_triangle(ctx,e2,e1,i,pv); \ -} while (0) +#define RENDER_TRI( v1, v2, v3 ) \ + TriangleFunc( ctx, v1, v2, v3 ) -#define RENDER_QUAD( i3, i2, i1, i, pv) \ - draw_quad(ctx,i3,i2,i1,i,pv) +#define RENDER_QUAD( v1, v2, v3, v4 ) \ + QuadFunc( ctx, v1, v2, v3, v4 ) +#define TAG(x) _tnl_##x##_verts #define LOCAL_VARS \ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; \ - (void)VB; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; \ + const GLuint * const elt = VB->Elts; \ + const line_func LineFunc = ctx->Driver.LineFunc; \ + const triangle_func TriangleFunc = ctx->Driver.TriangleFunc; \ + const quad_func QuadFunc = ctx->Driver.QuadFunc; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; -#define TAG(x) x##_clipped #define RESET_STIPPLE ctx->Driver.ResetLineStipple( ctx ) #define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE; +#define RENDER_TAB_QUALIFIER #define PRESERVE_VB_DEFS #include "t_vb_rendertmp.h" - -/* Elts, with the possibility of clipping. +/* Elts, no clipping. */ #undef ELT -#undef TAG -#undef LOCAL_VARS +#define TAG(x) _tnl_##x##_elts #define ELT(x) elt[x] -#define LOCAL_VARS \ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; \ - const GLuint * const elt = VB->Elts; \ - (void) elt; -#define TAG(x) x##_clipped_elts - #include "t_vb_rendertmp.h" + /**********************************************************************/ /* Clip and render whole vertex buffers */ /**********************************************************************/ @@ -520,40 +568,29 @@ static GLboolean run_render( GLcontext *ctx, render_func *tab; GLint pass = 0; -/* return GL_FALSE; */ + VB->interpfunc = RENDER_STAGE_DATA(stage)->interp; + VB->copypvfunc = RENDER_STAGE_DATA(stage)->copypv; - VB->interpfunc = (void *)RENDER_STAGE_DATA(stage)->interp; + /* Allow the drivers to lock before projected verts are built so + * that window coordinates are guarenteed not to change before + * rendering. + */ + if (ctx->Driver.RenderStart) + ctx->Driver.RenderStart( ctx ); - if (new_inputs) { - GLuint importable = new_inputs & VB->importable_data; - GLuint interested = 0; - - if (VB->ClipOrMask) - interested = ~0; - - if (ctx->_TriangleCaps & DD_TRI_UNFILLED) - interested |= VERT_EDGE; - - importable &= interested; - - if (importable) - VB->import_data( ctx, importable, VEC_NOT_WRITEABLE|VEC_BAD_STRIDE); - - if (ctx->Driver.BuildProjectedVertices) - ctx->Driver.BuildProjectedVertices( ctx, 0, VB->Count, new_inputs); - } + if (VB->ClipOrMask) { + tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts; - /* Rendering is considered a side-effect, and must be repeated each - * time the stage is run, even if no inputs have changed. - */ - if (VB->Elts) { - tab = VB->ClipOrMask ? render_tab_clipped_elts : render_tab_raw_elts; - } else { - tab = VB->ClipOrMask ? render_tab_clipped : render_tab_raw; + if (new_inputs & VB->importable_data) + VB->import_data( ctx, + new_inputs & VB->importable_data, + VEC_NOT_WRITEABLE|VEC_BAD_STRIDE); } + else { + tab = VB->Elts ? ctx->Driver.RenderTabElts : ctx->Driver.RenderTabVerts; + } - if (ctx->Driver.RenderStart) - ctx->Driver.RenderStart( ctx ); + ctx->Driver.BuildProjectedVertices( ctx, 0, VB->Count, new_inputs ); do { @@ -564,9 +601,6 @@ static GLboolean run_render( GLcontext *ctx, length= VB->PrimitiveLength[i]; ASSERT(length || (flags & PRIM_LAST)); ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); -/* fprintf(stderr, "render %s %d..%d\n", */ -/* _mesa_prim_name[flags & PRIM_MODE_MASK], */ -/* i, i+length); */ if (length) tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); } @@ -595,6 +629,7 @@ static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage ) { struct render_stage_data *store = RENDER_STAGE_DATA(stage); GLuint interp = 0; + GLuint copy = 0; GLuint inputs = VERT_CLIP; GLuint i; @@ -643,6 +678,12 @@ static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage ) inputs |= VERT_TEX_ANY; } + if (ctx->_TriangleCaps & DD_FLATSHADE) { + copy = interp & (INTERP_RGBA|INTERP_SPEC|INTERP_INDEX); + interp &= ~copy; + } + + store->copypv = copy_tab[copy]; store->interp = interp_tab[interp]; stage->inputs = inputs; } @@ -688,6 +729,7 @@ const struct gl_pipeline_stage _tnl_render_stage = "render", (_NEW_BUFFERS | _DD_NEW_SEPERATE_SPECULAR | + _DD_NEW_FLATSHADE | _NEW_TEXTURE| _NEW_LIGHT| _NEW_POINT| diff --git a/src/mesa/tnl/t_vb_rendertmp.h b/src/mesa/tnl/t_vb_rendertmp.h index 5712d342d2..9c9271ff22 100644 --- a/src/mesa/tnl/t_vb_rendertmp.h +++ b/src/mesa/tnl/t_vb_rendertmp.h @@ -1,4 +1,4 @@ -/* $Id: t_vb_rendertmp.h,v 1.3 2000/12/28 22:11:06 keithw Exp $ */ +/* $Id: t_vb_rendertmp.h,v 1.4 2001/01/05 02:26:49 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -60,6 +60,10 @@ #define ELT(x) x #endif +#ifndef RENDER_TAB_QUALIFIER +#define RENDER_TAB_QUALIFIER static +#endif + static void TAG(render_points)( GLcontext *ctx, GLuint start, GLuint count, @@ -68,7 +72,6 @@ static void TAG(render_points)( GLcontext *ctx, LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ RESET_OCCLUSION; INIT(GL_POINTS); RENDER_POINTS( start, count ); @@ -84,7 +87,6 @@ static void TAG(render_lines)( GLcontext *ctx, LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ RESET_OCCLUSION; INIT(GL_LINES); for (j=start+1; j<count; j+=2 ) { @@ -104,7 +106,6 @@ static void TAG(render_line_strip)( GLcontext *ctx, LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ RESET_OCCLUSION; INIT(GL_LINES); @@ -128,7 +129,6 @@ static void TAG(render_line_loop)( GLcontext *ctx, (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ RESET_OCCLUSION; INIT(GL_LINES); @@ -160,18 +160,17 @@ static void TAG(render_triangles)( GLcontext *ctx, LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ INIT(GL_POLYGON); if (NEED_EDGEFLAG_SETUP) { for (j=start+2; j<count; j+=3) { /* Leave the edgeflags as supplied by the user. */ - RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j), ELT(j), 0 ); + RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); RESET_STIPPLE; } } else { for (j=start+2; j<count; j+=3) { - RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j), ELT(j), 0 ); + RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); } } POSTFIX; @@ -191,15 +190,11 @@ static void TAG(render_tri_strip)( GLcontext *ctx, if (TEST_PRIM_PARITY(flags)) parity = 1; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ INIT(GL_POLYGON); if (NEED_EDGEFLAG_SETUP) { for (j=start+2;j<count;j++,parity^=1) { - /* All edges are boundary. Set edgeflags to 1, draw the - * triangle, and restore them to the original values. - */ - GLuint ej2 = ELT(j-2); - GLuint ej1 = ELT(j-1); + GLuint ej2 = ELT(j-2+parity); + GLuint ej1 = ELT(j-1-parity); GLuint ej = ELT(j); GLboolean ef2 = EDGEFLAG_GET( ej2 ); GLboolean ef1 = EDGEFLAG_GET( ej1 ); @@ -207,15 +202,15 @@ static void TAG(render_tri_strip)( GLcontext *ctx, EDGEFLAG_SET( ej2, GL_TRUE ); EDGEFLAG_SET( ej1, GL_TRUE ); EDGEFLAG_SET( ej, GL_TRUE ); - RENDER_TRI( ej2, ej1, ej, ej, parity ); + RENDER_TRI( ej2, ej1, ej ); EDGEFLAG_SET( ej2, ef2 ); EDGEFLAG_SET( ej1, ef1 ); EDGEFLAG_SET( ej, ef ); RESET_STIPPLE; } } else { - for (j=start+2;j<count;j++,parity^=1) { - RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j), ELT(j), parity ); + for (j=start+2; j<count ; j++, parity^=1) { + RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) ); } } POSTFIX; @@ -231,7 +226,6 @@ static void TAG(render_tri_fan)( GLcontext *ctx, LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ INIT(GL_POLYGON); if (NEED_EDGEFLAG_SETUP) { for (j=start+2;j<count;j++) { @@ -246,7 +240,7 @@ static void TAG(render_tri_fan)( GLcontext *ctx, EDGEFLAG_SET( ejs, GL_TRUE ); EDGEFLAG_SET( ej1, GL_TRUE ); EDGEFLAG_SET( ej, GL_TRUE ); - RENDER_TRI( ejs, ej1, ej, ej, 0); + RENDER_TRI( ejs, ej1, ej); EDGEFLAG_SET( ejs, efs ); EDGEFLAG_SET( ej1, ef1 ); EDGEFLAG_SET( ej, ef ); @@ -254,7 +248,7 @@ static void TAG(render_tri_fan)( GLcontext *ctx, } } else { for (j=start+2;j<count;j++) { - RENDER_TRI( ELT(start), ELT(j-1), ELT(j), ELT(j), 0 ); + RENDER_TRI( ELT(start), ELT(j-1), ELT(j) ); } } @@ -262,22 +256,15 @@ static void TAG(render_tri_fan)( GLcontext *ctx, } -/* This is a bit of a hack. Clipping produces polygons and really - * wants to use this function to render them (in particular to get the - * edgeflags right). However, the rule that pv==start for polys - * doens't hold there, hence the extra arg and the wrapper below. - */ -static void TAG(render_poly_pv)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags, - GLuint pv ) +static void TAG(render_poly)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) { GLuint j = start+2; LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ INIT(GL_POLYGON); if (NEED_EDGEFLAG_SETUP) { GLboolean efstart = EDGEFLAG_GET( ELT(start) ); @@ -300,7 +287,7 @@ static void TAG(render_poly_pv)( GLcontext *ctx, if (j<count-1) { GLboolean ef = EDGEFLAG_GET( ELT(j) ); EDGEFLAG_SET( ELT(j), GL_FALSE ); - RENDER_TRI( ELT(start), ELT(j-1), ELT(j), ELT(pv), 0 ); + RENDER_TRI( ELT(start), ELT(j-1), ELT(j) ); EDGEFLAG_SET( ELT(j), ef ); j++; @@ -311,7 +298,7 @@ static void TAG(render_poly_pv)( GLcontext *ctx, for (;j<count-1;j++) { GLboolean efj = EDGEFLAG_GET( ELT(j) ); EDGEFLAG_SET( ELT(j), GL_FALSE ); - RENDER_TRI( ELT(start), ELT(j-1), ELT(j), ELT(pv), 0 ); + RENDER_TRI( ELT(start), ELT(j-1), ELT(j) ); EDGEFLAG_SET( ELT(j), efj ); } } @@ -319,7 +306,7 @@ static void TAG(render_poly_pv)( GLcontext *ctx, /* Draw the last or only triangle */ if (j < count) - RENDER_TRI( ELT(start), ELT(j-1), ELT(j), ELT(pv), 0 ); + RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); /* Restore the first and last edgeflags: */ @@ -332,21 +319,12 @@ static void TAG(render_poly_pv)( GLcontext *ctx, } else { for (j=start+2;j<count;j++) { - RENDER_TRI( ELT(start), ELT(j-1), ELT(j), ELT(start), 0 ); + RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); } } POSTFIX; } -static void TAG(render_poly)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ - TAG(render_poly_pv)( ctx, start, count, flags, start ); -} - static void TAG(render_quads)( GLcontext *ctx, GLuint start, GLuint count, @@ -356,18 +334,17 @@ static void TAG(render_quads)( GLcontext *ctx, LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ INIT(GL_POLYGON); if (NEED_EDGEFLAG_SETUP) { for (j=start+3; j<count; j+=4) { /* Use user-specified edgeflags for quads. */ - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j), ELT(j) ); + RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); RESET_STIPPLE; } } else { for (j=start+3; j<count; j+=4) { - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j), ELT(j) ); + RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); } } POSTFIX; @@ -382,7 +359,6 @@ static void TAG(render_quad_strip)( GLcontext *ctx, LOCAL_VARS; (void) flags; -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ INIT(GL_POLYGON); if (NEED_EDGEFLAG_SETUP) { for (j=start+3;j<count;j+=2) { @@ -397,7 +373,7 @@ static void TAG(render_quad_strip)( GLcontext *ctx, EDGEFLAG_SET( ELT(j-2), GL_TRUE ); EDGEFLAG_SET( ELT(j-1), GL_TRUE ); EDGEFLAG_SET( ELT(j), GL_TRUE ); - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j), ELT(j-1), ELT(j) ); + RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); EDGEFLAG_SET( ELT(j-3), ef3 ); EDGEFLAG_SET( ELT(j-2), ef2 ); EDGEFLAG_SET( ELT(j-1), ef1 ); @@ -406,7 +382,7 @@ static void TAG(render_quad_strip)( GLcontext *ctx, } } else { for (j=start+3;j<count;j+=2) { - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j), ELT(j-1), ELT(j) ); + RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); } } POSTFIX; @@ -417,14 +393,13 @@ static void TAG(render_noop)( GLcontext *ctx, GLuint count, GLuint flags ) { -/* fprintf(stderr, "%s %d..%d\n", __FUNCTION__, start, count); */ (void)(ctx && start && count && flags); } -static void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *, - GLuint, - GLuint, - GLuint) = +RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *, + GLuint, + GLuint, + GLuint) = { TAG(render_points), TAG(render_lines), @@ -452,6 +427,7 @@ static void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *, #undef RESET_STIPPLE #undef DBG #undef ELT +#undef RENDER_TAB_QUALIFIER #endif #ifndef PRESERVE_TAG |