From 36a35c5614336bffdac4827c1e04bcaa8ab2fa27 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Sat, 22 Jan 2005 14:38:00 +0000 Subject: [PATCH] Determine ahead of time whether a display list will include vertices which have to be processed in the 'loopback' path. If so, send all vertices that way as the transition from playback->loopback has several problems. --- src/mesa/main/dd.h | 7 ++-- src/mesa/main/dlist.c | 60 ++++++++++++++++++++++++---------- src/mesa/main/mtypes.h | 21 ++++++++++++ src/mesa/tnl/t_context.h | 1 + src/mesa/tnl/t_save_api.c | 20 ++++++++---- src/mesa/tnl/t_save_api.h | 2 +- src/mesa/tnl/t_save_playback.c | 9 +++-- 7 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index f7f7eacf060..def550109cb 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -34,6 +34,7 @@ /* THIS FILE ONLY INCLUDED BY mtypes.h !!!!! */ struct gl_pixelstore_attrib; +struct mesa_display_list; /** * Device driver function table. @@ -886,12 +887,12 @@ struct dd_function_table { void (*EndList)( GLcontext *ctx ); /** - * Called by glCallList(s), but not recursively. + * Called by glCallList(s). * * Notify the T&L component before and after calling a display list. - * Called by glCallList(s), but not recursively. */ - void (*BeginCallList)( GLcontext *ctx, GLuint list ); + void (*BeginCallList)( GLcontext *ctx, + struct mesa_display_list *dlist ); /** * Called by glEndCallList(). * diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index beacf5b1f99..f95e8db98cb 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -412,11 +412,13 @@ void mesa_print_display_list( GLuint list ); * Make an empty display list. This is used by glGenLists() to * reserver display list IDs. */ -static Node *make_empty_list( void ) +static struct mesa_display_list *make_list( GLuint list, GLuint count ) { - Node *n = (Node *) MALLOC( sizeof(Node) ); - n[0].opcode = OPCODE_END_OF_LIST; - return n; + struct mesa_display_list *dlist = CALLOC_STRUCT( mesa_display_list ); + dlist->id = list; + dlist->node = (Node *) MALLOC( sizeof(Node) * count ); + dlist->node[0].opcode = OPCODE_END_OF_LIST; + return dlist; } @@ -427,14 +429,18 @@ static Node *make_empty_list( void ) */ void _mesa_destroy_list( GLcontext *ctx, GLuint list ) { + struct mesa_display_list *dlist; Node *n, *block; GLboolean done; if (list==0) return; - block = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list); - n = block; + dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + if (!dlist) + return; + + n = block = dlist->node; done = block ? GL_FALSE : GL_TRUE; while (!done) { @@ -572,6 +578,7 @@ void _mesa_destroy_list( GLcontext *ctx, GLuint list ) } } + FREE( dlist ); _mesa_HashRemove(ctx->Shared->DisplayList, list); } @@ -5637,18 +5644,29 @@ islist(GLcontext *ctx, GLuint list) static void GLAPIENTRY execute_list( GLcontext *ctx, GLuint list ) { + struct mesa_display_list *dlist; Node *n; GLboolean done; if (list == 0 || !islist(ctx,list)) return; - if (ctx->Driver.BeginCallList) - ctx->Driver.BeginCallList( ctx, list ); + if (ctx->ListState.CallDepth == MAX_LIST_NESTING) { + /* raise an error? */ + return; + } - ctx->ListState.CallDepth++; - n = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + if (!dlist) + return; + + ctx->ListState.CallStack[ctx->ListState.CallDepth++] = dlist; + + if (ctx->Driver.BeginCallList) + ctx->Driver.BeginCallList( ctx, dlist ); + + n = dlist->node; done = GL_FALSE; while (!done) { @@ -6501,10 +6519,11 @@ execute_list( GLcontext *ctx, GLuint list ) } } } - ctx->ListState.CallDepth--; if (ctx->Driver.EndCallList) ctx->Driver.EndCallList( ctx ); + + ctx->ListState.CallStack[ctx->ListState.CallDepth--] = NULL; } @@ -6583,7 +6602,7 @@ _mesa_GenLists(GLsizei range ) /* reserve the list IDs by with empty/dummy lists */ GLint i; for (i=0; iShared->DisplayList, base+i, make_empty_list()); + _mesa_HashInsert(ctx->Shared->DisplayList, base+i, make_list(base+i, 1)); } } @@ -6631,7 +6650,8 @@ _mesa_NewList( GLuint list, GLenum mode ) /* Allocate new display list */ ctx->ListState.CurrentListNum = list; - ctx->ListState.CurrentBlock = (Node *) CALLOC( sizeof(Node) * BLOCK_SIZE ); + ctx->ListState.CurrentList = make_list( list, BLOCK_SIZE ); + ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->node; ctx->ListState.CurrentListPtr = ctx->ListState.CurrentBlock; ctx->ListState.CurrentPos = 0; @@ -6679,19 +6699,20 @@ _mesa_EndList( void ) /* Destroy old list, if any */ _mesa_destroy_list(ctx, ctx->ListState.CurrentListNum); /* Install the list */ - _mesa_HashInsert(ctx->Shared->DisplayList, ctx->ListState.CurrentListNum, ctx->ListState.CurrentListPtr); + _mesa_HashInsert(ctx->Shared->DisplayList, ctx->ListState.CurrentListNum, ctx->ListState.CurrentList); if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) mesa_print_display_list(ctx->ListState.CurrentListNum); + ctx->Driver.EndList( ctx ); + + ctx->ListState.CurrentList = NULL; ctx->ListState.CurrentListNum = 0; ctx->ListState.CurrentListPtr = NULL; ctx->ExecuteFlag = GL_TRUE; ctx->CompileFlag = GL_FALSE; - ctx->Driver.EndList( ctx ); - ctx->CurrentDispatch = ctx->Exec; _glapi_set_dispatch( ctx->CurrentDispatch ); } @@ -8032,6 +8053,7 @@ static const char *enum_string( GLenum k ) */ static void GLAPIENTRY print_list( GLcontext *ctx, GLuint list ) { + struct mesa_display_list *dlist; Node *n; GLboolean done; @@ -8040,8 +8062,12 @@ static void GLAPIENTRY print_list( GLcontext *ctx, GLuint list ) return; } - n = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + if (!dlist) + return; + n = dlist->node; + _mesa_printf("START-LIST %u, address %p\n", list, (void*)n ); done = n ? GL_FALSE : GL_TRUE; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index ed6e6b02b36..dc3dcbba1a2 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2428,17 +2428,38 @@ struct gl_tnl_module /*@}*/ }; +/* Strictly this is a tnl/ private concept, but it doesn't seem + * worthwhile adding a tnl private structure just to hold this one bit + * of information: + */ +#define MESA_DLIST_DANGLING_REFS 0x1 + +/* Provide a location where information about a display list can be + * collected. Could be extended with driverPrivate structures, + * etc. in the future. + */ +struct mesa_display_list +{ + Node *node; + GLuint id; + GLuint flags; +}; + /** * State used during display list compilation and execution. */ struct mesa_list_state { + struct mesa_display_list *CallStack[MAX_LIST_NESTING]; GLuint CallDepth; /**< Current recursion calling depth */ + + struct mesa_display_list *CurrentList; Node *CurrentListPtr; /**< Head of list being compiled */ GLuint CurrentListNum; /**< Number of the list being compiled */ Node *CurrentBlock; /**< Pointer to current block of nodes */ GLuint CurrentPos; /**< Index into current block of nodes */ + GLvertexformat ListVtxfmt; GLubyte ActiveAttribSize[VERT_ATTRIB_MAX]; diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index 2d99c8576f0..56fc2013dc3 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -364,6 +364,7 @@ struct tnl_save { GLfloat *buffer; GLuint count; GLuint wrap_count; + GLuint replay_flags; struct tnl_prim *prim; GLuint prim_count, prim_max; diff --git a/src/mesa/tnl/t_save_api.c b/src/mesa/tnl/t_save_api.c index 81b68f77bea..6e737f400f4 100644 --- a/src/mesa/tnl/t_save_api.c +++ b/src/mesa/tnl/t_save_api.c @@ -248,7 +248,6 @@ static void _save_compile_vertex_list( GLcontext *ctx ) node->prim_count = tnl->save.prim_count; node->vertex_store = tnl->save.vertex_store; node->prim_store = tnl->save.prim_store; - node->dangling_attr_ref = tnl->save.dangling_attr_ref; node->normal_lengths = 0; node->vertex_store->refcount++; @@ -257,13 +256,17 @@ static void _save_compile_vertex_list( GLcontext *ctx ) assert(node->attrsz[_TNL_ATTRIB_POS] != 0 || node->count == 0); + if (tnl->save.dangling_attr_ref) + ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS; + /* Maybe calculate normal lengths: */ if (tnl->CalcDListNormalLengths && node->attrsz[_TNL_ATTRIB_NORMAL] == 3 && - !node->dangling_attr_ref) + !(ctx->ListState.CurrentList->flags & MESA_DLIST_DANGLING_REFS)) build_normal_lengths( node ); + tnl->save.vertex_store->used += tnl->save.vertex_size * node->count; tnl->save.prim_store->used += node->prim_count; @@ -1189,8 +1192,6 @@ static void GLAPIENTRY _save_Indexfv( const GLfloat *f ) do { \ TNLcontext *tnl = TNL_CONTEXT(ctx); \ \ - /*fprintf(stderr, "fallback %s inside begin/end\n", __FUNCTION__);*/ \ - \ if (tnl->save.initial_counter != tnl->save.counter || \ tnl->save.prim_count) \ _save_compile_vertex_list( ctx ); \ @@ -1577,14 +1578,19 @@ void _tnl_EndList( GLcontext *ctx ) assert(TNL_CONTEXT(ctx)->save.vertex_size == 0); } -void _tnl_BeginCallList( GLcontext *ctx, GLuint list ) +void _tnl_BeginCallList( GLcontext *ctx, struct mesa_display_list *dlist ) { - (void) ctx; (void) list; + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->save.replay_flags |= dlist->flags; + tnl->save.replay_flags |= tnl->LoopbackDListCassettes; } void _tnl_EndCallList( GLcontext *ctx ) { - (void) ctx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (ctx->ListState.CallDepth == 1) + tnl->save.replay_flags = 0; } diff --git a/src/mesa/tnl/t_save_api.h b/src/mesa/tnl/t_save_api.h index eec2d685b00..8ffb7f57331 100644 --- a/src/mesa/tnl/t_save_api.h +++ b/src/mesa/tnl/t_save_api.h @@ -43,7 +43,7 @@ extern void _tnl_EndList( GLcontext *ctx ); extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode ); extern void _tnl_EndCallList( GLcontext *ctx ); -extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list ); +extern void _tnl_BeginCallList( GLcontext *ctx, struct mesa_display_list *list ); extern void _tnl_SaveFlushVertices( GLcontext *ctx ); diff --git a/src/mesa/tnl/t_save_playback.c b/src/mesa/tnl/t_save_playback.c index 26c77bd7d8e..d5fcbe6c02a 100644 --- a/src/mesa/tnl/t_save_playback.c +++ b/src/mesa/tnl/t_save_playback.c @@ -178,7 +178,7 @@ void _tnl_playback_vertex_list( GLcontext *ctx, void *data ) if (node->prim_count > 0 && node->count > 0) { if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END && - (node->prim[0].mode & PRIM_BEGIN)) { + (node->prim[0].mode & PRIM_BEGIN)) { /* Degenerate case: list is called inside begin/end pair and * includes operations such as glBegin or glDrawArrays. @@ -187,10 +187,9 @@ void _tnl_playback_vertex_list( GLcontext *ctx, void *data ) _tnl_loopback_vertex_list( ctx, node ); return; } - else if (tnl->LoopbackDListCassettes || - node->dangling_attr_ref) { - /* Degenerate case: list references current data and would - * require fixup. Take the easier option & loop it back. + else if (tnl->save.replay_flags) { + /* Various degnerate cases: translate into immediate mode + * calls rather than trying to execute in place. */ _tnl_loopback_vertex_list( ctx, node ); return; -- 2.30.2