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.tags/jump_and_click
@@ -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->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; |
@@ -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; |