Merge commit 'origin/dlist-statechange-shortcircuit' into mesa_7_5_branch
authorKeith Whitwell <keithw@vmware.com>
Thu, 2 Jul 2009 12:29:46 +0000 (13:29 +0100)
committerKeith Whitwell <keithw@vmware.com>
Thu, 2 Jul 2009 12:29:46 +0000 (13:29 +0100)
Conflicts:
progs/trivial/Makefile

Pull in a minimal version of statechange shortcircuiting in display
list compilation.  This affects only glMaterial and glShadeModel state,
and includes quite a few tests to exercise various tricky cases.

If this goes well, will consider extending to all state in the future.

14 files changed:
progs/trivial/Makefile
progs/trivial/dlist-flat-tri.c [new file with mode: 0644]
progs/trivial/dlist-mat-tri.c [new file with mode: 0644]
progs/trivial/dlist-recursive-call.c [new file with mode: 0644]
progs/trivial/dlist-tri-flat-tri.c [new file with mode: 0644]
progs/trivial/dlist-tri-mat-tri.c [new file with mode: 0644]
src/mesa/main/dlist.c
src/mesa/main/enums.c
src/mesa/main/enums.h
src/mesa/main/mtypes.h
src/mesa/vbo/vbo_exec_draw.c
src/mesa/vbo/vbo_save_api.c
src/mesa/vbo/vbo_save_loopback.c
src/mesa/vbo/vbo_split_copy.c

index fa200dbf896fb036d83f498538124cd9e9415308..3bd8faff99a6ac09e02ec842dd205ae720a46aba 100644 (file)
@@ -19,6 +19,11 @@ SOURCES = \
        clear-random.c \
        clear.c \
        dlist-dangling.c \
+       dlist-flat-tri.c \
+       dlist-mat-tri.c \
+       dlist-tri-flat-tri.c \
+       dlist-tri-mat-tri.c \
+       dlist-recursive-call.c \
        dlist-begin-call-end.c \
        dlist-edgeflag-dangling.c \
        dlist-edgeflag.c \
diff --git a/progs/trivial/dlist-flat-tri.c b/progs/trivial/dlist-flat-tri.c
new file mode 100644 (file)
index 0000000..c3dd792
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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 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);
+
+   list = glGenLists(1);
+   glNewList(list, GL_COMPILE); 
+
+   /* XXX: this state-change will only be executed if list is called
+    * from outside a begin/end pair:
+    */
+   glShadeModel( GL_FLAT );
+   glBegin(GL_TRIANGLES);
+   glColor3f(0,0,.7);
+   glVertex3f( -0.9,  0.9, -30.0);
+   glColor3f(0,.9,0);
+   glVertex3f( -0.9, -0.9, -30.0);
+   glColor3f(.8,0,0);
+   glVertex3f(  0.9,  0.0, -30.0);
+   glEnd();
+
+   /* This statechange is potentially NOT redundant:
+    */
+   glShadeModel( GL_FLAT );
+   glBegin(GL_TRIANGLES);
+   glColor3f(0,1,0);
+   glVertex3f( -0.5,  0.5, -30.0);
+   glColor3f(0,0,1);
+   glVertex3f( -0.5, -0.5, -30.0);
+   glColor3f(1,0,0);
+   glVertex3f(  0.5,  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 );
+
+   glBegin(GL_TRIANGLES);
+
+   /* Note: call the list from inside a begin/end pair.  The end is
+    * provided by the display list...
+    */
+   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/progs/trivial/dlist-mat-tri.c b/progs/trivial/dlist-mat-tri.c
new file mode 100644 (file)
index 0000000..ed3a4c5
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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 list;
+
+static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
+static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
+/*static GLfloat blue[4] = {0.2, 0.2, .7, 1.0};*/
+
+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);
+
+   glClear(GL_COLOR_BUFFER_BIT); 
+
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+
+   glClearColor(0.0, 0.0, 1.0, 0.0);
+
+   list = glGenLists(1);
+   glNewList(list, GL_COMPILE); 
+
+   /* XXX: this state-change will be executed regardless of whether
+    * the list is called from outside a begin/end pair:
+    */
+   glMaterialfv(GL_FRONT, GL_AMBIENT, red);
+   glBegin(GL_TRIANGLES);
+   glVertex3f( -0.9,  0.9, -30.0);
+   glVertex3f( -0.9, -0.9, -30.0);
+   glVertex3f(  0.9,  0.0, -30.0);
+   glEnd();
+
+   glMaterialfv(GL_FRONT, GL_DIFFUSE, red);
+   glBegin(GL_TRIANGLES);
+   glVertex3f( -0.7,  0.7, -30.0);
+   glVertex3f( -0.7, -0.7, -30.0);
+   glVertex3f(  0.7,  0.0, -30.0);
+   glEnd();
+
+   /* This statechange is redundant:
+    */
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+   glBegin(GL_TRIANGLES);
+   glVertex3f( -0.5,  0.5, -30.0);
+   glVertex3f( -0.5, -0.5, -30.0);
+   glVertex3f(  0.5,  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 );
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+
+   glBegin(GL_TRIANGLES);
+
+   /* Note: call the list from inside a begin/end pair.  The end is
+    * provided by the display list...
+    */
+   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/progs/trivial/dlist-recursive-call.c b/progs/trivial/dlist-recursive-call.c
new file mode 100644 (file)
index 0000000..fe06b2b
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * 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); 
+   glShadeModel( GL_SMOOTH );
+   glEndList();
+
+
+   /* List that looks like it might have redundant state:
+    */
+   list = glGenLists(1);
+   glNewList(list, GL_COMPILE); 
+
+   glBegin(GL_TRIANGLES);
+   glColor3f(0,0,.7);
+   glVertex3f( 0.9, -0.9, -30.0);
+   glColor3f(.8,0,0);
+   glVertex3f( 0.9,  0.9, -30.0);
+   glColor3f(0,.9,0);
+   glVertex3f(-0.9,  0.0, -30.0);
+   glEnd();
+
+   glShadeModel( GL_FLAT );
+   glBegin(GL_TRIANGLES);
+   glColor3f(0,0,.7);
+   glVertex3f( -0.9,  0.9, -30.0);
+   glColor3f(0,.9,0);
+   glVertex3f( -0.9, -0.9, -30.0);
+   glColor3f(.8,0,0);
+   glVertex3f(  0.9,  0.0, -30.0);
+   glEnd();
+
+   glCallList( first_list );
+
+   /* Do a quick begin/end to ensure we are not inside a dangling
+    * primitive from the called list:
+    */
+   glBegin( GL_POINTS );
+   glEnd();
+
+   /* This statechange is NOT redundant:
+    */
+   glShadeModel( GL_FLAT );
+   glBegin(GL_TRIANGLES);
+   glColor3f(1,0,0);
+   glVertex3f( -0.5,  0.5, -30.0);
+   glColor3f(0,1,0);
+   glVertex3f( -0.5, -0.5, -30.0);
+   glColor3f(0,0,1);
+   glVertex3f(  0.5,  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/progs/trivial/dlist-tri-flat-tri.c b/progs/trivial/dlist-tri-flat-tri.c
new file mode 100644 (file)
index 0000000..4dbb788
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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 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);
+
+   list = glGenLists(1);
+   glNewList(list, GL_COMPILE); 
+
+   glBegin(GL_TRIANGLES);
+   glColor3f(0,0,.7);
+   glVertex3f( 0.9, -0.9, -30.0);
+   glColor3f(.8,0,0);
+   glVertex3f( 0.9,  0.9, -30.0);
+   glColor3f(0,.9,0);
+   glVertex3f(-0.9,  0.0, -30.0);
+   glEnd();
+
+   glShadeModel( GL_FLAT );
+   glBegin(GL_TRIANGLES);
+   glColor3f(0,0,.7);
+   glVertex3f( -0.9,  0.9, -30.0);
+   glColor3f(0,.9,0);
+   glVertex3f( -0.9, -0.9, -30.0);
+   glColor3f(.8,0,0);
+   glVertex3f(  0.9,  0.0, -30.0);
+   glEnd();
+
+   /* This statechange is redundant:
+    */
+   glShadeModel( GL_FLAT );
+   glBegin(GL_TRIANGLES);
+   glColor3f(1,0,0);
+   glVertex3f( -0.5,  0.5, -30.0);
+   glColor3f(0,1,0);
+   glVertex3f( -0.5, -0.5, -30.0);
+   glColor3f(0,0,1);
+   glVertex3f(  0.5,  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/progs/trivial/dlist-tri-mat-tri.c b/progs/trivial/dlist-tri-mat-tri.c
new file mode 100644 (file)
index 0000000..f69854a
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * 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 list;
+
+static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
+static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
+static GLfloat blue[4] = {0.2, 0.2, .9, 1.0};
+
+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);
+
+   glClear(GL_COLOR_BUFFER_BIT); 
+
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+
+   glClearColor(0.0, 0.0, 1.0, 0.0);
+
+   list = glGenLists(1);
+   glNewList(list, GL_COMPILE); 
+
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+
+   glBegin(GL_TRIANGLES);
+   glNormal3f(0,0,.7);
+   glVertex3f( 0.9, -0.9, -30.0);
+   glVertex3f( 0.9,  0.9, -30.0);
+   glVertex3f(-0.9,  0.0, -30.0);
+   glEnd();
+
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+
+   glBegin(GL_TRIANGLES);
+   glVertex3f( -0.9,  0.9, -30.0);
+   glVertex3f( -0.9, -0.9, -30.0);
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+   glVertex3f(  0.9,  0.0, -30.0);
+   glEnd();
+
+   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+   glBegin(GL_TRIANGLES);
+   glVertex3f( -0.5,  0.5, -30.0);
+   glVertex3f( -0.5, -0.5, -30.0);
+   glVertex3f(  0.5,  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;
+}
index 782f847904e580b742ecb88a01a01fdf9d375dc7..c5a1c1f38fcf9805486da64f3f87e7c90dda4cdb 100644 (file)
@@ -957,6 +957,20 @@ save_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
    }
 }
 
+static void invalidate_saved_current_state( GLcontext *ctx )
+{
+   GLint i;
+
+   for (i = 0; i < VERT_ATTRIB_MAX; i++)
+      ctx->ListState.ActiveAttribSize[i] = 0;
+
+   for (i = 0; i < MAT_ATTRIB_MAX; i++)
+      ctx->ListState.ActiveMaterialSize[i] = 0;
+
+   memset(&ctx->ListState.Current, 0, sizeof ctx->ListState.Current);
+
+   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+}
 
 void GLAPIENTRY
 _mesa_save_CallList(GLuint list)
@@ -970,9 +984,10 @@ _mesa_save_CallList(GLuint list)
       n[1].ui = list;
    }
 
-   /* After this, we don't know what begin/end state we're in:
+   /* After this, we don't know what state we're in.  Invalidate all
+    * cached information previously gathered:
     */
-   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+   invalidate_saved_current_state( ctx );
 
    if (ctx->ExecuteFlag) {
       _mesa_CallList(list);
@@ -1015,9 +1030,10 @@ _mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
       }
    }
 
-   /* After this, we don't know what begin/end state we're in:
+   /* After this, we don't know what state we're in.  Invalidate all
+    * cached information previously gathered:
     */
-   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+   invalidate_saved_current_state( ctx );
 
    if (ctx->ExecuteFlag) {
       CALL_CallLists(ctx->Exec, (n, type, lists));
@@ -3177,14 +3193,26 @@ save_ShadeModel(GLenum mode)
 {
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
-   ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+   ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx);
+
+   if (ctx->ExecuteFlag) {
+      CALL_ShadeModel(ctx->Exec, (mode));
+   }
+
+   if (ctx->ListState.Current.ShadeModel == mode)
+      return;
+
+   SAVE_FLUSH_VERTICES(ctx);
+
+   /* Only save the value if we know the statechange will take effect:
+    */
+   if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
+      ctx->ListState.Current.ShadeModel = mode;
+
    n = ALLOC_INSTRUCTION(ctx, OPCODE_SHADE_MODEL, 1);
    if (n) {
       n[1].e = mode;
    }
-   if (ctx->ExecuteFlag) {
-      CALL_ShadeModel(ctx->Exec, (mode));
-   }
 }
 
 
@@ -5146,14 +5174,21 @@ save_EdgeFlag(GLboolean x)
    save_Attr1fNV(VERT_ATTRIB_EDGEFLAG, x ? (GLfloat)1.0 : (GLfloat)0.0);
 }
 
+static INLINE GLboolean compare4fv( const GLfloat *a,
+                                    const GLfloat *b,
+                                    GLuint count )
+{
+   return memcmp( a, b, count * sizeof(GLfloat) ) == 0;
+}
+                              
+
 static void GLAPIENTRY
 save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
 {
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
    int args, i;
-
-   SAVE_FLUSH_VERTICES(ctx);
+   GLuint bitmask;
 
    switch (face) {
    case GL_BACK:
@@ -5183,26 +5218,43 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
       _mesa_compile_error(ctx, GL_INVALID_ENUM, "material(pname)");
       return;
    }
-
-   n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6);
-   if (n) {
-      n[1].e = face;
-      n[2].e = pname;
-      for (i = 0; i < args; i++)
-         n[3 + i].f = param[i];
+   
+   if (ctx->ExecuteFlag) {
+      CALL_Materialfv(ctx->Exec, (face, pname, param));
    }
 
-   {
-      GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL);
-      for (i = 0; i < MAT_ATTRIB_MAX; i++)
-         if (bitmask & (1 << i)) {
+   bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL);
+
+   /* Try to eliminate redundant statechanges.  Because it is legal to
+    * call glMaterial even inside begin/end calls, don't need to worry
+    * about ctx->Driver.CurrentSavePrimitive here.
+    */
+   for (i = 0; i < MAT_ATTRIB_MAX; i++) {
+      if (bitmask & (1 << i)) {
+         if (ctx->ListState.ActiveMaterialSize[i] == args &&
+             compare4fv(ctx->ListState.CurrentMaterial[i], param, args)) {
+            bitmask &= ~(1 << i);
+         }
+         else {
             ctx->ListState.ActiveMaterialSize[i] = args;
             COPY_SZ_4V(ctx->ListState.CurrentMaterial[i], args, param);
          }
+      }
    }
 
-   if (ctx->ExecuteFlag) {
-      CALL_Materialfv(ctx->Exec, (face, pname, param));
+   /* If this call has effect, return early:
+    */
+   if (bitmask == 0)
+      return;
+
+   SAVE_FLUSH_VERTICES(ctx);
+
+   n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6);
+   if (n) {
+      n[1].e = face;
+      n[2].e = pname;
+      for (i = 0; i < args; i++)
+         n[3 + i].f = param[i];
    }
 }
 
@@ -6771,7 +6823,6 @@ void GLAPIENTRY
 _mesa_NewList(GLuint name, GLenum mode)
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLint i;
 
    FLUSH_CURRENT(ctx, 0);       /* must be called before assert */
    ASSERT_OUTSIDE_BEGIN_END(ctx);
@@ -6799,20 +6850,15 @@ _mesa_NewList(GLuint name, GLenum mode)
    ctx->CompileFlag = GL_TRUE;
    ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE);
 
+   /* Reset acumulated list state:
+    */
+   invalidate_saved_current_state( ctx );
+
    /* Allocate new display list */
    ctx->ListState.CurrentList = make_list(name, BLOCK_SIZE);
    ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->Head;
    ctx->ListState.CurrentPos = 0;
 
-   /* Reset acumulated list state:
-    */
-   for (i = 0; i < VERT_ATTRIB_MAX; i++)
-      ctx->ListState.ActiveAttribSize[i] = 0;
-
-   for (i = 0; i < MAT_ATTRIB_MAX; i++)
-      ctx->ListState.ActiveMaterialSize[i] = 0;
-
-   ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
    ctx->Driver.NewList(ctx, name, mode);
 
    ctx->CurrentDispatch = ctx->Save;
index cf893fdac5112ffd97fe2cc2304ef2192e028956..417cee8fb2af968943aa658fd80dd6fd5b517794 100644 (file)
@@ -5059,6 +5059,28 @@ const char *_mesa_lookup_enum_by_nr( int nr )
    }
 }
 
+/* Get the name of an enum given that it is a primitive type.  Avoids
+ * GL_FALSE/GL_POINTS ambiguity and others.
+ */
+const char *_mesa_lookup_prim_by_nr( int nr )
+{
+   switch (nr) {
+   case GL_POINTS: return "GL_POINTS";
+   case GL_LINES: return "GL_LINES";
+   case GL_LINE_STRIP: return "GL_LINE_STRIP";
+   case GL_LINE_LOOP: return "GL_LINE_LOOP";
+   case GL_TRIANGLES: return "GL_TRIANGLES";
+   case GL_TRIANGLE_STRIP: return "GL_TRIANGLE_STRIP";
+   case GL_TRIANGLE_FAN: return "GL_TRIANGLE_FAN";
+   case GL_QUADS: return "GL_QUADS";
+   case GL_QUAD_STRIP: return "GL_QUAD_STRIP";
+   case GL_POLYGON: return "GL_POLYGON";
+   case GL_POLYGON+1: return "OUTSIDE_BEGIN_END";
+   default: return "<invalid>";
+   }
+}
+
+
 int _mesa_lookup_enum_by_name( const char *symbol )
 {
    enum_elt * f = NULL;
index 23a4767f3501eef2f920e59fb528f68998423f4d..b5f69001b84fe5ca9a676b329fe97a1229c3b1ca 100644 (file)
 #if defined(_HAVE_FULL_GL) && _HAVE_FULL_GL
 
 extern const char *_mesa_lookup_enum_by_nr( int nr );
+
+/* Get the name of an enum given that it is a primitive type.  Avoids
+ * GL_FALSE/GL_POINTS ambiguity and others.
+ */
+const char *_mesa_lookup_prim_by_nr( int nr );
+
 extern int _mesa_lookup_enum_by_name( const char *symbol );
 
 #else
index 84a082b253e3abc8705cbe085a01e6b5109bd9db..bdaa4977b72ad64fbd9300dcb5a6af02b3525507 100644 (file)
@@ -2806,6 +2806,13 @@ struct gl_dlist_state
    
    GLubyte ActiveEdgeFlag;
    GLboolean CurrentEdgeFlag;
+
+   struct {
+      /* State known to have been set by the currently-compiling display
+       * list.  Used to eliminate some redundant state changes.
+       */
+      GLenum ShadeModel;
+   } Current;
 };
 
 
index fdacb42e3571d9ffd395e992fff822602eea2de4..c53a4eee00cb65c3420055d77d6a9976afe03eba 100644 (file)
@@ -50,7 +50,7 @@ static void vbo_exec_debug_verts( struct vbo_exec_context *exec )
       struct _mesa_prim *prim = &exec->vtx.prim[i];
       _mesa_printf("   prim %d: %s%s %d..%d %s %s\n",
                   i, 
-                  _mesa_lookup_enum_by_nr(prim->mode),
+                  _mesa_lookup_prim_by_nr(prim->mode),
                   prim->weak ? " (weak)" : "",
                   prim->start, 
                   prim->start + prim->count,
index 7dcb5c8242283f50c5c1e765f46629170f48ee53..85cb79c71ce402a2cdfb2d34c00e01698bdc4a53 100644 (file)
@@ -1162,7 +1162,7 @@ static void vbo_print_vertex_list( GLcontext *ctx, void *data )
       struct _mesa_prim *prim = &node->prim[i];
       _mesa_debug(NULL, "   prim %d: %s%s %d..%d %s %s\n",
                  i, 
-                 _mesa_lookup_enum_by_nr(prim->mode),
+                 _mesa_lookup_prim_by_nr(prim->mode),
                  prim->weak ? " (weak)" : "",
                  prim->start, 
                  prim->start + prim->count,
index 92ca4ea95d3872d8d79a5a99db905157921ec605..b7a74e4535ae561c3fe9f1ef75a74efc2f0be78f 100644 (file)
@@ -97,7 +97,7 @@ static void loopback_prim( GLcontext *ctx,
 
    if (0)
       _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
-                  _mesa_lookup_enum_by_nr(prim->mode),
+                  _mesa_lookup_prim_by_nr(prim->mode),
                   prim->begin ? "begin" : "..",
                   prim->end ? "end" : "..",
                   start, 
index 5fb66d3318f6c77878c1ac14cfff3d9f0582d9ac..b9a5c569876b926bcc8ac72dc15d22ac76521a4a 100644 (file)
@@ -180,7 +180,7 @@ static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag
 {
    struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
 
-/*    _mesa_printf("begin %s (%d)\n", _mesa_lookup_enum_by_nr(mode), begin_flag); */
+/*    _mesa_printf("begin %s (%d)\n", _mesa_lookup_prim_by_nr(mode), begin_flag); */
                
    prim->mode = mode;
    prim->begin = begin_flag;