summaryrefslogtreecommitdiff
path: root/src/mesa
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2005-01-22 14:38:00 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2005-01-22 14:38:00 +0000
commit36a35c5614336bffdac4827c1e04bcaa8ab2fa27 (patch)
treee7a41d044ac2998fe23e89b0f36868de67fa05d1 /src/mesa
parent8fca9bdc35bfb5220012cfa5041504b0a05d2440 (diff)
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.
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/main/dd.h7
-rw-r--r--src/mesa/main/dlist.c60
-rw-r--r--src/mesa/main/mtypes.h21
-rw-r--r--src/mesa/tnl/t_context.h1
-rw-r--r--src/mesa/tnl/t_save_api.c20
-rw-r--r--src/mesa/tnl/t_save_api.h2
-rw-r--r--src/mesa/tnl/t_save_playback.c9
7 files changed, 87 insertions, 33 deletions
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index f7f7eacf06..def550109c 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 beacf5b1f9..f95e8db98c 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; i<range; i++) {
- _mesa_HashInsert(ctx->Shared->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 ed6e6b02b3..dc3dcbba1a 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 2d99c8576f..56fc2013dc 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 81b68f77be..6e737f400f 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 eec2d685b0..8ffb7f5733 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 26c77bd7d8..d5fcbe6c02 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;