gallium: notify drivers about possible changes in user buffer contents
authorMarek Olšák <maraeo@gmail.com>
Wed, 9 Feb 2011 00:10:11 +0000 (01:10 +0100)
committerMarek Olšák <maraeo@gmail.com>
Mon, 14 Feb 2011 20:50:08 +0000 (21:50 +0100)
Also implement the redefine_user_buffer hook in the drivers.

26 files changed:
src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_transfer.c
src/gallium/auxiliary/util/u_transfer.h
src/gallium/docs/source/context.rst
src/gallium/drivers/cell/ppu/cell_state_vertex.c
src/gallium/drivers/failover/fo_state.c
src/gallium/drivers/galahad/glhd_context.c
src/gallium/drivers/i915/i915_state.c
src/gallium/drivers/i965/brw_pipe_vertex.c
src/gallium/drivers/identity/id_context.c
src/gallium/drivers/llvmpipe/lp_state_vertex.c
src/gallium/drivers/noop/noop_state.c
src/gallium/drivers/nv50/nv50_state.c
src/gallium/drivers/nvc0/nvc0_state.c
src/gallium/drivers/nvfx/nvfx_vbo.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/rbug/rbug_context.c
src/gallium/drivers/softpipe/sp_state_vertex.c
src/gallium/drivers/svga/svga_pipe_vertex.c
src/gallium/drivers/trace/tr_context.c
src/gallium/include/pipe/p_context.h
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_draw.c

index e27c445096dc194f49ad6bda885cfe909c21e14b..fd1c2b72d044df1d96f4d8c9385eb88d5b302a7a 100644 (file)
@@ -639,6 +639,8 @@ static void blitter_draw_rectangle(struct blitter_context *blitter,
    }
 
    blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
+   ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
+                                        0, ctx->vbuf->width0);
    util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
                            PIPE_PRIM_TRIANGLE_FAN, 4, 2);
 }
@@ -867,6 +869,8 @@ void util_blitter_copy_region(struct blitter_context *blitter,
 
          /* Draw. */
          blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
+         ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
+                                              0, ctx->vbuf->width0);
          util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
                                  PIPE_PRIM_TRIANGLE_FAN, 4, 2);
          break;
index e2828cfd99e8ef54330f777dadc199b9335b9884..b6c63d9642f9914d98832ceeb659b0c2503253a7 100644 (file)
@@ -112,3 +112,10 @@ void u_default_transfer_destroy(struct pipe_context *pipe,
    FREE(transfer);
 }
 
+void u_default_redefine_user_buffer(struct pipe_context *ctx,
+                                    struct pipe_resource *resource,
+                                    unsigned offset,
+                                    unsigned size)
+{
+   resource->width0 = MAX2(resource->width0, offset + size);
+}
index 52191512ac7c7d91f234d17bc7bcedb832772526..8cf9c418b040fdbe0b4bbc7b7458f0cb6efd8706 100644 (file)
@@ -136,11 +136,9 @@ void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx,
                                    unsigned stride,
                                    unsigned layer_stride);
 
-
-
-
-
-
-
+void u_default_redefine_user_buffer(struct pipe_context *ctx,
+                                    struct pipe_resource *resource,
+                                    unsigned offset,
+                                    unsigned size);
 
 #endif
index da847262c1346e61c197c8229ca44f556d61e639..04a39511287cfeb19ef2f97968ff62a41555432d 100644 (file)
@@ -392,6 +392,22 @@ be flushed on write or unmap. Flushes must be requested with
 ``transfer_flush_region``. Flush ranges are relative to the mapped range, not
 the beginning of the resource.
 
+
+
+.. _redefine_user_buffer:
+
+redefine_user_buffer
+%%%%%%%%%%%%%%%%%%%%
+
+This function notifies a driver that the user buffer content has been changed.
+The updated region starts at ``offset`` and is ``size`` bytes large.
+The ``offset`` is relative to the pointer specified in ``user_buffer_create``.
+While uploading the user buffer, the driver is allowed not to upload
+the memory outside of this region.
+The width0 is redefined to ``MAX2(width0, offset+size)``.
+
+
+
 .. _pipe_transfer:
 
 PIPE_TRANSFER
index eb22a09a913b85182b1c469efebc097e07e1f055..7f65b82619eb7d5ddcec6f1b70b69057839cf619 100644 (file)
@@ -33,6 +33,7 @@
 #include "cell_state.h"
 
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 #include "draw/draw_context.h"
 
 
@@ -115,4 +116,5 @@ cell_init_vertex_functions(struct cell_context *cell)
    cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state;
    cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state;
    cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state;
+   cell->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index af1fd953aaf0b89c44973e88492449526cdc6967..b4da1b8b9016c00087a2f3265f6482522ec30516 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 
 #include "fo_context.h"
 
@@ -656,4 +657,5 @@ failover_init_state_functions( struct failover_context *failover )
    failover->pipe.set_constant_buffer = failover_set_constant_buffer;
    failover->pipe.create_sampler_view = failover_create_sampler_view;
    failover->pipe.sampler_view_destroy = failover_sampler_view_destroy;
+   failover->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index 8cbf0b1de4a6507517d99cabbe329c77ab9c4bb5..75e4c253dd98ab1f6115089518965b8573275835 100644 (file)
@@ -962,6 +962,19 @@ galahad_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void galahad_redefine_user_buffer(struct pipe_context *_context,
+                                         struct pipe_resource *_resource,
+                                         unsigned offset, unsigned size)
+{
+   struct galahad_context *glhd_context = galahad_context(_context);
+   struct galahad_resource *glhd_resource = galahad_resource(_resource);
+   struct pipe_context *context = glhd_context->pipe;
+   struct pipe_resource *resource = glhd_resource->resource;
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
+
+
 struct pipe_context *
 galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
 {
@@ -1036,6 +1049,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
    glhd_pipe->base.transfer_unmap = galahad_context_transfer_unmap;
    glhd_pipe->base.transfer_flush_region = galahad_context_transfer_flush_region;
    glhd_pipe->base.transfer_inline_write = galahad_context_transfer_inline_write;
+   glhd_pipe->base.redefine_user_buffer = galahad_redefine_user_buffer;
 
    glhd_pipe->pipe = pipe;
 
index b31cc306a441469ebefffd8383cee2ac59e8078a..f380708847bb9ce9541017dc9546070dce89966d 100644 (file)
@@ -33,6 +33,7 @@
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 #include "tgsi/tgsi_parse.h"
 
 #include "i915_context.h"
@@ -895,4 +896,5 @@ i915_init_state_functions( struct i915_context *i915 )
    i915->base.set_viewport_state = i915_set_viewport_state;
    i915->base.set_vertex_buffers = i915_set_vertex_buffers;
    i915->base.set_index_buffer = i915_set_index_buffer;
+   i915->base.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index b23454b5808c7f191003a30d08aa1c9f16f2109a..570ea23ff458ff83c50a3e44af5bd1d6b91eb673 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "util/u_memory.h"
 #include "util/u_format.h"
+#include "util/u_transfer.h"
 
 
 static unsigned brw_translate_surface_format( unsigned id )
@@ -302,6 +303,7 @@ brw_pipe_vertex_init( struct brw_context *brw )
    brw->base.create_vertex_elements_state = brw_create_vertex_elements_state;
    brw->base.bind_vertex_elements_state = brw_bind_vertex_elements_state;
    brw->base.delete_vertex_elements_state = brw_delete_vertex_elements_state;
+   brw->base.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
 
index 3efbd6a246d577d1c9d302a223ce8dade86e4c88..b533abe24c6145df45e783d190bdaa69e56ac441 100644 (file)
@@ -855,6 +855,19 @@ identity_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void identity_redefine_user_buffer(struct pipe_context *_context,
+                                          struct pipe_resource *_resource,
+                                          unsigned offset, unsigned size)
+{
+   struct identity_context *id_context = identity_context(_context);
+   struct identity_resource *id_resource = identity_resource(_resource);
+   struct pipe_context *context = id_context->pipe;
+   struct pipe_resource *resource = id_resource->resource;
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
+
+
 struct pipe_context *
 identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
 {
@@ -929,6 +942,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
    id_pipe->base.transfer_unmap = identity_context_transfer_unmap;
    id_pipe->base.transfer_flush_region = identity_context_transfer_flush_region;
    id_pipe->base.transfer_inline_write = identity_context_transfer_inline_write;
+   id_pipe->base.redefine_user_buffer = identity_redefine_user_buffer;
 
    id_pipe->pipe = pipe;
 
index fffdeb6ccde615cb7c16390d7d44c5b0a9fec2e1..be86f66de91aea20287b57e197be06d18501b90f 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "draw/draw_context.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 
 
 static void *
@@ -114,4 +115,6 @@ llvmpipe_init_vertex_funcs(struct llvmpipe_context *llvmpipe)
 
    llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers;
    llvmpipe->pipe.set_index_buffer = llvmpipe_set_index_buffer;
+
+   llvmpipe->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index ad324774c0347de38f50260accf28e2f0786dd13..00a4c1eb01ede7bc9e7d8723964f8163cd4949a7 100644 (file)
@@ -28,6 +28,7 @@
 #include <pipe/p_screen.h>
 #include <util/u_memory.h>
 #include <util/u_inlines.h>
+#include "util/u_transfer.h"
 
 static void noop_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
@@ -287,4 +288,5 @@ void noop_init_state_functions(struct pipe_context *ctx)
        ctx->sampler_view_destroy = noop_sampler_view_destroy;
        ctx->surface_destroy = noop_surface_destroy;
        ctx->draw_vbo = noop_draw_vbo;
+       ctx->redefine_user_buffer = u_default_redefine_user_buffer;
 }
index b4eda0f617d55b276beaeb8e92a44bb2f73d6004..ba2c3e8c2815e38bc0204eaa6b9aa53e09f001b9 100644 (file)
@@ -23,6 +23,7 @@
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 
 #include "tgsi/tgsi_parse.h"
 
@@ -886,5 +887,6 @@ nv50_init_state_functions(struct nv50_context *nv50)
 
        nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers;
        nv50->pipe.set_index_buffer = nv50_set_index_buffer;
+       nv50->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
index f6a7f824d5863b363351d63493998d87e41425b8..7fb91b1191d26df10930eab19eecf572ef1f8f4b 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 
 #include "tgsi/tgsi_parse.h"
 
@@ -934,5 +935,7 @@ nvc0_init_state_functions(struct nvc0_context *nvc0)
     nvc0->pipe.delete_stream_output_state = nvc0_tfb_state_delete;
     nvc0->pipe.bind_stream_output_state = nvc0_tfb_state_bind;
     nvc0->pipe.set_stream_output_buffers = nvc0_set_transform_feedback_buffers;
+
+    nvc0->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
index 01dacb43dad1155b77d350e72c3e4da2c7a78456..b72379d653694d6a920ad768dafaa91b528fbd78 100644 (file)
@@ -2,6 +2,7 @@
 #include "pipe/p_state.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
+#include "util/u_transfer.h"
 #include "translate/translate.h"
 
 #include "nvfx_context.h"
@@ -631,4 +632,6 @@ nvfx_init_vbo_functions(struct nvfx_context *nvfx)
        nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create;
        nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete;
        nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind;
+
+       nvfx->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index 242f883314e211a0a0faf5a1a62655ff5a5a9fbe..1ec942854ff8cfb8a33f25f10f0658b2d53f3dc1 100644 (file)
@@ -28,6 +28,7 @@
 #include "util/u_mm.h"
 #include "util/u_memory.h"
 #include "util/u_pack_color.h"
+#include "util/u_transfer.h"
 
 #include "tgsi/tgsi_parse.h"
 
@@ -1843,6 +1844,7 @@ void r300_init_state_functions(struct r300_context* r300)
 
     r300->context.set_vertex_buffers = r300_set_vertex_buffers;
     r300->context.set_index_buffer = r300_set_index_buffer;
+    r300->context.redefine_user_buffer = u_default_redefine_user_buffer;
 
     r300->context.create_vertex_elements_state = r300_create_vertex_elements_state;
     r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state;
index 88dcc9ba54491d01d5a9790a315fa4046e7e2b67..89e2d06abddf0d5164458b3187b758f80cae4919 100644 (file)
@@ -905,6 +905,7 @@ void evergreen_init_state_functions(struct r600_pipe_context *rctx)
        rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view;
        rctx->context.set_viewport_state = evergreen_set_viewport_state;
        rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
+       rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
 void evergreen_init_config(struct r600_pipe_context *rctx)
index 01c59072a266a1001e6f01dc5a89990071cd025e..43cba667de959973a63fc8ccfb44d9b39d6b54ca 100644 (file)
@@ -37,6 +37,7 @@
 #include <util/u_memory.h>
 #include <util/u_inlines.h>
 #include <util/u_framebuffer.h>
+#include "util/u_transfer.h"
 #include <pipebuffer/pb_buffer.h>
 #include "r600.h"
 #include "r600d.h"
@@ -941,6 +942,7 @@ void r600_init_state_functions(struct r600_pipe_context *rctx)
        rctx->context.set_vertex_sampler_views = r600_set_vs_sampler_view;
        rctx->context.set_viewport_state = r600_set_viewport_state;
        rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
+       rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
 void r600_init_config(struct r600_pipe_context *rctx)
index 94e57e40f86d78e7d4110dc5be00cf478897f7ea..3aefb5b3bb519ecee83038720b0df7f55e14af20 100644 (file)
@@ -987,6 +987,19 @@ rbug_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void rbug_redefine_user_buffer(struct pipe_context *_context,
+                                      struct pipe_resource *_resource,
+                                      unsigned offset, unsigned size)
+{
+   struct rbug_context *rb_pipe = rbug_context(_context);
+   struct rbug_resource *rb_resource = rbug_resource(_resource);
+   struct pipe_context *context = rb_pipe->pipe;
+   struct pipe_resource *resource = rb_resource->resource;
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
+
+
 struct pipe_context *
 rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
 {
@@ -1072,6 +1085,7 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
    rb_pipe->base.transfer_unmap = rbug_context_transfer_unmap;
    rb_pipe->base.transfer_flush_region = rbug_context_transfer_flush_region;
    rb_pipe->base.transfer_inline_write = rbug_context_transfer_inline_write;
+   rb_pipe->base.redefine_user_buffer = rbug_redefine_user_buffer;
 
    rb_pipe->pipe = pipe;
 
index 5f4d661abde74ed6cb0297ed69caacf4fe7bcda0..aa0b333c7a9ae348145f5a8e57cbf852fd8c83e2 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 #include "draw/draw_context.h"
 
 
@@ -119,4 +120,5 @@ softpipe_init_vertex_funcs(struct pipe_context *pipe)
 
    pipe->set_vertex_buffers = softpipe_set_vertex_buffers;
    pipe->set_index_buffer = softpipe_set_index_buffer;
+   pipe->redefine_user_buffer = u_default_redefine_user_buffer;
 }
index 86c79459f3e51c3c31e2d1d615da1e491c541a29..6bf37fbbbaf2f0f62dc7ac7ad64484a815184800 100644 (file)
@@ -27,6 +27,7 @@
 #include "pipe/p_defines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 #include "tgsi/tgsi_parse.h"
 
 #include "svga_screen.h"
@@ -131,6 +132,7 @@ void svga_init_vertex_functions( struct svga_context *svga )
    svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state;
    svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state;
    svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state;
+   svga->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
 
index eaabae8ce422137eb4564fc9d6a1035cd9ad3557..d24cc623c2ee26c82a4061c3596e7e8fbab99969 100644 (file)
@@ -1419,6 +1419,28 @@ trace_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void trace_redefine_user_buffer(struct pipe_context *_context,
+                                       struct pipe_resource *_resource,
+                                       unsigned offset, unsigned size)
+{
+   struct trace_context *tr_context = trace_context(_context);
+   struct trace_resource *tr_tex = trace_resource(_resource);
+   struct pipe_context *context = tr_context->pipe;
+   struct pipe_resource *resource = tr_tex->resource;
+
+   assert(resource->screen == context->screen);
+
+   trace_dump_call_begin("pipe_context", "redefine_user_buffer");
+
+   trace_dump_arg(ptr, context);
+   trace_dump_arg(ptr, resource);
+   trace_dump_arg(uint, offset);
+   trace_dump_arg(uint, size);
+
+   trace_dump_call_end();
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
 
 
 static const struct debug_named_value rbug_blocker_flags[] = {
@@ -1506,6 +1528,7 @@ trace_context_create(struct trace_screen *tr_scr,
    tr_ctx->base.transfer_unmap = trace_context_transfer_unmap;
    tr_ctx->base.transfer_flush_region = trace_context_transfer_flush_region;
    tr_ctx->base.transfer_inline_write = trace_context_transfer_inline_write;
+   tr_ctx->base.redefine_user_buffer = trace_redefine_user_buffer;
 
    tr_ctx->pipe = pipe;
 
index 589cac2ddd3b85da1621fed21168a49ded05f01f..24ee3fe117535a2a08013e38852ba1fef7532263 100644 (file)
@@ -399,6 +399,14 @@ struct pipe_context {
                                   unsigned stride,
                                   unsigned layer_stride);
 
+
+   /* Notify a driver that a content of a user buffer has been changed.
+    * The changed range is [offset, offset+size-1].
+    * The new width0 of the buffer is offset+size. */
+   void (*redefine_user_buffer)(struct pipe_context *,
+                                struct pipe_resource *,
+                                unsigned offset,
+                                unsigned size);
 };
 
 
index dccbff3c1dbe59997e8c4c15163067a21f55a4d0..7a19f35bbf5418a24cbbf406c2a1fdb8e540c718 100644 (file)
@@ -203,6 +203,11 @@ static void st_destroy_context_priv( struct st_context *st )
    st_destroy_drawpix(st);
    st_destroy_drawtex(st);
 
+   /* Unreference any user vertex buffers. */
+   for (i = 0; i < st->num_user_vbs; i++) {
+      pipe_resource_reference(&st->user_vb[i], NULL);
+   }
+
    for (i = 0; i < Elements(st->state.sampler_views); i++) {
       pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
    }
index 64a8f790e22bc20e481fa9db984c4869f1c41812..77765f0237967d08621165baa5ce7440bda96b04 100644 (file)
@@ -185,6 +185,11 @@ struct st_context
 
    int force_msaa;
    void *winsys_drawable_handle;
+
+   /* User vertex buffers. */
+   struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS];
+   unsigned user_vb_stride[PIPE_MAX_ATTRIBS];
+   unsigned num_user_vbs;
 };
 
 
index 34f75a379693f50ddd016a48c2faf5bf124c4c09..830e3e3c1bbd5004a69229bd1cec82b128bbb60f 100644 (file)
@@ -330,6 +330,11 @@ setup_interleaved_attribs(struct gl_context *ctx,
                                        stride * (max_index + 1),
                                       PIPE_BIND_VERTEX_BUFFER);
             vbuffer->buffer_offset = 0;
+
+            /* Track user vertex buffers. */
+            pipe_resource_reference(&st->user_vb[0], vbuffer->buffer);
+            st->user_vb_stride[0] = stride;
+            st->num_user_vbs = 1;
          }
          vbuffer->stride = stride; /* in bytes */
       }
@@ -405,6 +410,11 @@ setup_non_interleaved_attribs(struct gl_context *ctx,
          }
 
          vbuffer[attr].buffer_offset = 0;
+
+         /* Track user vertex buffers. */
+         pipe_resource_reference(&st->user_vb[attr], vbuffer->buffer);
+         st->user_vb_stride[attr] = stride;
+         st->num_user_vbs = MAX2(st->num_user_vbs, attr+1);
       }
 
       /* common-case setup */
@@ -538,12 +548,20 @@ st_validate_varrays(struct gl_context *ctx,
    struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
    unsigned num_vbuffers, num_velements;
    GLuint attr;
+   unsigned i;
 
    /* must get these after state validation! */
    vp = st->vp;
    vpv = st->vp_variant;
 
    memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
+
+   /* Unreference any user vertex buffers. */
+   for (i = 0; i < st->num_user_vbs; i++) {
+      pipe_resource_reference(&st->user_vb[i], NULL);
+   }
+   st->num_user_vbs = 0;
+
    /*
     * Setup the vbuffer[] and velements[] arrays.
     */
@@ -646,6 +664,26 @@ st_draw_vbo(struct gl_context *ctx,
 #endif
    }
 
+   /* Notify the driver that the content of user buffers may have been
+    * changed. */
+   if (!new_array && st->num_user_vbs) {
+      for (i = 0; i < st->num_user_vbs; i++) {
+         if (st->user_vb[i]) {
+            unsigned stride = st->user_vb_stride[i];
+
+            if (stride) {
+               pipe->redefine_user_buffer(pipe, st->user_vb[i],
+                                          min_index * stride,
+                                          (max_index + 1 - min_index) * stride);
+            } else {
+               /* stride == 0 */
+               pipe->redefine_user_buffer(pipe, st->user_vb[i],
+                                          0, st->user_vb[i]->width0);
+            }
+         }
+      }
+   }
+
    setup_index_buffer(ctx, ib, &ibuffer);
    pipe->set_index_buffer(pipe, &ibuffer);