Mesa (mesa_7_5_branch): mesa/vbo: fix compile and replay of nodes ending in a FALLBACK

Keith Whitwell keithw at kemper.freedesktop.org
Tue Jun 30 19:01:49 UTC 2009


Module: Mesa
Branch: mesa_7_5_branch
Commit: e5cb11addad31f698dc8261e7f96d5e3af4a85d6
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e5cb11addad31f698dc8261e7f96d5e3af4a85d6

Author: Keith Whitwell <keithw at vmware.com>
Date:   Tue Jun 30 19:52:44 2009 +0100

mesa/vbo: fix compile and replay of nodes ending in a FALLBACK

Where vbo save nodes are terminated with a call to DO_FALLBACK(), as in
the case of a recursive CallList which is itself within a Begin/End pair,
there two problems:
1) The display list node's primitive information was incorrect, stating
the cut-off prim had zero vertices
2) On replay, we would get confused by a primitive that started in a
node, but was terminated by individual opcodes.

This change fixes the first problem by correctly terminating the last
primitive on fallback, and the second by forcing the display list to
use the Loopback path, converting all nodes into immediate-mode rendering.

The loopback fix is a performance hit, but avoiding this would require
a fairly large rework of this code.

---

 progs/trivial/Makefile               |    1 +
 progs/trivial/dlist-begin-call-end.c |  159 ++++++++++++++++++++++++++++++++++
 src/mesa/vbo/vbo_save_api.c          |   40 ++++++---
 3 files changed, 187 insertions(+), 13 deletions(-)

diff --git a/progs/trivial/Makefile b/progs/trivial/Makefile
index de862b0..fa200db 100644
--- a/progs/trivial/Makefile
+++ b/progs/trivial/Makefile
@@ -19,6 +19,7 @@ SOURCES = \
 	clear-random.c \
 	clear.c \
 	dlist-dangling.c \
+	dlist-begin-call-end.c \
 	dlist-edgeflag-dangling.c \
 	dlist-edgeflag.c \
 	dlist-degenerate.c \
diff --git a/progs/trivial/dlist-begin-call-end.c b/progs/trivial/dlist-begin-call-end.c
new file mode 100644
index 0000000..0d0aed7
--- /dev/null
+++ b/progs/trivial/dlist-begin-call-end.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the name of
+ * Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
+ * ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <GL/glut.h>
+
+
+#define CI_OFFSET_1 16
+#define CI_OFFSET_2 32
+
+
+GLenum doubleBuffer;
+GLint first_list, list;
+
+static void Init(void)
+{
+   fprintf(stderr, "GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
+   fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
+   fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
+   fflush(stderr);
+
+   glClearColor(0.0, 0.0, 1.0, 0.0);
+
+   /* First list will disrupt state which might potentially be
+    * short-circuited in calling list:
+    */
+   first_list = glGenLists(1);
+   glNewList(first_list, GL_COMPILE); 
+//   glColor3f(0,1,0);
+   glEndList();
+
+
+   /* List that looks like it might have redundant state:
+    */
+   list = glGenLists(1);
+   glNewList(list, GL_COMPILE); 
+
+   glShadeModel(GL_FLAT);
+   glBegin(GL_TRIANGLES);
+   glColor3f(1,0,0);
+   glVertex3f( -0.9,  0.9, -30.0);
+   glVertex3f( -0.9, -0.9, -30.0);
+   glCallList( first_list );
+   glVertex3f(  0.9,  0.0, -30.0);
+   glEnd();
+   glEndList();
+}
+
+static void Reshape(int width, int height)
+{
+
+    glViewport(0, 0, (GLint)width, (GLint)height);
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
+    glMatrixMode(GL_MODELVIEW);
+}
+
+static void Key(unsigned char key, int x, int y)
+{
+
+    switch (key) {
+      case 27:
+	exit(1);
+      default:
+	return;
+    }
+
+    glutPostRedisplay();
+}
+
+
+
+
+static void Draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT); 
+
+   glShadeModel( GL_SMOOTH );
+   glCallList(list);
+
+   glFlush();
+
+   if (doubleBuffer) {
+      glutSwapBuffers();
+   }
+}
+
+static GLenum Args(int argc, char **argv)
+{
+    GLint i;
+
+    doubleBuffer = GL_FALSE;
+
+    for (i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-sb") == 0) {
+	    doubleBuffer = GL_FALSE;
+	} else if (strcmp(argv[i], "-db") == 0) {
+	    doubleBuffer = GL_TRUE;
+	} else {
+	    fprintf(stderr, "%s (Bad option).\n", argv[i]);
+	    return GL_FALSE;
+	}
+    }
+    return GL_TRUE;
+}
+
+int main(int argc, char **argv)
+{
+    GLenum type;
+
+    glutInit(&argc, argv);
+
+    if (Args(argc, argv) == GL_FALSE) {
+	exit(1);
+    }
+
+    glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
+
+    type = GLUT_RGB | GLUT_ALPHA;
+    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
+    glutInitDisplayMode(type);
+
+    if (glutCreateWindow(*argv) == GL_FALSE) {
+	exit(1);
+    }
+
+    Init();
+
+    glutReshapeFunc(Reshape);
+    glutKeyboardFunc(Key);
+    glutDisplayFunc(Draw);
+    glutMainLoop();
+	return 0;
+}
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index 8682260..7dcb5c8 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -667,19 +667,33 @@ do {								\
  *     -- Flush current buffer
  *     -- Fallback to opcodes for the rest of the begin/end object.
  */
-#define DO_FALLBACK(ctx) 							\
-do {									\
-   struct vbo_save_context *save = &vbo_context(ctx)->save;					\
-									\
-   if (save->vert_count || save->prim_count) 						\
-      _save_compile_vertex_list( ctx );					\
-									\
-   _save_copy_to_current( ctx );					\
-   _save_reset_vertex( ctx );						\
-   _save_reset_counters( ctx );  \
-   _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );	\
-   ctx->Driver.SaveNeedFlush = 0;					\
-} while (0)
+static void DO_FALLBACK( GLcontext *ctx )
+{
+   struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+   if (save->vert_count || save->prim_count) {
+      GLint i = save->prim_count - 1;
+
+      /* Close off in-progress primitive.
+       */
+      save->prim[i].count = (save->vert_count - 
+                             save->prim[i].start);
+
+      /* Need to replay this display list with loopback,
+       * unfortunately, otherwise this primitive won't be handled
+       * properly:
+       */
+      save->dangling_attr_ref = 1;
+      
+      _save_compile_vertex_list( ctx );
+   }
+
+   _save_copy_to_current( ctx );
+   _save_reset_vertex( ctx );
+   _save_reset_counters( ctx );
+   _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+   ctx->Driver.SaveNeedFlush = 0;
+}
 
 static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
 {




More information about the mesa-commit mailing list