Skip to content
Snippets Groups Projects
Commit 86ac3e3c authored by Keith Whitwell's avatar Keith Whitwell
Browse files

Deal with wrapped, weak primitives correctly.

parent 5c2d467e
No related branches found
No related tags found
No related merge requests found
......@@ -41,6 +41,9 @@
* glVertex()
* ... lots of vertices ...
* glEnd()
*
* or:
* glDrawArrays(...)
*
* and then tries to execute it like this:
*
......@@ -58,7 +61,7 @@
* usage.
*
* Further, replaying degenerately-called lists in this fashion is
* probably no worse than the replay using opcodes.
* probably still faster than the replay using opcodes.
*/
typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
......@@ -174,6 +177,82 @@ struct loopback_attr {
attr_func func;
};
/* Don't emit ends and begins on wrapped primitives. Don't replay
* wrapped vertices. If we get here, it's probably because the the
* precalculated wrapping is wrong.
*/
static void loopback_prim( GLcontext *ctx,
struct tnl_vertex_list *list, GLuint i,
struct loopback_attr *la, GLuint nr )
{
struct tnl_prim *prim = &list->prim[i];
GLint begin = prim->start;
GLint end = begin + prim->count;
GLfloat *data;
GLint j, k;
if (prim->mode & PRIM_BEGIN) {
glBegin( prim->mode & PRIM_MODE_MASK );
} else {
assert(i == 0);
assert(begin == 0);
begin += list->wrap_count;
}
data = list->buffer + begin * list->vertex_size;
for (j = begin ; j < end ; j++) {
GLfloat *tmp = data + la[0].sz;
for (k = 1 ; k < nr ; k++) {
la[k].func( ctx, la[k].target, tmp );
tmp += la[k].sz;
}
/* Fire the vertex
*/
la[0].func( ctx, VERT_ATTRIB_POS, data );
data = tmp;
}
if (prim->mode & PRIM_END) {
glEnd();
}
else {
assert (i == list->prim_count-1);
}
}
/* Primitives generated by DrawArrays/DrawElements/Rectf may be
* caught here. If there is no primitive in progress, execute them
* normally, otherwise need to track and discard the generated
* primitives.
*/
static void loopback_weak_prim( GLcontext *ctx,
struct tnl_vertex_list *list, GLuint i,
struct loopback_attr *la, GLuint nr )
{
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END)
loopback_prim( ctx, list, i, la, nr );
else {
struct tnl_prim *prim = &list->prim[i];
/* Use the prim_weak flag to ensure that if this primitive
* wraps, we don't mistake future vertex_lists for part of the
* surrounding primitive.
*
* While this flag is set, we are simply disposing of data
* generated by an operation now known to be a noop.
*/
if (prim->mode & PRIM_BEGIN)
ctx->Driver.CurrentExecPrimitive |= PRIM_WEAK;
if (prim->mode & PRIM_END)
ctx->Driver.CurrentExecPrimitive &= ~PRIM_WEAK;
}
}
void _tnl_loopback_vertex_list( GLcontext *ctx, struct tnl_vertex_list *list )
{
struct loopback_attr la[_TNL_ATTRIB_MAX];
......@@ -213,46 +292,10 @@ void _tnl_loopback_vertex_list( GLcontext *ctx, struct tnl_vertex_list *list )
nr++;
}
/* Don't emit ends and begins on wrapped primitives. Don't replay
* wrapped vertices. If we get here, it's probably because the the
* precalculated wrapping is wrong.
*/
for (i = 0 ; i < list->prim_count ; i++) {
struct tnl_prim *prim = &list->prim[i];
GLint begin = prim->start;
GLint end = begin + prim->count;
GLfloat *data;
GLint j, k;
if (prim->mode & PRIM_BEGIN) {
glBegin( prim->mode & PRIM_MODE_MASK );
} else {
assert(i == 0);
assert(begin == 0);
begin += list->wrap_count;
}
data = list->buffer + begin * list->vertex_size;
for (j = begin ; j < end ; j++) {
GLfloat *tmp = data + la[0].sz;
for (k = 1 ; k < nr ; k++) {
la[k].func( ctx, la[k].target, tmp );
tmp += la[k].sz;
}
/* Fire the vertex
*/
la[0].func( ctx, VERT_ATTRIB_POS, data );
data = tmp;
}
if (prim->mode & PRIM_END) {
glEnd();
}
else {
assert (i == list->prim_count-1);
}
if (list->prim[i].mode & PRIM_WEAK)
loopback_weak_prim( ctx, list, i, la, nr );
else
loopback_prim( ctx, list, i, la, nr );
}
}
......@@ -65,9 +65,6 @@ static void _tnl_bind_vertex_list( GLcontext *ctx,
VB->PrimitiveCount = node->prim_count;
VB->Elts = NULL;
VB->NormalLengthPtr = NULL;
VB->ColorPtr[1] = NULL;
VB->SecondaryColorPtr[1] = NULL;
VB->IndexPtr[1] = NULL;
for (attr = 0; attr <= _TNL_ATTRIB_INDEX; attr++) {
if (node->attrsz[attr]) {
......@@ -108,8 +105,11 @@ static void _tnl_bind_vertex_list( GLcontext *ctx,
VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
VB->ColorPtr[1] = 0;
VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_INDEX];
VB->IndexPtr[1] = 0;
VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1];
VB->SecondaryColorPtr[1] = 0;
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
......@@ -179,8 +179,7 @@ void _tnl_playback_vertex_list( GLcontext *ctx, void *data )
* includes operations such as glBegin or glDrawArrays.
*/
_mesa_error( ctx, GL_INVALID_OPERATION, "displaylist recursive begin");
if (!(node->prim[0].mode & PRIM_WEAK))
_tnl_loopback_vertex_list( ctx, data );
_tnl_loopback_vertex_list( ctx, data );
return;
}
else if (node->dangling_attr_ref) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment