mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 07:28:11 +02:00
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.
This commit is contained in:
parent
8fca9bdc35
commit
36a35c5614
7 changed files with 87 additions and 33 deletions
|
|
@ -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().
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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->ListState.CallDepth == MAX_LIST_NESTING) {
|
||||
/* raise an error? */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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, list );
|
||||
ctx->Driver.BeginCallList( ctx, dlist );
|
||||
|
||||
ctx->ListState.CallDepth++;
|
||||
|
||||
n = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue