From 0e3699334faf92f508b6c187a261548b656b0dd3 Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Fri, 20 Apr 2012 17:07:15 +0200
Subject: fontconfig libX11 mesa pixman xserver git update 20 april 2012

---
 mesalib/src/gallium/auxiliary/util/u_blit.c       |  17 +-
 mesalib/src/gallium/auxiliary/util/u_blit.h       | 191 +++---
 mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c |  17 +-
 mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h | 134 ++--
 mesalib/src/gallium/auxiliary/util/u_inlines.h    |   2 +-
 mesalib/src/glsl/ast_function.cpp                 |  29 +-
 mesalib/src/glsl/ast_to_hir.cpp                   |  70 ++
 mesalib/src/glsl/ir.h                             |  13 +
 mesalib/src/glsl/main.cpp                         |   2 +-
 mesalib/src/glsl/opt_array_splitting.cpp          |  53 +-
 mesalib/src/glsl/opt_structure_splitting.cpp      | 739 +++++++++++-----------
 mesalib/src/mesa/main/attrib.c                    |   3 -
 mesalib/src/mesa/main/context.c                   |   5 +-
 mesalib/src/mesa/main/ff_fragment_shader.cpp      |   2 +-
 mesalib/src/mesa/main/mtypes.h                    |   2 +-
 mesalib/src/mesa/main/readpix.c                   |  62 +-
 mesalib/src/mesa/main/state.c                     |  22 +-
 mesalib/src/mesa/main/varray.c                    |   2 +-
 mesalib/src/mesa/state_tracker/st_cb_bitmap.c     | 124 ++--
 mesalib/src/mesa/state_tracker/st_cb_clear.c      |  95 +--
 mesalib/src/mesa/state_tracker/st_cb_clear.h      | 101 ++-
 mesalib/src/mesa/state_tracker/st_cb_drawpixels.c |  33 +-
 mesalib/src/mesa/state_tracker/st_cb_drawtex.c    |  26 +-
 mesalib/src/mesa/state_tracker/st_cb_flush.c      | 324 +++++-----
 mesalib/src/mesa/state_tracker/st_context.c       |   3 +
 mesalib/src/mesa/state_tracker/st_context.h       |  20 +-
 mesalib/src/mesa/vbo/vbo_context.c                |  13 +-
 mesalib/src/mesa/vbo/vbo_context.h                |  10 -
 mesalib/src/mesa/vbo/vbo_exec.c                   |   4 +
 mesalib/src/mesa/vbo/vbo_exec.h                   |   1 +
 mesalib/src/mesa/vbo/vbo_exec_api.c               |  10 +-
 mesalib/src/mesa/vbo/vbo_exec_array.c             | 100 +--
 mesalib/src/mesa/vbo/vbo_exec_draw.c              |  12 +-
 mesalib/src/mesa/vbo/vbo_save.c                   |  10 +-
 mesalib/src/mesa/vbo/vbo_save_draw.c              |  10 +-
 35 files changed, 1132 insertions(+), 1129 deletions(-)

(limited to 'mesalib/src')

diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.c b/mesalib/src/gallium/auxiliary/util/u_blit.c
index 127973388..e5b97f720 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blit.c
+++ b/mesalib/src/gallium/auxiliary/util/u_blit.c
@@ -232,8 +232,10 @@ get_next_slot( struct blit_state *ctx )
 {
    const unsigned max_slots = 4096 / sizeof ctx->vertices;
 
-   if (ctx->vbuf_slot >= max_slots) 
-      util_blit_flush( ctx );
+   if (ctx->vbuf_slot >= max_slots) {
+      pipe_resource_reference(&ctx->vbuf, NULL);
+      ctx->vbuf_slot = 0;
+   }
 
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
@@ -674,17 +676,6 @@ util_blit_pixels(struct blit_state *ctx,
 }
 
 
-/* Release vertex buffer at end of frame to avoid synchronous
- * rendering.
- */
-void util_blit_flush( struct blit_state *ctx )
-{
-   pipe_resource_reference(&ctx->vbuf, NULL);
-   ctx->vbuf_slot = 0;
-} 
-
-
-
 /**
  * Copy pixel block from src texture to dst surface.
  * The sampler view's first_level field indicates the source
diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.h b/mesalib/src/gallium/auxiliary/util/u_blit.h
index 23a427d34..810d01b04 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blit.h
+++ b/mesalib/src/gallium/auxiliary/util/u_blit.h
@@ -1,98 +1,93 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#ifndef U_BLIT_H
-#define U_BLIT_H
-
-
-#include "pipe/p_compiler.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-   
-struct cso_context;
-struct pipe_context;
-struct pipe_resource;
-struct pipe_sampler_view;
-struct pipe_surface;
-
-
-extern struct blit_state *
-util_create_blit(struct pipe_context *pipe, struct cso_context *cso);
-
-extern void
-util_destroy_blit(struct blit_state *ctx);
-
-extern void
-util_blit_pixels(struct blit_state *ctx,
-                 struct pipe_resource *src_tex,
-                 unsigned src_level,
-                 int srcX0, int srcY0,
-                 int srcX1, int srcY1,
-                 int srcZ0,
-                 struct pipe_surface *dst,
-                 int dstX0, int dstY0,
-                 int dstX1, int dstY1,
-                 float z, uint filter);
-
-void
-util_blit_pixels_writemask(struct blit_state *ctx,
-                           struct pipe_resource *src_tex,
-                           unsigned src_level,
-                           int srcX0, int srcY0,
-                           int srcX1, int srcY1,
-                           int srcZ0,
-                           struct pipe_surface *dst,
-                           int dstX0, int dstY0,
-                           int dstX1, int dstY1,
-                           float z, uint filter,
-                           uint writemask);
-
-extern void
-util_blit_pixels_tex(struct blit_state *ctx,
-                     struct pipe_sampler_view *src_sampler_view,
-                     int srcX0, int srcY0,
-                     int srcX1, int srcY1,
-                     struct pipe_surface *dst,
-                     int dstX0, int dstY0,
-                     int dstX1, int dstY1,
-                     float z, uint filter);
-
-/* Call at end of frame to avoid synchronous rendering.
- */
-extern void
-util_blit_flush( struct blit_state *ctx );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef U_BLIT_H
+#define U_BLIT_H
+
+
+#include "pipe/p_compiler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   
+struct cso_context;
+struct pipe_context;
+struct pipe_resource;
+struct pipe_sampler_view;
+struct pipe_surface;
+
+
+extern struct blit_state *
+util_create_blit(struct pipe_context *pipe, struct cso_context *cso);
+
+extern void
+util_destroy_blit(struct blit_state *ctx);
+
+extern void
+util_blit_pixels(struct blit_state *ctx,
+                 struct pipe_resource *src_tex,
+                 unsigned src_level,
+                 int srcX0, int srcY0,
+                 int srcX1, int srcY1,
+                 int srcZ0,
+                 struct pipe_surface *dst,
+                 int dstX0, int dstY0,
+                 int dstX1, int dstY1,
+                 float z, uint filter);
+
+void
+util_blit_pixels_writemask(struct blit_state *ctx,
+                           struct pipe_resource *src_tex,
+                           unsigned src_level,
+                           int srcX0, int srcY0,
+                           int srcX1, int srcY1,
+                           int srcZ0,
+                           struct pipe_surface *dst,
+                           int dstX0, int dstY0,
+                           int dstX1, int dstY1,
+                           float z, uint filter,
+                           uint writemask);
+
+extern void
+util_blit_pixels_tex(struct blit_state *ctx,
+                     struct pipe_sampler_view *src_sampler_view,
+                     int srcX0, int srcY0,
+                     int srcX1, int srcY1,
+                     struct pipe_surface *dst,
+                     int dstX0, int dstY0,
+                     int dstX1, int dstY1,
+                     float z, uint filter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c
index a28d41825..82474cd7b 100644
--- a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -1361,8 +1361,10 @@ get_next_slot(struct gen_mipmap_state *ctx)
 {
    const unsigned max_slots = 4096 / sizeof ctx->vertices;
 
-   if (ctx->vbuf_slot >= max_slots) 
-      util_gen_mipmap_flush( ctx );
+   if (ctx->vbuf_slot >= max_slots) {
+      pipe_resource_reference(&ctx->vbuf, NULL);
+      ctx->vbuf_slot = 0;
+   }
 
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
@@ -1475,17 +1477,6 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
 }
 
 
-
-/* Release vertex buffer at end of frame to avoid synchronous
- * rendering.
- */
-void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
-{
-   pipe_resource_reference(&ctx->vbuf, NULL);
-   ctx->vbuf_slot = 0;
-} 
-
-
 /**
  * Generate mipmap images.  It's assumed all needed texture memory is
  * already allocated.
diff --git a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h
index e4670a43c..1bcc50f51 100644
--- a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h
+++ b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -1,70 +1,64 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef U_GENMIPMAP_H
-#define U_GENMIPMAP_H
-
-#include "pipe/p_state.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-   
-struct pipe_context;
-struct pipe_resource;
-struct cso_context;
-
-struct gen_mipmap_state;
-
-
-extern struct gen_mipmap_state *
-util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso);
-
-
-extern void
-util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
-
-/* Release vertex buffer at end of frame to avoid synchronous
- * rendering.
- */
-extern void 
-util_gen_mipmap_flush( struct gen_mipmap_state *ctx );
-
-
-extern void
-util_gen_mipmap(struct gen_mipmap_state *ctx,
-                struct pipe_sampler_view *psv,
-                uint layer, uint baseLevel, uint lastLevel, uint filter);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef U_GENMIPMAP_H
+#define U_GENMIPMAP_H
+
+#include "pipe/p_state.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   
+struct pipe_context;
+struct pipe_resource;
+struct cso_context;
+
+struct gen_mipmap_state;
+
+
+extern struct gen_mipmap_state *
+util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso);
+
+
+extern void
+util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
+
+
+extern void
+util_gen_mipmap(struct gen_mipmap_state *ctx,
+                struct pipe_sampler_view *psv,
+                uint layer, uint baseLevel, uint lastLevel, uint filter);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h
index 23658bc88..49b4531db 100644
--- a/mesalib/src/gallium/auxiliary/util/u_inlines.h
+++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h
@@ -370,7 +370,7 @@ pipe_buffer_write_nooverlap(struct pipe_context *pipe,
                                buf,
                                0,
                                (PIPE_TRANSFER_WRITE |
-                                PIPE_TRANSFER_NOOVERWRITE),
+                                PIPE_TRANSFER_UNSYNCHRONIZED),
                                &box,
                                data,
                                0, 0);
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 39401017b..8bf0ba2a8 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -152,19 +152,22 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
 	    return false;
 	 }
 
-	 if (actual->variable_referenced()
-	     && actual->variable_referenced()->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;
+	 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;
+	    }
+	    var->assigned = true;
 	 }
       }
 
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 820c86c5e..e24914b83 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -57,6 +57,10 @@
 #include "program/hash_table.h"
 #include "ir.h"
 
+static void
+detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
+			       exec_list *instructions);
+
 void
 _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
 {
@@ -87,6 +91,7 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
       ast->hir(instructions, state);
 
    detect_recursion_unlinked(state, instructions);
+   detect_conflicting_assignments(state, instructions);
 
    state->toplevel_ir = NULL;
 }
@@ -672,6 +677,10 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
    void *ctx = state;
    bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
 
+   ir_variable *lhs_var = lhs->variable_referenced();
+   if (lhs_var)
+      lhs_var->assigned = true;
+
    if (!error_emitted) {
       if (non_lvalue_description != NULL) {
          _mesa_glsl_error(&lhs_loc, state,
@@ -4013,3 +4022,64 @@ ast_struct_specifier::hir(exec_list *instructions,
     */
    return NULL;
 }
+
+static void
+detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
+			       exec_list *instructions)
+{
+   bool gl_FragColor_assigned = false;
+   bool gl_FragData_assigned = false;
+   bool user_defined_fs_output_assigned = false;
+   ir_variable *user_defined_fs_output = NULL;
+
+   /* It would be nice to have proper location information. */
+   YYLTYPE loc;
+   memset(&loc, 0, sizeof(loc));
+
+   foreach_list(node, instructions) {
+      ir_variable *var = ((ir_instruction *)node)->as_variable();
+
+      if (!var)
+	 continue;
+
+      if (strcmp(var->name, "gl_FragColor") == 0)
+	 gl_FragColor_assigned = var->assigned;
+      else if (strcmp(var->name, "gl_FragData") == 0)
+	 gl_FragData_assigned = var->assigned;
+      else if (strncmp(var->name, "gl_", 3) != 0) {
+	 if (state->target == fragment_shader &&
+	     (var->mode == ir_var_out || var->mode == ir_var_inout)) {
+	    user_defined_fs_output_assigned = true;
+	    user_defined_fs_output = var;
+	 }
+      }
+   }
+
+   /* From the GLSL 1.30 spec:
+    *
+    *     "If a shader statically assigns a value to gl_FragColor, it
+    *      may not assign a value to any element of gl_FragData. If a
+    *      shader statically writes a value to any element of
+    *      gl_FragData, it may not assign a value to
+    *      gl_FragColor. That is, a shader may assign values to either
+    *      gl_FragColor or gl_FragData, but not both. Multiple shaders
+    *      linked together must also consistently write just one of
+    *      these variables.  Similarly, if user declared output
+    *      variables are in use (statically assigned to), then the
+    *      built-in variables gl_FragColor and gl_FragData may not be
+    *      assigned to. These incorrect usages all generate compile
+    *      time errors."
+    */
+   if (gl_FragColor_assigned && gl_FragData_assigned) {
+      _mesa_glsl_error(&loc, state, "fragment shader writes to both "
+		       "`gl_FragColor' and `gl_FragData'\n");
+   } else if (gl_FragColor_assigned && user_defined_fs_output_assigned) {
+      _mesa_glsl_error(&loc, state, "fragment shader writes to both "
+		       "`gl_FragColor' and `%s'\n",
+		       user_defined_fs_output->name);
+   } else if (gl_FragData_assigned && user_defined_fs_output_assigned) {
+      _mesa_glsl_error(&loc, state, "fragment shader writes to both "
+		       "`gl_FragData' and `%s'\n",
+		       user_defined_fs_output->name);
+   }
+}
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index d6c6a607a..ddfaf3614 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -353,9 +353,22 @@ public:
     * Several GLSL semantic checks require knowledge of whether or not a
     * variable has been used.  For example, it is an error to redeclare a
     * variable as invariant after it has been used.
+    *
+    * This is only maintained in the ast_to_hir.cpp path, not in
+    * Mesa's fixed function or ARB program paths.
     */
    unsigned used:1;
 
+   /**
+    * Has this variable been statically assigned?
+    *
+    * This answers whether the variable was assigned in any path of
+    * the shader during ast_to_hir.  This doesn't answer whether it is
+    * still written after dead code removal, nor is it maintained in
+    * non-ast_to_hir.cpp (GLSL parsing) paths.
+    */
+   unsigned assigned:1;
+
    /**
     * Storage class of the variable.
     *
diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp
index d43bf1a74..3231b1be9 100644
--- a/mesalib/src/glsl/main.cpp
+++ b/mesalib/src/glsl/main.cpp
@@ -238,7 +238,7 @@ main(int argc, char **argv)
 	 usage_fail(argv[0]);
 
       const char *const ext = & argv[optind][len - 5];
-      if (strncmp(".vert", ext, 5) == 0)
+      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
 	 shader->Type = GL_VERTEX_SHADER;
       else if (strncmp(".geom", ext, 5) == 0)
 	 shader->Type = GL_GEOMETRY_SHADER;
diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp
index f11b51631..67733ca6b 100644
--- a/mesalib/src/glsl/opt_array_splitting.cpp
+++ b/mesalib/src/glsl/opt_array_splitting.cpp
@@ -49,7 +49,7 @@ public:
    variable_entry(ir_variable *var)
    {
       this->var = var;
-      this->whole_array_access = 0;
+      this->split = true;
       this->declaration = false;
       this->components = NULL;
       this->mem_ctx = NULL;
@@ -62,10 +62,14 @@ public:
    ir_variable *var; /* The key: the variable's pointer. */
    unsigned size; /* array length or matrix columns */
 
-   /** Number of times the variable is referenced, including assignments. */
-   unsigned whole_array_access;
+   /** Whether this array should be split or not. */
+   bool split;
 
-   bool declaration; /* If the variable had a decl in the instruction stream */
+   /* If the variable had a decl we can work with in the instruction
+    * stream.  We can't do splitting on function arguments, which
+    * don't get this variable set.
+    */
+   bool declaration;
 
    ir_variable **components;
 
@@ -99,6 +103,7 @@ public:
    virtual ir_visitor_status visit(ir_variable *);
    virtual ir_visitor_status visit(ir_dereference_variable *);
    virtual ir_visitor_status visit_enter(ir_dereference_array *);
+   virtual ir_visitor_status visit_enter(ir_function_signature *);
 
    variable_entry *get_variable_entry(ir_variable *var);
 
@@ -154,12 +159,13 @@ ir_array_reference_visitor::visit(ir_dereference_variable *ir)
 {
    variable_entry *entry = this->get_variable_entry(ir->var);
 
-   /* If we made it to here, then the dereference of this array didn't
-    * have a constant index (see the visit_continue_with_parent
-    * below), so we can't split the variable.
+   /* If we made it to here without seeing an ir_dereference_array,
+    * then the dereference of this array didn't have a constant index
+    * (see the visit_continue_with_parent below), so we can't split
+    * the variable.
     */
    if (entry)
-      entry->whole_array_access++;
+      entry->split = false;
 
    return visit_continue;
 }
@@ -173,12 +179,26 @@ ir_array_reference_visitor::visit_enter(ir_dereference_array *ir)
 
    variable_entry *entry = this->get_variable_entry(deref->var);
 
+   /* If the access to the array has a variable index, we wouldn't
+    * know which split variable this dereference should go to.
+    */
    if (entry && !ir->array_index->as_constant())
-      entry->whole_array_access++;
+      entry->split = false;
 
    return visit_continue_with_parent;
 }
 
+ir_visitor_status
+ir_array_reference_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* We don't have logic for array-splitting function arguments,
+    * so just look at the body instructions and not the parameter
+    * declarations.
+    */
+   visit_list_elements(this, &ir->body);
+   return visit_continue_with_parent;
+}
+
 bool
 ir_array_reference_visitor::get_split_list(exec_list *instructions,
 					   bool linked)
@@ -204,12 +224,12 @@ ir_array_reference_visitor::get_split_list(exec_list *instructions,
       variable_entry *entry = (variable_entry *)iter.get();
 
       if (debug) {
-	 printf("array %s@%p: decl %d, whole_access %d\n",
+	 printf("array %s@%p: decl %d, split %d\n",
 		entry->var->name, (void *) entry->var, entry->declaration,
-		entry->whole_array_access);
+		entry->split);
       }
 
-      if (!entry->declaration || entry->whole_array_access) {
+      if (!(entry->declaration && entry->split)) {
 	 entry->remove();
       }
    }
@@ -217,7 +237,10 @@ ir_array_reference_visitor::get_split_list(exec_list *instructions,
    return !variable_list.is_empty();
 }
 
-/** This is the class that does the actual work of splitting. */
+/**
+ * This class rewrites the dereferences of arrays that have been split
+ * to use the newly created ir_variables for each component.
+ */
 class ir_array_splitting_visitor : public ir_rvalue_visitor {
 public:
    ir_array_splitting_visitor(exec_list *vars)
@@ -236,7 +259,6 @@ public:
    variable_entry *get_splitting_entry(ir_variable *var);
 
    exec_list *variable_list;
-   void *mem_ctx;
 };
 
 variable_entry *
@@ -348,8 +370,7 @@ optimize_split_arrays(exec_list *instructions, bool linked)
       const struct glsl_type *subtype;
 
       if (type->is_matrix())
-	 subtype = glsl_type::get_instance(GLSL_TYPE_FLOAT,
-					   type->vector_elements, 1);
+	 subtype = type->column_type();
       else
 	 subtype = type->fields.array;
 
diff --git a/mesalib/src/glsl/opt_structure_splitting.cpp b/mesalib/src/glsl/opt_structure_splitting.cpp
index d08a5cee1..6dd228e4e 100644
--- a/mesalib/src/glsl/opt_structure_splitting.cpp
+++ b/mesalib/src/glsl/opt_structure_splitting.cpp
@@ -1,367 +1,372 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file opt_structure_splitting.cpp
- *
- * If a structure is only ever referenced by its components, then
- * split those components out to individual variables so they can be
- * handled normally by other optimization passes.
- *
- * This skips structures like uniforms, which need to be accessible as
- * structures for their access by the GL.
- */
-
-#include "ir.h"
-#include "ir_visitor.h"
-#include "ir_print_visitor.h"
-#include "ir_rvalue_visitor.h"
-#include "glsl_types.h"
-
-static bool debug = false;
-
-// XXX using variable_entry2 here to avoid collision (MSVC multiply-defined
-// function) with the variable_entry class seen in ir_variable_refcount.h
-// Perhaps we can use the one in ir_variable_refcount.h and make this class
-// here go away?
-class variable_entry2 : public exec_node
-{
-public:
-   variable_entry2(ir_variable *var)
-   {
-      this->var = var;
-      this->whole_structure_access = 0;
-      this->declaration = false;
-      this->components = NULL;
-      this->mem_ctx = NULL;
-   }
-
-   ir_variable *var; /* The key: the variable's pointer. */
-
-   /** Number of times the variable is referenced, including assignments. */
-   unsigned whole_structure_access;
-
-   bool declaration; /* If the variable had a decl in the instruction stream */
-
-   ir_variable **components;
-
-   /** ralloc_parent(this->var) -- the shader's ralloc context. */
-   void *mem_ctx;
-};
-
-
-class ir_structure_reference_visitor : public ir_hierarchical_visitor {
-public:
-   ir_structure_reference_visitor(void)
-   {
-      this->mem_ctx = ralloc_context(NULL);
-      this->variable_list.make_empty();
-   }
-
-   ~ir_structure_reference_visitor(void)
-   {
-      ralloc_free(mem_ctx);
-   }
-
-   virtual ir_visitor_status visit(ir_variable *);
-   virtual ir_visitor_status visit(ir_dereference_variable *);
-   virtual ir_visitor_status visit_enter(ir_dereference_record *);
-   virtual ir_visitor_status visit_enter(ir_assignment *);
-   virtual ir_visitor_status visit_enter(ir_function_signature *);
-
-   variable_entry2 *get_variable_entry2(ir_variable *var);
-
-   /* List of variable_entry */
-   exec_list variable_list;
-
-   void *mem_ctx;
-};
-
-variable_entry2 *
-ir_structure_reference_visitor::get_variable_entry2(ir_variable *var)
-{
-   assert(var);
-
-   if (!var->type->is_record() || var->mode == ir_var_uniform)
-      return NULL;
-
-   foreach_iter(exec_list_iterator, iter, this->variable_list) {
-      variable_entry2 *entry = (variable_entry2 *)iter.get();
-      if (entry->var == var)
-	 return entry;
-   }
-
-   variable_entry2 *entry = new(mem_ctx) variable_entry2(var);
-   this->variable_list.push_tail(entry);
-   return entry;
-}
-
-
-ir_visitor_status
-ir_structure_reference_visitor::visit(ir_variable *ir)
-{
-   variable_entry2 *entry = this->get_variable_entry2(ir);
-
-   if (entry)
-      entry->declaration = true;
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_structure_reference_visitor::visit(ir_dereference_variable *ir)
-{
-   ir_variable *const var = ir->variable_referenced();
-   variable_entry2 *entry = this->get_variable_entry2(var);
-
-   if (entry)
-      entry->whole_structure_access++;
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_structure_reference_visitor::visit_enter(ir_dereference_record *ir)
-{
-   (void) ir;
-   /* Don't descend into the ir_dereference_variable below. */
-   return visit_continue_with_parent;
-}
-
-ir_visitor_status
-ir_structure_reference_visitor::visit_enter(ir_assignment *ir)
-{
-   /* If there are no structure references yet, no need to bother with
-    * processing the expression tree.
-    */
-   if (this->variable_list.is_empty())
-      return visit_continue_with_parent;
-
-   if (ir->lhs->as_dereference_variable() &&
-       ir->rhs->as_dereference_variable() &&
-       !ir->condition) {
-      /* We'll split copies of a structure to copies of components, so don't
-       * descend to the ir_dereference_variables.
-       */
-      return visit_continue_with_parent;
-   }
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_structure_reference_visitor::visit_enter(ir_function_signature *ir)
-{
-   /* We don't want to descend into the function parameters and
-    * dead-code eliminate them, so just accept the body here.
-    */
-   visit_list_elements(this, &ir->body);
-   return visit_continue_with_parent;
-}
-
-class ir_structure_splitting_visitor : public ir_rvalue_visitor {
-public:
-   ir_structure_splitting_visitor(exec_list *vars)
-   {
-      this->variable_list = vars;
-   }
-
-   virtual ~ir_structure_splitting_visitor()
-   {
-   }
-
-   virtual ir_visitor_status visit_leave(ir_assignment *);
-
-   void split_deref(ir_dereference **deref);
-   void handle_rvalue(ir_rvalue **rvalue);
-   variable_entry2 *get_splitting_entry(ir_variable *var);
-
-   exec_list *variable_list;
-   void *mem_ctx;
-};
-
-variable_entry2 *
-ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var)
-{
-   assert(var);
-
-   if (!var->type->is_record())
-      return NULL;
-
-   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
-      variable_entry2 *entry = (variable_entry2 *)iter.get();
-      if (entry->var == var) {
-	 return entry;
-      }
-   }
-
-   return NULL;
-}
-
-void
-ir_structure_splitting_visitor::split_deref(ir_dereference **deref)
-{
-   if ((*deref)->ir_type != ir_type_dereference_record)
-      return;
-
-   ir_dereference_record *deref_record = (ir_dereference_record *)*deref;
-   ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable();
-   if (!deref_var)
-      return;
-
-   variable_entry2 *entry = get_splitting_entry(deref_var->var);
-   if (!entry)
-      return;
-
-   unsigned int i;
-   for (i = 0; i < entry->var->type->length; i++) {
-      if (strcmp(deref_record->field,
-		 entry->var->type->fields.structure[i].name) == 0)
-	 break;
-   }
-   assert(i != entry->var->type->length);
-
-   *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]);
-}
-
-void
-ir_structure_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
-{
-   if (!*rvalue)
-      return;
-
-   ir_dereference *deref = (*rvalue)->as_dereference();
-
-   if (!deref)
-      return;
-
-   split_deref(&deref);
-   *rvalue = deref;
-}
-
-ir_visitor_status
-ir_structure_splitting_visitor::visit_leave(ir_assignment *ir)
-{
-   ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
-   ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
-   variable_entry2 *lhs_entry = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
-   variable_entry2 *rhs_entry = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
-   const glsl_type *type = ir->rhs->type;
-
-   if ((lhs_entry || rhs_entry) && !ir->condition) {
-      for (unsigned int i = 0; i < type->length; i++) {
-	 ir_dereference *new_lhs, *new_rhs;
-	 void *mem_ctx = lhs_entry ? lhs_entry->mem_ctx : rhs_entry->mem_ctx;
-
-	 if (lhs_entry) {
-	    new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]);
-	 } else {
-	    new_lhs = new(mem_ctx)
-	       ir_dereference_record(ir->lhs->clone(mem_ctx, NULL),
-				     type->fields.structure[i].name);
-	 }
-
-	 if (rhs_entry) {
-	    new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]);
-	 } else {
-	    new_rhs = new(mem_ctx)
-	       ir_dereference_record(ir->rhs->clone(mem_ctx, NULL),
-				     type->fields.structure[i].name);
-	 }
-
-	 ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
-						      new_rhs,
-						      NULL));
-      }
-      ir->remove();
-   } else {
-      handle_rvalue(&ir->rhs);
-      split_deref(&ir->lhs);
-   }
-
-   handle_rvalue(&ir->condition);
-
-   return visit_continue;
-}
-
-bool
-do_structure_splitting(exec_list *instructions)
-{
-   ir_structure_reference_visitor refs;
-
-   visit_list_elements(&refs, instructions);
-
-   /* Trim out variables we can't split. */
-   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
-      variable_entry2 *entry = (variable_entry2 *)iter.get();
-
-      if (debug) {
-	 printf("structure %s@%p: decl %d, whole_access %d\n",
-		entry->var->name, (void *) entry->var, entry->declaration,
-		entry->whole_structure_access);
-      }
-
-      if (!entry->declaration || entry->whole_structure_access) {
-	 entry->remove();
-      }
-   }
-
-   if (refs.variable_list.is_empty())
-      return false;
-
-   void *mem_ctx = ralloc_context(NULL);
-
-   /* Replace the decls of the structures to be split with their split
-    * components.
-    */
-   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
-      variable_entry2 *entry = (variable_entry2 *)iter.get();
-      const struct glsl_type *type = entry->var->type;
-
-      entry->mem_ctx = ralloc_parent(entry->var);
-
-      entry->components = ralloc_array(mem_ctx,
-				       ir_variable *,
-				       type->length);
-
-      for (unsigned int i = 0; i < entry->var->type->length; i++) {
-	 const char *name = ralloc_asprintf(mem_ctx, "%s_%s",
-					    entry->var->name,
-					    type->fields.structure[i].name);
-
-	 entry->components[i] =
-	    new(entry->mem_ctx) ir_variable(type->fields.structure[i].type,
-					    name,
-					    ir_var_temporary);
-	 entry->var->insert_before(entry->components[i]);
-      }
-
-      entry->var->remove();
-   }
-
-   ir_structure_splitting_visitor split(&refs.variable_list);
-   visit_list_elements(&split, instructions);
-
-   ralloc_free(mem_ctx);
-
-   return true;
-}
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file opt_structure_splitting.cpp
+ *
+ * If a structure is only ever referenced by its components, then
+ * split those components out to individual variables so they can be
+ * handled normally by other optimization passes.
+ *
+ * This skips structures like uniforms, which need to be accessible as
+ * structures for their access by the GL.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_print_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+// XXX using variable_entry2 here to avoid collision (MSVC multiply-defined
+// function) with the variable_entry class seen in ir_variable_refcount.h
+// Perhaps we can use the one in ir_variable_refcount.h and make this class
+// here go away?
+class variable_entry2 : public exec_node
+{
+public:
+   variable_entry2(ir_variable *var)
+   {
+      this->var = var;
+      this->whole_structure_access = 0;
+      this->declaration = false;
+      this->components = NULL;
+      this->mem_ctx = NULL;
+   }
+
+   ir_variable *var; /* The key: the variable's pointer. */
+
+   /** Number of times the variable is referenced, including assignments. */
+   unsigned whole_structure_access;
+
+   /* If the variable had a decl we can work with in the instruction
+    * stream.  We can't do splitting on function arguments, which
+    * don't get this variable set.
+    */
+   bool declaration;
+
+   ir_variable **components;
+
+   /** ralloc_parent(this->var) -- the shader's ralloc context. */
+   void *mem_ctx;
+};
+
+
+class ir_structure_reference_visitor : public ir_hierarchical_visitor {
+public:
+   ir_structure_reference_visitor(void)
+   {
+      this->mem_ctx = ralloc_context(NULL);
+      this->variable_list.make_empty();
+   }
+
+   ~ir_structure_reference_visitor(void)
+   {
+      ralloc_free(mem_ctx);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *);
+   virtual ir_visitor_status visit(ir_dereference_variable *);
+   virtual ir_visitor_status visit_enter(ir_dereference_record *);
+   virtual ir_visitor_status visit_enter(ir_assignment *);
+   virtual ir_visitor_status visit_enter(ir_function_signature *);
+
+   variable_entry2 *get_variable_entry2(ir_variable *var);
+
+   /* List of variable_entry */
+   exec_list variable_list;
+
+   void *mem_ctx;
+};
+
+variable_entry2 *
+ir_structure_reference_visitor::get_variable_entry2(ir_variable *var)
+{
+   assert(var);
+
+   if (!var->type->is_record() || var->mode == ir_var_uniform)
+      return NULL;
+
+   foreach_iter(exec_list_iterator, iter, this->variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+      if (entry->var == var)
+	 return entry;
+   }
+
+   variable_entry2 *entry = new(mem_ctx) variable_entry2(var);
+   this->variable_list.push_tail(entry);
+   return entry;
+}
+
+
+ir_visitor_status
+ir_structure_reference_visitor::visit(ir_variable *ir)
+{
+   variable_entry2 *entry = this->get_variable_entry2(ir);
+
+   if (entry)
+      entry->declaration = true;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit(ir_dereference_variable *ir)
+{
+   ir_variable *const var = ir->variable_referenced();
+   variable_entry2 *entry = this->get_variable_entry2(var);
+
+   if (entry)
+      entry->whole_structure_access++;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_dereference_record *ir)
+{
+   (void) ir;
+   /* Don't descend into the ir_dereference_variable below. */
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_assignment *ir)
+{
+   /* If there are no structure references yet, no need to bother with
+    * processing the expression tree.
+    */
+   if (this->variable_list.is_empty())
+      return visit_continue_with_parent;
+
+   if (ir->lhs->as_dereference_variable() &&
+       ir->rhs->as_dereference_variable() &&
+       !ir->condition) {
+      /* We'll split copies of a structure to copies of components, so don't
+       * descend to the ir_dereference_variables.
+       */
+      return visit_continue_with_parent;
+   }
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* We don't have logic for structure-splitting function arguments,
+    * so just look at the body instructions and not the parameter
+    * declarations.
+    */
+   visit_list_elements(this, &ir->body);
+   return visit_continue_with_parent;
+}
+
+class ir_structure_splitting_visitor : public ir_rvalue_visitor {
+public:
+   ir_structure_splitting_visitor(exec_list *vars)
+   {
+      this->variable_list = vars;
+   }
+
+   virtual ~ir_structure_splitting_visitor()
+   {
+   }
+
+   virtual ir_visitor_status visit_leave(ir_assignment *);
+
+   void split_deref(ir_dereference **deref);
+   void handle_rvalue(ir_rvalue **rvalue);
+   variable_entry2 *get_splitting_entry(ir_variable *var);
+
+   exec_list *variable_list;
+   void *mem_ctx;
+};
+
+variable_entry2 *
+ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var)
+{
+   assert(var);
+
+   if (!var->type->is_record())
+      return NULL;
+
+   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+      if (entry->var == var) {
+	 return entry;
+      }
+   }
+
+   return NULL;
+}
+
+void
+ir_structure_splitting_visitor::split_deref(ir_dereference **deref)
+{
+   if ((*deref)->ir_type != ir_type_dereference_record)
+      return;
+
+   ir_dereference_record *deref_record = (ir_dereference_record *)*deref;
+   ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable();
+   if (!deref_var)
+      return;
+
+   variable_entry2 *entry = get_splitting_entry(deref_var->var);
+   if (!entry)
+      return;
+
+   unsigned int i;
+   for (i = 0; i < entry->var->type->length; i++) {
+      if (strcmp(deref_record->field,
+		 entry->var->type->fields.structure[i].name) == 0)
+	 break;
+   }
+   assert(i != entry->var->type->length);
+
+   *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]);
+}
+
+void
+ir_structure_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return;
+
+   ir_dereference *deref = (*rvalue)->as_dereference();
+
+   if (!deref)
+      return;
+
+   split_deref(&deref);
+   *rvalue = deref;
+}
+
+ir_visitor_status
+ir_structure_splitting_visitor::visit_leave(ir_assignment *ir)
+{
+   ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
+   ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
+   variable_entry2 *lhs_entry = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
+   variable_entry2 *rhs_entry = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
+   const glsl_type *type = ir->rhs->type;
+
+   if ((lhs_entry || rhs_entry) && !ir->condition) {
+      for (unsigned int i = 0; i < type->length; i++) {
+	 ir_dereference *new_lhs, *new_rhs;
+	 void *mem_ctx = lhs_entry ? lhs_entry->mem_ctx : rhs_entry->mem_ctx;
+
+	 if (lhs_entry) {
+	    new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]);
+	 } else {
+	    new_lhs = new(mem_ctx)
+	       ir_dereference_record(ir->lhs->clone(mem_ctx, NULL),
+				     type->fields.structure[i].name);
+	 }
+
+	 if (rhs_entry) {
+	    new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]);
+	 } else {
+	    new_rhs = new(mem_ctx)
+	       ir_dereference_record(ir->rhs->clone(mem_ctx, NULL),
+				     type->fields.structure[i].name);
+	 }
+
+	 ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
+						      new_rhs,
+						      NULL));
+      }
+      ir->remove();
+   } else {
+      handle_rvalue(&ir->rhs);
+      split_deref(&ir->lhs);
+   }
+
+   handle_rvalue(&ir->condition);
+
+   return visit_continue;
+}
+
+bool
+do_structure_splitting(exec_list *instructions)
+{
+   ir_structure_reference_visitor refs;
+
+   visit_list_elements(&refs, instructions);
+
+   /* Trim out variables we can't split. */
+   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+
+      if (debug) {
+	 printf("structure %s@%p: decl %d, whole_access %d\n",
+		entry->var->name, (void *) entry->var, entry->declaration,
+		entry->whole_structure_access);
+      }
+
+      if (!entry->declaration || entry->whole_structure_access) {
+	 entry->remove();
+      }
+   }
+
+   if (refs.variable_list.is_empty())
+      return false;
+
+   void *mem_ctx = ralloc_context(NULL);
+
+   /* Replace the decls of the structures to be split with their split
+    * components.
+    */
+   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+      const struct glsl_type *type = entry->var->type;
+
+      entry->mem_ctx = ralloc_parent(entry->var);
+
+      entry->components = ralloc_array(mem_ctx,
+				       ir_variable *,
+				       type->length);
+
+      for (unsigned int i = 0; i < entry->var->type->length; i++) {
+	 const char *name = ralloc_asprintf(mem_ctx, "%s_%s",
+					    entry->var->name,
+					    type->fields.structure[i].name);
+
+	 entry->components[i] =
+	    new(entry->mem_ctx) ir_variable(type->fields.structure[i].type,
+					    name,
+					    ir_var_temporary);
+	 entry->var->insert_before(entry->components[i]);
+      }
+
+      entry->var->remove();
+   }
+
+   ir_structure_splitting_visitor split(&refs.variable_list);
+   visit_list_elements(&split, instructions);
+
+   ralloc_free(mem_ctx);
+
+   return true;
+}
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
index 7042312a8..9b90b05f7 100644
--- a/mesalib/src/mesa/main/attrib.c
+++ b/mesalib/src/mesa/main/attrib.c
@@ -1448,9 +1448,6 @@ restore_array_attrib(struct gl_context *ctx,
       _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
 			  src->ArrayObj->ElementArrayBufferObj->Name);
 
-   /* Better safe than sorry?! */
-   dest->RebindArrays = GL_TRUE;
-
    /* FIXME: Should some bits in ctx->Array->NewState also be set
     * FIXME: here?  It seems like it should be set to inclusive-or
     * FIXME: of the old ArrayObj->_Enabled and the new _Enabled.
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 51b024143..d75351c85 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -1104,6 +1104,9 @@ _mesa_free_context_data( struct gl_context *ctx )
    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
 
+   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, NULL);
+   _mesa_reference_array_object(ctx, &ctx->Array.DefaultArrayObj, NULL);
+
    _mesa_free_attrib_data(ctx);
    _mesa_free_buffer_objects(ctx);
    _mesa_free_lighting_data( ctx );
@@ -1118,8 +1121,6 @@ _mesa_free_context_data( struct gl_context *ctx )
    _mesa_free_varray_data(ctx);
    _mesa_free_transform_feedback(ctx);
 
-   _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
-
 #if FEATURE_ARB_pixel_buffer_object
    _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
    _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp
index 3c91b1a42..8a42281db 100644
--- a/mesalib/src/mesa/main/ff_fragment_shader.cpp
+++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp
@@ -337,7 +337,7 @@ static GLbitfield get_fp_input_mask( struct gl_context *ctx )
    }
    else if (!(vertexProgram || vertexShader)) {
       /* Fixed function vertex logic */
-      /* _NEW_ARRAY */
+      /* _NEW_VARYING_VP_INPUTS */
       GLbitfield64 varying_inputs = ctx->varying_vp_inputs;
 
       /* These get generated in the setup routine regardless of the
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index bfa320a52..f277307a8 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -1632,7 +1632,6 @@ struct gl_array_attrib
    GLuint RestartIndex;
 
    GLbitfield64 NewState;		/**< mask of VERT_BIT_* values */
-   GLboolean RebindArrays; /**< whether the VBO module should rebind arrays */
 
    /* GL_ARB_vertex_buffer_object */
    struct gl_buffer_object *ArrayBufferObj;
@@ -3063,6 +3062,7 @@ struct gl_matrix_stack
 #define _NEW_BUFFER_OBJECT     (1 << 28)
 #define _NEW_FRAG_CLAMP        (1 << 29)
 #define _NEW_TRANSFORM_FEEDBACK (1 << 30) /**< gl_context::TransformFeedback */
+#define _NEW_VARYING_VP_INPUTS (1 << 31) /**< gl_context::varying_vp_inputs */
 #define _NEW_ALL ~0
 
 /**
diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c
index 491854955..31acfcbf1 100644
--- a/mesalib/src/mesa/main/readpix.c
+++ b/mesalib/src/mesa/main/readpix.c
@@ -208,6 +208,11 @@ read_stencil_pixels( struct gl_context *ctx,
    ctx->Driver.UnmapRenderbuffer(ctx, rb);
 }
 
+
+/**
+ * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
+ * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
+ */
 static GLboolean
 fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
 			      GLint x, GLint y,
@@ -220,9 +225,23 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
    struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
    GLubyte *dst, *map;
    int dstStride, stride, j, texelBytes;
-
-   if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
-                                             ctx->Pack.SwapBytes))
+   GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE;
+
+   /* XXX we could check for other swizzle/special cases here as needed */
+   if (rb->Format == MESA_FORMAT_RGBA8888_REV &&
+       format == GL_BGRA &&
+       type == GL_UNSIGNED_INT_8_8_8_8_REV &&
+       !ctx->Pack.SwapBytes) {
+      swizzle_rb = GL_TRUE;
+   }
+   else if (rb->Format == MESA_FORMAT_XRGB8888 &&
+       format == GL_BGRA &&
+       type == GL_UNSIGNED_INT_8_8_8_8_REV &&
+       !ctx->Pack.SwapBytes) {
+      copy_xrgb = GL_TRUE;
+   }
+   else if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
+                                                  ctx->Pack.SwapBytes))
       return GL_FALSE;
 
    /* If the format is unsigned normalized then we can ignore clamping
@@ -247,10 +266,39 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
    }
 
    texelBytes = _mesa_get_format_bytes(rb->Format);
-   for (j = 0; j < height; j++) {
-      memcpy(dst, map, width * texelBytes);
-      dst += dstStride;
-      map += stride;
+
+   if (swizzle_rb) {
+      /* swap R/B */
+      for (j = 0; j < height; j++) {
+         int i;
+         for (i = 0; i < width; i++) {
+            GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
+            GLuint pixel = map4[i];
+            dst4[i] = (pixel & 0xff00ff00)
+                   | ((pixel & 0x00ff0000) >> 16)
+                   | ((pixel & 0x000000ff) << 16);
+         }
+         dst += dstStride;
+         map += stride;
+      }
+   } else if (copy_xrgb) {
+      /* convert xrgb -> argb */
+      for (j = 0; j < height; j++) {
+         GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
+         int i;
+         for (i = 0; i < width; i++) {
+            dst4[i] = map4[i] | 0xff000000;  /* set A=0xff */
+         }
+         dst += dstStride;
+         map += stride;
+      }
+   } else {
+      /* just memcpy */
+      for (j = 0; j < height; j++) {
+         memcpy(dst, map, width * texelBytes);
+         dst += dstStride;
+         map += stride;
+      }
    }
 
    ctx->Driver.UnmapRenderbuffer(ctx, rb);
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index b01926622..f82e4a25e 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -473,12 +473,13 @@ _mesa_update_state_locked( struct gl_context *ctx )
    /* Determine which state flags effect vertex/fragment program state */
    if (ctx->FragmentProgram._MaintainTexEnvProgram) {
       prog_flags |= (_NEW_BUFFERS | _NEW_TEXTURE | _NEW_FOG |
-		     _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE |
-		     _NEW_PROGRAM | _NEW_FRAG_CLAMP | _NEW_COLOR);
+		     _NEW_VARYING_VP_INPUTS | _NEW_LIGHT | _NEW_POINT |
+		     _NEW_RENDERMODE | _NEW_PROGRAM | _NEW_FRAG_CLAMP |
+		     _NEW_COLOR);
    }
    if (ctx->VertexProgram._MaintainTnlProgram) {
-      prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
-                     _NEW_TRANSFORM | _NEW_POINT |
+      prog_flags |= (_NEW_VARYING_VP_INPUTS | _NEW_TEXTURE |
+                     _NEW_TEXTURE_MATRIX | _NEW_TRANSFORM | _NEW_POINT |
                      _NEW_FOG | _NEW_LIGHT |
                      _MESA_NEW_NEED_EYE_COORDS);
    }
@@ -580,8 +581,6 @@ _mesa_update_state_locked( struct gl_context *ctx )
    ctx->NewState = 0;
    ctx->Driver.UpdateState(ctx, new_state);
    ctx->Array.NewState = 0;
-   if (!ctx->Array.RebindArrays)
-      ctx->Array.RebindArrays = (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) != 0;
 }
 
 
@@ -626,7 +625,16 @@ _mesa_set_varying_vp_inputs( struct gl_context *ctx,
 {
    if (ctx->varying_vp_inputs != varying_inputs) {
       ctx->varying_vp_inputs = varying_inputs;
-      ctx->NewState |= _NEW_ARRAY;
+
+      /* Only the fixed-func generated programs need to use the flag
+       * and the fixed-func fragment program uses it only if there is also
+       * a fixed-func vertex program, so this only depends on the latter.
+       *
+       * It's okay to check the VP pointer here, because this is called after
+       * _mesa_update_state in the vbo module. */
+      if (ctx->VertexProgram._TnlProgram) {
+         ctx->NewState |= _NEW_VARYING_VP_INPUTS;
+      }
       /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/
    }
 }
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
index a402c7b22..1c1484323 100644
--- a/mesalib/src/mesa/main/varray.c
+++ b/mesalib/src/mesa/main/varray.c
@@ -1221,7 +1221,7 @@ _mesa_print_arrays(struct gl_context *ctx)
 void 
 _mesa_init_varray(struct gl_context *ctx)
 {
-   ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
+   ctx->Array.DefaultArrayObj = ctx->Driver.NewArrayObject(ctx, 0);
    _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
                                 ctx->Array.DefaultArrayObj);
    ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
diff --git a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c
index 7c0254d8d..09152c79a 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c
@@ -52,6 +52,7 @@
 #include "util/u_inlines.h"
 #include "util/u_draw_quad.h"
 #include "util/u_simple_shaders.h"
+#include "util/u_upload_mgr.h"
 #include "program/prog_instruction.h"
 #include "cso_cache/cso_context.h"
 
@@ -327,12 +328,13 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
    return pt;
 }
 
-static GLuint
+static void
 setup_bitmap_vertex_data(struct st_context *st, bool normalized,
                          int x, int y, int width, int height,
-                         float z, const float color[4])
+                         float z, const float color[4],
+			 struct pipe_resource **vbuf,
+			 unsigned *vbuf_offset)
 {
-   struct pipe_context *pipe = st->pipe;
    const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
    const GLfloat fb_width = (GLfloat)fb->Width;
    const GLfloat fb_height = (GLfloat)fb->Height;
@@ -346,8 +348,8 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized,
    const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
    const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
    const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
-   const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
    GLuint i;
+   float (*vertices)[3][4];  /**< vertex pos + color + texcoord */
 
    if(!normalized)
    {
@@ -355,77 +357,48 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized,
       tBot = (GLfloat) height;
    }
 
-   /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
-    * no_flush) updates to buffers where we know there is no conflict
-    * with previous data.  Currently using max_slots > 1 will cause
-    * synchronous rendering if the driver flushes its command buffers
-    * between one bitmap and the next.  Our flush hook below isn't
-    * sufficient to catch this as the driver doesn't tell us when it
-    * flushes its own command buffers.  Until this gets fixed, pay the
-    * price of allocating a new buffer for each bitmap cache-flush to
-    * avoid synchronous rendering.
-    */
-   if (st->bitmap.vbuf_slot >= max_slots) {
-      pipe_resource_reference(&st->bitmap.vbuf, NULL);
-      st->bitmap.vbuf_slot = 0;
-   }
-
-   if (!st->bitmap.vbuf) {
-      st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 
-                                           PIPE_BIND_VERTEX_BUFFER,
-                                           PIPE_USAGE_STREAM,
-                                           max_slots *
-                                           sizeof(st->bitmap.vertices));
-      if (!st->bitmap.vbuf) {
-         /* out of memory */
-         return 0;
-      }
+   u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]), vbuf_offset, vbuf,
+		  (void**)&vertices);
+   if (!vbuf) {
+      return;
    }
 
    /* Positions are in clip coords since we need to do clipping in case
     * the bitmap quad goes beyond the window bounds.
     */
-   st->bitmap.vertices[0][0][0] = clip_x0;
-   st->bitmap.vertices[0][0][1] = clip_y0;
-   st->bitmap.vertices[0][2][0] = sLeft;
-   st->bitmap.vertices[0][2][1] = tTop;
-
-   st->bitmap.vertices[1][0][0] = clip_x1;
-   st->bitmap.vertices[1][0][1] = clip_y0;
-   st->bitmap.vertices[1][2][0] = sRight;
-   st->bitmap.vertices[1][2][1] = tTop;
+   vertices[0][0][0] = clip_x0;
+   vertices[0][0][1] = clip_y0;
+   vertices[0][2][0] = sLeft;
+   vertices[0][2][1] = tTop;
+
+   vertices[1][0][0] = clip_x1;
+   vertices[1][0][1] = clip_y0;
+   vertices[1][2][0] = sRight;
+   vertices[1][2][1] = tTop;
    
-   st->bitmap.vertices[2][0][0] = clip_x1;
-   st->bitmap.vertices[2][0][1] = clip_y1;
-   st->bitmap.vertices[2][2][0] = sRight;
-   st->bitmap.vertices[2][2][1] = tBot;
+   vertices[2][0][0] = clip_x1;
+   vertices[2][0][1] = clip_y1;
+   vertices[2][2][0] = sRight;
+   vertices[2][2][1] = tBot;
    
-   st->bitmap.vertices[3][0][0] = clip_x0;
-   st->bitmap.vertices[3][0][1] = clip_y1;
-   st->bitmap.vertices[3][2][0] = sLeft;
-   st->bitmap.vertices[3][2][1] = tBot;
+   vertices[3][0][0] = clip_x0;
+   vertices[3][0][1] = clip_y1;
+   vertices[3][2][0] = sLeft;
+   vertices[3][2][1] = tBot;
    
    /* same for all verts: */
    for (i = 0; i < 4; i++) {
-      st->bitmap.vertices[i][0][2] = z;
-      st->bitmap.vertices[i][0][3] = 1.0f;
-      st->bitmap.vertices[i][1][0] = color[0];
-      st->bitmap.vertices[i][1][1] = color[1];
-      st->bitmap.vertices[i][1][2] = color[2];
-      st->bitmap.vertices[i][1][3] = color[3];
-      st->bitmap.vertices[i][2][2] = 0.0; /*R*/
-      st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
+      vertices[i][0][2] = z;
+      vertices[i][0][3] = 1.0f;
+      vertices[i][1][0] = color[0];
+      vertices[i][1][1] = color[1];
+      vertices[i][1][2] = color[2];
+      vertices[i][1][3] = color[3];
+      vertices[i][2][2] = 0.0; /*R*/
+      vertices[i][2][3] = 1.0; /*Q*/
    }
 
-   /* put vertex data into vbuf */
-   pipe_buffer_write_nooverlap(st->pipe,
-                               st->bitmap.vbuf,
-                               st->bitmap.vbuf_slot
-                               * sizeof(st->bitmap.vertices),
-                               sizeof st->bitmap.vertices,
-                               st->bitmap.vertices);
-
-   return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
+   u_upload_unmap(st->uploader);
 }
 
 
@@ -446,6 +419,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    struct st_fp_variant_key key;
    GLuint maxSize;
    GLuint offset;
+   struct pipe_resource *vbuf = NULL;
 
    memset(&key, 0, sizeof(key));
    key.st = st;
@@ -551,12 +525,11 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    z = z * 2.0f - 1.0f;
 
    /* draw textured quad */
-   offset = setup_bitmap_vertex_data(st,
-                                     sv->texture->target != PIPE_TEXTURE_RECT,
-                                     x, y, width, height, z, color);
+   setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT,
+			    x, y, width, height, z, color, &vbuf, &offset);
 
-   if (st->bitmap.vbuf) {
-      util_draw_vertex_buffer(pipe, st->cso_context, st->bitmap.vbuf, offset,
+   if (vbuf) {
+      util_draw_vertex_buffer(pipe, st->cso_context, vbuf, offset,
                               PIPE_PRIM_TRIANGLE_FAN,
                               4,  /* verts */
                               3); /* attribs/vert */
@@ -573,6 +546,8 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_restore_vertex_elements(cso);
    cso_restore_vertex_buffers(cso);
    cso_restore_stream_outputs(cso);
+
+   pipe_resource_reference(&vbuf, NULL);
 }
 
 
@@ -709,18 +684,12 @@ st_flush_bitmap_cache(struct st_context *st)
 
 
 /**
- * Flush bitmap cache and release vertex buffer.
+ * Flush bitmap cache.
  */
 void
 st_flush_bitmap( struct st_context *st )
 {
    st_flush_bitmap_cache(st);
-
-   /* Release vertex buffer to avoid synchronous rendering if we were
-    * to map it in the next frame.
-    */
-   pipe_resource_reference(&st->bitmap.vbuf, NULL);
-   st->bitmap.vbuf_slot = 0;
 }
 
 
@@ -914,11 +883,6 @@ st_destroy_bitmap(struct st_context *st)
       st->bitmap.vs = NULL;
    }
 
-   if (st->bitmap.vbuf) {
-      pipe_resource_reference(&st->bitmap.vbuf, NULL);
-      st->bitmap.vbuf = NULL;
-   }
-
    if (cache) {
       if (cache->trans) {
          pipe_transfer_unmap(pipe, cache->trans);
diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c
index 193583372..3cd8756f2 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_clear.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c
@@ -53,6 +53,7 @@
 #include "util/u_inlines.h"
 #include "util/u_simple_shaders.h"
 #include "util/u_draw_quad.h"
+#include "util/u_upload_mgr.h"
 
 #include "cso_cache/cso_context.h"
 
@@ -87,10 +88,6 @@ st_destroy_clear(struct st_context *st)
       cso_delete_vertex_shader(st->cso_context, st->clear.vs);
       st->clear.vs = NULL;
    }
-   if (st->clear.vbuf) {
-      pipe_resource_reference(&st->clear.vbuf, NULL);
-      st->clear.vbuf = NULL;
-   }
 }
 
 
@@ -140,78 +137,50 @@ draw_quad(struct st_context *st,
           const union pipe_color_union *color)
 {
    struct pipe_context *pipe = st->pipe;
+   struct pipe_resource *vbuf = NULL;
+   GLuint i, offset;
+   float (*vertices)[2][4];  /**< vertex pos + color */
 
-   /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
-    * no_flush) updates to buffers where we know there is no conflict
-    * with previous data.  Currently using max_slots > 1 will cause
-    * synchronous rendering if the driver flushes its command buffers
-    * between one bitmap and the next.  Our flush hook below isn't
-    * sufficient to catch this as the driver doesn't tell us when it
-    * flushes its own command buffers.  Until this gets fixed, pay the
-    * price of allocating a new buffer for each bitmap cache-flush to
-    * avoid synchronous rendering.
-    */
-   const GLuint max_slots = 1; /* 1024 / sizeof(st->clear.vertices); */
-   GLuint i;
-
-   if (st->clear.vbuf_slot >= max_slots) {
-      pipe_resource_reference(&st->clear.vbuf, NULL);
-      st->clear.vbuf_slot = 0;
-   }
-
-   if (!st->clear.vbuf) {
-      st->clear.vbuf = pipe_buffer_create(pipe->screen,
-                                          PIPE_BIND_VERTEX_BUFFER,
-                                          PIPE_USAGE_STREAM,
-                                          max_slots * sizeof(st->clear.vertices));
-   }
-
-   if (!st->clear.vbuf) {
-      /* ran out of memory */
+   u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]), &offset, &vbuf,
+		  (void**)&vertices);
+   if (!vbuf) {
       return;
    }
 
    /* positions */
-   st->clear.vertices[0][0][0] = x0;
-   st->clear.vertices[0][0][1] = y0;
+   vertices[0][0][0] = x0;
+   vertices[0][0][1] = y0;
 
-   st->clear.vertices[1][0][0] = x1;
-   st->clear.vertices[1][0][1] = y0;
+   vertices[1][0][0] = x1;
+   vertices[1][0][1] = y0;
 
-   st->clear.vertices[2][0][0] = x1;
-   st->clear.vertices[2][0][1] = y1;
+   vertices[2][0][0] = x1;
+   vertices[2][0][1] = y1;
 
-   st->clear.vertices[3][0][0] = x0;
-   st->clear.vertices[3][0][1] = y1;
+   vertices[3][0][0] = x0;
+   vertices[3][0][1] = y1;
 
    /* same for all verts: */
    for (i = 0; i < 4; i++) {
-      st->clear.vertices[i][0][2] = z;
-      st->clear.vertices[i][0][3] = 1.0;
-      st->clear.vertices[i][1][0] = color->f[0];
-      st->clear.vertices[i][1][1] = color->f[1];
-      st->clear.vertices[i][1][2] = color->f[2];
-      st->clear.vertices[i][1][3] = color->f[3];
+      vertices[i][0][2] = z;
+      vertices[i][0][3] = 1.0;
+      vertices[i][1][0] = color->f[0];
+      vertices[i][1][1] = color->f[1];
+      vertices[i][1][2] = color->f[2];
+      vertices[i][1][3] = color->f[3];
    }
 
-   /* put vertex data into vbuf */
-   pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf,
-                                           st->clear.vbuf_slot
-                                             * sizeof(st->clear.vertices),
-                                           sizeof(st->clear.vertices),
-                                           st->clear.vertices);
+   u_upload_unmap(st->uploader);
 
    /* draw */
    util_draw_vertex_buffer(pipe,
                            st->cso_context,
-                           st->clear.vbuf, 
-                           st->clear.vbuf_slot * sizeof(st->clear.vertices),
+                           vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
 
-   /* Increment slot */
-   st->clear.vbuf_slot++;
+   pipe_resource_reference(&vbuf, NULL);
 }
 
 
@@ -465,22 +434,6 @@ check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb
 }
 
 
-
-/**
- * Called when we need to flush.
- */
-void
-st_flush_clear(struct st_context *st)
-{
-   /* Release vertex buffer to avoid synchronous rendering if we were
-    * to map it in the next frame.
-    */
-   pipe_resource_reference(&st->clear.vbuf, NULL);
-   st->clear.vbuf_slot = 0;
-}
- 
-
-
 /**
  * Called via ctx->Driver.Clear()
  */
diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.h b/mesalib/src/mesa/state_tracker/st_cb_clear.h
index 8eafae5a4..e9297de9c 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_clear.h
+++ b/mesalib/src/mesa/state_tracker/st_cb_clear.h
@@ -1,52 +1,49 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-
-#ifndef ST_CB_CLEAR_H
-#define ST_CB_CLEAR_H
-
-
-struct dd_function_table;
-struct st_context;
-
-extern void
-st_init_clear(struct st_context *st);
-
-
-extern void
-st_destroy_clear(struct st_context *st);
-
-extern void
-st_flush_clear(struct st_context *st);
-
-
-extern void
-st_init_clear_functions(struct dd_function_table *functions);
-
-
-#endif /* ST_CB_CLEAR_H */
-
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef ST_CB_CLEAR_H
+#define ST_CB_CLEAR_H
+
+
+struct dd_function_table;
+struct st_context;
+
+extern void
+st_init_clear(struct st_context *st);
+
+
+extern void
+st_destroy_clear(struct st_context *st);
+
+
+extern void
+st_init_clear_functions(struct dd_function_table *functions);
+
+
+#endif /* ST_CB_CLEAR_H */
+
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
index 18d0e53d4..5e078a85e 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -66,6 +66,7 @@
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_tile.h"
+#include "util/u_upload_mgr.h"
 #include "cso_cache/cso_context.h"
 
 
@@ -554,7 +555,15 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
-   GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
+   GLfloat (*verts)[3][4]; /* four verts, three attribs, XYZW */
+   struct pipe_resource *buf = NULL;
+   unsigned offset;
+
+   u_upload_alloc(st->uploader, 0, 4 * sizeof(verts[0]), &offset, &buf,
+		  (void**)&verts);
+   if (!buf) {
+      return;
+   }
 
    /* setup vertex data */
    {
@@ -618,22 +627,12 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
       }
    }
 
-   {
-      struct pipe_resource *buf;
-
-      /* allocate/load buffer object with vertex data */
-      buf = pipe_buffer_create(pipe->screen,
-			       PIPE_BIND_VERTEX_BUFFER,
-			       PIPE_USAGE_STATIC,
-                               sizeof(verts));
-      pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts);
-
-      util_draw_vertex_buffer(pipe, st->cso_context, buf, 0,
-                              PIPE_PRIM_QUADS,
-                              4,  /* verts */
-                              3); /* attribs/vert */
-      pipe_resource_reference(&buf, NULL);
-   }
+   u_upload_unmap(st->uploader);
+   util_draw_vertex_buffer(pipe, st->cso_context, buf, offset,
+			   PIPE_PRIM_QUADS,
+			   4,  /* verts */
+			   3); /* attribs/vert */
+   pipe_resource_reference(&buf, NULL);
 }
 
 
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
index 6144eb99c..d57e629f1 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c
@@ -29,6 +29,7 @@
 #include "pipe/p_shader_tokens.h"
 #include "util/u_draw_quad.h"
 #include "util/u_simple_shaders.h"
+#include "util/u_upload_mgr.h"
 
 #include "cso_cache/cso_context.h"
 
@@ -107,13 +108,13 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
    struct st_context *st = ctx->st;
    struct pipe_context *pipe = st->pipe;
    struct cso_context *cso = ctx->st->cso_context;
-   struct pipe_resource *vbuffer;
-   struct pipe_transfer *vbuffer_transfer;
+   struct pipe_resource *vbuffer = NULL;
    GLuint i, numTexCoords, numAttribs;
    GLboolean emitColor;
    uint semantic_names[2 + MAX_TEXTURE_UNITS];
    uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
    struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
+   unsigned offset;
 
    st_validate_state(st);
 
@@ -134,12 +135,6 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
    /* total number of attributes per vertex */
    numAttribs = 1 + emitColor + numTexCoords;
 
-
-   /* create the vertex buffer */
-   vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
-                                PIPE_USAGE_STREAM,
-                                numAttribs * 4 * 4 * sizeof(GLfloat));
-
    /* load vertex buffer */
    {
 #define SET_ATTRIB(VERT, ATTR, X, Y, Z, W)                              \
@@ -153,10 +148,15 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
       } while (0)
 
       const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
-      GLfloat *vbuf = (GLfloat *) pipe_buffer_map(pipe, vbuffer,
-                                                  PIPE_TRANSFER_WRITE,
-                                                  &vbuffer_transfer);
+      GLfloat *vbuf = NULL;
       GLuint attr;
+
+      u_upload_alloc(st->uploader, 0,
+		     numAttribs * 4 * 4 * sizeof(GLfloat),
+		     &offset, &vbuffer, (void**)&vbuf);
+      if (!vbuffer) {
+         return;
+      }
       
       z = CLAMP(z, 0.0f, 1.0f);
 
@@ -220,7 +220,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
          }
       }
 
-      pipe_buffer_unmap(pipe, vbuffer_transfer);
+      u_upload_unmap(st->uploader);
 
 #undef SET_ATTRIB
    }
@@ -269,7 +269,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
 
 
    util_draw_vertex_buffer(pipe, cso, vbuffer,
-                           0,  /* offset */
+                           offset,  /* offset */
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            numAttribs); /* attribs/vert */
diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.c b/mesalib/src/mesa/state_tracker/st_cb_flush.c
index c029fad48..4e40a93f5 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_flush.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_flush.c
@@ -1,165 +1,159 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
- /*
-  * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
-  *   Brian Paul
-  */
-
-#include "main/glheader.h"
-#include "main/macros.h"
-#include "main/context.h"
-#include "st_context.h"
-#include "st_cb_bitmap.h"
-#include "st_cb_flush.h"
-#include "st_cb_clear.h"
-#include "st_cb_fbo.h"
-#include "st_manager.h"
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "pipe/p_screen.h"
-#include "util/u_gen_mipmap.h"
-#include "util/u_blit.h"
-
-
-/** Check if we have a front color buffer and if it's been drawn to. */
-static INLINE GLboolean
-is_front_buffer_dirty(struct st_context *st)
-{
-   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
-   struct st_renderbuffer *strb
-      = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
-   return strb && strb->defined;
-}
-
-
-/**
- * Tell the screen to display the front color buffer on-screen.
- */
-static void
-display_front_buffer(struct st_context *st)
-{
-   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
-   struct st_renderbuffer *strb
-      = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
-
-   if (strb) {
-      /* Hook for copying "fake" frontbuffer if necessary:
-       */
-      st_manager_flush_frontbuffer(st);
-   }
-}
-
-
-void st_flush( struct st_context *st,
-               struct pipe_fence_handle **fence )
-{
-   FLUSH_CURRENT(st->ctx, 0);
-
-   /* Release any vertex buffers that might potentially be accessed in
-    * successive frames:
-    */
-   st_flush_bitmap(st);
-   st_flush_clear(st);
-   util_blit_flush(st->blit);
-   util_gen_mipmap_flush(st->gen_mipmap);
-
-   st->pipe->flush( st->pipe, fence );
-}
-
-
-/**
- * Flush, and wait for completion.
- */
-void st_finish( struct st_context *st )
-{
-   struct pipe_fence_handle *fence = NULL;
-
-   st_flush(st, &fence);
-
-   if(fence) {
-      st->pipe->screen->fence_finish(st->pipe->screen, fence,
-                                     PIPE_TIMEOUT_INFINITE);
-      st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
-   }
-}
-
-
-
-/**
- * Called via ctx->Driver.Flush()
- */
-static void st_glFlush(struct gl_context *ctx)
-{
-   struct st_context *st = st_context(ctx);
-
-   /* Don't call st_finish() here.  It is not the state tracker's
-    * responsibilty to inject sleeps in the hope of avoiding buffer
-    * synchronization issues.  Calling finish() here will just hide
-    * problems that need to be fixed elsewhere.
-    */
-   st_flush(st, NULL);
-
-   if (is_front_buffer_dirty(st)) {
-      display_front_buffer(st);
-   }
-}
-
-
-/**
- * Called via ctx->Driver.Finish()
- */
-static void st_glFinish(struct gl_context *ctx)
-{
-   struct st_context *st = st_context(ctx);
-
-   st_finish(st);
-
-   if (is_front_buffer_dirty(st)) {
-      display_front_buffer(st);
-   }
-}
-
-
-void st_init_flush_functions(struct dd_function_table *functions)
-{
-   functions->Flush = st_glFlush;
-   functions->Finish = st_glFinish;
-
-   /* Windows opengl32.dll calls glFinish prior to every swapbuffers.
-    * This is unnecessary and degrades performance.  Luckily we have some
-    * scope to work around this, as the externally-visible behaviour of
-    * Finish() is identical to Flush() in all cases - no differences in
-    * rendering or ReadPixels are visible if we opt not to wait here.
-    *
-    * Only set this up on windows to avoid suprise elsewhere.
-    */
-#ifdef PIPE_OS_WINDOWS
-   functions->Finish = st_glFlush;
-#endif
-}
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "st_context.h"
+#include "st_cb_bitmap.h"
+#include "st_cb_flush.h"
+#include "st_cb_clear.h"
+#include "st_cb_fbo.h"
+#include "st_manager.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "util/u_gen_mipmap.h"
+#include "util/u_blit.h"
+
+
+/** Check if we have a front color buffer and if it's been drawn to. */
+static INLINE GLboolean
+is_front_buffer_dirty(struct st_context *st)
+{
+   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+   struct st_renderbuffer *strb
+      = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+   return strb && strb->defined;
+}
+
+
+/**
+ * Tell the screen to display the front color buffer on-screen.
+ */
+static void
+display_front_buffer(struct st_context *st)
+{
+   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+   struct st_renderbuffer *strb
+      = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+
+   if (strb) {
+      /* Hook for copying "fake" frontbuffer if necessary:
+       */
+      st_manager_flush_frontbuffer(st);
+   }
+}
+
+
+void st_flush( struct st_context *st,
+               struct pipe_fence_handle **fence )
+{
+   FLUSH_CURRENT(st->ctx, 0);
+
+   st_flush_bitmap(st);
+
+   st->pipe->flush( st->pipe, fence );
+}
+
+
+/**
+ * Flush, and wait for completion.
+ */
+void st_finish( struct st_context *st )
+{
+   struct pipe_fence_handle *fence = NULL;
+
+   st_flush(st, &fence);
+
+   if(fence) {
+      st->pipe->screen->fence_finish(st->pipe->screen, fence,
+                                     PIPE_TIMEOUT_INFINITE);
+      st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
+   }
+}
+
+
+
+/**
+ * Called via ctx->Driver.Flush()
+ */
+static void st_glFlush(struct gl_context *ctx)
+{
+   struct st_context *st = st_context(ctx);
+
+   /* Don't call st_finish() here.  It is not the state tracker's
+    * responsibilty to inject sleeps in the hope of avoiding buffer
+    * synchronization issues.  Calling finish() here will just hide
+    * problems that need to be fixed elsewhere.
+    */
+   st_flush(st, NULL);
+
+   if (is_front_buffer_dirty(st)) {
+      display_front_buffer(st);
+   }
+}
+
+
+/**
+ * Called via ctx->Driver.Finish()
+ */
+static void st_glFinish(struct gl_context *ctx)
+{
+   struct st_context *st = st_context(ctx);
+
+   st_finish(st);
+
+   if (is_front_buffer_dirty(st)) {
+      display_front_buffer(st);
+   }
+}
+
+
+void st_init_flush_functions(struct dd_function_table *functions)
+{
+   functions->Flush = st_glFlush;
+   functions->Finish = st_glFinish;
+
+   /* Windows opengl32.dll calls glFinish prior to every swapbuffers.
+    * This is unnecessary and degrades performance.  Luckily we have some
+    * scope to work around this, as the externally-visible behaviour of
+    * Finish() is identical to Flush() in all cases - no differences in
+    * rendering or ReadPixels are visible if we opt not to wait here.
+    *
+    * Only set this up on windows to avoid suprise elsewhere.
+    */
+#ifdef PIPE_OS_WINDOWS
+   functions->Finish = st_glFlush;
+#endif
+}
diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c
index a3fd4dbcb..0245fd92b 100644
--- a/mesalib/src/mesa/state_tracker/st_context.c
+++ b/mesalib/src/mesa/state_tracker/st_context.c
@@ -63,6 +63,7 @@
 #include "st_program.h"
 #include "pipe/p_context.h"
 #include "util/u_inlines.h"
+#include "util/u_upload_mgr.h"
 #include "cso_cache/cso_context.h"
 
 
@@ -130,6 +131,7 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
    st->dirty.mesa = ~0;
    st->dirty.st = ~0;
 
+   st->uploader = u_upload_create(st->pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
    st->cso_context = cso_create_context(pipe);
 
    st_init_atoms( st );
@@ -235,6 +237,7 @@ static void st_destroy_context_priv( struct st_context *st )
       st->default_texture = NULL;
    }
 
+   u_upload_destroy(st->uploader);
    free( st );
 }
 
diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h
index da03719fd..e3d65d97a 100644
--- a/mesalib/src/mesa/state_tracker/st_context.h
+++ b/mesalib/src/mesa/state_tracker/st_context.h
@@ -40,14 +40,15 @@ struct draw_stage;
 struct gen_mipmap_state;
 struct st_context;
 struct st_fragment_program;
+struct u_upload_mgr;
 
 
-#define ST_NEW_MESA                    0x1 /* Mesa state has changed */
-#define ST_NEW_FRAGMENT_PROGRAM        0x2
-#define ST_NEW_VERTEX_PROGRAM          0x4
-#define ST_NEW_FRAMEBUFFER             0x8
-#define ST_NEW_EDGEFLAGS_DATA          0x10
-#define ST_NEW_GEOMETRY_PROGRAM        0x20
+#define ST_NEW_MESA                    (1 << 0) /* Mesa state has changed */
+#define ST_NEW_FRAGMENT_PROGRAM        (1 << 1)
+#define ST_NEW_VERTEX_PROGRAM          (1 << 2)
+#define ST_NEW_FRAMEBUFFER             (1 << 3)
+#define ST_NEW_EDGEFLAGS_DATA          (1 << 4)
+#define ST_NEW_GEOMETRY_PROGRAM        (1 << 5)
 
 
 struct st_state_flags {
@@ -71,6 +72,7 @@ struct st_context
 
    struct pipe_context *pipe;
 
+   struct u_upload_mgr *uploader;
    struct draw_context *draw;  /**< For selection/feedback/rastpos only */
    struct draw_stage *feedback_stage;  /**< For GL_FEEDBACK rendermode */
    struct draw_stage *selection_stage;  /**< For GL_SELECT rendermode */
@@ -153,9 +155,6 @@ struct st_context
       struct pipe_sampler_state samplers[2];
       enum pipe_format tex_format;
       void *vs;
-      float vertices[4][3][4];  /**< vertex pos + color + texcoord */
-      struct pipe_resource *vbuf;
-      unsigned vbuf_slot;       /* next free slot in vbuf */
       struct bitmap_cache *cache;
    } bitmap;
 
@@ -171,9 +170,6 @@ struct st_context
       struct pipe_viewport_state viewport;
       void *vs;
       void *fs;
-      float vertices[4][2][4];  /**< vertex pos + color */
-      struct pipe_resource *vbuf;
-      unsigned vbuf_slot;
       boolean enable_ds_separate;
    } clear;
 
diff --git a/mesalib/src/mesa/vbo/vbo_context.c b/mesalib/src/mesa/vbo/vbo_context.c
index d83f2fd23..5f1c72bc1 100644
--- a/mesalib/src/mesa/vbo/vbo_context.c
+++ b/mesalib/src/mesa/vbo/vbo_context.c
@@ -47,7 +47,7 @@ static GLuint check_size( const GLfloat *attr )
 static void init_legacy_currval(struct gl_context *ctx)
 {
    struct vbo_context *vbo = vbo_context(ctx);
-   struct gl_client_array *arrays = vbo->legacy_currval;
+   struct gl_client_array *arrays = &vbo->currval[VBO_ATTRIB_POS];
    GLuint i;
 
    memset(arrays, 0, sizeof(*arrays) * VERT_ATTRIB_FF_MAX);
@@ -77,7 +77,7 @@ static void init_legacy_currval(struct gl_context *ctx)
 static void init_generic_currval(struct gl_context *ctx)
 {
    struct vbo_context *vbo = vbo_context(ctx);
-   struct gl_client_array *arrays = vbo->generic_currval;
+   struct gl_client_array *arrays = &vbo->currval[VBO_ATTRIB_GENERIC0];
    GLuint i;
 
    memset(arrays, 0, sizeof(*arrays) * VERT_ATTRIB_GENERIC_MAX);
@@ -104,7 +104,8 @@ static void init_generic_currval(struct gl_context *ctx)
 static void init_mat_currval(struct gl_context *ctx)
 {
    struct vbo_context *vbo = vbo_context(ctx);
-   struct gl_client_array *arrays = vbo->mat_currval;
+   struct gl_client_array *arrays =
+      &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT];
    GLuint i;
 
    ASSERT(NR_MAT_ATTRIBS == MAT_ATTRIB_MAX);
@@ -160,12 +161,6 @@ GLboolean _vbo_CreateContext( struct gl_context *ctx )
       return GL_FALSE;
    }
 
-   /* TODO: remove these pointers.
-    */
-   vbo->legacy_currval = &vbo->currval[VBO_ATTRIB_POS];
-   vbo->generic_currval = &vbo->currval[VBO_ATTRIB_GENERIC0];
-   vbo->mat_currval = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT];
-
    init_legacy_currval( ctx );
    init_generic_currval( ctx );
    init_mat_currval( ctx );
diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h
index 1a1cc928b..b9a8affa5 100644
--- a/mesalib/src/mesa/vbo/vbo_context.h
+++ b/mesalib/src/mesa/vbo/vbo_context.h
@@ -61,20 +61,10 @@
 struct vbo_context {
    struct gl_client_array currval[VBO_ATTRIB_MAX];
    
-   /* These point into the above.  TODO: remove. 
-    */
-   struct gl_client_array *legacy_currval;
-   struct gl_client_array *generic_currval;
-   struct gl_client_array *mat_currval;
-
    /** Map VERT_ATTRIB_x to VBO_ATTRIB_y */
    GLuint map_vp_none[VERT_ATTRIB_MAX];
    GLuint map_vp_arb[VERT_ATTRIB_MAX];
 
-   GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
-   GLfloat CurrentFloatEdgeFlag;
-
-
    struct vbo_exec_context exec;
 #if FEATURE_dlist
    struct vbo_save_context save;
diff --git a/mesalib/src/mesa/vbo/vbo_exec.c b/mesalib/src/mesa/vbo/vbo_exec.c
index 05c3ec1ae..fd5e0f891 100644
--- a/mesalib/src/mesa/vbo/vbo_exec.c
+++ b/mesalib/src/mesa/vbo/vbo_exec.c
@@ -85,6 +85,10 @@ void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state )
 {
    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
+   if (new_state & (_NEW_PROGRAM|_NEW_ARRAY)) {
+      exec->array.recalculate_inputs = GL_TRUE;
+   }
+
    if (new_state & (_NEW_PROGRAM|_NEW_EVAL))
       exec->eval.recalculate_maps = 1;
 
diff --git a/mesalib/src/mesa/vbo/vbo_exec.h b/mesalib/src/mesa/vbo/vbo_exec.h
index f6ede99cd..5cdf5ced9 100644
--- a/mesalib/src/mesa/vbo/vbo_exec.h
+++ b/mesalib/src/mesa/vbo/vbo_exec.h
@@ -141,6 +141,7 @@ struct vbo_exec_context
        * programs:
        */
       const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
+      GLboolean recalculate_inputs;
    } array;
 
    /* Which flags to set in vbo_exec_BeginVertices() */
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c
index 306199067..3f9541089 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_api.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_api.c
@@ -1089,24 +1089,26 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
       struct gl_client_array *arrays = exec->vtx.arrays;
       unsigned i;
 
-      memcpy(arrays, vbo->legacy_currval,
+      memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS],
              VERT_ATTRIB_FF_MAX * sizeof(arrays[0]));
       for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) {
          struct gl_client_array *array;
          array = &arrays[VERT_ATTRIB_FF(i)];
          array->BufferObj = NULL;
          _mesa_reference_buffer_object(ctx, &arrays->BufferObj,
-                                       vbo->legacy_currval[i].BufferObj);
+                                 vbo->currval[VBO_ATTRIB_POS+i].BufferObj);
       }
 
-      memcpy(arrays + VERT_ATTRIB_GENERIC(0), vbo->generic_currval,
+      memcpy(arrays + VERT_ATTRIB_GENERIC(0),
+             &vbo->currval[VBO_ATTRIB_GENERIC0],
              VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0]));
+
       for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) {
          struct gl_client_array *array;
          array = &arrays[VERT_ATTRIB_GENERIC(i)];
          array->BufferObj = NULL;
          _mesa_reference_buffer_object(ctx, &array->BufferObj,
-                                       vbo->generic_currval[i].BufferObj);
+                           vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj);
       }
    }
 
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c
index b0a4261e7..f95e062fb 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_array.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_array.c
@@ -420,13 +420,14 @@ recalculate_input_bindings(struct gl_context *ctx)
 	 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
 	    inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
 	 else {
-	    inputs[i] = &vbo->legacy_currval[i];
+	    inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
             const_inputs |= VERT_BIT(i);
          }
       }
 
       for (i = 0; i < MAT_ATTRIB_MAX; i++) {
-	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->mat_currval[i];
+	 inputs[VERT_ATTRIB_GENERIC(i)] =
+	    &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i];
          const_inputs |= VERT_BIT_GENERIC(i);
       }
 
@@ -434,7 +435,7 @@ recalculate_input_bindings(struct gl_context *ctx)
        * slots:
        */
       for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
-	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
+	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
          const_inputs |= VERT_BIT_GENERIC(i);
       }
 
@@ -459,7 +460,7 @@ recalculate_input_bindings(struct gl_context *ctx)
 	 else if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
 	    inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
 	 else {
-	    inputs[i] = &vbo->legacy_currval[i];
+	    inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
             const_inputs |= VERT_BIT_FF(i);
          }
       }
@@ -468,7 +469,7 @@ recalculate_input_bindings(struct gl_context *ctx)
        * slots:
        */
       for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
-	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
+	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
          const_inputs |= VERT_BIT_GENERIC(i);
       }
 
@@ -488,7 +489,7 @@ recalculate_input_bindings(struct gl_context *ctx)
       else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
 	 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
       else {
-	 inputs[0] = &vbo->legacy_currval[0];
+	 inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
          const_inputs |= VERT_BIT_POS;
       }
 
@@ -496,7 +497,7 @@ recalculate_input_bindings(struct gl_context *ctx)
 	 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
 	    inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
 	 else {
-	    inputs[i] = &vbo->legacy_currval[i];
+	    inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
             const_inputs |= VERT_BIT_FF(i);
          }
       }
@@ -505,7 +506,7 @@ recalculate_input_bindings(struct gl_context *ctx)
 	 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
 	    inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
 	 else {
-	    inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
+	    inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
             const_inputs |= VERT_BIT_GENERIC(i);
          }
       }
@@ -523,18 +524,31 @@ recalculate_input_bindings(struct gl_context *ctx)
  * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
  * These will point to the arrays to actually use for drawing.  Some will
  * be user-provided arrays, other will be zero-stride const-valued arrays.
- * Note that this might set the _NEW_ARRAY dirty flag so state validation
- * must be done after this call.
+ * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
+ * validation must be done after this call.
  */
 void
 vbo_bind_arrays(struct gl_context *ctx)
 {
-   if (!ctx->Array.RebindArrays) {
-      return;
-   }
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_exec_context *exec = &vbo->exec;
+
+   vbo_draw_method(exec, DRAW_ARRAYS);
+
+   if (exec->array.recalculate_inputs) {
+      recalculate_input_bindings(ctx);
+
+      /* Again... because we may have changed the bitmask of per-vertex varying
+       * attributes.  If we regenerate the fixed-function vertex program now
+       * we may be able to prune down the number of vertex attributes which we
+       * need in the shader.
+       */
+      if (ctx->NewState) {
+         _mesa_update_state(ctx);
+      }
 
-   recalculate_input_bindings(ctx);
-   ctx->Array.RebindArrays = GL_FALSE;
+      exec->array.recalculate_inputs = GL_FALSE;
+   }
 }
 
 
@@ -554,16 +568,6 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
 
    vbo_bind_arrays(ctx);
 
-   vbo_draw_method(exec, DRAW_ARRAYS);
-
-   /* Again... because we may have changed the bitmask of per-vertex varying
-    * attributes.  If we regenerate the fixed-function vertex program now
-    * we may be able to prune down the number of vertex attributes which we
-    * need in the shader.
-    */
-   if (ctx->NewState)
-      _mesa_update_state(ctx);
-
    /* init most fields to zero */
    memset(prim, 0, sizeof(prim));
    prim[0].begin = 1;
@@ -641,10 +645,6 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
 
    FLUSH_CURRENT( ctx, 0 );
 
-   if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
-      return;
-   }
-
    if (0)
       check_draw_arrays_data(ctx, start, count);
 
@@ -674,10 +674,6 @@ vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
 
    FLUSH_CURRENT( ctx, 0 );
 
-   if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
-      return;
-   }
-
    if (0)
       check_draw_arrays_data(ctx, start, count);
 
@@ -767,17 +763,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
 
    FLUSH_CURRENT( ctx, 0 );
 
-   if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
-      return;
-   }
-
-   vbo_bind_arrays( ctx );
-
-   vbo_draw_method(exec, DRAW_ARRAYS);
-
-   /* check for dirty state again */
-   if (ctx->NewState)
-      _mesa_update_state( ctx );
+   vbo_bind_arrays(ctx);
 
    ib.count = count;
    ib.type = type;
@@ -1053,25 +1039,13 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
 
    FLUSH_CURRENT( ctx, 0 );
 
-   if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
-      return;
-   }
-
    prim = calloc(1, primcount * sizeof(*prim));
    if (prim == NULL) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
       return;
    }
 
-   /* Decide if we can do this all as one set of primitives sharing the
-    * same index buffer, or if we have to reset the index pointer per
-    * primitive.
-    */
-   vbo_bind_arrays( ctx );
-
-   /* check for dirty state again */
-   if (ctx->NewState)
-      _mesa_update_state( ctx );
+   vbo_bind_arrays(ctx);
 
    min_index_ptr = (uintptr_t)indices[0];
    max_index_ptr = 0;
@@ -1217,14 +1191,6 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
 
    vbo_bind_arrays(ctx);
 
-   /* Again... because we may have changed the bitmask of per-vertex varying
-    * attributes.  If we regenerate the fixed-function vertex program now
-    * we may be able to prune down the number of vertex attributes which we
-    * need in the shader.
-    */
-   if (ctx->NewState)
-      _mesa_update_state(ctx);
-
    /* init most fields to zero */
    memset(prim, 0, sizeof(prim));
    prim[0].begin = 1;
@@ -1266,10 +1232,6 @@ vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
 
    FLUSH_CURRENT(ctx, 0);
 
-   if (!_mesa_valid_to_render(ctx, "glDrawTransformFeedback")) {
-      return;
-   }
-
    vbo_draw_transform_feedback(ctx, mode, obj, 1);
 }
 
diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c
index dd5363beb..5cc6586b3 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_draw.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c
@@ -174,11 +174,12 @@ vbo_exec_bind_arrays( struct gl_context *ctx )
    switch (get_program_mode(exec->ctx)) {
    case VP_NONE:
       for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) {
-         exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+         exec->vtx.inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr];
       }
       for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
          ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs));
-         exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->mat_currval[attr];
+         exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] =
+            &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+attr];
       }
       map = vbo->map_vp_none;
       break;
@@ -189,11 +190,12 @@ vbo_exec_bind_arrays( struct gl_context *ctx )
        * nor attributes greater than VERT_ATTRIB_TEX7.  
        */
       for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) {
-         exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+         exec->vtx.inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr];
       }
       for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) {
          ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs));
-         exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->generic_currval[attr];
+         exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] =
+            &vbo->currval[VBO_ATTRIB_GENERIC0+attr];
       }
       map = vbo->map_vp_arb;
 
@@ -388,7 +390,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped)
       if (exec->vtx.copied.nr != exec->vtx.vert_count) {
 	 struct gl_context *ctx = exec->ctx;
 	 
-	 /* Before the update_state() as this may raise _NEW_ARRAY
+	 /* Before the update_state() as this may raise _NEW_VARYING_VP_INPUTS
           * from _mesa_set_varying_vp_inputs().
 	  */
 	 vbo_exec_bind_arrays( ctx );
diff --git a/mesalib/src/mesa/vbo/vbo_save.c b/mesalib/src/mesa/vbo/vbo_save.c
index e02706191..040c9b7a9 100644
--- a/mesalib/src/mesa/vbo/vbo_save.c
+++ b/mesalib/src/mesa/vbo/vbo_save.c
@@ -63,24 +63,26 @@ void vbo_save_init( struct gl_context *ctx )
       struct gl_client_array *arrays = save->arrays;
       unsigned i;
 
-      memcpy(arrays, vbo->legacy_currval,
+      memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS],
              VERT_ATTRIB_FF_MAX * sizeof(arrays[0]));
       for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) {
          struct gl_client_array *array;
          array = &arrays[VERT_ATTRIB_FF(i)];
          array->BufferObj = NULL;
          _mesa_reference_buffer_object(ctx, &arrays->BufferObj,
-                                       vbo->legacy_currval[i].BufferObj);
+                                       vbo->currval[VBO_ATTRIB_POS+i].BufferObj);
       }
 
-      memcpy(arrays + VERT_ATTRIB_GENERIC(0), vbo->generic_currval,
+      memcpy(arrays + VERT_ATTRIB_GENERIC(0),
+             &vbo->currval[VBO_ATTRIB_GENERIC0],
              VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0]));
+
       for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) {
          struct gl_client_array *array;
          array = &arrays[VERT_ATTRIB_GENERIC(i)];
          array->BufferObj = NULL;
          _mesa_reference_buffer_object(ctx, &array->BufferObj,
-                                       vbo->generic_currval[i].BufferObj);
+                           vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj);
       }
    }
 
diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c
index b8e1e7883..57186de64 100644
--- a/mesalib/src/mesa/vbo/vbo_save_draw.c
+++ b/mesalib/src/mesa/vbo/vbo_save_draw.c
@@ -147,10 +147,11 @@ static void vbo_bind_vertex_list(struct gl_context *ctx,
    switch (get_program_mode(ctx)) {
    case VP_NONE:
       for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) {
-         save->inputs[attr] = &vbo->legacy_currval[attr];
+         save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr];
       }
       for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
-         save->inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->mat_currval[attr];
+         save->inputs[VERT_ATTRIB_GENERIC(attr)] =
+            &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+attr];
       }
       map = vbo->map_vp_none;
       break;
@@ -161,10 +162,11 @@ static void vbo_bind_vertex_list(struct gl_context *ctx,
        * nor attributes greater than VERT_ATTRIB_TEX7.  
        */
       for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) {
-         save->inputs[attr] = &vbo->legacy_currval[attr];
+         save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr];
       }
       for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) {
-         save->inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->generic_currval[attr];
+         save->inputs[VERT_ATTRIB_GENERIC(attr)] =
+            &vbo->currval[VBO_ATTRIB_GENERIC0+attr];
       }
       map = vbo->map_vp_arb;
 
-- 
cgit v1.2.3