summaryrefslogtreecommitdiffstats
path: root/src/mesa/tnl/t_save_loopback.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/tnl/t_save_loopback.c')
-rw-r--r--src/mesa/tnl/t_save_loopback.c125
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 );
}
}