diff options
Diffstat (limited to 'src/mesa/tnl/t_save_loopback.c')
-rw-r--r-- | src/mesa/tnl/t_save_loopback.c | 125 |
1 files changed, 84 insertions, 41 deletions
diff --git a/src/mesa/tnl/t_save_loopback.c b/src/mesa/tnl/t_save_loopback.c index 0798203c4bf..b496a784c35 100644 --- a/src/mesa/tnl/t_save_loopback.c +++ b/src/mesa/tnl/t_save_loopback.c @@ -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 ); } } |