mesa: fix glMaterial / dlist bug
authorBrian Paul <brianp@vmware.com>
Tue, 8 May 2012 17:41:03 +0000 (11:41 -0600)
committerBrian Paul <brianp@vmware.com>
Fri, 11 May 2012 22:13:14 +0000 (16:13 -0600)
When glColorMaterial() is used to latch glColor commands to a material
attribute, glMaterial calls to change that material should become no-ops.
This failed to work properly when the glMaterial call was inside a
display list.

This removes the Material function from the vbo_attrib_tmp.h template
file.  We have separate/different implementations for the "save" and
"exec" cases now.

NOTE: This is a candidate for the 8.0 branch.

src/mesa/vbo/vbo_attrib_tmp.h
src/mesa/vbo/vbo_exec_api.c
src/mesa/vbo/vbo_save_api.c

index 0bf5c91658dbca4ac16ef4ceaef37bee3bef6ddd..d3fc77eefdee2a84a7d5c4b41fd3562dbfecf37e 100644 (file)
@@ -792,63 +792,6 @@ TAG(VertexAttrib4fvNV)(GLuint index, const GLfloat * v)
 }
 
 
-
-#define MAT( ATTR, N, face, params )                   \
-do {                                                   \
-   if (face != GL_BACK)                                        \
-      MAT_ATTR( ATTR, N, params ); /* front */         \
-   if (face != GL_FRONT)                               \
-      MAT_ATTR( ATTR + 1, N, params ); /* back */      \
-} while (0)
-
-
-/* Colormaterial conflicts are dealt with later.
- */
-static void GLAPIENTRY
-TAG(Materialfv)(GLenum face, GLenum pname,
-                 const GLfloat * params)
-{
-   GET_CURRENT_CONTEXT(ctx);
-
-   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
-      return;
-   }
-
-   switch (pname) {
-   case GL_EMISSION:
-      MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
-      break;
-   case GL_AMBIENT:
-      MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
-      break;
-   case GL_DIFFUSE:
-      MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
-      break;
-   case GL_SPECULAR:
-      MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
-      break;
-   case GL_SHININESS:
-      if (*params < 0 || *params > ctx->Const.MaxShininess)
-         _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glMaterial(invalid shininess: %f out range [0, %f])",
-                    *params, ctx->Const.MaxShininess);
-      else
-         MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
-      break;
-   case GL_COLOR_INDEXES:
-      MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
-      break;
-   case GL_AMBIENT_AND_DIFFUSE:
-      MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
-      MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
-      break;
-   default:
-      ERROR(GL_INVALID_ENUM);
-      return;
-   }
-}
-
 static void GLAPIENTRY
 TAG(VertexP2ui)(GLenum type, GLuint value)
 {
@@ -1145,4 +1088,3 @@ TAG(VertexAttribP4uiv)(GLuint index, GLenum type, GLboolean normalized,
 #undef ATTR_UI
 
 #undef MAT
-#undef MAT_ATTR
index b87da18f3ebdf55b3ccb4b52da4754c4f3788e1d..0fd8d5915171b1fa8d8d3d4d848ff73376dadd14 100644 (file)
@@ -433,6 +433,101 @@ do {                                                                      \
 #include "vbo_attrib_tmp.h"
 
 
+
+/**
+ * Execute a glMaterial call.  Note that if GL_COLOR_MATERIAL is enabled,
+ * this may be a (partial) no-op.
+ */
+static void GLAPIENTRY
+vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
+{
+   GLbitfield updateMats;
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* This function should be a no-op when it tries to update material
+    * attributes which are currently tracking glColor via glColorMaterial.
+    * The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits
+    * indicating which material attributes can actually be updated below.
+    */
+   if (ctx->Light.ColorMaterialEnabled) {
+      updateMats = ~ctx->Light.ColorMaterialBitmask;
+   }
+   else {
+      /* GL_COLOR_MATERIAL is disabled so don't skip any material updates */
+      updateMats = ALL_MATERIAL_BITS;
+   }
+
+   if (face == GL_FRONT) {
+      updateMats &= FRONT_MATERIAL_BITS;
+   }
+   else if (face == GL_BACK) {
+      updateMats &= BACK_MATERIAL_BITS;
+   }
+   else if (face != GL_FRONT_AND_BACK) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
+      return;
+   }
+
+   switch (pname) {
+   case GL_EMISSION:
+      if (updateMats & MAT_BIT_FRONT_EMISSION)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params);
+      if (updateMats & MAT_BIT_BACK_EMISSION)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params);
+      break;
+   case GL_AMBIENT:
+      if (updateMats & MAT_BIT_FRONT_AMBIENT)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
+      if (updateMats & MAT_BIT_BACK_AMBIENT)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
+      break;
+   case GL_DIFFUSE:
+      if (updateMats & MAT_BIT_FRONT_DIFFUSE)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
+      if (updateMats & MAT_BIT_BACK_DIFFUSE)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
+      break;
+   case GL_SPECULAR:
+      if (updateMats & MAT_BIT_FRONT_SPECULAR)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params);
+      if (updateMats & MAT_BIT_BACK_SPECULAR)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params);
+      break;
+   case GL_SHININESS:
+      if (*params < 0 || *params > ctx->Const.MaxShininess) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glMaterial(invalid shininess: %f out range [0, %f])",
+                    *params, ctx->Const.MaxShininess);
+         return;
+      }
+      if (updateMats & MAT_BIT_FRONT_SHININESS)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params);
+      if (updateMats & MAT_BIT_BACK_SHININESS)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params);
+      break;
+   case GL_COLOR_INDEXES:
+      if (updateMats & MAT_BIT_FRONT_INDEXES)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params);
+      if (updateMats & MAT_BIT_BACK_INDEXES)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params);
+      break;
+   case GL_AMBIENT_AND_DIFFUSE:
+      if (updateMats & MAT_BIT_FRONT_AMBIENT)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
+      if (updateMats & MAT_BIT_FRONT_DIFFUSE)
+         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
+      if (updateMats & MAT_BIT_BACK_AMBIENT)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
+      if (updateMats & MAT_BIT_BACK_DIFFUSE)
+         MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
+      break;
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
+      return;
+   }
+}
+
+
 /**
  * Flush (draw) vertices.
  * \param  unmap - leave VBO unmapped after flushing?
index 74f5dc9ce68bcc25f298f3fd52edb0ab950ab292..f202375caa4613fb781b74ca96e2134b76b78088 100644 (file)
@@ -724,6 +724,63 @@ do {                                                               \
 
 
 
+#define MAT( ATTR, N, face, params )                   \
+do {                                                   \
+   if (face != GL_BACK)                                        \
+      MAT_ATTR( ATTR, N, params ); /* front */         \
+   if (face != GL_FRONT)                               \
+      MAT_ATTR( ATTR + 1, N, params ); /* back */      \
+} while (0)
+
+
+/**
+ * Save a glMaterial call found between glBegin/End.
+ * glMaterial calls outside Begin/End are handled in dlist.c.
+ */
+static void GLAPIENTRY
+_save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
+      _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
+      return;
+   }
+
+   switch (pname) {
+   case GL_EMISSION:
+      MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
+      break;
+   case GL_AMBIENT:
+      MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
+      break;
+   case GL_DIFFUSE:
+      MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
+      break;
+   case GL_SPECULAR:
+      MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
+      break;
+   case GL_SHININESS:
+      if (*params < 0 || *params > ctx->Const.MaxShininess) {
+         _mesa_compile_error(ctx, GL_INVALID_VALUE, "glMaterial(shininess)");
+      }
+      else {
+         MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
+      }
+      break;
+   case GL_COLOR_INDEXES:
+      MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
+      break;
+   case GL_AMBIENT_AND_DIFFUSE:
+      MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
+      MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
+      break;
+   default:
+      _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
+      return;
+   }
+}
+
 
 /* Cope with EvalCoord/CallList called within a begin/end object:
  *     -- Flush current buffer