From 51b36396ae45f9ee9cec8d612787d038641dc6c8 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 4 Jun 2001 16:09:28 +0000 Subject: [PATCH] Adaptor code that lets tnl convert compiled (display list) cassettes back to glVertex() type calls. Allows driver-supplied tnl modules to avoid fallback on glCallList inside begin/end pairs. Still a little buggy... --- src/mesa/tnl/t_context.c | 14 +- src/mesa/tnl/t_context.h | 3 +- src/mesa/tnl/t_imm_api.c | 6 +- src/mesa/tnl/t_imm_dlist.c | 295 +++++++++++++++++++++++++++++++++++-- src/mesa/tnl/t_imm_fixup.c | 89 +---------- src/mesa/tnl/t_imm_fixup.h | 5 +- src/mesa/tnl/tnl.h | 5 +- 7 files changed, 305 insertions(+), 112 deletions(-) diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c index 37b04836632..e842bd14224 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.18 2001/05/11 08:11:31 keithw Exp $ */ +/* $Id: t_context.c,v 1.19 2001/06/04 16:09:28 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -103,6 +103,7 @@ _tnl_CreateContext( GLcontext *ctx ) tnl->NeedProjCoords = GL_TRUE; + tnl->LoopbackDListCassettes = GL_FALSE; /* Hook our functions into exec and compile dispatch tables. */ @@ -123,6 +124,8 @@ _tnl_CreateContext( GLcontext *ctx ) tnl->Driver.RenderTabElts = _tnl_render_tab_elts; tnl->Driver.RenderTabVerts = _tnl_render_tab_verts; + + return GL_TRUE; } @@ -210,3 +213,12 @@ _tnl_need_projected_coords( GLcontext *ctx, GLboolean mode ) _tnl_InvalidateState( ctx, _NEW_PROJECTION ); } } + +void +_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean mode ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + if (tnl->LoopbackDListCassettes != mode) { + tnl->LoopbackDListCassettes = mode; + } +} diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index 54f13e46490..226b877d852 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.27 2001/06/01 16:29:18 brianp Exp $ */ +/* $Id: t_context.h,v 1.28 2001/06/04 16:09:28 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -524,6 +524,7 @@ typedef struct { /* Probably need a better configuration mechanism: */ GLboolean NeedProjCoords; + GLboolean LoopbackDListCassettes; /* Derived state and storage for _tnl_eval_vb: */ diff --git a/src/mesa/tnl/t_imm_api.c b/src/mesa/tnl/t_imm_api.c index 2a55e0ef637..9c4894ada74 100644 --- a/src/mesa/tnl/t_imm_api.c +++ b/src/mesa/tnl/t_imm_api.c @@ -1,4 +1,4 @@ -/* $Id: t_imm_api.c,v 1.14 2001/05/11 15:53:06 keithw Exp $ */ +/* $Id: t_imm_api.c,v 1.15 2001/06/04 16:09:28 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -294,7 +294,9 @@ _tnl_end( GLcontext *ctx ) IM->Flag[count] |= VERT_END; IM->Primitive[last] |= PRIM_END; IM->PrimitiveLength[last] = count - last; - IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; + IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; /* removes PRIM_BEGIN + * flag if length == 0 + */ IM->LastPrimitive = count; if (IM->FlushElt == FLUSH_ELT_EAGER) { diff --git a/src/mesa/tnl/t_imm_dlist.c b/src/mesa/tnl/t_imm_dlist.c index c9d375831e4..722d67b1435 100644 --- a/src/mesa/tnl/t_imm_dlist.c +++ b/src/mesa/tnl/t_imm_dlist.c @@ -1,4 +1,4 @@ -/* $Id: t_imm_dlist.c,v 1.19 2001/05/14 09:00:51 keithw Exp $ */ +/* $Id: t_imm_dlist.c,v 1.20 2001/06/04 16:09:28 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -63,6 +63,7 @@ typedef struct { } TNLvertexcassette; static void execute_compiled_cassette( GLcontext *ctx, void *data ); +static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM ); /* Insert the active immediate struct onto the display list currently @@ -143,6 +144,93 @@ _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM ) } +static void fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* Can potentially overwrite primitive details - need to save the + * first slot: + */ + tnl->DlistPrimitive = IM->Primitive[IM->Start]; + tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start]; + tnl->DlistLastPrimitive = IM->LastPrimitive; + + /* The first primitive may be different from what was recorded in + * the immediate struct. Consider an immediate that starts with a + * glBegin, compiled in a display list, which is called from within + * an existing Begin/End object. + */ + if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { + GLuint i; + + if (IM->BeginState & VERT_ERROR_1) + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); + + for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) + if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB)) + break; + + /* Would like to just ignore vertices upto this point. Can't + * set copystart because it might skip materials? + */ + ASSERT(IM->Start == IM->CopyStart); + if (i > IM->CopyStart) { + IM->Primitive[IM->CopyStart] = GL_POLYGON+1; + IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; + if (IM->Flag[i] & VERT_END_VB) { + IM->Primitive[IM->CopyStart] |= PRIM_LAST; + IM->LastPrimitive = IM->CopyStart; + } + } + } else { + GLuint i; + + if (IM->BeginState & VERT_ERROR_0) + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); + + if (IM->CopyStart == IM->Start && + IM->Flag[IM->Start] & (VERT_END|VERT_END_VB)) + { + } + else + { + IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive; + if (tnl->ExecParity) + IM->Primitive[IM->CopyStart] |= PRIM_PARITY; + + /* one of these should be true, else we'll be in an infinite loop + */ + ASSERT(IM->PrimitiveLength[IM->Start] > 0 || + IM->Flag[IM->Start] & (VERT_END|VERT_END_VB)); + + for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) + if (IM->Flag[i] & (VERT_END|VERT_END_VB)) { + IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; + if (IM->Flag[i] & VERT_END_VB) { + IM->Primitive[IM->CopyStart] |= PRIM_LAST; + IM->LastPrimitive = IM->CopyStart; + } + if (IM->Flag[i] & VERT_END) { + IM->Primitive[IM->CopyStart] |= PRIM_END; + } + break; + } + } + } +} + +/* Undo any changes potentially made to the immediate in the range + * IM->Start..IM->Count above. + */ +static void restore_compiled_primitives( GLcontext *ctx, struct immediate *IM ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + IM->Primitive[IM->Start] = tnl->DlistPrimitive; + IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength; +} + + + static void execute_compiled_cassette( GLcontext *ctx, void *data ) { @@ -152,12 +240,6 @@ execute_compiled_cassette( GLcontext *ctx, void *data ) /* fprintf(stderr, "%s\n", __FUNCTION__); */ - if (ctx->NewState) - _mesa_update_state(ctx); - - if (tnl->pipeline.build_state_changes) - _tnl_validate_pipeline( ctx ); - IM->Start = node->Start; IM->CopyStart = node->Start; IM->Count = node->Count; @@ -183,11 +265,10 @@ execute_compiled_cassette( GLcontext *ctx, void *data ) _tnl_print_vert_flags("orflag", IM->OrFlag); } - if (IM->Count == IM->Start) { - _tnl_copy_to_current( ctx, IM, IM->OrFlag ); - return; - } + /* Need to respect 'HardBeginEnd' even if the commands are looped + * back to a driver tnl module. + */ if (IM->SavedBeginState) { if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) tnl->ReplayHardBeginEnd = 1; @@ -202,10 +283,35 @@ execute_compiled_cassette( GLcontext *ctx, void *data ) } } - _tnl_fixup_compiled_cassette( ctx, IM ); - _tnl_get_exec_copy_verts( ctx, IM ); - _tnl_run_cassette( ctx, IM ); - _tnl_restore_compiled_cassette( ctx, IM ); + if (tnl->LoopbackDListCassettes) { + fixup_compiled_primitives( ctx, IM ); + loopback_compiled_cassette( ctx, IM ); + restore_compiled_primitives( ctx, IM ); + } + else if (IM->Count == IM->Start) { + _tnl_copy_to_current( ctx, IM, IM->OrFlag ); + } + else { + if (ctx->NewState) + _mesa_update_state(ctx); + + if (tnl->pipeline.build_state_changes) + _tnl_validate_pipeline( ctx ); + + _tnl_fixup_compiled_cassette( ctx, IM ); + fixup_compiled_primitives( ctx, IM ); + + if (IM->Primitive[IM->LastPrimitive] & PRIM_END) + ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; + else + ctx->Driver.CurrentExecPrimitive = + IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK; + + _tnl_get_exec_copy_verts( ctx, IM ); + _tnl_run_cassette( ctx, IM ); + + restore_compiled_primitives( ctx, IM ); + } if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) tnl->ReplayHardBeginEnd = 0; @@ -322,3 +428,162 @@ _tnl_dlist_init( GLcontext *ctx ) destroy_compiled_cassette, print_compiled_cassette ); } + + +static void emit_material( struct gl_material *src, GLuint bitmask ) +{ + if (bitmask & FRONT_EMISSION_BIT) + glMaterialfv( GL_FRONT, GL_EMISSION, src[0].Emission ); + + if (bitmask & BACK_EMISSION_BIT) + glMaterialfv( GL_BACK, GL_EMISSION, src[1].Emission ); + + if (bitmask & FRONT_AMBIENT_BIT) + glMaterialfv( GL_FRONT, GL_AMBIENT, src[0].Ambient ); + + if (bitmask & BACK_AMBIENT_BIT) + glMaterialfv( GL_BACK, GL_AMBIENT, src[1].Ambient ); + + if (bitmask & FRONT_DIFFUSE_BIT) + glMaterialfv( GL_FRONT, GL_DIFFUSE, src[0].Diffuse ); + + if (bitmask & BACK_DIFFUSE_BIT) + glMaterialfv( GL_BACK, GL_DIFFUSE, src[1].Diffuse ); + + if (bitmask & FRONT_SPECULAR_BIT) + glMaterialfv( GL_FRONT, GL_SPECULAR, src[0].Specular ); + + if (bitmask & BACK_SPECULAR_BIT) + glMaterialfv( GL_BACK, GL_SPECULAR, src[1].Specular ); + + if (bitmask & FRONT_SHININESS_BIT) + glMaterialfv( GL_FRONT, GL_SHININESS, &src[0].Shininess ); + + if (bitmask & BACK_SHININESS_BIT) + glMaterialfv( GL_BACK, GL_SHININESS, &src[1].Shininess ); + + if (bitmask & FRONT_INDEXES_BIT) { + GLfloat ind[3]; + ind[0] = src[0].AmbientIndex; + ind[1] = src[0].DiffuseIndex; + ind[2] = src[0].SpecularIndex; + glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, ind ); + } + + if (bitmask & BACK_INDEXES_BIT) { + GLfloat ind[3]; + ind[0] = src[1].AmbientIndex; + ind[1] = src[1].DiffuseIndex; + ind[2] = src[1].SpecularIndex; + glMaterialfv( GL_BACK, GL_COLOR_INDEXES, ind ); + } +} + + +/* Low-performance helper function to allow driver-supplied tnl + * modules to process tnl display lists. This is primarily supplied + * to avoid fallbacks if CallList is invoked inside a Begin/End pair. + * For higher performance, drivers should fallback to tnl (if outside + * begin/end), or (for tnl hardware) implement their own display list + * mechanism. + */ +static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM ) +{ + GLuint i; + GLuint *flags = IM->Flag; + GLuint orflag = IM->OrFlag; + GLuint j; + void (*vertex)( const GLfloat * ); + void (*texcoordfv[MAX_TEXTURE_UNITS])( GLuint, const GLfloat * ); + GLuint maxtex = 0; + GLuint p, length, prim = 0; + + if (orflag & VERT_OBJ_234) + vertex = glVertex4fv; + else + vertex = glVertex3fv; + + if (orflag & VERT_TEX_ANY) { + for (j = 0 ; j < ctx->Const.MaxTextureUnits ; j++) { + if (orflag & VERT_TEX(j)) { + maxtex = j+1; + if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j)) + texcoordfv[j] = glMultiTexCoord4fvARB; + else if (IM->TexSize & TEX_SIZE_3(j)) + texcoordfv[j] = glMultiTexCoord3fvARB; + else + texcoordfv[j] = glMultiTexCoord2fvARB; + } + } + } + + for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length) + { + prim = IM->Primitive[p]; + length= IM->PrimitiveLength[p]; + ASSERT(length || (prim & PRIM_LAST)); + ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1); + + if (prim & PRIM_BEGIN) { +/* fprintf(stderr, "begin %s\n", _mesa_prim_name[prim&PRIM_MODE_MASK]); */ + glBegin(prim & PRIM_MODE_MASK); + } + + for ( i = p ; i <= p+length ; i++) { + if (flags[i] & VERT_TEX_ANY) { + GLuint k; + for (k = 0 ; k < maxtex ; k++) { + if (flags[i] & VERT_TEX(k)) { + texcoordfv[k]( GL_TEXTURE0_ARB + k, IM->TexCoord[k][i] ); + } + } + } + + if (flags[i] & VERT_NORM) { +/* fprintf(stderr, "normal %d: %f %f %f\n", i, */ +/* IM->Normal[i][0], IM->Normal[i][1], IM->Normal[i][2]); */ + glNormal3fv(IM->Normal[i]); + } + + if (flags[i] & VERT_RGBA) { +/* fprintf(stderr, "color %d: %f %f %f\n", i, */ +/* IM->Color[i][0], IM->Color[i][1], IM->Color[i][2]); */ + glColor4fv( IM->Color[i] ); + } + + if (flags[i] & VERT_SPEC_RGB) + glSecondaryColor3fvEXT( IM->SecondaryColor[i] ); + + if (flags[i] & VERT_FOG_COORD) + glFogCoordfEXT( IM->FogCoord[i] ); + + if (flags[i] & VERT_INDEX) + glIndexi( IM->Index[i] ); + + if (flags[i] & VERT_EDGE) + glEdgeFlag( IM->EdgeFlag[i] ); + + if (flags[i] & VERT_MATERIAL) + emit_material( IM->Material[i], IM->MaterialMask[i] ); + + if (flags[i]&VERT_OBJ_234) { +/* fprintf(stderr, "vertex %d: %f %f %f\n", i, */ +/* IM->Obj[i][0], IM->Obj[i][1], IM->Obj[i][2]); */ + vertex( IM->Obj[i] ); + } + else if (flags[i] & VERT_EVAL_C1) + glEvalCoord1f(IM->Obj[i][0]); + else if (flags[i] & VERT_EVAL_P1) + glEvalPoint1(IM->Obj[i][0]); + else if (flags[i] & VERT_EVAL_C2) + glEvalCoord2f( IM->Obj[i][0], IM->Obj[i][1]); + else if (flags[i] & VERT_EVAL_P2) + glEvalPoint2( IM->Obj[i][0], IM->Obj[i][1]); + } + + if (prim & PRIM_END) { +/* fprintf(stderr, "end\n"); */ + glEnd(); + } + } +} diff --git a/src/mesa/tnl/t_imm_fixup.c b/src/mesa/tnl/t_imm_fixup.c index 126aba10068..fdfeff566a1 100644 --- a/src/mesa/tnl/t_imm_fixup.c +++ b/src/mesa/tnl/t_imm_fixup.c @@ -1,4 +1,4 @@ -/* $Id: t_imm_fixup.c,v 1.19 2001/05/16 09:28:32 keithw Exp $ */ +/* $Id: t_imm_fixup.c,v 1.20 2001/06/04 16:09:28 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -592,93 +592,6 @@ void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM ) } while (vulnerable); } - - /* Can potentially overwrite primitive details - need to save the - * first slot: - */ - tnl->DlistPrimitive = IM->Primitive[IM->Start]; - tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start]; - tnl->DlistLastPrimitive = IM->LastPrimitive; - - /* The first primitive may be different from what was recorded in - * the immediate struct. Consider an immediate that starts with a - * glBegin, compiled in a display list, which is called from within - * an existing Begin/End object. - */ - if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { - GLuint i; - - if (IM->BeginState & VERT_ERROR_1) - _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); - - for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) - if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB)) - break; - - /* Would like to just ignore vertices upto this point. Can't - * set copystart because it might skip materials? - */ - ASSERT(IM->Start == IM->CopyStart); - if (i > IM->CopyStart) { - IM->Primitive[IM->CopyStart] = GL_POLYGON+1; - IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; - if (IM->Flag[i] & VERT_END_VB) { - IM->Primitive[IM->CopyStart] |= PRIM_LAST; - IM->LastPrimitive = IM->CopyStart; - } - } - } else { - GLuint i; - - if (IM->BeginState & VERT_ERROR_0) - _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); - - if (IM->CopyStart == IM->Start && - IM->Flag[IM->Start] & (VERT_END|VERT_END_VB)) - { - } - else - { - IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive; - if (tnl->ExecParity) - IM->Primitive[IM->CopyStart] |= PRIM_PARITY; - - /* one of these should be true, else we'll be in an infinite loop - */ - ASSERT(IM->PrimitiveLength[IM->Start] > 0 || - IM->Flag[IM->Start] & (VERT_END|VERT_END_VB)); - - for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) - if (IM->Flag[i] & (VERT_END|VERT_END_VB)) { - IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; - if (IM->Flag[i] & VERT_END_VB) { - IM->Primitive[IM->CopyStart] |= PRIM_LAST; - IM->LastPrimitive = IM->CopyStart; - } - if (IM->Flag[i] & VERT_END) { - IM->Primitive[IM->CopyStart] |= PRIM_END; - } - break; - } - } - } - - if (IM->Primitive[IM->LastPrimitive] & PRIM_END) - ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; - else - ctx->Driver.CurrentExecPrimitive = - IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK; -} - - -/* Undo any changes potentially made to the immediate in the range - * IM->Start..IM->Count above. - */ -void _tnl_restore_compiled_cassette( GLcontext *ctx, struct immediate *IM ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - IM->Primitive[IM->Start] = tnl->DlistPrimitive; - IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength; } diff --git a/src/mesa/tnl/t_imm_fixup.h b/src/mesa/tnl/t_imm_fixup.h index 5ca68b297a0..806933aa68a 100644 --- a/src/mesa/tnl/t_imm_fixup.h +++ b/src/mesa/tnl/t_imm_fixup.h @@ -1,4 +1,4 @@ -/* $Id: t_imm_fixup.h,v 1.5 2001/04/30 21:08:52 keithw Exp $ */ +/* $Id: t_imm_fixup.h,v 1.6 2001/06/04 16:09:28 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -51,9 +51,6 @@ extern void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM ); extern void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM ); -extern void _tnl_restore_compiled_cassette( GLcontext *ctx, - struct immediate *IM ); - extern void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *IM ); diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h index 9ca530797e5..413864aba1f 100644 --- a/src/mesa/tnl/tnl.h +++ b/src/mesa/tnl/tnl.h @@ -1,4 +1,4 @@ -/* $Id: tnl.h,v 1.6 2001/03/12 00:48:44 gareth Exp $ */ +/* $Id: tnl.h,v 1.7 2001/06/04 16:09:28 keithw Exp $ */ /* * Mesa 3-D graphics library @@ -64,4 +64,7 @@ _tnl_wakeup_save_exec( GLcontext *ctx ); extern void _tnl_need_projected_coords( GLcontext *ctx, GLboolean flag ); +extern void +_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean flag ); + #endif -- 2.30.2