[Mesa-dev] [PATCH 19/21] gallium: make user vertex buffers optional

Marek Olšák maraeo at gmail.com
Wed Apr 11 08:38:53 PDT 2012


This couldn't be split because it would break bisecting.

Summary:
* r300g,r600g: stop using u_vbuf
* r300g,r600g: also report that the FIXED vertex type is unsupported
* u_vbuf: refactor for use in the state tracker
* cso: wire up u_vbuf with cso_context
* st/mesa: conditionally install u_vbuf
---
 src/gallium/auxiliary/cso_cache/cso_context.c |   66 +++++-
 src/gallium/auxiliary/cso_cache/cso_context.h |    3 +
 src/gallium/auxiliary/util/u_vbuf.c           |  304 ++++++++++++-------------
 src/gallium/auxiliary/util/u_vbuf.h           |   50 ++---
 src/gallium/drivers/r300/r300_blit.c          |   12 +-
 src/gallium/drivers/r300/r300_context.c       |   16 --
 src/gallium/drivers/r300/r300_context.h       |    1 -
 src/gallium/drivers/r300/r300_screen.c        |    7 +-
 src/gallium/drivers/r600/r600_blit.c          |    6 +-
 src/gallium/drivers/r600/r600_buffer.c        |    4 +-
 src/gallium/drivers/r600/r600_formats.h       |    3 +-
 src/gallium/drivers/r600/r600_pipe.c          |   14 --
 src/gallium/drivers/r600/r600_pipe.h          |    1 -
 src/mesa/state_tracker/st_context.c           |   26 ++
 src/mesa/state_tracker/st_context.h           |    3 +
 15 files changed, 276 insertions(+), 240 deletions(-)

diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index 5fea531..f49d95c 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -40,6 +40,7 @@
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_vbuf.h"
 #include "tgsi/tgsi_parse.h"
 
 #include "cso_cache/cso_context.h"
@@ -77,6 +78,7 @@ struct sampler_info
 struct cso_context {
    struct pipe_context *pipe;
    struct cso_cache *cache;
+   struct u_vbuf *vbuf;
 
    boolean has_geometry_shader;
    boolean has_streamout;
@@ -267,6 +269,10 @@ out:
    return NULL;
 }
 
+void cso_install_vbuf(struct cso_context *ctx, struct u_vbuf *vbuf)
+{
+   ctx->vbuf = vbuf;
+}
 
 /**
  * Prior to context destruction, this function unbinds all state objects.
@@ -779,11 +785,17 @@ enum pipe_error cso_set_vertex_elements(struct cso_context *ctx,
                                         unsigned count,
                                         const struct pipe_vertex_element *states)
 {
+   struct u_vbuf *vbuf = ctx->vbuf;
    unsigned key_size, hash_key;
    struct cso_hash_iter iter;
    void *handle;
    struct cso_velems_state velems_state;
 
+   if (vbuf) {
+      u_vbuf_set_vertex_elements(vbuf, count, states);
+      return PIPE_OK;
+   }
+
    /* need to include the count into the stored state data too.
       Otherwise first few count pipe_vertex_elements could be identical even if count
       is different, and there's no guarantee the hash would be different in that
@@ -825,12 +837,26 @@ enum pipe_error cso_set_vertex_elements(struct cso_context *ctx,
 
 void cso_save_vertex_elements(struct cso_context *ctx)
 {
+   struct u_vbuf *vbuf = ctx->vbuf;
+
+   if (vbuf) {
+      u_vbuf_save_vertex_elements(vbuf);
+      return;
+   }
+
    assert(!ctx->velements_saved);
    ctx->velements_saved = ctx->velements;
 }
 
 void cso_restore_vertex_elements(struct cso_context *ctx)
 {
+   struct u_vbuf *vbuf = ctx->vbuf;
+
+   if (vbuf) {
+      u_vbuf_restore_vertex_elements(vbuf);
+      return;
+   }
+
    if (ctx->velements != ctx->velements_saved) {
       ctx->velements = ctx->velements_saved;
       ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved);
@@ -844,6 +870,13 @@ void cso_set_vertex_buffers(struct cso_context *ctx,
                             unsigned count,
                             const struct pipe_vertex_buffer *buffers)
 {
+   struct u_vbuf *vbuf = ctx->vbuf;
+
+   if (vbuf) {
+      u_vbuf_set_vertex_buffers(vbuf, count, buffers);
+      return;
+   }
+
    if (count != ctx->nr_vertex_buffers ||
        memcmp(buffers, ctx->vertex_buffers,
               sizeof(struct pipe_vertex_buffer) * count) != 0) {
@@ -855,6 +888,13 @@ void cso_set_vertex_buffers(struct cso_context *ctx,
 
 void cso_save_vertex_buffers(struct cso_context *ctx)
 {
+   struct u_vbuf *vbuf = ctx->vbuf;
+
+   if (vbuf) {
+      u_vbuf_save_vertex_buffers(vbuf);
+      return;
+   }
+
    util_copy_vertex_buffers(ctx->vertex_buffers_saved,
                             &ctx->nr_vertex_buffers_saved,
                             ctx->vertex_buffers,
@@ -864,6 +904,12 @@ void cso_save_vertex_buffers(struct cso_context *ctx)
 void cso_restore_vertex_buffers(struct cso_context *ctx)
 {
    unsigned i;
+   struct u_vbuf *vbuf = ctx->vbuf;
+
+   if (vbuf) {
+      u_vbuf_restore_vertex_buffers(vbuf);
+      return;
+   }
 
    util_copy_vertex_buffers(ctx->vertex_buffers,
                             &ctx->nr_vertex_buffers,
@@ -1297,14 +1343,26 @@ void
 cso_set_index_buffer(struct cso_context *cso,
                      const struct pipe_index_buffer *ib)
 {
-   struct pipe_context *pipe = cso->pipe;
-   pipe->set_index_buffer(pipe, ib);
+   struct u_vbuf *vbuf = cso->vbuf;
+
+   if (vbuf) {
+      u_vbuf_set_index_buffer(vbuf, ib);
+   } else {
+      struct pipe_context *pipe = cso->pipe;
+      pipe->set_index_buffer(pipe, ib);
+   }
 }
 
 void
 cso_draw_vbo(struct cso_context *cso,
              const struct pipe_draw_info *info)
 {
-   struct pipe_context *pipe = cso->pipe;
-   pipe->draw_vbo(pipe, info);
+   struct u_vbuf *vbuf = cso->vbuf;
+
+   if (vbuf) {
+      u_vbuf_draw_vbo(vbuf, info);
+   } else {
+      struct pipe_context *pipe = cso->pipe;
+      pipe->draw_vbo(pipe, info);
+   }
 }
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h
index 84203e6..54fa48c 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.h
+++ b/src/gallium/auxiliary/cso_cache/cso_context.h
@@ -39,9 +39,12 @@ extern "C" {
 #endif
 
 struct cso_context;
+struct u_vbuf;
 
 struct cso_context *cso_create_context( struct pipe_context *pipe );
 
+void cso_install_vbuf(struct cso_context *ctx, struct u_vbuf *vbuf);
+
 void cso_release_all( struct cso_context *ctx );
 
 void cso_destroy_context( struct cso_context *cso );
diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c
index 932b040..3356f35 100644
--- a/src/gallium/auxiliary/util/u_vbuf.c
+++ b/src/gallium/auxiliary/util/u_vbuf.c
@@ -66,12 +66,22 @@ enum {
    VB_NUM = 3
 };
 
-struct u_vbuf_priv {
-   struct u_vbuf b;
+struct u_vbuf {
    struct u_vbuf_caps caps;
+
    struct pipe_context *pipe;
    struct translate_cache *translate_cache;
    struct cso_cache *cso_cache;
+   struct u_upload_mgr *uploader;
+
+   /* This is what was set in set_vertex_buffers.
+    * May contain user buffers. */
+   struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+   unsigned nr_vertex_buffers;
+
+   /* Saved vertex buffers. */
+   struct pipe_vertex_buffer vertex_buffer_saved[PIPE_MAX_ATTRIBS];
+   unsigned nr_vertex_buffers_saved;
 
    /* Vertex buffers for the driver.
     * There are no user buffers. */
@@ -82,14 +92,14 @@ struct u_vbuf_priv {
    /* The index buffer. */
    struct pipe_index_buffer index_buffer;
 
-   /* and its associated helper structure for this module. */
-   struct u_vbuf_elements *ve;
+   /* Vertex elements. */
+   struct u_vbuf_elements *ve, *ve_saved;
 
    /* Vertex elements used for the translate fallback. */
    struct pipe_vertex_element fallback_velems[PIPE_MAX_ATTRIBS];
    /* If non-NULL, this is a vertex element state used for the translate
     * fallback and therefore used for rendering too. */
-   void *fallback_ve;
+   boolean using_translate;
    /* The vertex buffer slot index where translated vertices have been
     * stored in. */
    unsigned fallback_vbs[VB_NUM];
@@ -100,21 +110,14 @@ struct u_vbuf_priv {
    boolean incompatible_vb_layout;
    /* Per-buffer flags. */
    boolean incompatible_vb[PIPE_MAX_ATTRIBS];
-
-   void (*driver_set_index_buffer)(struct pipe_context *pipe,
-				   const struct pipe_index_buffer *);
-   void (*driver_set_vertex_buffers)(struct pipe_context *,
-				     unsigned num_buffers,
-				     const struct pipe_vertex_buffer *);
-   void *(*driver_create_vertex_elements_state)(struct pipe_context *,
-                                          unsigned num_elements,
-                                          const struct pipe_vertex_element *);
-   void (*driver_bind_vertex_elements_state)(struct pipe_context *, void *);
-   void (*driver_delete_vertex_elements_state)(struct pipe_context *, void *);
-   void (*driver_draw_vbo)(struct pipe_context *pipe,
-                           const struct pipe_draw_info *info);
 };
 
+static void *
+u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
+                              const struct pipe_vertex_element *attribs);
+static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso);
+
+
 void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps)
 {
    caps->format_fixed32 =
@@ -153,16 +156,11 @@ void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps)
       screen->get_param(screen, PIPE_CAP_USER_VERTEX_BUFFERS);
 }
 
-static void u_vbuf_install(struct u_vbuf_priv *mgr);
-
 struct u_vbuf *
 u_vbuf_create(struct pipe_context *pipe,
-              struct u_vbuf_caps *caps,
-              unsigned upload_buffer_size,
-              unsigned upload_buffer_alignment,
-              unsigned upload_buffer_bind)
+              struct u_vbuf_caps *caps)
 {
-   struct u_vbuf_priv *mgr = CALLOC_STRUCT(u_vbuf_priv);
+   struct u_vbuf *mgr = CALLOC_STRUCT(u_vbuf);
 
    mgr->caps = *caps;
    mgr->pipe = pipe;
@@ -170,23 +168,22 @@ u_vbuf_create(struct pipe_context *pipe,
    mgr->translate_cache = translate_cache_create();
    memset(mgr->fallback_vbs, ~0, sizeof(mgr->fallback_vbs));
 
-   mgr->b.uploader = u_upload_create(pipe, upload_buffer_size,
-                                     upload_buffer_alignment,
-                                     upload_buffer_bind);
+   mgr->uploader = u_upload_create(pipe, 1024 * 1024, 256,
+                                   PIPE_BIND_VERTEX_BUFFER);
 
-   u_vbuf_install(mgr);
-   return &mgr->b;
+   return mgr;
 }
 
-/* XXX I had to fork this off of cso_context. */
-static void *
-u_vbuf_cache_set_vertex_elements(struct u_vbuf_priv *mgr,
-                                unsigned count,
-                                const struct pipe_vertex_element *states)
+/* u_vbuf uses its own caching for vertex elements, because it needs to keep
+ * its own preprocessed state per vertex element CSO. */
+static struct u_vbuf_elements *
+u_vbuf_set_vertex_elements_internal(struct u_vbuf *mgr, unsigned count,
+                                    const struct pipe_vertex_element *states)
 {
+   struct pipe_context *pipe = mgr->pipe;
    unsigned key_size, hash_key;
    struct cso_hash_iter iter;
-   void *handle;
+   struct u_vbuf_elements *ve;
    struct cso_velems_state velems_state;
 
    /* need to include the count into the stored state data too. */
@@ -201,50 +198,50 @@ u_vbuf_cache_set_vertex_elements(struct u_vbuf_priv *mgr,
    if (cso_hash_iter_is_null(iter)) {
       struct cso_velements *cso = MALLOC_STRUCT(cso_velements);
       memcpy(&cso->state, &velems_state, key_size);
-      cso->data =
-            mgr->driver_create_vertex_elements_state(mgr->pipe, count,
-                                                     &cso->state.velems[0]);
-      cso->delete_state =
-            (cso_state_callback)mgr->driver_delete_vertex_elements_state;
-      cso->context = mgr->pipe;
+      cso->data = u_vbuf_create_vertex_elements(mgr, count, states);
+      cso->delete_state = (cso_state_callback)u_vbuf_delete_vertex_elements;
+      cso->context = (void*)mgr;
 
       iter = cso_insert_state(mgr->cso_cache, hash_key, CSO_VELEMENTS, cso);
-      handle = cso->data;
+      ve = cso->data;
    } else {
-      handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
+      ve = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
    }
 
-   mgr->driver_bind_vertex_elements_state(mgr->pipe, handle);
-   return handle;
+   assert(ve);
+   pipe->bind_vertex_elements_state(pipe, ve->driver_cso);
+   return ve;
 }
 
-void u_vbuf_destroy(struct u_vbuf *mgrb)
+void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count,
+                               const struct pipe_vertex_element *states)
 {
-   struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb;
-   unsigned i;
+   mgr->ve = u_vbuf_set_vertex_elements_internal(mgr, count, states);
+}
 
-   assert(mgr->pipe->draw);
-   mgr->pipe->draw = NULL;
+void u_vbuf_destroy(struct u_vbuf *mgr)
+{
+   unsigned i;
 
-   for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
-      pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL);
+   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
+      pipe_resource_reference(&mgr->vertex_buffer[i].buffer, NULL);
    }
    for (i = 0; i < mgr->nr_real_vertex_buffers; i++) {
       pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL);
    }
 
    translate_cache_destroy(mgr->translate_cache);
-   u_upload_destroy(mgr->b.uploader);
+   u_upload_destroy(mgr->uploader);
    cso_cache_delete(mgr->cso_cache);
    FREE(mgr);
 }
 
 static void
-u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key,
+u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key,
                          unsigned vb_mask, unsigned out_vb,
                          int start_vertex, unsigned num_vertices,
                          int start_index, unsigned num_indices, int min_index,
-                         bool unroll_indices)
+                         boolean unroll_indices)
 {
    struct translate *tr;
    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
@@ -256,9 +253,9 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key,
    tr = translate_cache_find(mgr->translate_cache, key);
 
    /* Map buffers we want to translate. */
-   for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
+   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
       if (vb_mask & (1 << i)) {
-         struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[i];
+         struct pipe_vertex_buffer *vb = &mgr->vertex_buffer[i];
          unsigned offset = vb->buffer_offset + vb->stride * start_vertex;
          uint8_t *map;
 
@@ -303,7 +300,7 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key,
       }
 
       /* Create and map the output buffer. */
-      u_upload_alloc(mgr->b.uploader, 0,
+      u_upload_alloc(mgr->uploader, 0,
                      key->output_stride * num_indices,
                      &out_offset, &out_buffer,
                      (void**)&out_map);
@@ -325,7 +322,7 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key,
       }
    } else {
       /* Create and map the output buffer. */
-      u_upload_alloc(mgr->b.uploader,
+      u_upload_alloc(mgr->uploader,
                      key->output_stride * start_vertex,
                      key->output_stride * num_vertices,
                      &out_offset, &out_buffer,
@@ -337,7 +334,7 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key,
    }
 
    /* Unmap all buffers. */
-   for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
+   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
       if (vb_transfer[i]) {
          pipe_buffer_unmap(mgr->pipe, vb_transfer[i]);
       }
@@ -354,7 +351,7 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key,
 }
 
 static boolean
-u_vbuf_translate_find_free_vb_slots(struct u_vbuf_priv *mgr,
+u_vbuf_translate_find_free_vb_slots(struct u_vbuf *mgr,
                                     unsigned mask[VB_NUM])
 {
    unsigned i, type;
@@ -392,7 +389,7 @@ u_vbuf_translate_find_free_vb_slots(struct u_vbuf_priv *mgr,
          }
          if (i == PIPE_MAX_ATTRIBS) {
             /* fail, reset the number to its original value */
-            mgr->nr_real_vertex_buffers = mgr->b.nr_vertex_buffers;
+            mgr->nr_real_vertex_buffers = mgr->nr_vertex_buffers;
             return FALSE;
          }
       }
@@ -403,11 +400,11 @@ u_vbuf_translate_find_free_vb_slots(struct u_vbuf_priv *mgr,
 }
 
 static boolean
-u_vbuf_translate_begin(struct u_vbuf_priv *mgr,
+u_vbuf_translate_begin(struct u_vbuf *mgr,
                        int start_vertex, unsigned num_vertices,
                        int start_instance, unsigned num_instances,
                        int start_index, unsigned num_indices, int min_index,
-                       bool unroll_indices)
+                       boolean unroll_indices)
 {
    unsigned mask[VB_NUM] = {0};
    struct translate_key key[VB_NUM];
@@ -434,7 +431,7 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr,
    for (i = 0; i < mgr->ve->count; i++) {
       unsigned vb_index = mgr->ve->ve[i].vertex_buffer_index;
 
-      if (!mgr->b.vertex_buffer[vb_index].stride) {
+      if (!mgr->vertex_buffer[vb_index].stride) {
          if (!mgr->ve->incompatible_layout_elem[i] &&
              !mgr->incompatible_vb[vb_index]) {
             continue;
@@ -543,18 +540,19 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr,
       }
    }
 
-   mgr->fallback_ve = u_vbuf_cache_set_vertex_elements(mgr, mgr->ve->count,
-                                                       mgr->fallback_velems);
+   u_vbuf_set_vertex_elements_internal(mgr, mgr->ve->count,
+                                       mgr->fallback_velems);
+   mgr->using_translate = TRUE;
    return TRUE;
 }
 
-static void u_vbuf_translate_end(struct u_vbuf_priv *mgr)
+static void u_vbuf_translate_end(struct u_vbuf *mgr)
 {
    unsigned i;
 
    /* Restore vertex elements. */
-   mgr->driver_bind_vertex_elements_state(mgr->pipe, mgr->ve->driver_cso);
-   mgr->fallback_ve = NULL;
+   mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->ve->driver_cso);
+   mgr->using_translate = FALSE;
 
    /* Unreference the now-unused VBOs. */
    for (i = 0; i < VB_NUM; i++) {
@@ -564,18 +562,17 @@ static void u_vbuf_translate_end(struct u_vbuf_priv *mgr)
          mgr->fallback_vbs[i] = ~0;
       }
    }
-   mgr->nr_real_vertex_buffers = mgr->b.nr_vertex_buffers;
+   mgr->nr_real_vertex_buffers = mgr->nr_vertex_buffers;
 }
 
 #define FORMAT_REPLACE(what, withwhat) \
     case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break
 
 static void *
-u_vbuf_create_vertex_elements(struct pipe_context *pipe,
-                              unsigned count,
+u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
                               const struct pipe_vertex_element *attribs)
 {
-   struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw;
+   struct pipe_context *pipe = mgr->pipe;
    unsigned i;
    struct pipe_vertex_element native_attribs[PIPE_MAX_ATTRIBS];
    struct u_vbuf_elements *ve = CALLOC_STRUCT(u_vbuf_elements);
@@ -670,36 +667,22 @@ u_vbuf_create_vertex_elements(struct pipe_context *pipe,
    }
 
    ve->driver_cso =
-      mgr->driver_create_vertex_elements_state(pipe, count, native_attribs);
+      pipe->create_vertex_elements_state(pipe, count, native_attribs);
    return ve;
 }
 
-static void u_vbuf_bind_vertex_elements(struct pipe_context *pipe,
-                                        void *cso)
+static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso)
 {
-   struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw;
-   struct u_vbuf_elements *ve = cso;
-
-   mgr->ve = ve;
-   mgr->b.vertex_elements = ve;
-   mgr->driver_bind_vertex_elements_state(pipe, ve ? ve->driver_cso : NULL);
-}
-
-static void u_vbuf_delete_vertex_elements(struct pipe_context *pipe,
-                                          void *cso)
-{
-   struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw;
+   struct pipe_context *pipe = mgr->pipe;
    struct u_vbuf_elements *ve = cso;
 
-   mgr->driver_delete_vertex_elements_state(pipe, ve->driver_cso);
+   pipe->delete_vertex_elements_state(pipe, ve->driver_cso);
    FREE(ve);
 }
 
-static void u_vbuf_set_vertex_buffers(struct pipe_context *pipe,
-                                      unsigned count,
-                                      const struct pipe_vertex_buffer *bufs)
+void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned count,
+                               const struct pipe_vertex_buffer *bufs)
 {
-   struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw;
    unsigned i;
 
    mgr->any_user_vbs = FALSE;
@@ -722,13 +705,13 @@ static void u_vbuf_set_vertex_buffers(struct pipe_context *pipe,
    for (i = 0; i < count; i++) {
       const struct pipe_vertex_buffer *vb = &bufs[i];
 
-      pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer);
+      pipe_resource_reference(&mgr->vertex_buffer[i].buffer, vb->buffer);
 
       mgr->real_vertex_buffer[i].buffer_offset =
-      mgr->b.vertex_buffer[i].buffer_offset = vb->buffer_offset;
+      mgr->vertex_buffer[i].buffer_offset = vb->buffer_offset;
 
       mgr->real_vertex_buffer[i].stride =
-      mgr->b.vertex_buffer[i].stride = vb->stride;
+      mgr->vertex_buffer[i].stride = vb->stride;
 
       if (!vb->buffer ||
           mgr->incompatible_vb[i]) {
@@ -745,22 +728,22 @@ static void u_vbuf_set_vertex_buffers(struct pipe_context *pipe,
       pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, vb->buffer);
    }
 
-   for (i = count; i < mgr->b.nr_vertex_buffers; i++) {
-      pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL);
+   for (i = count; i < mgr->nr_vertex_buffers; i++) {
+      pipe_resource_reference(&mgr->vertex_buffer[i].buffer, NULL);
    }
    for (i = count; i < mgr->nr_real_vertex_buffers; i++) {
       pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL);
    }
 
-   mgr->b.nr_vertex_buffers = count;
+   mgr->nr_vertex_buffers = count;
    mgr->nr_real_vertex_buffers = count;
    mgr->vertex_buffers_dirty = TRUE;
 }
 
-static void u_vbuf_set_index_buffer(struct pipe_context *pipe,
-                                    const struct pipe_index_buffer *ib)
+void u_vbuf_set_index_buffer(struct u_vbuf *mgr,
+                             const struct pipe_index_buffer *ib)
 {
-   struct u_vbuf_priv *mgr = pipe->draw;
+   struct pipe_context *pipe = mgr->pipe;
 
    if (ib && ib->buffer) {
       assert(ib->offset % ib->index_size == 0);
@@ -771,19 +754,19 @@ static void u_vbuf_set_index_buffer(struct pipe_context *pipe,
       pipe_resource_reference(&mgr->index_buffer.buffer, NULL);
    }
 
-   mgr->driver_set_index_buffer(pipe, ib);
+   pipe->set_index_buffer(pipe, ib);
 }
 
 static void
-u_vbuf_upload_buffers(struct u_vbuf_priv *mgr,
+u_vbuf_upload_buffers(struct u_vbuf *mgr,
                       int start_vertex, unsigned num_vertices,
                       int start_instance, unsigned num_instances)
 {
    unsigned i;
    unsigned nr_velems = mgr->ve->count;
-   unsigned nr_vbufs = mgr->b.nr_vertex_buffers;
+   unsigned nr_vbufs = mgr->nr_vertex_buffers;
    struct pipe_vertex_element *velems =
-         mgr->fallback_ve ? mgr->fallback_velems : mgr->ve->ve;
+         mgr->using_translate ? mgr->fallback_velems : mgr->ve->ve;
    unsigned start_offset[PIPE_MAX_ATTRIBS];
    unsigned end_offset[PIPE_MAX_ATTRIBS] = {0};
 
@@ -791,7 +774,7 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr,
    for (i = 0; i < nr_velems; i++) {
       struct pipe_vertex_element *velem = &velems[i];
       unsigned index = velem->vertex_buffer_index;
-      struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index];
+      struct pipe_vertex_buffer *vb = &mgr->vertex_buffer[index];
       unsigned instance_div, first, size;
 
       /* Skip the buffers generated by translate. */
@@ -850,16 +833,16 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr,
       assert(start < end);
 
       real_vb = &mgr->real_vertex_buffer[i];
-      ptr = mgr->b.vertex_buffer[i].buffer->user_ptr;
+      ptr = mgr->vertex_buffer[i].buffer->user_ptr;
 
-      u_upload_data(mgr->b.uploader, start, end - start, ptr + start,
+      u_upload_data(mgr->uploader, start, end - start, ptr + start,
                     &real_vb->buffer_offset, &real_vb->buffer);
 
       real_vb->buffer_offset -= start;
    }
 }
 
-static boolean u_vbuf_need_minmax_index(struct u_vbuf_priv *mgr)
+static boolean u_vbuf_need_minmax_index(struct u_vbuf *mgr)
 {
    unsigned i, nr = mgr->ve->count;
 
@@ -873,7 +856,7 @@ static boolean u_vbuf_need_minmax_index(struct u_vbuf_priv *mgr)
       }
 
       index = mgr->ve->ve[i].vertex_buffer_index;
-      vb = &mgr->b.vertex_buffer[index];
+      vb = &mgr->vertex_buffer[index];
 
       /* Constant attribs don't need min/max_index. */
       if (!vb->stride) {
@@ -891,7 +874,7 @@ static boolean u_vbuf_need_minmax_index(struct u_vbuf_priv *mgr)
    return FALSE;
 }
 
-static boolean u_vbuf_mapping_vertex_buffer_blocks(struct u_vbuf_priv *mgr)
+static boolean u_vbuf_mapping_vertex_buffer_blocks(struct u_vbuf *mgr)
 {
    unsigned i, nr = mgr->ve->count;
 
@@ -905,7 +888,7 @@ static boolean u_vbuf_mapping_vertex_buffer_blocks(struct u_vbuf_priv *mgr)
       }
 
       index = mgr->ve->ve[i].vertex_buffer_index;
-      vb = &mgr->b.vertex_buffer[index];
+      vb = &mgr->vertex_buffer[index];
 
       /* Constant attribs are not per-vertex data. */
       if (!vb->stride) {
@@ -1023,13 +1006,12 @@ static void u_vbuf_get_minmax_index(struct pipe_context *pipe,
    }
 }
 
-static void u_vbuf_draw_vbo(struct pipe_context *pipe,
-                            const struct pipe_draw_info *info)
+void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
 {
-   struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw;
+   struct pipe_context *pipe = mgr->pipe;
    int start_vertex, min_index;
    unsigned num_vertices;
-   bool unroll_indices = false;
+   boolean unroll_indices = FALSE;
 
    /* Normal draw. No fallback and no user buffers. */
    if (!mgr->incompatible_vb_layout &&
@@ -1037,27 +1019,27 @@ static void u_vbuf_draw_vbo(struct pipe_context *pipe,
        !mgr->any_user_vbs) {
       /* Set vertex buffers if needed. */
       if (mgr->vertex_buffers_dirty) {
-         mgr->driver_set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers,
-                                        mgr->real_vertex_buffer);
+         pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers,
+                                  mgr->real_vertex_buffer);
          mgr->vertex_buffers_dirty = FALSE;
       }
 
-      mgr->driver_draw_vbo(pipe, info);
+      pipe->draw_vbo(pipe, info);
       return;
    }
 
    if (info->indexed) {
       int max_index;
-      bool index_bounds_valid = false;
+      boolean index_bounds_valid = FALSE;
 
       if (info->max_index != ~0) {
          min_index = info->min_index;
          max_index = info->max_index;
-         index_bounds_valid = true;
+         index_bounds_valid = TRUE;
       } else if (u_vbuf_need_minmax_index(mgr)) {
          u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer, info,
                                  &min_index, &max_index);
-         index_bounds_valid = true;
+         index_bounds_valid = TRUE;
       }
 
       /* If the index bounds are valid, it means some upload or translation
@@ -1077,7 +1059,7 @@ static void u_vbuf_draw_vbo(struct pipe_context *pipe,
              num_vertices-info->count > 32 &&
              !u_vbuf_mapping_vertex_buffer_blocks(mgr)) {
             /*printf("num_vertices=%i count=%i\n", num_vertices, info->count);*/
-            unroll_indices = true;
+            unroll_indices = TRUE;
          }
       } else {
          /* Nothing to do for per-vertex attribs. */
@@ -1117,9 +1099,9 @@ static void u_vbuf_draw_vbo(struct pipe_context *pipe,
    }
 
    unsigned i;
-   for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
+   for (i = 0; i < mgr->nr_vertex_buffers; i++) {
       printf("input %i: ", i);
-      util_dump_vertex_buffer(stdout, mgr->b.vertex_buffer+i);
+      util_dump_vertex_buffer(stdout, mgr->vertex_buffer+i);
       printf("\n");
    }
    for (i = 0; i < mgr->nr_real_vertex_buffers; i++) {
@@ -1129,8 +1111,9 @@ static void u_vbuf_draw_vbo(struct pipe_context *pipe,
    }
    */
 
-   mgr->driver_set_vertex_buffers(mgr->pipe, mgr->nr_real_vertex_buffers,
-                                  mgr->real_vertex_buffer);
+   u_upload_unmap(mgr->uploader);
+   pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers,
+                            mgr->real_vertex_buffer);
 
    if (unlikely(unroll_indices)) {
       struct pipe_draw_info new_info = *info;
@@ -1140,36 +1123,51 @@ static void u_vbuf_draw_vbo(struct pipe_context *pipe,
       new_info.max_index = info->count - 1;
       new_info.start = 0;
 
-      mgr->driver_draw_vbo(pipe, &new_info);
+      pipe->draw_vbo(pipe, &new_info);
    } else {
-      mgr->driver_draw_vbo(pipe, info);
+      pipe->draw_vbo(pipe, info);
    }
 
-   if (mgr->fallback_ve) {
+   if (mgr->using_translate) {
       u_vbuf_translate_end(mgr);
    }
    mgr->vertex_buffers_dirty = TRUE;
 }
 
-static void u_vbuf_install(struct u_vbuf_priv *mgr)
+void u_vbuf_save_vertex_elements(struct u_vbuf *mgr)
 {
-   struct pipe_context *pipe = mgr->pipe;
-   assert(!pipe->draw);
-
-   pipe->draw = mgr;
-   mgr->driver_set_index_buffer = pipe->set_index_buffer;
-   mgr->driver_set_vertex_buffers = pipe->set_vertex_buffers;
-   mgr->driver_create_vertex_elements_state =
-      pipe->create_vertex_elements_state;
-   mgr->driver_bind_vertex_elements_state = pipe->bind_vertex_elements_state;
-   mgr->driver_delete_vertex_elements_state =
-      pipe->delete_vertex_elements_state;
-   mgr->driver_draw_vbo = pipe->draw_vbo;
-
-   pipe->set_index_buffer = u_vbuf_set_index_buffer;
-   pipe->set_vertex_buffers = u_vbuf_set_vertex_buffers;
-   pipe->create_vertex_elements_state = u_vbuf_create_vertex_elements;
-   pipe->bind_vertex_elements_state = u_vbuf_bind_vertex_elements;
-   pipe->delete_vertex_elements_state = u_vbuf_delete_vertex_elements;
-   pipe->draw_vbo = u_vbuf_draw_vbo;
+   assert(!mgr->ve_saved);
+   mgr->ve_saved = mgr->ve;
+}
+
+void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr)
+{
+   if (mgr->ve != mgr->ve_saved) {
+      struct pipe_context *pipe = mgr->pipe;
+
+      mgr->ve = mgr->ve_saved;
+      pipe->bind_vertex_elements_state(pipe,
+                                       mgr->ve ? mgr->ve->driver_cso : NULL);
+   }
+   mgr->ve_saved = NULL;
+}
+
+void u_vbuf_save_vertex_buffers(struct u_vbuf *mgr)
+{
+   util_copy_vertex_buffers(mgr->vertex_buffer_saved,
+                            &mgr->nr_vertex_buffers_saved,
+                            mgr->vertex_buffer,
+                            mgr->nr_vertex_buffers);
+}
+
+void u_vbuf_restore_vertex_buffers(struct u_vbuf *mgr)
+{
+   unsigned i;
+
+   u_vbuf_set_vertex_buffers(mgr, mgr->nr_vertex_buffers_saved,
+                             mgr->vertex_buffer_saved);
+   for (i = 0; i < mgr->nr_vertex_buffers_saved; i++) {
+      pipe_resource_reference(&mgr->vertex_buffer_saved[i].buffer, NULL);
+   }
+   mgr->nr_vertex_buffers_saved = 0;
 }
diff --git a/src/gallium/auxiliary/util/u_vbuf.h b/src/gallium/auxiliary/util/u_vbuf.h
index 80983f7..1613499 100644
--- a/src/gallium/auxiliary/util/u_vbuf.h
+++ b/src/gallium/auxiliary/util/u_vbuf.h
@@ -25,8 +25,8 @@
  *
  **************************************************************************/
 
-#ifndef U_VBUF_MGR_H
-#define U_VBUF_MGR_H
+#ifndef U_VBUF_H
+#define U_VBUF_H
 
 /* This module builds upon u_upload_mgr and translate_cache and takes care of
  * user buffer uploads and vertex format fallbacks. It's designed
@@ -36,6 +36,9 @@
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
 
+struct cso_context;
+struct u_vbuf;
+
 /* Hardware vertex fetcher limitations can be described by this structure. */
 struct u_vbuf_caps {
    /* Vertex format CAPs. */
@@ -54,41 +57,28 @@ struct u_vbuf_caps {
    unsigned user_vertex_buffers:1;
 };
 
-/* The manager.
- * This structure should also be used to access vertex buffers
- * from a driver. */
-struct u_vbuf {
-   /* This is what was set in set_vertex_buffers.
-    * May contain user buffers. */
-   struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
-   unsigned nr_vertex_buffers;
-
-   /* This uploader can optionally be used by the driver.
-    *
-    * Allowed functions:
-    * - u_upload_alloc
-    * - u_upload_data
-    * - u_upload_buffer
-    * - u_upload_flush */
-   struct u_upload_mgr *uploader;
-
-   /* Vertex elements state as created by u_vbuf.
-    * This is used when saving the state into u_blitter, there's no other
-    * usage. */
-   void *vertex_elements;
-};
-
 
 void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps);
 
 struct u_vbuf *
 u_vbuf_create(struct pipe_context *pipe,
-              struct u_vbuf_caps *caps,
-              unsigned upload_buffer_size,
-              unsigned upload_buffer_alignment,
-              unsigned upload_buffer_bind);
+              struct u_vbuf_caps *caps);
 
 void u_vbuf_destroy(struct u_vbuf *mgr);
 
+/* State and draw functions. */
+void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count,
+                                const struct pipe_vertex_element *states);
+void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned count,
+                               const struct pipe_vertex_buffer *bufs);
+void u_vbuf_set_index_buffer(struct u_vbuf *mgr,
+                             const struct pipe_index_buffer *ib);
+void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info);
+
+/* Save/restore functionality. */
+void u_vbuf_save_vertex_elements(struct u_vbuf *mgr);
+void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr);
+void u_vbuf_save_vertex_buffers(struct u_vbuf *mgr);
+void u_vbuf_restore_vertex_buffers(struct u_vbuf *mgr);
 
 #endif
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 5b76c4b..8d82bb9 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -62,15 +62,9 @@ static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op o
     util_blitter_save_fragment_shader(r300->blitter, r300->fs.state);
     util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state);
     util_blitter_save_viewport(r300->blitter, &r300->viewport);
-    if (r300->vbuf_mgr) {
-        util_blitter_save_vertex_buffers(r300->blitter, r300->vbuf_mgr->nr_vertex_buffers,
-                                         r300->vbuf_mgr->vertex_buffer);
-        util_blitter_save_vertex_elements(r300->blitter, r300->vbuf_mgr->vertex_elements);
-    } else {
-        util_blitter_save_vertex_buffers(r300->blitter, r300->nr_vertex_buffers,
-                                         r300->vertex_buffer);
-        util_blitter_save_vertex_elements(r300->blitter, r300->velems);
-    }
+    util_blitter_save_vertex_buffers(r300->blitter, r300->nr_vertex_buffers,
+                                     r300->vertex_buffer);
+    util_blitter_save_vertex_elements(r300->blitter, r300->velems);
 
     if (op & R300_SAVE_FRAMEBUFFER) {
         util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 658ce1e..a8e6870 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -100,9 +100,6 @@ static void r300_destroy_context(struct pipe_context* context)
     if (r300->draw)
         draw_destroy(r300->draw);
 
-    if (r300->vbuf_mgr)
-        u_vbuf_destroy(r300->vbuf_mgr);
-
     u_upload_destroy(r300->uploader);
 
     /* XXX: This function assumes r300->query_list was initialized */
@@ -429,19 +426,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     r300->context.create_video_decoder = vl_create_decoder;
     r300->context.create_video_buffer = vl_video_buffer_create;
 
-    if (r300->screen->caps.has_tcl) {
-        struct u_vbuf_caps caps;
-
-        u_vbuf_get_caps(screen, &caps);
-        caps.format_fixed32 = 0;
-
-        r300->vbuf_mgr = u_vbuf_create(&r300->context, &caps, 1024 * 1024, 16,
-                                       PIPE_BIND_VERTEX_BUFFER |
-                                       PIPE_BIND_INDEX_BUFFER);
-        if (!r300->vbuf_mgr)
-            goto fail;
-    }
-
     r300->uploader = u_upload_create(&r300->context, 256 * 1024, 16,
                                      PIPE_BIND_INDEX_BUFFER);
 
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 8f125d1..a4a19da 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -576,7 +576,6 @@ struct r300_context {
 
     void *dsa_decompress_zmask;
 
-    struct u_vbuf *vbuf_mgr;
     struct pipe_index_buffer index_buffer;
     struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
     unsigned nr_vertex_buffers;
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index b9eb709..657b0a7 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -361,10 +361,6 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
                             format == PIPE_FORMAT_R16G16_FLOAT ||
                             format == PIPE_FORMAT_R16G16B16_FLOAT ||
                             format == PIPE_FORMAT_R16G16B16A16_FLOAT;
-    boolean is_fixed = format == PIPE_FORMAT_R32_FIXED ||
-                       format == PIPE_FORMAT_R32G32_FIXED ||
-                       format == PIPE_FORMAT_R32G32B32_FIXED ||
-                       format == PIPE_FORMAT_R32G32B32A32_FIXED;
 
     if (!util_format_is_supported(format, usage))
        return FALSE;
@@ -428,8 +424,7 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
     if (usage & PIPE_BIND_VERTEX_BUFFER &&
         /* Half float is supported on >= R400. */
         (is_r400 || is_r500 || !is_half_float) &&
-        /* We have a fallback for FIXED. */
-        (is_fixed || r300_translate_vertex_data_type(format) != R300_INVALID_FORMAT)) {
+        r300_translate_vertex_data_type(format) != R300_INVALID_FORMAT) {
         retval |= PIPE_BIND_VERTEX_BUFFER;
     }
 
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index a7a0d9d..1122f3e 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -55,13 +55,13 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
 	util_blitter_save_rasterizer(rctx->blitter, rctx->states[R600_PIPE_STATE_RASTERIZER]);
 	util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader);
 	util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader);
-	util_blitter_save_vertex_elements(rctx->blitter, rctx->vbuf_mgr->vertex_elements);
+	util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_elements);
 	if (rctx->states[R600_PIPE_STATE_VIEWPORT]) {
 		util_blitter_save_viewport(rctx->blitter, &rctx->viewport);
 	}
 	util_blitter_save_vertex_buffers(rctx->blitter,
-					 rctx->vbuf_mgr->nr_vertex_buffers,
-					 rctx->vbuf_mgr->vertex_buffer);
+					 rctx->nr_vertex_buffers,
+					 rctx->vertex_buffer);
 	util_blitter_save_so_targets(rctx->blitter, rctx->num_so_targets,
 				     (struct pipe_stream_output_target**)rctx->so_targets);
 
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
index c22d361..cb3ea21 100644
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ b/src/gallium/drivers/r600/r600_buffer.c
@@ -106,8 +106,8 @@ static void *r600_buffer_transfer_map(struct pipe_context *pipe,
 
 			/* We changed the buffer, now we need to bind it where the old one was bound. */
 			/* Vertex buffers. */
-			for (i = 0; i < rctx->vbuf_mgr->nr_vertex_buffers; i++) {
-				if (rctx->vbuf_mgr->vertex_buffer[i].buffer == &rbuffer->b.b) {
+			for (i = 0; i < rctx->nr_vertex_buffers; i++) {
+				if (rctx->vertex_buffer[i].buffer == &rbuffer->b.b) {
 					r600_inval_vertex_cache(rctx);
 					r600_atom_dirty(rctx, &rctx->vertex_buffer_state);
 				}
diff --git a/src/gallium/drivers/r600/r600_formats.h b/src/gallium/drivers/r600/r600_formats.h
index af6de1c..6f57228 100644
--- a/src/gallium/drivers/r600/r600_formats.h
+++ b/src/gallium/drivers/r600/r600_formats.h
@@ -101,7 +101,8 @@ static INLINE bool r600_is_vertex_format_supported(enum pipe_format format)
 	/* No fixed, no double. */
 	if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
 	    (desc->channel[i].size == 64 &&
-	     desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT))
+	     desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) ||
+	    desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED)
 		return false;
 
 	/* No scaled/norm formats with 32 bits per channel. */
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 814274e..633c357 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -192,9 +192,6 @@ static void r600_destroy_context(struct pipe_context *context)
 		free(rctx->states[i]);
 	}
 
-	if (rctx->vbuf_mgr) {
-		u_vbuf_destroy(rctx->vbuf_mgr);
-	}
 	if (rctx->uploader) {
 		u_upload_destroy(rctx->uploader);
 	}
@@ -216,7 +213,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 {
 	struct r600_context *rctx = CALLOC_STRUCT(r600_context);
 	struct r600_screen* rscreen = (struct r600_screen *)screen;
-	struct u_vbuf_caps vbuf_caps;
 
 	if (rctx == NULL)
 		return NULL;
@@ -298,16 +294,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 	rctx->ws->cs_set_flush_callback(rctx->cs, r600_flush_from_winsys, rctx);
 	r600_emit_atom(rctx, &rctx->start_cs_cmd.atom);
 
-	u_vbuf_get_caps(screen, &vbuf_caps);
-	vbuf_caps.format_fixed32 = 0;
-	rctx->vbuf_mgr = u_vbuf_create(&rctx->context, &vbuf_caps,
-				       1024 * 1024, 256,
-				       PIPE_BIND_VERTEX_BUFFER |
-				       PIPE_BIND_INDEX_BUFFER |
-				       PIPE_BIND_CONSTANT_BUFFER);
-	if (!rctx->vbuf_mgr)
-		goto fail;
-
         rctx->uploader = u_upload_create(&rctx->context, 1024 * 1024, 256,
                                          PIPE_BIND_INDEX_BUFFER |
                                          PIPE_BIND_CONSTANT_BUFFER);
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 76b20b8..c4ab0bc 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -279,7 +279,6 @@ struct r600_context {
 	struct r600_textures_info	vs_samplers;
 	struct r600_textures_info	ps_samplers;
 
-	struct u_vbuf			*vbuf_mgr;
 	struct u_upload_mgr	        *uploader;
 	struct util_slab_mempool	pool_transfers;
 	boolean				have_depth_texture, have_depth_fb;
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index a3fd4db..9c9140a 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -64,6 +64,7 @@
 #include "pipe/p_context.h"
 #include "util/u_inlines.h"
 #include "cso_cache/cso_context.h"
+#include "util/u_vbuf.h"
 
 
 DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
@@ -110,6 +111,27 @@ st_get_msaa(void)
 }
 
 
+static void st_init_vbuf(struct st_context *st)
+{
+   struct u_vbuf_caps caps;
+
+   u_vbuf_get_caps(st->pipe->screen, &caps);
+
+   /* Create u_vbuf if there is anything unsupported. */
+   if (!caps.fetch_dword_unaligned ||
+       !caps.format_fixed32 ||
+       !caps.format_float16 ||
+       !caps.format_float64 ||
+       !caps.format_norm32 ||
+       !caps.format_scaled32 ||
+       !caps.user_vertex_buffers) {
+      /* XXX user vertex buffers are always uploaded regardless of the CAP. */
+      st->vbuf = u_vbuf_create(st->pipe, &caps);
+      cso_install_vbuf(st->cso_context, st->vbuf);
+   }
+}
+
+
 static struct st_context *
 st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
 {
@@ -132,6 +154,7 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
 
    st->cso_context = cso_create_context(pipe);
 
+   st_init_vbuf(st);
    st_init_atoms( st );
    st_init_bitmap(st);
    st_init_clear(st);
@@ -274,6 +297,9 @@ void st_destroy_context( struct st_context *st )
 
    st_destroy_context_priv(st);
 
+   if (st->vbuf)
+      u_vbuf_destroy(st->vbuf);
+
    cso_destroy_context(cso);
 
    pipe->destroy( pipe );
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index da03719..7c08253 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -40,6 +40,7 @@ struct draw_stage;
 struct gen_mipmap_state;
 struct st_context;
 struct st_fragment_program;
+struct u_vbuf;
 
 
 #define ST_NEW_MESA                    0x1 /* Mesa state has changed */
@@ -71,6 +72,8 @@ struct st_context
 
    struct pipe_context *pipe;
 
+   struct u_vbuf *vbuf;
+
    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 */
-- 
1.7.5.4



More information about the mesa-dev mailing list