From 62068b3bc534d504e40df34847b4436f1a496f35 Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Thu, 3 May 2012 13:38:22 +0200
Subject: xserver mesa git update 3 May 2012

---
 mesalib/src/gallium/auxiliary/util/u_format.h | 13 +++++++
 mesalib/src/glsl/glsl_parser_extras.cpp       | 51 +++++++++++++++++++--------
 mesalib/src/glsl/glsl_parser_extras.h         |  3 +-
 mesalib/src/glsl/standalone_scaffolding.cpp   |  6 ++++
 mesalib/src/glsl/standalone_scaffolding.h     |  4 +++
 mesalib/src/mesa/main/errors.c                | 43 ++++++++++++++++++++++
 mesalib/src/mesa/main/errors.h                |  3 ++
 7 files changed, 107 insertions(+), 16 deletions(-)

(limited to 'mesalib')

diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h
index bd4e51d27..1718fb5e2 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.h
+++ b/mesalib/src/gallium/auxiliary/util/u_format.h
@@ -549,6 +549,19 @@ util_format_colormask(const struct util_format_description *desc)
 }
 
 
+/**
+ * Checks if color mask covers every channel for the specified format
+ *
+ * @param desc       a format description to check colormask with
+ * @param colormask  a bit mask for channels, matches format of PIPE_MASK_RGBA
+ */
+static INLINE boolean
+util_format_colormask_full(const struct util_format_description *desc, unsigned colormask)
+{
+   return (~colormask & util_format_colormask(desc)) == 0;
+}
+
+
 boolean
 util_format_is_float(enum pipe_format format);
 
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index ae7a365f4..6f1c86b43 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -36,8 +36,9 @@ extern "C" {
 #include "ir_optimization.h"
 #include "loop_analysis.h"
 
-_mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx,
+_mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
 					       GLenum target, void *mem_ctx)
+ : ctx(_ctx)
 {
    switch (target) {
    case GL_VERTEX_SHADER:   this->target = vertex_shader; break;
@@ -134,24 +135,49 @@ _mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
    return "unknown";
 }
 
+/* This helper function will append the given message to the shader's
+   info log and report it via GL_ARB_debug_output. Per that extension,
+   'type' is one of the enum values classifying the message, and
+   'id' is the implementation-defined ID of the given message. */
+static void
+_mesa_glsl_msg(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
+               GLenum type, GLuint id, const char *fmt, va_list ap)
+{
+   bool error = (type == GL_DEBUG_TYPE_ERROR_ARB);
+
+   assert(state->info_log != NULL);
+
+   /* Get the offset that the new message will be written to. */
+   int msg_offset = strlen(state->info_log);
+
+   ralloc_asprintf_append(&state->info_log, "%u:%u(%u): %s: ",
+					    locp->source,
+					    locp->first_line,
+					    locp->first_column,
+					    error ? "error" : "warning");
+   ralloc_vasprintf_append(&state->info_log, fmt, ap);
+
+   const char *const msg = &state->info_log[msg_offset];
+   struct gl_context *ctx = state->ctx;
+   /* Report the error via GL_ARB_debug_output. */
+   if (error)
+      _mesa_shader_debug(ctx, type, id, msg, strlen(msg));
+
+   ralloc_strcat(&state->info_log, "\n");
+}
 
 void
 _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
 		 const char *fmt, ...)
 {
    va_list ap;
+   GLenum type = GL_DEBUG_TYPE_ERROR_ARB;
 
    state->error = true;
 
-   assert(state->info_log != NULL);
-   ralloc_asprintf_append(&state->info_log, "%u:%u(%u): error: ",
-					    locp->source,
-					    locp->first_line,
-					    locp->first_column);
    va_start(ap, fmt);
-   ralloc_vasprintf_append(&state->info_log, fmt, ap);
+   _mesa_glsl_msg(locp, state, type, SHADER_ERROR_UNKNOWN, fmt, ap);
    va_end(ap);
-   ralloc_strcat(&state->info_log, "\n");
 }
 
 
@@ -160,16 +186,11 @@ _mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
 		   const char *fmt, ...)
 {
    va_list ap;
+   GLenum type = GL_DEBUG_TYPE_OTHER_ARB;
 
-   assert(state->info_log != NULL);
-   ralloc_asprintf_append(&state->info_log, "%u:%u(%u): warning: ",
-					    locp->source,
-					    locp->first_line,
-					    locp->first_column);
    va_start(ap, fmt);
-   ralloc_vasprintf_append(&state->info_log, fmt, ap);
+   _mesa_glsl_msg(locp, state, type, 0, fmt, ap);
    va_end(ap);
-   ralloc_strcat(&state->info_log, "\n");
 }
 
 
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index 55676f5a9..1a909c68b 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -57,7 +57,7 @@ struct glsl_switch_state {
 };
 
 struct _mesa_glsl_parse_state {
-   _mesa_glsl_parse_state(struct gl_context *ctx, GLenum target,
+   _mesa_glsl_parse_state(struct gl_context *_ctx, GLenum target,
 			  void *mem_ctx);
 
    /* Callers of this ralloc-based new need not call delete. It's
@@ -77,6 +77,7 @@ struct _mesa_glsl_parse_state {
       ralloc_free(mem);
    }
 
+   struct gl_context *const ctx;
    void *scanner;
    exec_list translation_unit;
    glsl_symbol_table *symbols;
diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp
index 24cc64ad9..f15f2d882 100644
--- a/mesalib/src/glsl/standalone_scaffolding.cpp
+++ b/mesalib/src/glsl/standalone_scaffolding.cpp
@@ -41,6 +41,12 @@ _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
    *ptr = sh;
 }
 
+void
+_mesa_shader_debug(struct gl_context *, GLenum, GLuint,
+                   const char *, int)
+{
+}
+
 struct gl_shader *
 _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
 {
diff --git a/mesalib/src/glsl/standalone_scaffolding.h b/mesalib/src/glsl/standalone_scaffolding.h
index 877332006..41ce35bef 100644
--- a/mesalib/src/glsl/standalone_scaffolding.h
+++ b/mesalib/src/glsl/standalone_scaffolding.h
@@ -40,6 +40,10 @@ _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
 extern "C" struct gl_shader *
 _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
 
+extern "C" void
+_mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint id,
+                   const char *msg, int len);
+
 /**
  * Initialize the given gl_context structure to a reasonable set of
  * defaults representing the minimum capabilities required by the
diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c
index fcf873f18..4a187b7b0 100644
--- a/mesalib/src/mesa/main/errors.c
+++ b/mesalib/src/mesa/main/errors.c
@@ -1062,4 +1062,47 @@ _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
    (void) fmtString;
 }
 
+
+/**
+ * Report debug information from the shader compiler via GL_ARB_debug_output.
+ *
+ * \param ctx GL context.
+ * \param type The namespace to which this message belongs.
+ * \param id The message ID within the given namespace.
+ * \param msg The message to output. Need not be null-terminated.
+ * \param len The length of 'msg'. If negative, 'msg' must be null-terminated.
+ */
+void
+_mesa_shader_debug( struct gl_context *ctx, GLenum type, GLuint id,
+                    const char *msg, int len )
+{
+   GLenum source = GL_DEBUG_SOURCE_SHADER_COMPILER_ARB,
+          severity;
+
+   switch (type) {
+   case GL_DEBUG_TYPE_ERROR_ARB:
+      assert(id < SHADER_ERROR_COUNT);
+      severity = GL_DEBUG_SEVERITY_HIGH_ARB;
+      break;
+   case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
+   case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
+   case GL_DEBUG_TYPE_PORTABILITY_ARB:
+   case GL_DEBUG_TYPE_PERFORMANCE_ARB:
+   case GL_DEBUG_TYPE_OTHER_ARB:
+      assert(0 && "other categories not implemented yet");
+   default:
+      _mesa_problem(ctx, "bad enum in _mesa_shader_debug()");
+      return;
+   }
+
+   if (len < 0)
+      len = strlen(msg);
+
+   /* Truncate the message if necessary. */
+   if (len >= MAX_DEBUG_MESSAGE_LENGTH)
+      len = MAX_DEBUG_MESSAGE_LENGTH - 1;
+
+   _mesa_log_msg(ctx, source, type, id, severity, len, msg);
+}
+
 /*@}*/
diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h
index ed1c6fc7f..b4490fac9 100644
--- a/mesalib/src/mesa/main/errors.h
+++ b/mesalib/src/mesa/main/errors.h
@@ -68,6 +68,9 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
 extern void
 _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3);
 
+extern void
+_mesa_shader_debug( struct gl_context *ctx, GLenum type, GLuint id, const char *msg, int len );
+
 #ifdef __cplusplus
 }
 #endif
-- 
cgit v1.2.3


From 8a448108ec0bc3a0a488b2234e0d12aee503c67c Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Wed, 9 May 2012 15:52:33 +0200
Subject: libX11 mesa xserver xkeyboard-config

---
 mesalib/configs/default                           |   2 +-
 mesalib/docs/GL3.txt                              |   2 +-
 mesalib/docs/viewperf.html                        |   5 +
 mesalib/include/GL/internal/dri_interface.h       |  10 +-
 mesalib/src/SConscript                            |   2 +-
 mesalib/src/glsl/ast_function.cpp                 |  30 +-
 mesalib/src/glsl/ast_to_hir.cpp                   |   6 +-
 mesalib/src/glsl/ir.cpp                           | 107 +++-
 mesalib/src/glsl/ir.h                             | 110 +++-
 mesalib/src/glsl/ir_clone.cpp                     |   8 +-
 mesalib/src/glsl/ir_constant_expression.cpp       | 673 +++++++++-------------
 mesalib/src/mesa/main/api_arrayelt.c              |  10 +-
 mesalib/src/mesa/main/context.c                   |   2 +
 mesalib/src/mesa/main/dlist.c                     |  32 +-
 mesalib/src/mesa/main/extensions.c                |   2 +-
 mesalib/src/mesa/main/fbobject.c                  |  14 +-
 mesalib/src/mesa/main/mtypes.h                    |  19 +
 mesalib/src/mesa/main/teximage.c                  |  32 +-
 mesalib/src/mesa/state_tracker/st_cb_rasterpos.c  |  10 +-
 mesalib/src/mesa/state_tracker/st_context.c       |   6 +
 mesalib/src/mesa/state_tracker/st_context.h       |   1 +
 mesalib/src/mesa/state_tracker/st_draw.c          |  14 +-
 mesalib/src/mesa/state_tracker/st_draw.h          |   2 -
 mesalib/src/mesa/state_tracker/st_draw_feedback.c |   2 +-
 mesalib/src/mesa/tnl/t_draw.c                     |   3 +-
 mesalib/src/mesa/tnl/tnl.h                        |   1 -
 mesalib/src/mesa/vbo/vbo.h                        |   1 -
 mesalib/src/mesa/vbo/vbo_context.h                |  50 ++
 mesalib/src/mesa/vbo/vbo_exec.h                   |  36 --
 mesalib/src/mesa/vbo/vbo_exec_api.c               |   2 +-
 mesalib/src/mesa/vbo/vbo_exec_array.c             |  16 +-
 mesalib/src/mesa/vbo/vbo_exec_draw.c              |   5 +-
 mesalib/src/mesa/vbo/vbo_rebase.c                 |  10 +-
 mesalib/src/mesa/vbo/vbo_save.c                   |   3 +
 mesalib/src/mesa/vbo/vbo_save_api.c               |   5 +-
 mesalib/src/mesa/vbo/vbo_save_draw.c              |   8 +-
 mesalib/src/mesa/vbo/vbo_split_copy.c             |  11 +-
 mesalib/src/mesa/vbo/vbo_split_inplace.c          |  11 +-
 38 files changed, 724 insertions(+), 539 deletions(-)

(limited to 'mesalib')

diff --git a/mesalib/configs/default b/mesalib/configs/default
index cdaeec8b4..40fa5e31e 100644
--- a/mesalib/configs/default
+++ b/mesalib/configs/default
@@ -9,7 +9,7 @@ CONFIG_NAME = default
 
 # Version info
 MESA_MAJOR=8
-MESA_MINOR=0
+MESA_MINOR=1
 MESA_TINY=0
 MESA_VERSION = $(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY)
 
diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt
index 0a860bb3c..5fc6c69ba 100644
--- a/mesalib/docs/GL3.txt
+++ b/mesalib/docs/GL3.txt
@@ -88,7 +88,7 @@ GL 4.0:
 
 GLSL 4.0                                             not started
 GL_ARB_texture_query_lod                             not started
-GL_ARB_draw_buffers_blend                            DONE (r600, softpipe)
+GL_ARB_draw_buffers_blend                            DONE (i965, r600, softpipe)
 GL_ARB_draw_indirect                                 not started
 GL_ARB_gpu_shader_fp64                               not started
 GL_ARB_sample_shading                                not started
diff --git a/mesalib/docs/viewperf.html b/mesalib/docs/viewperf.html
index 279625046..af351bc42 100644
--- a/mesalib/docs/viewperf.html
+++ b/mesalib/docs/viewperf.html
@@ -84,6 +84,11 @@ If the Mesa driver doesn't support this extension the rendering will
 be incorrect and the test will fail.
 </p>
 
+<p>
+Also, the color of the line drawings in test 2 seem to appear in a random
+color.  This is probably due to some uninitialized state somewhere.
+</p>
+
 
 
 <h2>sw-02 test 6</h2>
diff --git a/mesalib/include/GL/internal/dri_interface.h b/mesalib/include/GL/internal/dri_interface.h
index eafbe10f9..e37917eda 100644
--- a/mesalib/include/GL/internal/dri_interface.h
+++ b/mesalib/include/GL/internal/dri_interface.h
@@ -894,7 +894,7 @@ struct __DRIdri2ExtensionRec {
  * extensions.
  */
 #define __DRI_IMAGE "DRI_IMAGE"
-#define __DRI_IMAGE_VERSION 3
+#define __DRI_IMAGE_VERSION 4
 
 /**
  * These formats correspond to the similarly named MESA_FORMAT_*
@@ -911,6 +911,7 @@ struct __DRIdri2ExtensionRec {
 #define __DRI_IMAGE_USE_SHARE		0x0001
 #define __DRI_IMAGE_USE_SCANOUT		0x0002
 #define __DRI_IMAGE_USE_CURSOR		0x0004
+#define __DRI_IMAGE_USE_WRITE		0x0008
 
 /**
  * queryImage attributes
@@ -955,6 +956,13 @@ struct __DRIimageExtensionRec {
     * \since 2
     */
    GLboolean (*validateUsage)(__DRIimage *image, unsigned int use);
+
+   /**
+    * Write data into image.
+    *
+    * \since 4
+    */
+   int (*write)(__DRIimage *image, const void *buf, size_t count);
 };
 
 
diff --git a/mesalib/src/SConscript b/mesalib/src/SConscript
index ba6be0be1..777ad23f2 100644
--- a/mesalib/src/SConscript
+++ b/mesalib/src/SConscript
@@ -24,7 +24,7 @@ SConscript('mapi/vgapi/SConscript')
 if not env['embedded']:
     if env['platform'] not in ['windows', 'darwin', 'haiku']:
         SConscript('glx/SConscript')
-    if env['platform'] not in ['darwin', 'haiku']:
+    if env['platform'] not in ['darwin', 'haiku', 'sunos']:
         SConscript('egl/main/SConscript')
     if env['platform'] not in ['darwin']:
         SConscript('glu/sgi/SConscript')
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 8bf0ba2a8..9e7c5995f 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -153,21 +153,21 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
 	 }
 
 	 ir_variable *var = actual->variable_referenced();
-	 if (var) {
-	    if (var->read_only) {
-	       _mesa_glsl_error(&loc, state,
-				"function parameter '%s %s' references the "
-				"read-only variable '%s'",
-				mode, formal->name,
-				actual->variable_referenced()->name);
-	       return false;
-	    } else if (!actual->is_lvalue()) {
-	       _mesa_glsl_error(&loc, state,
-				"function parameter '%s %s' is not an lvalue",
-				mode, formal->name);
-	       return false;
-	    }
+	 if (var)
 	    var->assigned = true;
+
+	 if (var && var->read_only) {
+	    _mesa_glsl_error(&loc, state,
+			     "function parameter '%s %s' references the "
+			     "read-only variable '%s'",
+			     mode, formal->name,
+			     actual->variable_referenced()->name);
+	    return false;
+	 } else if (!actual->is_lvalue()) {
+	    _mesa_glsl_error(&loc, state,
+			     "function parameter '%s %s' is not an lvalue",
+			     mode, formal->name);
+	    return false;
 	 }
       }
 
@@ -278,7 +278,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
     * Function calls were first allowed to be constant expressions in GLSL 1.20.
     */
    if (state->language_version >= 120) {
-      ir_constant *value = sig->constant_expression_value(actual_parameters);
+      ir_constant *value = sig->constant_expression_value(actual_parameters, NULL);
       if (value != NULL) {
 	 return value;
       }
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index e24914b83..86bb8741b 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -4039,13 +4039,13 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
    foreach_list(node, instructions) {
       ir_variable *var = ((ir_instruction *)node)->as_variable();
 
-      if (!var)
+      if (!var || !var->assigned)
 	 continue;
 
       if (strcmp(var->name, "gl_FragColor") == 0)
-	 gl_FragColor_assigned = var->assigned;
+	 gl_FragColor_assigned = true;
       else if (strcmp(var->name, "gl_FragData") == 0)
-	 gl_FragData_assigned = var->assigned;
+	 gl_FragData_assigned = true;
       else if (strncmp(var->name, "gl_", 3) != 0) {
 	 if (state->target == fragment_shader &&
 	     (var->mode == ir_var_out || var->mode == ir_var_inout)) {
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 1ba87515e..970d8f3ba 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -716,12 +716,27 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
 ir_constant *
 ir_constant::zero(void *mem_ctx, const glsl_type *type)
 {
-   assert(type->is_numeric() || type->is_boolean());
+   assert(type->is_scalar() || type->is_vector() || type->is_matrix()
+	  || type->is_record() || type->is_array());
 
    ir_constant *c = new(mem_ctx) ir_constant;
    c->type = type;
    memset(&c->value, 0, sizeof(c->value));
 
+   if (type->is_array()) {
+      c->array_elements = ralloc_array(c, ir_constant *, type->length);
+
+      for (unsigned i = 0; i < type->length; i++)
+	 c->array_elements[i] = ir_constant::zero(c, type->element_type());
+   }
+
+   if (type->is_record()) {
+      for (unsigned i = 0; i < type->length; i++) {
+	 ir_constant *comp = ir_constant::zero(mem_ctx, type->fields.structure[i].type);
+	 c->components.push_tail(comp);
+      }
+   }
+
    return c;
 }
 
@@ -841,6 +856,95 @@ ir_constant::get_record_field(const char *name)
    return (ir_constant *) node;
 }
 
+void
+ir_constant::copy_offset(ir_constant *src, int offset)
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL: {
+      unsigned int size = src->type->components();
+      assert (size <= this->type->components() - offset);
+      for (unsigned int i=0; i<size; i++) {
+	 switch (this->type->base_type) {
+	 case GLSL_TYPE_UINT:
+	    value.u[i+offset] = src->get_uint_component(i);
+	    break;
+	 case GLSL_TYPE_INT:
+	    value.i[i+offset] = src->get_int_component(i);
+	    break;
+	 case GLSL_TYPE_FLOAT:
+	    value.f[i+offset] = src->get_float_component(i);
+	    break;
+	 case GLSL_TYPE_BOOL:
+	    value.b[i+offset] = src->get_bool_component(i);
+	    break;
+	 default: // Shut up the compiler
+	    break;
+	 }
+      }
+      break;
+   }
+
+   case GLSL_TYPE_STRUCT: {
+      assert (src->type == this->type);
+      this->components.make_empty();
+      foreach_list(node, &src->components) {
+	 ir_constant *const orig = (ir_constant *) node;
+
+	 this->components.push_tail(orig->clone(this, NULL));
+      }
+      break;
+   }
+
+   case GLSL_TYPE_ARRAY: {
+      assert (src->type == this->type);
+      for (unsigned i = 0; i < this->type->length; i++) {
+	 this->array_elements[i] = src->array_elements[i]->clone(this, NULL);
+      }
+      break;
+   }
+
+   default:
+      assert(!"Should not get here.");
+      break;
+   }
+}
+
+void
+ir_constant::copy_masked_offset(ir_constant *src, int offset, unsigned int mask)
+{
+   assert (!type->is_array() && !type->is_record());
+
+   if (!type->is_vector() && !type->is_matrix()) {
+      offset = 0;
+      mask = 1;
+   }
+
+   int id = 0;
+   for (int i=0; i<4; i++) {
+      if (mask & (1 << i)) {
+	 switch (this->type->base_type) {
+	 case GLSL_TYPE_UINT:
+	    value.u[i+offset] = src->get_uint_component(id++);
+	    break;
+	 case GLSL_TYPE_INT:
+	    value.i[i+offset] = src->get_int_component(id++);
+	    break;
+	 case GLSL_TYPE_FLOAT:
+	    value.f[i+offset] = src->get_float_component(id++);
+	    break;
+	 case GLSL_TYPE_BOOL:
+	    value.b[i+offset] = src->get_bool_component(id++);
+	    break;
+	 default:
+	    assert(!"Should not get here.");
+	    return;
+	 }
+      }
+   }
+}
 
 bool
 ir_constant::has_value(const ir_constant *c) const
@@ -1377,6 +1481,7 @@ ir_function_signature::ir_function_signature(const glsl_type *return_type)
 {
    this->ir_type = ir_type_function_signature;
    this->is_builtin = false;
+   this->origin = NULL;
 }
 
 
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index ddfaf3614..9c7961ab9 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -146,7 +146,7 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual ir_rvalue * as_rvalue()
    {
@@ -502,10 +502,11 @@ public:
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
    /**
-    * Attempt to evaluate this function as a constant expression, given
-    * a list of the actual parameters.  Returns NULL for non-built-ins.
+    * Attempt to evaluate this function as a constant expression,
+    * given a list of the actual parameters and the variable context.
+    * Returns NULL for non-built-ins.
     */
-   ir_constant *constant_expression_value(exec_list *actual_parameters);
+   ir_constant *constant_expression_value(exec_list *actual_parameters, struct hash_table *variable_context);
 
    /**
     * Get the name of the function for which this is a signature
@@ -571,7 +572,25 @@ private:
    /** Function of which this signature is one overload. */
    class ir_function *_function;
 
+   /** Function signature of which this one is a prototype clone */
+   const ir_function_signature *origin;
+
    friend class ir_function;
+
+   /**
+    * Helper function to run a list of instructions for constant
+    * expression evaluation.
+    *
+    * The hash table represents the values of the visible variables.
+    * There are no scoping issues because the table is indexed on
+    * ir_variable pointers, not variable names.
+    *
+    * Returns false if the expression is not constant, true otherwise,
+    * and the value in *result if result is non-NULL.
+    */
+   bool constant_expression_evaluate_expression_list(const struct exec_list &body,
+						     struct hash_table *variable_context,
+						     ir_constant **result);
 };
 
 
@@ -763,7 +782,7 @@ public:
 
    virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual void accept(ir_visitor *v)
    {
@@ -999,10 +1018,14 @@ public:
    /**
     * Attempt to constant-fold the expression
     *
+    * The "variable_context" hash table links ir_variable * to ir_constant *
+    * that represent the variables' values.  \c NULL represents an empty
+    * context.
+    *
     * If the expression cannot be constant folded, this method will return
     * \c NULL.
     */
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    /**
     * Determine the number of operands used by an expression
@@ -1065,7 +1088,7 @@ public:
 
    virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual ir_call *as_call()
    {
@@ -1297,7 +1320,7 @@ public:
 
    virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual void accept(ir_visitor *v)
    {
@@ -1389,7 +1412,7 @@ public:
 
    virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual ir_swizzle *as_swizzle()
    {
@@ -1446,6 +1469,15 @@ public:
     * Get the variable that is ultimately referenced by an r-value
     */
    virtual ir_variable *variable_referenced() const = 0;
+
+   /**
+    * Get the constant that is ultimately referenced by an r-value,
+    * in a constant expression evaluation context.
+    *
+    * The offset is used when the reference is to a specific column of
+    * a matrix.
+    */
+  virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const = 0;
 };
 
 
@@ -1456,7 +1488,7 @@ public:
    virtual ir_dereference_variable *clone(void *mem_ctx,
 					  struct hash_table *) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual ir_dereference_variable *as_dereference_variable()
    {
@@ -1471,6 +1503,15 @@ public:
       return this->var;
    }
 
+   /**
+    * Get the constant that is ultimately referenced by an r-value,
+    * in a constant expression evaluation context.
+    *
+    * The offset is used when the reference is to a specific column of
+    * a matrix.
+    */
+   virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
+
    virtual ir_variable *whole_variable_referenced()
    {
       /* ir_dereference_variable objects always dereference the entire
@@ -1505,7 +1546,7 @@ public:
    virtual ir_dereference_array *clone(void *mem_ctx,
 				       struct hash_table *) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual ir_dereference_array *as_dereference_array()
    {
@@ -1520,6 +1561,15 @@ public:
       return this->array->variable_referenced();
    }
 
+   /**
+    * Get the constant that is ultimately referenced by an r-value,
+    * in a constant expression evaluation context.
+    *
+    * The offset is used when the reference is to a specific column of
+    * a matrix.
+    */
+   virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -1544,7 +1594,7 @@ public:
    virtual ir_dereference_record *clone(void *mem_ctx,
 					struct hash_table *) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    /**
     * Get the variable that is ultimately referenced by an r-value
@@ -1554,6 +1604,15 @@ public:
       return this->record->variable_referenced();
    }
 
+   /**
+    * Get the constant that is ultimately referenced by an r-value,
+    * in a constant expression evaluation context.
+    *
+    * The offset is used when the reference is to a specific column of
+    * a matrix.
+    */
+   virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -1609,7 +1668,7 @@ public:
 
    virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
 
-   virtual ir_constant *constant_expression_value();
+   virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
    virtual ir_constant *as_constant()
    {
@@ -1641,6 +1700,31 @@ public:
 
    ir_constant *get_record_field(const char *name);
 
+   /**
+    * Copy the values on another constant at a given offset.
+    *
+    * The offset is ignored for array or struct copies, it's only for
+    * scalars or vectors into vectors or matrices.
+    *
+    * With identical types on both sides and zero offset it's clone()
+    * without creating a new object.
+    */
+
+   void copy_offset(ir_constant *src, int offset);
+
+   /**
+    * Copy the values on another constant at a given offset and
+    * following an assign-like mask.
+    *
+    * The mask is ignored for scalars.
+    *
+    * Note that this function only handles what assign can handle,
+    * i.e. at most a vector as source and a column of a matrix as
+    * destination.
+    */
+
+   void copy_masked_offset(ir_constant *src, int offset, unsigned int mask);
+
    /**
     * Determine whether a constant has the same value as another constant
     *
diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp
index 5a7a71cf6..591fe7b77 100644
--- a/mesalib/src/glsl/ir_clone.cpp
+++ b/mesalib/src/glsl/ir_clone.cpp
@@ -53,6 +53,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
    var->invariant = this->invariant;
    var->interpolation = this->interpolation;
    var->location = this->location;
+   var->index = this->index;
    var->warn_extension = this->warn_extension;
    var->origin_upper_left = this->origin_upper_left;
    var->pixel_center_integer = this->pixel_center_integer;
@@ -72,12 +73,6 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
 	     sizeof(this->state_slots[0]) * var->num_state_slots);
    }
 
-   if (this->explicit_location)
-      var->location = this->location;
-
-   if (this->explicit_index)
-      var->index = this->index;
-
    if (this->constant_value)
       var->constant_value = this->constant_value->clone(mem_ctx, ht);
 
@@ -329,6 +324,7 @@ ir_function_signature::clone_prototype(void *mem_ctx, struct hash_table *ht) con
 
    copy->is_defined = false;
    copy->is_builtin = this->is_builtin;
+   copy->origin = this;
 
    /* Clone the parameter list, but NOT the body.
     */
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index 4e1714a84..08a33285b 100644
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -38,6 +38,7 @@
 #include "ir.h"
 #include "ir_visitor.h"
 #include "glsl_types.h"
+#include "program/hash_table.h"
 
 /* Using C99 rounding functions for roundToEven() implementation is
  * difficult, because round(), rint, and nearbyint() are affected by
@@ -71,14 +72,14 @@ dot(ir_constant *op0, ir_constant *op1)
 }
 
 ir_constant *
-ir_rvalue::constant_expression_value()
+ir_rvalue::constant_expression_value(struct hash_table *variable_context)
 {
    assert(this->type->is_error());
    return NULL;
 }
 
 ir_constant *
-ir_expression::constant_expression_value()
+ir_expression::constant_expression_value(struct hash_table *variable_context)
 {
    if (this->type->is_error())
       return NULL;
@@ -89,7 +90,7 @@ ir_expression::constant_expression_value()
    memset(&data, 0, sizeof(data));
 
    for (unsigned operand = 0; operand < this->get_num_operands(); operand++) {
-      op[operand] = this->operands[operand]->constant_expression_value();
+      op[operand] = this->operands[operand]->constant_expression_value(variable_context);
       if (!op[operand])
 	 return NULL;
    }
@@ -640,13 +641,13 @@ ir_expression::constant_expression_value()
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
 	 switch (op[0]->type->base_type) {
 	 case GLSL_TYPE_UINT:
-	    data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
+	    data.b[c] = op[0]->value.u[c] < op[1]->value.u[c];
 	    break;
 	 case GLSL_TYPE_INT:
-	    data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
+	    data.b[c] = op[0]->value.i[c] < op[1]->value.i[c];
 	    break;
 	 case GLSL_TYPE_FLOAT:
-	    data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
+	    data.b[c] = op[0]->value.f[c] < op[1]->value.f[c];
 	    break;
 	 default:
 	    assert(0);
@@ -676,13 +677,13 @@ ir_expression::constant_expression_value()
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
 	 switch (op[0]->type->base_type) {
 	 case GLSL_TYPE_UINT:
-	    data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
+	    data.b[c] = op[0]->value.u[c] <= op[1]->value.u[c];
 	    break;
 	 case GLSL_TYPE_INT:
-	    data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
+	    data.b[c] = op[0]->value.i[c] <= op[1]->value.i[c];
 	    break;
 	 case GLSL_TYPE_FLOAT:
-	    data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
+	    data.b[c] = op[0]->value.f[c] <= op[1]->value.f[c];
 	    break;
 	 default:
 	    assert(0);
@@ -694,13 +695,13 @@ ir_expression::constant_expression_value()
       for (unsigned c = 0; c < op[0]->type->components(); c++) {
 	 switch (op[0]->type->base_type) {
 	 case GLSL_TYPE_UINT:
-	    data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
+	    data.b[c] = op[0]->value.u[c] >= op[1]->value.u[c];
 	    break;
 	 case GLSL_TYPE_INT:
-	    data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
+	    data.b[c] = op[0]->value.i[c] >= op[1]->value.i[c];
 	    break;
 	 case GLSL_TYPE_FLOAT:
-	    data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
+	    data.b[c] = op[0]->value.f[c] >= op[1]->value.f[c];
 	    break;
 	 default:
 	    assert(0);
@@ -886,7 +887,7 @@ ir_expression::constant_expression_value()
 
 
 ir_constant *
-ir_texture::constant_expression_value()
+ir_texture::constant_expression_value(struct hash_table *variable_context)
 {
    /* texture lookups aren't constant expressions */
    return NULL;
@@ -894,9 +895,9 @@ ir_texture::constant_expression_value()
 
 
 ir_constant *
-ir_swizzle::constant_expression_value()
+ir_swizzle::constant_expression_value(struct hash_table *variable_context)
 {
-   ir_constant *v = this->val->constant_expression_value();
+   ir_constant *v = this->val->constant_expression_value(variable_context);
 
    if (v != NULL) {
       ir_constant_data data = { { 0 } };
@@ -922,13 +923,33 @@ ir_swizzle::constant_expression_value()
 }
 
 
+void
+ir_dereference_variable::constant_referenced(struct hash_table *variable_context,
+					     ir_constant *&store, int &offset) const
+{
+   if (variable_context) {
+      store = (ir_constant *)hash_table_find(variable_context, var);
+      offset = 0;
+   } else {
+      store = NULL;
+      offset = 0;
+   }
+}
+
 ir_constant *
-ir_dereference_variable::constant_expression_value()
+ir_dereference_variable::constant_expression_value(struct hash_table *variable_context)
 {
    /* This may occur during compile and var->type is glsl_type::error_type */
    if (!var)
       return NULL;
 
+   /* Give priority to the context hashtable, if it exists */
+   if (variable_context) {
+      ir_constant *value = (ir_constant *)hash_table_find(variable_context, var);
+      if(value)
+	 return value;
+   }
+
    /* The constant_value of a uniform variable is its initializer,
     * not the lifetime constant value of the uniform.
     */
@@ -942,11 +963,65 @@ ir_dereference_variable::constant_expression_value()
 }
 
 
+void
+ir_dereference_array::constant_referenced(struct hash_table *variable_context,
+					  ir_constant *&store, int &offset) const
+{
+   ir_constant *index_c = array_index->constant_expression_value(variable_context);
+
+   if (!index_c || !index_c->type->is_scalar() || !index_c->type->is_integer()) {
+      store = 0;
+      offset = 0;
+      return;
+   }
+
+   int index = index_c->type->base_type == GLSL_TYPE_INT ?
+      index_c->get_int_component(0) :
+      index_c->get_uint_component(0);
+
+   ir_constant *substore;
+   int suboffset;
+   const ir_dereference *deref = array->as_dereference();
+   if (!deref) {
+      store = 0;
+      offset = 0;
+      return;
+   }
+
+   deref->constant_referenced(variable_context, substore, suboffset);
+
+   if (!substore) {
+      store = 0;
+      offset = 0;
+      return;
+   }
+
+   const glsl_type *vt = substore->type;
+   if (vt->is_array()) {
+      store = substore->get_array_element(index);
+      offset = 0;
+      return;
+   }
+   if (vt->is_matrix()) {
+      store = substore;
+      offset = index * vt->vector_elements;
+      return;
+   }
+   if (vt->is_vector()) {
+      store = substore;
+      offset = suboffset + index;
+      return;
+   }
+
+   store = 0;
+   offset = 0;
+}
+
 ir_constant *
-ir_dereference_array::constant_expression_value()
+ir_dereference_array::constant_expression_value(struct hash_table *variable_context)
 {
-   ir_constant *array = this->array->constant_expression_value();
-   ir_constant *idx = this->array_index->constant_expression_value();
+   ir_constant *array = this->array->constant_expression_value(variable_context);
+   ir_constant *idx = this->array_index->constant_expression_value(variable_context);
 
    if ((array != NULL) && (idx != NULL)) {
       void *ctx = ralloc_parent(this);
@@ -997,8 +1072,33 @@ ir_dereference_array::constant_expression_value()
 }
 
 
+void
+ir_dereference_record::constant_referenced(struct hash_table *variable_context,
+					   ir_constant *&store, int &offset) const
+{
+   ir_constant *substore;
+   int suboffset;
+   const ir_dereference *deref = record->as_dereference();
+   if (!deref) {
+      store = 0;
+      offset = 0;
+      return;
+   }
+
+   deref->constant_referenced(variable_context, substore, suboffset);
+
+   if (!substore) {
+      store = 0;
+      offset = 0;
+      return;
+   }
+
+   store = substore->get_record_field(field);
+   offset = 0;
+}
+
 ir_constant *
-ir_dereference_record::constant_expression_value()
+ir_dereference_record::constant_expression_value(struct hash_table *variable_context)
 {
    ir_constant *v = this->record->constant_expression_value();
 
@@ -1007,7 +1107,7 @@ ir_dereference_record::constant_expression_value()
 
 
 ir_constant *
-ir_assignment::constant_expression_value()
+ir_assignment::constant_expression_value(struct hash_table *variable_context)
 {
    /* FINISHME: Handle CEs involving assignment (return RHS) */
    return NULL;
@@ -1015,21 +1115,130 @@ ir_assignment::constant_expression_value()
 
 
 ir_constant *
-ir_constant::constant_expression_value()
+ir_constant::constant_expression_value(struct hash_table *variable_context)
 {
    return this;
 }
 
 
 ir_constant *
-ir_call::constant_expression_value()
+ir_call::constant_expression_value(struct hash_table *variable_context)
 {
-   return this->callee->constant_expression_value(&this->actual_parameters);
+   return this->callee->constant_expression_value(&this->actual_parameters, variable_context);
 }
 
 
+bool ir_function_signature::constant_expression_evaluate_expression_list(const struct exec_list &body,
+									 struct hash_table *variable_context,
+									 ir_constant **result)
+{
+   foreach_list(n, &body) {
+      ir_instruction *inst = (ir_instruction *)n;
+      switch(inst->ir_type) {
+
+	 /* (declare () type symbol) */
+      case ir_type_variable: {
+	 ir_variable *var = inst->as_variable();
+	 hash_table_insert(variable_context, ir_constant::zero(this, var->type), var);
+	 break;
+      }
+
+	 /* (assign [condition] (write-mask) (ref) (value)) */
+      case ir_type_assignment: {
+	 ir_assignment *asg = inst->as_assignment();
+	 if (asg->condition) {
+	    ir_constant *cond = asg->condition->constant_expression_value(variable_context);
+	    if (!cond)
+	       return false;
+	    if (!cond->get_bool_component(0))
+	       break;
+	 }
+
+	 ir_constant *store = NULL;
+	 int offset = 0;
+	 asg->lhs->constant_referenced(variable_context, store, offset);
+
+	 if (!store)
+	    return false;
+
+	 ir_constant *value = asg->rhs->constant_expression_value(variable_context);
+
+	 if (!value)
+	    return false;
+
+	 store->copy_masked_offset(value, offset, asg->write_mask);
+	 break;
+      }
+
+	 /* (return (expression)) */
+      case ir_type_return:
+	 assert (result);
+	 *result = inst->as_return()->value->constant_expression_value(variable_context);
+	 return *result != NULL;
+
+	 /* (call name (ref) (params))*/
+      case ir_type_call: {
+	 ir_call *call = inst->as_call();
+
+	 /* Just say no to void functions in constant expressions.  We
+	  * don't need them at that point.
+	  */
+
+	 if (!call->return_deref)
+	    return false;
+
+	 ir_constant *store = NULL;
+	 int offset = 0;
+	 call->return_deref->constant_referenced(variable_context, store, offset);
+
+	 if (!store)
+	    return false;
+
+	 ir_constant *value = call->constant_expression_value(variable_context);
+
+	 if(!value)
+	    return false;
+
+	 store->copy_offset(value, offset);
+	 break;
+      }
+
+	 /* (if condition (then-instructions) (else-instructions)) */
+      case ir_type_if: {
+	 ir_if *iif = inst->as_if();
+
+	 ir_constant *cond = iif->condition->constant_expression_value(variable_context);
+	 if (!cond || !cond->type->is_boolean())
+	    return false;
+
+	 exec_list &branch = cond->get_bool_component(0) ? iif->then_instructions : iif->else_instructions;
+
+	 *result = NULL;
+	 if (!constant_expression_evaluate_expression_list(branch, variable_context, result))
+	    return false;
+
+	 /* If there was a return in the branch chosen, drop out now. */
+	 if (*result)
+	    return true;
+
+	 break;
+      }
+
+	 /* Every other expression type, we drop out. */
+      default:
+	 return false;
+      }
+   }
+
+   /* Reaching the end of the block is not an error condition */
+   if (result)
+      *result = NULL;
+
+   return true;
+}
+
 ir_constant *
-ir_function_signature::constant_expression_value(exec_list *actual_parameters)
+ir_function_signature::constant_expression_value(exec_list *actual_parameters, struct hash_table *variable_context)
 {
    const glsl_type *type = this->return_type;
    if (type == glsl_type::void_type)
@@ -1042,396 +1251,48 @@ ir_function_signature::constant_expression_value(exec_list *actual_parameters)
    if (!this->is_builtin)
       return NULL;
 
-   unsigned num_parameters = 0;
+   /*
+    * Of the builtin functions, only the texture lookups and the noise
+    * ones must not be used in constant expressions.  They all include
+    * specific opcodes so they don't need to be special-cased at this
+    * point.
+    */
+
+   /* Initialize the table of dereferencable names with the function
+    * parameters.  Verify their const-ness on the way.
+    *
+    * We expect the correctness of the number of parameters to have
+    * been checked earlier.
+    */
+   hash_table *deref_hash = hash_table_ctor(8, hash_table_pointer_hash,
+					    hash_table_pointer_compare);
+
+   /* If "origin" is non-NULL, then the function body is there.  So we
+    * have to use the variable objects from the object with the body,
+    * but the parameter instanciation on the current object.
+    */
+   const exec_node *parameter_info = origin ? origin->parameters.head : parameters.head;
 
-   /* Check if all parameters are constant */
-   ir_constant *op[3];
    foreach_list(n, actual_parameters) {
-      ir_constant *constant = ((ir_rvalue *) n)->constant_expression_value();
+      ir_constant *constant = ((ir_rvalue *) n)->constant_expression_value(variable_context);
       if (constant == NULL)
 	 return NULL;
 
-      op[num_parameters] = constant;
+      ir_variable *var = (ir_variable *)parameter_info;
+      hash_table_insert(deref_hash, constant, var);
 
-      assert(num_parameters < 3);
-      num_parameters++;
+      parameter_info = parameter_info->next;
    }
 
-   /* Individual cases below can either:
-    * - Assign "expr" a new ir_expression to evaluate (for basic opcodes)
-    * - Fill "data" with appopriate constant data
-    * - Return an ir_constant directly.
-    */
-   void *mem_ctx = ralloc_parent(this);
-   ir_expression *expr = NULL;
-
-   ir_constant_data data;
-   memset(&data, 0, sizeof(data));
-
-   const char *callee = this->function_name();
-   if (strcmp(callee, "abs") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_abs, type, op[0], NULL);
-   } else if (strcmp(callee, "all") == 0) {
-      assert(op[0]->type->is_boolean());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 if (!op[0]->value.b[c])
-	    return new(mem_ctx) ir_constant(false);
-      }
-      return new(mem_ctx) ir_constant(true);
-   } else if (strcmp(callee, "any") == 0) {
-      assert(op[0]->type->is_boolean());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 if (op[0]->value.b[c])
-	    return new(mem_ctx) ir_constant(true);
-      }
-      return new(mem_ctx) ir_constant(false);
-   } else if (strcmp(callee, "acos") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = acosf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "acosh") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = acoshf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "asin") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = asinf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "asinh") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = asinhf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "atan") == 0) {
-      assert(op[0]->type->is_float());
-      if (num_parameters == 2) {
-	 assert(op[1]->type->is_float());
-	 for (unsigned c = 0; c < op[0]->type->components(); c++)
-	    data.f[c] = atan2f(op[0]->value.f[c], op[1]->value.f[c]);
-      } else {
-	 for (unsigned c = 0; c < op[0]->type->components(); c++)
-	    data.f[c] = atanf(op[0]->value.f[c]);
-      }
-   } else if (strcmp(callee, "atanh") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = atanhf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "dFdx") == 0 || strcmp(callee, "dFdy") == 0) {
-      return ir_constant::zero(mem_ctx, type);
-   } else if (strcmp(callee, "ceil") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_ceil, type, op[0], NULL);
-   } else if (strcmp(callee, "clamp") == 0) {
-      assert(num_parameters == 3);
-      unsigned c1_inc = op[1]->type->is_scalar() ? 0 : 1;
-      unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
-      for (unsigned c = 0, c1 = 0, c2 = 0;
-	   c < op[0]->type->components();
-	   c1 += c1_inc, c2 += c2_inc, c++) {
-
-	 switch (op[0]->type->base_type) {
-	 case GLSL_TYPE_UINT:
-	    data.u[c] = CLAMP(op[0]->value.u[c], op[1]->value.u[c1],
-			      op[2]->value.u[c2]);
-	    break;
-	 case GLSL_TYPE_INT:
-	    data.i[c] = CLAMP(op[0]->value.i[c], op[1]->value.i[c1],
-			      op[2]->value.i[c2]);
-	    break;
-	 case GLSL_TYPE_FLOAT:
-	    data.f[c] = CLAMP(op[0]->value.f[c], op[1]->value.f[c1],
-			      op[2]->value.f[c2]);
-	    break;
-	 default:
-	    assert(!"Should not get here.");
-	 }
-      }
-   } else if (strcmp(callee, "cos") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_cos, type, op[0], NULL);
-   } else if (strcmp(callee, "cosh") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = coshf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "cross") == 0) {
-      assert(op[0]->type == glsl_type::vec3_type);
-      assert(op[1]->type == glsl_type::vec3_type);
-      data.f[0] = (op[0]->value.f[1] * op[1]->value.f[2] -
-		   op[1]->value.f[1] * op[0]->value.f[2]);
-      data.f[1] = (op[0]->value.f[2] * op[1]->value.f[0] -
-		   op[1]->value.f[2] * op[0]->value.f[0]);
-      data.f[2] = (op[0]->value.f[0] * op[1]->value.f[1] -
-		   op[1]->value.f[0] * op[0]->value.f[1]);
-   } else if (strcmp(callee, "degrees") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = 180.0F / M_PI * op[0]->value.f[c];
-   } else if (strcmp(callee, "distance") == 0) {
-      assert(op[0]->type->is_float() && op[1]->type->is_float());
-      float length_squared = 0.0;
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 float t = op[0]->value.f[c] - op[1]->value.f[c];
-	 length_squared += t * t;
-      }
-      return new(mem_ctx) ir_constant(sqrtf(length_squared));
-   } else if (strcmp(callee, "dot") == 0) {
-      return new(mem_ctx) ir_constant(dot(op[0], op[1]));
-   } else if (strcmp(callee, "equal") == 0) {
-      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 switch (op[0]->type->base_type) {
-	 case GLSL_TYPE_UINT:
-	    data.b[c] = op[0]->value.u[c] == op[1]->value.u[c];
-	    break;
-	 case GLSL_TYPE_INT:
-	    data.b[c] = op[0]->value.i[c] == op[1]->value.i[c];
-	    break;
-	 case GLSL_TYPE_FLOAT:
-	    data.b[c] = op[0]->value.f[c] == op[1]->value.f[c];
-	    break;
-	 case GLSL_TYPE_BOOL:
-	    data.b[c] = op[0]->value.b[c] == op[1]->value.b[c];
-	    break;
-	 default:
-	    assert(!"Should not get here.");
-	 }
-      }
-   } else if (strcmp(callee, "exp") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_exp, type, op[0], NULL);
-   } else if (strcmp(callee, "exp2") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_exp2, type, op[0], NULL);
-   } else if (strcmp(callee, "faceforward") == 0) {
-      if (dot(op[2], op[1]) < 0)
-	 return op[0];
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = -op[0]->value.f[c];
-   } else if (strcmp(callee, "floor") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_floor, type, op[0], NULL);
-   } else if (strcmp(callee, "fract") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_fract, type, op[0], NULL);
-   } else if (strcmp(callee, "fwidth") == 0) {
-      return ir_constant::zero(mem_ctx, type);
-   } else if (strcmp(callee, "greaterThan") == 0) {
-      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 switch (op[0]->type->base_type) {
-	 case GLSL_TYPE_UINT:
-	    data.b[c] = op[0]->value.u[c] > op[1]->value.u[c];
-	    break;
-	 case GLSL_TYPE_INT:
-	    data.b[c] = op[0]->value.i[c] > op[1]->value.i[c];
-	    break;
-	 case GLSL_TYPE_FLOAT:
-	    data.b[c] = op[0]->value.f[c] > op[1]->value.f[c];
-	    break;
-	 default:
-	    assert(!"Should not get here.");
-	 }
-      }
-   } else if (strcmp(callee, "greaterThanEqual") == 0) {
-      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 switch (op[0]->type->base_type) {
-	 case GLSL_TYPE_UINT:
-	    data.b[c] = op[0]->value.u[c] >= op[1]->value.u[c];
-	    break;
-	 case GLSL_TYPE_INT:
-	    data.b[c] = op[0]->value.i[c] >= op[1]->value.i[c];
-	    break;
-	 case GLSL_TYPE_FLOAT:
-	    data.b[c] = op[0]->value.f[c] >= op[1]->value.f[c];
-	    break;
-	 default:
-	    assert(!"Should not get here.");
-	 }
-      }
-   } else if (strcmp(callee, "inversesqrt") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_rsq, type, op[0], NULL);
-   } else if (strcmp(callee, "length") == 0) {
-      return new(mem_ctx) ir_constant(sqrtf(dot(op[0], op[0])));
-   } else if (strcmp(callee, "lessThan") == 0) {
-      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 switch (op[0]->type->base_type) {
-	 case GLSL_TYPE_UINT:
-	    data.b[c] = op[0]->value.u[c] < op[1]->value.u[c];
-	    break;
-	 case GLSL_TYPE_INT:
-	    data.b[c] = op[0]->value.i[c] < op[1]->value.i[c];
-	    break;
-	 case GLSL_TYPE_FLOAT:
-	    data.b[c] = op[0]->value.f[c] < op[1]->value.f[c];
-	    break;
-	 default:
-	    assert(!"Should not get here.");
-	 }
-      }
-   } else if (strcmp(callee, "lessThanEqual") == 0) {
-      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 switch (op[0]->type->base_type) {
-	 case GLSL_TYPE_UINT:
-	    data.b[c] = op[0]->value.u[c] <= op[1]->value.u[c];
-	    break;
-	 case GLSL_TYPE_INT:
-	    data.b[c] = op[0]->value.i[c] <= op[1]->value.i[c];
-	    break;
-	 case GLSL_TYPE_FLOAT:
-	    data.b[c] = op[0]->value.f[c] <= op[1]->value.f[c];
-	    break;
-	 default:
-	    assert(!"Should not get here.");
-	 }
-      }
-   } else if (strcmp(callee, "log") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_log, type, op[0], NULL);
-   } else if (strcmp(callee, "log2") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_log2, type, op[0], NULL);
-   } else if (strcmp(callee, "matrixCompMult") == 0) {
-      assert(op[0]->type->is_float() && op[1]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = op[0]->value.f[c] * op[1]->value.f[c];
-   } else if (strcmp(callee, "max") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_binop_max, type, op[0], op[1]);
-   } else if (strcmp(callee, "min") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_binop_min, type, op[0], op[1]);
-   } else if (strcmp(callee, "mix") == 0) {
-      assert(op[0]->type->is_float() && op[1]->type->is_float());
-      if (op[2]->type->is_float()) {
-	 unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
-	 unsigned components = op[0]->type->components();
-	 for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
-	    data.f[c] = op[0]->value.f[c] * (1 - op[2]->value.f[c2]) +
-			op[1]->value.f[c] * op[2]->value.f[c2];
-	 }
-      } else {
-	 assert(op[2]->type->is_boolean());
-	 for (unsigned c = 0; c < op[0]->type->components(); c++)
-	    data.f[c] = op[op[2]->value.b[c] ? 1 : 0]->value.f[c];
-      }
-   } else if (strcmp(callee, "mod") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_binop_mod, type, op[0], op[1]);
-   } else if (strcmp(callee, "normalize") == 0) {
-      assert(op[0]->type->is_float());
-      float length = sqrtf(dot(op[0], op[0]));
-
-      if (length == 0)
-	 return ir_constant::zero(mem_ctx, type);
+   ir_constant *result = NULL;
 
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = op[0]->value.f[c] / length;
-   } else if (strcmp(callee, "not") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_logic_not, type, op[0], NULL);
-   } else if (strcmp(callee, "notEqual") == 0) {
-      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
-      for (unsigned c = 0; c < op[0]->type->components(); c++) {
-	 switch (op[0]->type->base_type) {
-	 case GLSL_TYPE_UINT:
-	    data.b[c] = op[0]->value.u[c] != op[1]->value.u[c];
-	    break;
-	 case GLSL_TYPE_INT:
-	    data.b[c] = op[0]->value.i[c] != op[1]->value.i[c];
-	    break;
-	 case GLSL_TYPE_FLOAT:
-	    data.b[c] = op[0]->value.f[c] != op[1]->value.f[c];
-	    break;
-	 case GLSL_TYPE_BOOL:
-	    data.b[c] = op[0]->value.b[c] != op[1]->value.b[c];
-	    break;
-	 default:
-	    assert(!"Should not get here.");
-	 }
-      }
-   } else if (strcmp(callee, "outerProduct") == 0) {
-      assert(op[0]->type->is_vector() && op[1]->type->is_vector());
-      const unsigned m = op[0]->type->vector_elements;
-      const unsigned n = op[1]->type->vector_elements;
-      for (unsigned j = 0; j < n; j++) {
-	 for (unsigned i = 0; i < m; i++) {
-	    data.f[i+m*j] = op[0]->value.f[i] * op[1]->value.f[j];
-	 }
-      }
-   } else if (strcmp(callee, "pow") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_binop_pow, type, op[0], op[1]);
-   } else if (strcmp(callee, "radians") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = M_PI / 180.0F * op[0]->value.f[c];
-   } else if (strcmp(callee, "reflect") == 0) {
-      assert(op[0]->type->is_float());
-      float dot_NI = dot(op[1], op[0]);
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = op[0]->value.f[c] - 2 * dot_NI * op[1]->value.f[c];
-   } else if (strcmp(callee, "refract") == 0) {
-      const float eta = op[2]->value.f[0];
-      const float dot_NI = dot(op[1], op[0]);
-      const float k = 1.0F - eta * eta * (1.0F - dot_NI * dot_NI);
-      if (k < 0.0) {
-	 return ir_constant::zero(mem_ctx, type);
-      } else {
-	 for (unsigned c = 0; c < type->components(); c++) {
-	    data.f[c] = eta * op[0]->value.f[c] - (eta * dot_NI + sqrtf(k))
-			    * op[1]->value.f[c];
-	 }
-      }
-   } else if (strcmp(callee, "round") == 0 ||
-	      strcmp(callee, "roundEven") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_round_even, op[0]);
-   } else if (strcmp(callee, "sign") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_sign, type, op[0], NULL);
-   } else if (strcmp(callee, "sin") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_sin, type, op[0], NULL);
-   } else if (strcmp(callee, "sinh") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = sinhf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "smoothstep") == 0) {
-      assert(num_parameters == 3);
-      assert(op[1]->type == op[0]->type);
-      unsigned edge_inc = op[0]->type->is_scalar() ? 0 : 1;
-      for (unsigned c = 0, e = 0; c < type->components(); e += edge_inc, c++) {
-	 const float edge0 = op[0]->value.f[e];
-	 const float edge1 = op[1]->value.f[e];
-	 if (edge0 == edge1) {
-	    data.f[c] = 0.0; /* Avoid a crash - results are undefined anyway */
-	 } else {
-	    const float numerator = op[2]->value.f[c] - edge0;
-	    const float denominator = edge1 - edge0;
-	    const float t = CLAMP(numerator/denominator, 0, 1);
-	    data.f[c] = t * t * (3 - 2 * t);
-	 }
-      }
-   } else if (strcmp(callee, "sqrt") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_sqrt, type, op[0], NULL);
-   } else if (strcmp(callee, "step") == 0) {
-      assert(op[0]->type->is_float() && op[1]->type->is_float());
-      /* op[0] (edge) may be either a scalar or a vector */
-      const unsigned c0_inc = op[0]->type->is_scalar() ? 0 : 1;
-      for (unsigned c = 0, c0 = 0; c < type->components(); c0 += c0_inc, c++)
-	 data.f[c] = (op[1]->value.f[c] < op[0]->value.f[c0]) ? 0.0F : 1.0F;
-   } else if (strcmp(callee, "tan") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = tanf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "tanh") == 0) {
-      assert(op[0]->type->is_float());
-      for (unsigned c = 0; c < op[0]->type->components(); c++)
-	 data.f[c] = tanhf(op[0]->value.f[c]);
-   } else if (strcmp(callee, "transpose") == 0) {
-      assert(op[0]->type->is_matrix());
-      const unsigned n = op[0]->type->vector_elements;
-      const unsigned m = op[0]->type->matrix_columns;
-      for (unsigned j = 0; j < m; j++) {
-	 for (unsigned i = 0; i < n; i++) {
-	    data.f[m*i+j] += op[0]->value.f[i+n*j];
-	 }
-      }
-   } else if (strcmp(callee, "trunc") == 0) {
-      expr = new(mem_ctx) ir_expression(ir_unop_trunc, op[0]);
-   } else {
-      /* Unsupported builtin - some are not allowed in constant expressions. */
-      return NULL;
-   }
+   /* Now run the builtin function until something non-constant
+    * happens or we get the result.
+    */
+   if (constant_expression_evaluate_expression_list(origin ? origin->body : body, deref_hash, &result) && result)
+      result = result->clone(ralloc_parent(this), NULL);
 
-   if (expr != NULL)
-      return expr->constant_expression_value();
+   hash_table_dtor(deref_hash);
 
-   return new(mem_ctx) ir_constant(type, &data);
+   return result;
 }
diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c
index 7bf55f319..6de6de2b7 100644
--- a/mesalib/src/mesa/main/api_arrayelt.c
+++ b/mesalib/src/mesa/main/api_arrayelt.c
@@ -1643,12 +1643,20 @@ void GLAPIENTRY _ae_ArrayElement( GLint elt )
    const struct _glapi_table * const disp = GET_DISPATCH();
    GLboolean do_map;
 
+   /* If PrimitiveRestart is enabled and the index is the RestartIndex
+    * then we call PrimitiveRestartNV and return.
+    */
+   if (ctx->Array.PrimitiveRestart && (elt == ctx->Array.RestartIndex)) {
+      CALL_PrimitiveRestartNV((struct _glapi_table *)disp, ());
+      return;
+   }
+
    if (actx->NewState) {
       assert(!actx->mapped_vbos);
       _ae_update_state( ctx );
    }
 
-   /* Determine if w need to map/unmap VBOs */
+   /* Determine if we need to map/unmap VBOs */
    do_map = actx->nr_vbos && !actx->mapped_vbos;
 
    if (do_map)
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index d75351c85..7e2ac98b9 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -792,6 +792,7 @@ init_attrib_groups(struct gl_context *ctx)
 
    /* Miscellaneous */
    ctx->NewState = _NEW_ALL;
+   ctx->NewDriverState = ~0;
    ctx->ErrorValue = (GLenum) GL_NO_ERROR;
    ctx->ResetStatus = (GLenum) GL_NO_ERROR;
    ctx->varying_vp_inputs = VERT_BIT_ALL;
@@ -1290,6 +1291,7 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
    /* XXX FIXME:  Call callbacks?
     */
    dst->NewState = _NEW_ALL;
+   dst->NewDriverState = ~0;
 }
 #endif
 
diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c
index 8cfb97c26..c1c65ea25 100644
--- a/mesalib/src/mesa/main/dlist.c
+++ b/mesalib/src/mesa/main/dlist.c
@@ -134,7 +134,7 @@ do {						\
 do {									\
    if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON ||		\
        ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) {	\
-      _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" );	\
+      _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" );	\
       return retval;							\
    }									\
 } while (0)
@@ -149,7 +149,7 @@ do {									\
 do {									\
    if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON ||		\
        ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) {	\
-      _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" );	\
+      _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" );	\
       return;								\
    }									\
 } while (0)
@@ -5673,17 +5673,25 @@ save_Indexfv(const GLfloat * v)
 static void GLAPIENTRY
 save_EdgeFlag(GLboolean x)
 {
-   save_Attr1fNV(VERT_ATTRIB_EDGEFLAG, x ? (GLfloat)1.0 : (GLfloat)0.0);
+   save_Attr1fNV(VERT_ATTRIB_EDGEFLAG, x ? 1.0f : 0.0f);
 }
 
-static inline GLboolean compare4fv( const GLfloat *a,
-                                    const GLfloat *b,
-                                    GLuint count )
+
+/**
+ * Compare 'count' elements of vectors 'a' and 'b'.
+ * \return GL_TRUE if equal, GL_FALSE if different.
+ */
+static inline GLboolean
+compare_vec(const GLfloat *a, const GLfloat *b, GLuint count)
 {
    return memcmp( a, b, count * sizeof(GLfloat) ) == 0;
 }
-                              
 
+
+/**
+ * This glMaterial function is used for glMaterial calls that are outside
+ * a glBegin/End pair.  For glMaterial inside glBegin/End, see the VBO code.
+ */
 static void GLAPIENTRY
 save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
 {
@@ -5698,7 +5706,7 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
    case GL_FRONT_AND_BACK:
       break;
    default:
-      _mesa_compile_error(ctx, GL_INVALID_ENUM, "material(face)");
+      _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
       return;
    }
 
@@ -5717,7 +5725,7 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
       args = 3;
       break;
    default:
-      _mesa_compile_error(ctx, GL_INVALID_ENUM, "material(pname)");
+      _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
       return;
    }
    
@@ -5734,7 +5742,8 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
    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)) {
+             compare_vec(ctx->ListState.CurrentMaterial[i], param, args)) {
+            /* no change in material value */
             bitmask &= ~(1 << i);
          }
          else {
@@ -5744,8 +5753,7 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
       }
    }
 
-   /* If this call has effect, return early:
-    */
+   /* If this call has no effect, return early */
    if (bitmask == 0)
       return;
 
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 5f2c74a75..a843a4092 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -754,7 +754,7 @@ get_extension_override( struct gl_context *ctx )
 
    /* Remove trailing space. */
    len = strlen(extra_exts);
-   if (extra_exts[len - 1] == ' ')
+   if (len > 0 && extra_exts[len - 1] == ' ')
       extra_exts[len - 1] = '\0';
 
    return extra_exts;
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index 26ae1087c..f56369483 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -2023,7 +2023,11 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
    _glthread_LOCK_MUTEX(fb->Mutex);
    if (texObj) {
       if (attachment == GL_DEPTH_ATTACHMENT &&
-	   texObj == fb->Attachment[BUFFER_STENCIL].Texture) {
+          texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
+          level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
+          _mesa_tex_target_to_face(textarget) ==
+          fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
+          zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
 	 /* The texture object is already attached to the stencil attachment
 	  * point. Don't create a new renderbuffer; just reuse the stencil
 	  * attachment's. This is required to prevent a GL error in
@@ -2032,8 +2036,12 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
 	 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
 	                                      BUFFER_STENCIL);
       } else if (attachment == GL_STENCIL_ATTACHMENT &&
-	         texObj == fb->Attachment[BUFFER_DEPTH].Texture) {
-	 /* As above, but with depth and stencil juxtaposed. */
+	         texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
+                 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
+                 _mesa_tex_target_to_face(textarget) ==
+                 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
+                 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
+	 /* As above, but with depth and stencil transposed. */
 	 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
 	                                      BUFFER_DEPTH);
       } else {
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 2b709ded6..06ca0d5df 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -1636,6 +1636,11 @@ struct gl_array_attrib
 
    /* GL_ARB_vertex_buffer_object */
    struct gl_buffer_object *ArrayBufferObj;
+
+   /**
+    * Vertex arrays as consumed by a driver.
+    * The array pointer is set up only by the VBO module. */
+   const struct gl_client_array **_DrawArrays; /**< 0..VERT_ATTRIB_MAX-1 */
 };
 
 
@@ -3252,6 +3257,17 @@ typedef enum
    API_OPENGLES2
 } gl_api;
 
+/**
+ * Driver-specific state flags.
+ *
+ * These are or'd with gl_context::NewDriverState to notify a driver about
+ * a state change. The driver sets the flags at context creation and
+ * the meaning of the bits set is opaque to core Mesa.
+ */
+struct gl_driver_flags
+{
+   GLbitfield NewArray;             /**< Vertex array state */
+};
 
 /**
  * Mesa rendering context.
@@ -3411,6 +3427,9 @@ struct gl_context
 
    GLenum RenderMode;        /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
    GLbitfield NewState;      /**< bitwise-or of _NEW_* flags */
+   GLbitfield NewDriverState;/**< bitwise-or of flags from DriverFlags */
+
+   struct gl_driver_flags DriverFlags;
 
    GLboolean ViewportInitialized;  /**< has viewport size been initialized? */
 
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index 50095d2c6..694f6fa00 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -530,6 +530,32 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
 }
 
 
+/**
+ * Is the given texture format a generic compressed format?
+ */
+static GLboolean
+is_generic_compressed_format(GLenum format)
+{
+   switch (format) {
+   case GL_COMPRESSED_RED:
+   case GL_COMPRESSED_RG:
+   case GL_COMPRESSED_RGB:
+   case GL_COMPRESSED_RGBA:
+   case GL_COMPRESSED_ALPHA:
+   case GL_COMPRESSED_LUMINANCE:
+   case GL_COMPRESSED_LUMINANCE_ALPHA:
+   case GL_COMPRESSED_INTENSITY:
+   case GL_COMPRESSED_SRGB:
+   case GL_COMPRESSED_SRGB_ALPHA:
+   case GL_COMPRESSED_SLUMINANCE:
+   case GL_COMPRESSED_SLUMINANCE_ALPHA:
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+
 /**
  * For cube map faces, return a face index in [0,5].
  * For other targets return 0;
@@ -1705,7 +1731,8 @@ texture_error_check( struct gl_context *ctx,
    }
 
    /* additional checks for compressed textures */
-   if (_mesa_is_compressed_format(ctx, internalFormat)) {
+   if (_mesa_is_compressed_format(ctx, internalFormat) ||
+       is_generic_compressed_format(internalFormat)) {
       if (!target_can_be_compressed(ctx, target, internalFormat)) {
          if (!isProxy)
             _mesa_error(ctx, GL_INVALID_ENUM,
@@ -2036,7 +2063,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
       return GL_TRUE;
    }
 
-   if (_mesa_is_compressed_format(ctx, internalFormat)) {
+   if (_mesa_is_compressed_format(ctx, internalFormat) ||
+       is_generic_compressed_format(internalFormat)) {
       if (!target_can_be_compressed(ctx, target, internalFormat)) {
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glCopyTexImage%dD(target)", dimensions);
diff --git a/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c b/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c
index 2c21dc9a7..8337f4624 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_rasterpos.c
@@ -225,6 +225,7 @@ st_RasterPos(struct gl_context *ctx, const GLfloat v[4])
    struct st_context *st = st_context(ctx);
    struct draw_context *draw = st->draw;
    struct rastpos_stage *rs;
+   const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays;
 
    if (st->rastpos_stage) {
       /* get rastpos stage info */
@@ -250,9 +251,14 @@ st_RasterPos(struct gl_context *ctx, const GLfloat v[4])
     */
    rs->array[0].Ptr = (GLubyte *) v;
 
-   /* draw the point */
-   st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1,
+   /* Draw the point.
+    *
+    * Don't set DriverFlags.NewArray.
+    * st_feedback_draw_vbo doesn't check for that flag. */
+   ctx->Array._DrawArrays = rs->arrays;
+   st_feedback_draw_vbo(ctx, &rs->prim, 1, NULL, GL_TRUE, 0, 1,
                         NULL);
+   ctx->Array._DrawArrays = saved_arrays;
 
    /* restore draw's rasterization stage depending on rendermode */
    if (ctx->RenderMode == GL_FEEDBACK) {
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index 19d9da131..ce7dbb3f3 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -203,6 +203,10 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
    return st;
 }
 
+static void st_init_driver_flags(struct gl_driver_flags *f)
+{
+   f->NewArray = ST_NEW_VERTEX_ARRAYS;
+}
 
 struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
                                      const struct gl_config *visual,
@@ -225,6 +229,8 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
       return NULL;
    }
 
+   st_init_driver_flags(&ctx->DriverFlags);
+
    /* XXX: need a capability bit in gallium to query if the pipe
     * driver prefers DP4 or MUL/MAD for vertex transformation.
     */
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index 3ec98ada1..4786ed22f 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -50,6 +50,7 @@ struct u_vbuf;
 #define ST_NEW_FRAMEBUFFER             (1 << 3)
 #define ST_NEW_EDGEFLAGS_DATA          (1 << 4)
 #define ST_NEW_GEOMETRY_PROGRAM        (1 << 5)
+#define ST_NEW_VERTEX_ARRAYS           (1 << 6)
 
 
 struct st_state_flags {
diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c
index edab76bf5..42dc37576 100644
--- a/mesalib/src/mesa/state_tracker/st_draw.c
+++ b/mesalib/src/mesa/state_tracker/st_draw.c
@@ -966,7 +966,6 @@ st_validate_varrays(struct gl_context *ctx,
  */
 void
 st_draw_vbo(struct gl_context *ctx,
-            const struct gl_client_array **arrays,
             const struct _mesa_prim *prims,
             GLuint nr_prims,
             const struct _mesa_index_buffer *ib,
@@ -979,15 +978,22 @@ st_draw_vbo(struct gl_context *ctx,
    struct pipe_context *pipe = st->pipe;
    struct pipe_index_buffer ibuffer;
    struct pipe_draw_info info;
+   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
    unsigned i, num_instances = 1;
    unsigned max_index_plus_base;
-   GLboolean new_array =
-      st->dirty.st &&
-      (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
+   GLboolean new_array;
 
    /* Mesa core state should have been validated already */
    assert(ctx->NewState == 0x0);
 
+   /* Get Mesa driver state. */
+   st->dirty.st |= ctx->NewDriverState;
+   ctx->NewDriverState = 0;
+
+   new_array =
+      (st->dirty.st & (ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM)) ||
+      (st->dirty.mesa & (_NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
+
    if (ib) {
       int max_base_vertex = 0;
 
diff --git a/mesalib/src/mesa/state_tracker/st_draw.h b/mesalib/src/mesa/state_tracker/st_draw.h
index 47bdb11f8..c608051eb 100644
--- a/mesalib/src/mesa/state_tracker/st_draw.h
+++ b/mesalib/src/mesa/state_tracker/st_draw.h
@@ -49,7 +49,6 @@ void st_destroy_draw( struct st_context *st );
 
 extern void
 st_draw_vbo(struct gl_context *ctx,
-            const struct gl_client_array **arrays,
             const struct _mesa_prim *prims,
             GLuint nr_prims,
             const struct _mesa_index_buffer *ib,
@@ -60,7 +59,6 @@ st_draw_vbo(struct gl_context *ctx,
 
 extern void
 st_feedback_draw_vbo(struct gl_context *ctx,
-                     const struct gl_client_array **arrays,
                      const struct _mesa_prim *prims,
                      GLuint nr_prims,
                      const struct _mesa_index_buffer *ib,
diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c
index a559b733a..257618aa9 100644
--- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c
+++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c
@@ -91,7 +91,6 @@ set_feedback_vertex_format(struct gl_context *ctx)
  */
 void
 st_feedback_draw_vbo(struct gl_context *ctx,
-                     const struct gl_client_array **arrays,
                      const struct _mesa_prim *prims,
                      GLuint nr_prims,
                      const struct _mesa_index_buffer *ib,
@@ -110,6 +109,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
    struct pipe_index_buffer ibuffer;
    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
    struct pipe_transfer *ib_transfer = NULL;
+   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
    GLuint attr, i;
    const GLubyte *low_addr = NULL;
    const void *mapped_indices = NULL;
diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c
index 17042cf8f..6a3c9662e 100644
--- a/mesalib/src/mesa/tnl/t_draw.c
+++ b/mesalib/src/mesa/tnl/t_draw.c
@@ -408,7 +408,6 @@ static void unmap_vbos( struct gl_context *ctx,
 
 
 void _tnl_vbo_draw_prims(struct gl_context *ctx,
-			 const struct gl_client_array *arrays[],
 			 const struct _mesa_prim *prim,
 			 GLuint nr_prims,
 			 const struct _mesa_index_buffer *ib,
@@ -417,6 +416,8 @@ void _tnl_vbo_draw_prims(struct gl_context *ctx,
 			 GLuint max_index,
 			 struct gl_transform_feedback_object *tfb_vertcount)
 {
+   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
+
    if (!index_bounds_valid)
       vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims);
 
diff --git a/mesalib/src/mesa/tnl/tnl.h b/mesalib/src/mesa/tnl/tnl.h
index 434bd7fcd..f6b70e323 100644
--- a/mesalib/src/mesa/tnl/tnl.h
+++ b/mesalib/src/mesa/tnl/tnl.h
@@ -86,7 +86,6 @@ _tnl_draw_prims( struct gl_context *ctx,
 
 void
 _tnl_vbo_draw_prims( struct gl_context *ctx,
-		     const struct gl_client_array *arrays[],
 		     const struct _mesa_prim *prim,
 		     GLuint nr_prims,
 		     const struct _mesa_index_buffer *ib,
diff --git a/mesalib/src/mesa/vbo/vbo.h b/mesalib/src/mesa/vbo/vbo.h
index 2d01d9823..3cff8987e 100644
--- a/mesalib/src/mesa/vbo/vbo.h
+++ b/mesalib/src/mesa/vbo/vbo.h
@@ -72,7 +72,6 @@ void _vbo_InvalidateState( struct gl_context *ctx, GLuint new_state );
 
 
 typedef void (*vbo_draw_func)( struct gl_context *ctx,
-			       const struct gl_client_array **arrays,
 			       const struct _mesa_prim *prims,
 			       GLuint nr_prims,
 			       const struct _mesa_index_buffer *ib,
diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h
index b9a8affa5..1c49de0ca 100644
--- a/mesalib/src/mesa/vbo/vbo_context.h
+++ b/mesalib/src/mesa/vbo/vbo_context.h
@@ -58,6 +58,18 @@
 #include "vbo_save.h"
 
 
+/** Used to signal when transitioning from one kind of drawing method
+ * to another.
+ */
+enum draw_method
+{
+   DRAW_NONE,          /**< Initial value only */
+   DRAW_BEGIN_END,
+   DRAW_DISPLAY_LIST,
+   DRAW_ARRAYS
+};
+
+
 struct vbo_context {
    struct gl_client_array currval[VBO_ATTRIB_MAX];
    
@@ -74,6 +86,8 @@ struct vbo_context {
     * is responsible for initiating any fallback actions required:
     */
    vbo_draw_func draw_prims;
+
+   enum draw_method last_draw_method;
 };
 
 
@@ -101,4 +115,40 @@ get_program_mode( struct gl_context *ctx )
 }
 
 
+/**
+ * This is called by glBegin, glDrawArrays and glDrawElements (and
+ * variations of those calls).  When we transition from immediate mode
+ * drawing to array drawing we need to invalidate the array state.
+ *
+ * glBegin/End builds vertex arrays.  Those arrays may look identical
+ * to glDrawArrays arrays except that the position of the elements may
+ * be different.  For example, arrays of (position3v, normal3f) vs. arrays
+ * of (normal3f, position3f).  So we need to make sure we notify drivers
+ * that arrays may be changing.
+ */
+static inline void
+vbo_draw_method(struct vbo_context *vbo, enum draw_method method)
+{
+   if (vbo->last_draw_method != method) {
+      struct gl_context *ctx = vbo->exec.ctx;
+
+      switch (method) {
+      case DRAW_ARRAYS:
+         ctx->Array._DrawArrays = vbo->exec.array.inputs;
+         break;
+      case DRAW_BEGIN_END:
+         ctx->Array._DrawArrays = vbo->exec.vtx.inputs;
+         break;
+      case DRAW_DISPLAY_LIST:
+         ctx->Array._DrawArrays = vbo->save.inputs;
+         break;
+      default:
+         ASSERT(0);
+      }
+
+      ctx->NewDriverState |= ctx->DriverFlags.NewArray;
+      vbo->last_draw_method = method;
+   }
+}
+
 #endif
diff --git a/mesalib/src/mesa/vbo/vbo_exec.h b/mesalib/src/mesa/vbo/vbo_exec.h
index be9f3d78d..4ac7d168d 100644
--- a/mesalib/src/mesa/vbo/vbo_exec.h
+++ b/mesalib/src/mesa/vbo/vbo_exec.h
@@ -78,26 +78,12 @@ struct vbo_exec_copied_vtx {
 };
 
 
-/** Used to signal when transitioning from one kind of drawing method
- * to another.
- */
-enum draw_method
-{
-   DRAW_NONE,          /**< Initial value only */
-   DRAW_BEGIN_END,
-   DRAW_DISPLAY_LIST,
-   DRAW_ARRAYS
-};
-
-
 struct vbo_exec_context
 {
    struct gl_context *ctx;   
    GLvertexformat vtxfmt;
    GLvertexformat vtxfmt_noop;
 
-   enum draw_method last_draw_method;
-
    struct {
       struct gl_buffer_object *bufferobj;
 
@@ -174,28 +160,6 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec );
 void vbo_exec_vtx_destroy( struct vbo_exec_context *exec );
 
 
-/**
- * This is called by glBegin, glDrawArrays and glDrawElements (and
- * variations of those calls).  When we transition from immediate mode
- * drawing to array drawing we need to invalidate the array state.
- *
- * glBegin/End builds vertex arrays.  Those arrays may look identical
- * to glDrawArrays arrays except that the position of the elements may
- * be different.  For example, arrays of (position3v, normal3f) vs. arrays
- * of (normal3f, position3f).  So we need to make sure we notify drivers
- * that arrays may be changing.
- */
-static inline void
-vbo_draw_method(struct vbo_exec_context *exec, enum draw_method method)
-{
-   if (exec->last_draw_method != method) {
-      struct gl_context *ctx = exec->ctx;
-      ctx->Driver.UpdateState(ctx, _NEW_ARRAY);
-      exec->last_draw_method = method;
-   }
-}
-
-
 #if FEATURE_beginend
 
 void vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap );
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c
index 3f9541089..b87da18f3 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_api.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_api.c
@@ -700,7 +700,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
          return;
       }
 
-      vbo_draw_method(exec, DRAW_BEGIN_END);
+      vbo_draw_method(vbo_context(ctx), DRAW_BEGIN_END);
 
       if (ctx->Driver.PrepareExecBegin)
 	 ctx->Driver.PrepareExecBegin(ctx);
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c
index 2dcfb8e5b..cc94e761b 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_array.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_array.c
@@ -506,7 +506,7 @@ recalculate_input_bindings(struct gl_context *ctx)
    }
 
    _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
-   ctx->Driver.UpdateState(ctx, _NEW_ARRAY);
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
 }
 
 
@@ -523,7 +523,7 @@ vbo_bind_arrays(struct gl_context *ctx)
    struct vbo_context *vbo = vbo_context(ctx);
    struct vbo_exec_context *exec = &vbo->exec;
 
-   vbo_draw_method(exec, DRAW_ARRAYS);
+   vbo_draw_method(vbo, DRAW_ARRAYS);
 
    if (exec->array.recalculate_inputs) {
       recalculate_input_bindings(ctx);
@@ -600,7 +600,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
       if (primCount > 0) {
          /* draw one or two prims */
          check_buffers_are_unmapped(exec->array.inputs);
-         vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
+         vbo->draw_prims(ctx, prim, primCount, NULL,
                          GL_TRUE, start, start + count - 1, NULL);
       }
    }
@@ -610,7 +610,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
       prim[0].count = count;
 
       check_buffers_are_unmapped(exec->array.inputs);
-      vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
+      vbo->draw_prims(ctx, prim, 1, NULL,
                       GL_TRUE, start, start + count - 1,
                       NULL);
    }
@@ -801,7 +801,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
     */
 
    check_buffers_are_unmapped(exec->array.inputs);
-   vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
+   vbo->draw_prims( ctx, prim, 1, &ib,
 		    index_bounds_valid, start, end, NULL );
 }
 
@@ -1096,7 +1096,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
       }
 
       check_buffers_are_unmapped(exec->array.inputs);
-      vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
+      vbo->draw_prims(ctx, prim, primcount, &ib,
 		      GL_FALSE, ~0, ~0, NULL);
    } else {
       /* render one prim at a time */
@@ -1121,7 +1121,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
 	    prim[0].basevertex = 0;
 
          check_buffers_are_unmapped(exec->array.inputs);
-         vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
+         vbo->draw_prims(ctx, prim, 1, &ib,
                          GL_FALSE, ~0, ~0, NULL);
       }
    }
@@ -1199,7 +1199,7 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
     * will be rendered. */
 
    check_buffers_are_unmapped(exec->array.inputs);
-   vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
+   vbo->draw_prims(ctx, prim, 1, NULL,
                    GL_TRUE, 0, 0, obj);
 }
 
diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c
index da5ca695e..77db8ec7f 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_draw.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c
@@ -257,7 +257,7 @@ vbo_exec_bind_arrays( struct gl_context *ctx )
    }
 
    _mesa_set_varying_vp_inputs( ctx, varying_inputs );
-   ctx->Driver.UpdateState(ctx, _NEW_ARRAY);
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
 }
 
 
@@ -407,8 +407,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped)
 		   exec->vtx.vert_count);
 
 	 vbo_context(ctx)->draw_prims( ctx, 
-				       exec->vtx.inputs, 
-				       exec->vtx.prim, 
+				       exec->vtx.prim,
 				       exec->vtx.prim_count,
 				       NULL,
 				       GL_TRUE,
diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c
index 597a8f469..fff9df0c2 100644
--- a/mesalib/src/mesa/vbo/vbo_rebase.c
+++ b/mesalib/src/mesa/vbo/vbo_rebase.c
@@ -129,6 +129,7 @@ void vbo_rebase_prims( struct gl_context *ctx,
 
    struct _mesa_index_buffer tmp_ib;
    struct _mesa_prim *tmp_prims = NULL;
+   const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays;
    void *tmp_indices = NULL;
    GLuint i;
 
@@ -226,15 +227,20 @@ void vbo_rebase_prims( struct gl_context *ctx,
    
    /* Re-issue the draw call.
     */
+   ctx->Array._DrawArrays = tmp_array_pointers;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
+
    draw( ctx, 
-	 tmp_array_pointers, 
-	 prim, 
+	 prim,
 	 nr_prims, 
 	 ib, 
 	 GL_TRUE,
 	 0, 
 	 max_index - min_index,
 	 NULL );
+
+   ctx->Array._DrawArrays = saved_arrays;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
    
    if (tmp_indices)
       free(tmp_indices);
diff --git a/mesalib/src/mesa/vbo/vbo_save.c b/mesalib/src/mesa/vbo/vbo_save.c
index 040c9b7a9..7a97d3c65 100644
--- a/mesalib/src/mesa/vbo/vbo_save.c
+++ b/mesalib/src/mesa/vbo/vbo_save.c
@@ -49,6 +49,9 @@ static void vbo_save_callback_init( struct gl_context *ctx )
 
 
 
+/**
+ * Called at context creation time.
+ */
 void vbo_save_init( struct gl_context *ctx )
 {
    struct vbo_context *vbo = vbo_context(ctx);
diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c
index 13604333e..74f5dc9ce 100644
--- a/mesalib/src/mesa/vbo/vbo_save_api.c
+++ b/mesalib/src/mesa/vbo/vbo_save_api.c
@@ -1506,6 +1506,9 @@ vbo_print_vertex_list(struct gl_context *ctx, void *data)
 }
 
 
+/**
+ * Called during context creation/init.
+ */
 static void
 _save_current_init(struct gl_context *ctx)
 {
@@ -1529,7 +1532,7 @@ _save_current_init(struct gl_context *ctx)
 
 
 /**
- * Initialize the display list compiler
+ * Initialize the display list compiler.  Called during context creation.
  */
 void
 vbo_save_api_init(struct vbo_save_context *save)
diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c
index 88a9a7e34..c6425ab1b 100644
--- a/mesalib/src/mesa/vbo/vbo_save_draw.c
+++ b/mesalib/src/mesa/vbo/vbo_save_draw.c
@@ -213,7 +213,7 @@ static void vbo_bind_vertex_list(struct gl_context *ctx,
    }
 
    _mesa_set_varying_vp_inputs( ctx, varying_inputs );
-   ctx->Driver.UpdateState(ctx, _NEW_ARRAY);
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
 }
 
 
@@ -250,7 +250,6 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
    const struct vbo_save_vertex_list *node =
       (const struct vbo_save_vertex_list *) data;
    struct vbo_save_context *save = &vbo_context(ctx)->save;
-   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
    GLboolean remap_vertex_store = GL_FALSE;
 
    if (save->vertex_store->buffer) {
@@ -304,7 +303,7 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
 
       vbo_bind_vertex_list( ctx, node );
 
-      vbo_draw_method(exec, DRAW_DISPLAY_LIST);
+      vbo_draw_method(vbo_context(ctx), DRAW_DISPLAY_LIST);
 
       /* Again...
        */
@@ -313,8 +312,7 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
 
       if (node->count > 0) {
          vbo_context(ctx)->draw_prims(ctx, 
-                                      save->inputs, 
-                                      node->prim, 
+                                      node->prim,
                                       node->prim_count,
                                       NULL,
                                       GL_TRUE,
diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c
index b53293c31..528fcfd7f 100644
--- a/mesalib/src/mesa/vbo/vbo_split_copy.c
+++ b/mesalib/src/mesa/vbo/vbo_split_copy.c
@@ -171,6 +171,8 @@ dump_draw_info(struct gl_context *ctx,
 static void
 flush( struct copy_context *copy )
 {
+   struct gl_context *ctx = copy->ctx;
+   const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays;
    GLuint i;
 
    /* Set some counters: 
@@ -189,8 +191,10 @@ flush( struct copy_context *copy )
    (void) dump_draw_info;
 #endif
 
-   copy->draw( copy->ctx,
-	       copy->dstarray_ptr,
+   ctx->Array._DrawArrays = copy->dstarray_ptr;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
+
+   copy->draw( ctx,
 	       copy->dstprim,
 	       copy->dstprim_nr,
 	       &copy->dstib,
@@ -199,6 +203,9 @@ flush( struct copy_context *copy )
 	       copy->dstbuf_nr - 1,
 	       NULL );
 
+   ctx->Array._DrawArrays = saved_arrays;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
+
    /* Reset all pointers: 
     */
    copy->dstprim_nr = 0;
diff --git a/mesalib/src/mesa/vbo/vbo_split_inplace.c b/mesalib/src/mesa/vbo/vbo_split_inplace.c
index 9e596f668..00464049d 100644
--- a/mesalib/src/mesa/vbo/vbo_split_inplace.c
+++ b/mesalib/src/mesa/vbo/vbo_split_inplace.c
@@ -62,6 +62,8 @@ struct split_context {
 
 static void flush_vertex( struct split_context *split )
 {
+   struct gl_context *ctx = split->ctx;
+   const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays;
    struct _mesa_index_buffer ib;
    GLuint i;
 
@@ -82,8 +84,10 @@ static void flush_vertex( struct split_context *split )
 
    assert(split->max_index >= split->min_index);
 
-   split->draw(split->ctx,
-	       split->array,
+   ctx->Array._DrawArrays = split->array;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
+
+   split->draw(ctx,
 	       split->dstprim,
 	       split->dstprim_nr,
 	       split->ib ? &ib : NULL,
@@ -92,6 +96,9 @@ static void flush_vertex( struct split_context *split )
 	       split->max_index,
 	       NULL);
 
+   ctx->Array._DrawArrays = saved_arrays;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
+
    split->dstprim_nr = 0;
    split->min_index = ~0;
    split->max_index = 0;
-- 
cgit v1.2.3