Mesa (gallium-0.1): gallium: avoid mapping same vertex buffer in subsequent frames

Keith Whitwell keithw at kemper.freedesktop.org
Fri Dec 12 08:58:22 PST 2008


Module: Mesa
Branch: gallium-0.1
Commit: d2c2e9316d043ab584794a3524f22776deb4c777
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d2c2e9316d043ab584794a3524f22776deb4c777

Author: Keith Whitwell <keith at tungstengraphics.com>
Date:   Fri Dec 12 16:46:34 2008 +0000

gallium: avoid mapping same vertex buffer in subsequent frames

Quite a few util modules were maintaining a single vertex buffer over multiple
frames, and potentially reusing it in subsequent frames.  Unfortunately that
would force us into syncrhonous rendering as the buffer manager would be
forced to wait for the previous rendering to complete prior to allowing the
map.

This resolves that issue, but requires the state tracker to issue a few new
flush() calls at the end of each frame.

---

 src/gallium/auxiliary/util/u_blit.c       |   88 ++++++++++++++++++++---------
 src/gallium/auxiliary/util/u_blit.h       |    4 +
 src/gallium/auxiliary/util/u_draw_quad.c  |    5 +-
 src/gallium/auxiliary/util/u_draw_quad.h  |    2 +-
 src/gallium/auxiliary/util/u_gen_mipmap.c |   51 +++++++++++++++--
 src/gallium/auxiliary/util/u_gen_mipmap.h |    5 ++
 src/mesa/state_tracker/st_cb_accum.c      |    3 +-
 src/mesa/state_tracker/st_cb_bitmap.c     |   60 +++++++++++++++-----
 src/mesa/state_tracker/st_cb_bitmap.h     |    6 ++
 src/mesa/state_tracker/st_cb_clear.c      |   31 +++++++++-
 src/mesa/state_tracker/st_cb_clear.h      |    3 +
 src/mesa/state_tracker/st_cb_drawpixels.c |    2 +-
 src/mesa/state_tracker/st_cb_fbo.c        |    2 +-
 src/mesa/state_tracker/st_cb_flush.c      |   11 +++-
 src/mesa/state_tracker/st_cb_readpixels.c |    4 +-
 src/mesa/state_tracker/st_context.h       |    2 +
 16 files changed, 219 insertions(+), 60 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index d28201a..2cef333 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -66,6 +66,8 @@ struct blit_state
    void *fs;
 
    struct pipe_buffer *vbuf;  /**< quad vertices */
+   unsigned vbuf_slot;
+
    float vertices[4][2][4];   /**< vertex/texcoords for quad */
 };
 
@@ -138,17 +140,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
 
    /* fragment shader */
    ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
-
-   ctx->vbuf = pipe_buffer_create(pipe->screen,
-                                  32,
-                                  PIPE_BUFFER_USAGE_VERTEX,
-                                  sizeof(ctx->vertices));
-   if (!ctx->vbuf) {
-      FREE(ctx);
-      ctx->pipe->delete_fs_state(ctx->pipe, ctx->fs);
-      ctx->pipe->delete_vs_state(ctx->pipe, ctx->vs);
-      return NULL;
-   }
+   ctx->vbuf = NULL;
 
    /* init vertex data that doesn't change */
    for (i = 0; i < 4; i++) {
@@ -181,15 +173,35 @@ util_destroy_blit(struct blit_state *ctx)
 }
 
 
+static unsigned 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) {
+      ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
+                                     32,
+                                     PIPE_BUFFER_USAGE_VERTEX,
+                                     max_slots * sizeof ctx->vertices);
+   }
+   
+   return ctx->vbuf_slot++ * sizeof ctx->vertices;
+}
+                               
+
+
 /**
  * Setup vertex data for the textured quad we'll draw.
  * Note: y=0=top
  */
-static void
+static unsigned
 setup_vertex_data(struct blit_state *ctx,
                   float x0, float y0, float x1, float y1, float z)
 {
    void *buf;
+   unsigned offset;
 
    ctx->vertices[0][0][0] = x0;
    ctx->vertices[0][0][1] = y0;
@@ -215,12 +227,16 @@ setup_vertex_data(struct blit_state *ctx,
    ctx->vertices[3][1][0] = 0.0f;
    ctx->vertices[3][1][1] = 1.0f;
 
+   offset = get_next_slot( ctx );
+
    buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
                          PIPE_BUFFER_USAGE_CPU_WRITE);
 
-   memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+   memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
 
    pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
+
+   return offset;
 }
 
 
@@ -228,13 +244,14 @@ setup_vertex_data(struct blit_state *ctx,
  * Setup vertex data for the textured quad we'll draw.
  * Note: y=0=top
  */
-static void
+static unsigned
 setup_vertex_data_tex(struct blit_state *ctx,
                       float x0, float y0, float x1, float y1,
                       float s0, float t0, float s1, float t1,
                       float z)
 {
    void *buf;
+   unsigned offset;
 
    ctx->vertices[0][0][0] = x0;
    ctx->vertices[0][0][1] = y0;
@@ -260,12 +277,16 @@ setup_vertex_data_tex(struct blit_state *ctx,
    ctx->vertices[3][1][0] = s0;
    ctx->vertices[3][1][1] = t1;
 
+   offset = get_next_slot( ctx );
+
    buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
                          PIPE_BUFFER_USAGE_CPU_WRITE);
 
-   memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+   memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
 
    pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
+
+   return offset;
 }
 /**
  * Copy pixel block from src surface to dst surface.
@@ -291,6 +312,7 @@ util_blit_pixels(struct blit_state *ctx,
    const int srcH = abs(srcY1 - srcY0);
    const int srcLeft = MIN2(srcX0, srcX1);
    const int srcTop = MIN2(srcY0, srcY1);
+   unsigned offset;
 
    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
           filter == PIPE_TEX_MIPFILTER_LINEAR);
@@ -398,11 +420,11 @@ util_blit_pixels(struct blit_state *ctx,
    cso_set_framebuffer(ctx->cso, &fb);
 
    /* draw quad */
-   setup_vertex_data(ctx,
-                     (float) dstX0, (float) dstY0, 
-                     (float) dstX1, (float) dstY1, z);
+   offset = setup_vertex_data(ctx,
+                              (float) dstX0, (float) dstY0, 
+                              (float) dstX1, (float) dstY1, z);
 
-   util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+   util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
@@ -421,6 +443,18 @@ util_blit_pixels(struct blit_state *ctx,
    screen->texture_release(screen, &tex);
 }
 
+
+/* Release vertex buffer at end of frame to avoid synchronous
+ * rendering.
+ */
+void util_blit_flush( struct blit_state *ctx )
+{
+   pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
+   ctx->vbuf_slot = 0;
+} 
+
+
+
 /**
  * Copy pixel block from src texture to dst surface.
  * Overlapping regions are acceptable.
@@ -442,6 +476,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
    struct pipe_screen *screen = pipe->screen;
    struct pipe_framebuffer_state fb;
    float s0, t0, s1, t1;
+   unsigned offset;
 
    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
           filter == PIPE_TEX_MIPFILTER_LINEAR);
@@ -496,13 +531,14 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_set_framebuffer(ctx->cso, &fb);
 
    /* draw quad */
-   setup_vertex_data_tex(ctx,
-                     (float) dstX0, (float) dstY0,
-                     (float) dstX1, (float) dstY1,
-                     s0, t0, s1, t1,
-                     z);
-
-   util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+   offset = setup_vertex_data_tex(ctx,
+                                  (float) dstX0, (float) dstY0,
+                                  (float) dstX1, (float) dstY1,
+                                  s0, t0, s1, t1,
+                                  z);
+
+   util_draw_vertex_buffer(ctx->pipe, 
+                           ctx->vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
index 3080756..c35bece 100644
--- a/src/gallium/auxiliary/util/u_blit.h
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -70,6 +70,10 @@ util_blit_pixels_tex(struct blit_state *ctx,
                      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
 }
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
index 8ecae71..d7bb74b 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.c
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -40,6 +40,7 @@
 void 
 util_draw_vertex_buffer(struct pipe_context *pipe,
                         struct pipe_buffer *vbuf,
+                        uint offset,
                         uint prim_type,
                         uint num_verts,
                         uint num_attribs)
@@ -53,7 +54,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
    /* tell pipe about the vertex buffer */
    vbuffer.buffer = vbuf;
    vbuffer.pitch = num_attribs * 4 * sizeof(float);  /* vertex size */
-   vbuffer.buffer_offset = 0;
+   vbuffer.buffer_offset = offset;
    pipe->set_vertex_buffers(pipe, 1, &vbuffer);
 
    /* tell pipe about the vertex attributes */
@@ -124,7 +125,7 @@ util_draw_texquad(struct pipe_context *pipe,
          v[29] = 1.0;
 
          pipe_buffer_unmap(pipe->screen, vbuf);
-         util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
+         util_draw_vertex_buffer(pipe, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
       }
 
       pipe_buffer_reference(pipe->screen, &vbuf, NULL);
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
index ec4862e..00d3f5b 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.h
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -37,7 +37,7 @@ struct pipe_buffer;
 
 extern void 
 util_draw_vertex_buffer(struct pipe_context *pipe,
-                        struct pipe_buffer *vbuf,
+                        struct pipe_buffer *vbuf, uint offset,
                         uint num_attribs, uint num_verts, uint prim_type);
 
 
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index 9d305ad..5f395ec 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -69,6 +69,8 @@ struct gen_mipmap_state
    void *fs;
 
    struct pipe_buffer *vbuf;  /**< quad vertices */
+   unsigned vbuf_slot;
+
    float vertices[4][2][4];   /**< vertex/texcoords for quad */
 };
 
@@ -779,10 +781,28 @@ util_create_gen_mipmap(struct pipe_context *pipe,
 }
 
 
-static void
+static unsigned 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) {
+      ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
+                                     32,
+                                     PIPE_BUFFER_USAGE_VERTEX,
+                                     max_slots * sizeof ctx->vertices);
+   }
+   
+   return ctx->vbuf_slot++ * sizeof ctx->vertices;
+}
+
+static unsigned
 set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
 {
    void *buf;
+   unsigned offset;
 
    ctx->vertices[0][0][0] = 0.0f; /*x*/
    ctx->vertices[0][0][1] = 0.0f; /*y*/
@@ -804,12 +824,16 @@ set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
    ctx->vertices[3][1][0] = 0.0f;
    ctx->vertices[3][1][1] = 1.0f;
 
+   offset = get_next_slot( ctx );
+
    buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
                          PIPE_BUFFER_USAGE_CPU_WRITE);
 
-   memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+   memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
 
    pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
+
+   return offset;
 }
 
 
@@ -834,6 +858,17 @@ 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_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
+   ctx->vbuf_slot = 0;
+} 
+
+
 /**
  * Generate mipmap images.  It's assumed all needed texture memory is
  * already allocated.
@@ -855,6 +890,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
    struct pipe_framebuffer_state fb;
    uint dstLevel;
    uint zslice = 0;
+   uint offset;
 
    /* check if we can render in the texture's format */
    if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
@@ -925,10 +961,13 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
       cso_set_sampler_textures(ctx->cso, 1, &pt);
 
       /* quad coords in window coords (bypassing clipping, viewport mapping) */
-      set_vertex_data(ctx,
-                      (float) pt->width[dstLevel],
-                      (float) pt->height[dstLevel]);
-      util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+      offset = set_vertex_data(ctx,
+                               (float) pt->width[dstLevel],
+                               (float) pt->height[dstLevel]);
+
+      util_draw_vertex_buffer(ctx->pipe, 
+                              ctx->vbuf,
+                              offset,
                               PIPE_PRIM_TRIANGLE_FAN,
                               4,  /* verts */
                               2); /* attribs/vert */
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h
index 3277024..54608f9 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.h
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -50,6 +50,11 @@ 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
diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c
index cf3a99e..a4e72b4 100644
--- a/src/mesa/state_tracker/st_cb_accum.c
+++ b/src/mesa/state_tracker/st_cb_accum.c
@@ -38,6 +38,7 @@
 #include "st_cb_accum.h"
 #include "st_cb_fbo.h"
 #include "st_draw.h"
+#include "st_public.h"
 #include "st_format.h"
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
@@ -324,7 +325,7 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
    const GLint height = ctx->DrawBuffer->_Ymax - ypos;
 
    /* make sure color bufs aren't cached */
-   pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+   st_flush( st, PIPE_FLUSH_RENDER_CACHE, NULL );
 
    switch (op) {
    case GL_ADD:
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 7364520..bc05ca6 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -349,8 +349,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
    return pt;
 }
 
-
-static void
+static GLuint
 setup_bitmap_vertex_data(struct st_context *st,
                          int x, int y, int width, int height,
                          float z, const float color[4])
@@ -369,12 +368,18 @@ setup_bitmap_vertex_data(struct st_context *st,
    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 = 4096 / sizeof(st->bitmap.vertices);
    GLuint i;
-   void *buf;
+
+   if (st->bitmap.vbuf_slot >= max_slots) {
+      pipe_buffer_reference(pipe->screen, &st->bitmap.vbuf, NULL);
+      st->bitmap.vbuf_slot = 0;
+   }
 
    if (!st->bitmap.vbuf) {
-      st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
-                                           sizeof(st->bitmap.vertices));
+      st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 32, 
+                                           PIPE_BUFFER_USAGE_VERTEX,
+                                           max_slots * sizeof(st->bitmap.vertices));
    }
 
    /* Positions are in clip coords since we need to do clipping in case
@@ -413,9 +418,19 @@ setup_bitmap_vertex_data(struct st_context *st,
    }
 
    /* put vertex data into vbuf */
-   buf = pipe_buffer_map(pipe->screen, st->bitmap.vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
-   memcpy(buf, st->bitmap.vertices, sizeof(st->bitmap.vertices));
-   pipe_buffer_unmap(pipe->screen, st->bitmap.vbuf);
+   {
+      char *buf = pipe_buffer_map(pipe->screen, 
+                                  st->bitmap.vbuf, 
+                                  PIPE_BUFFER_USAGE_CPU_WRITE);
+
+      memcpy(buf + st->bitmap.vbuf_slot * sizeof st->bitmap.vertices, 
+             st->bitmap.vertices, 
+             sizeof st->bitmap.vertices);
+
+      pipe_buffer_unmap(pipe->screen, st->bitmap.vbuf);
+   }
+
+   return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
 }
 
 
@@ -434,6 +449,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    struct cso_context *cso = ctx->st->cso_context;
    struct st_fragment_program *stfp;
    GLuint maxSize;
+   GLuint offset;
 
    stfp = combined_bitmap_fragment_program(ctx);
 
@@ -518,11 +534,11 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    }
 
    /* draw textured quad */
-   setup_bitmap_vertex_data(st, x, y, width, height,
-                            ctx->Current.RasterPos[2],
-                            color);
+   offset = setup_bitmap_vertex_data(st, x, y, width, height,
+                                     ctx->Current.RasterPos[2],
+                                     color);
 
-   util_draw_vertex_buffer(pipe, st->bitmap.vbuf,
+   util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            3); /* attribs/vert */
@@ -592,12 +608,12 @@ st_flush_bitmap_cache(struct st_context *st)
          struct pipe_screen *screen = pipe->screen;
 
          assert(cache->xmin <= cache->xmax);
-         /*
-         printf("flush size %d x %d  at %d, %d\n",
+ 
+/*         printf("flush size %d x %d  at %d, %d\n",
                 cache->xmax - cache->xmin,
                 cache->ymax - cache->ymin,
                 cache->xpos, cache->ypos);
-         */
+*/
 
          /* The texture surface has been mapped until now.
           * So unmap and release the texture surface before drawing.
@@ -623,6 +639,20 @@ st_flush_bitmap_cache(struct st_context *st)
    }
 }
 
+/* Flush bitmap cache and release vertex buffer.
+ */
+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_buffer_reference(st->pipe->screen, &st->bitmap.vbuf, NULL);
+   st->bitmap.vbuf_slot = 0;
+}
+
 
 /**
  * Try to accumulate this glBitmap call in the bitmap cache.
diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h
index aae11d3..81cf619 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.h
+++ b/src/mesa/state_tracker/st_cb_bitmap.h
@@ -42,5 +42,11 @@ st_destroy_bitmap(struct st_context *st);
 extern void
 st_flush_bitmap_cache(struct st_context *st);
 
+/* Flush bitmap cache and release vertex buffer.  Needed at end of
+ * frame to avoid synchronous rendering.
+ */
+extern void
+st_flush_bitmap(struct st_context *st);
+
 
 #endif /* ST_CB_BITMAP_H */
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index bc3055c..b6cea16 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -148,12 +148,18 @@ draw_quad(GLcontext *ctx,
 {
    struct st_context *st = ctx->st;
    struct pipe_context *pipe = st->pipe;
+   const GLuint max_slots = 1024 / sizeof(st->clear.vertices);
    GLuint i;
    void *buf;
 
+   if (st->clear.vbuf_slot >= max_slots) {
+      pipe_buffer_reference(pipe->screen, &st->clear.vbuf, NULL);
+      st->clear.vbuf_slot = 0;
+   }
+
    if (!st->clear.vbuf) {
       st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
-                                          sizeof(st->clear.vertices));
+                                          max_slots * sizeof(st->clear.vertices));
    }
 
    /* positions */
@@ -181,14 +187,23 @@ draw_quad(GLcontext *ctx,
 
    /* put vertex data into vbuf */
    buf = pipe_buffer_map(pipe->screen, st->clear.vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
-   memcpy(buf, st->clear.vertices, sizeof(st->clear.vertices));
+
+   memcpy((char *)buf + st->clear.vbuf_slot * sizeof(st->clear.vertices), 
+          st->clear.vertices, 
+          sizeof(st->clear.vertices));
+
    pipe_buffer_unmap(pipe->screen, st->clear.vbuf);
 
    /* draw */
-   util_draw_vertex_buffer(pipe, st->clear.vbuf,
+   util_draw_vertex_buffer(pipe, 
+                           st->clear.vbuf, 
+                           st->clear.vbuf_slot * sizeof(st->clear.vertices),
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
+
+   /* Increment slot */
+   st->clear.vbuf_slot++;
 }
 
 
@@ -508,6 +523,16 @@ clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
 }
 
 
+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_buffer_reference(st->pipe->screen, &st->clear.vbuf, NULL);
+   st->clear.vbuf_slot = 0;
+}
+ 
+
 
 /**
  * Called via ctx->Driver.Clear()
diff --git a/src/mesa/state_tracker/st_cb_clear.h b/src/mesa/state_tracker/st_cb_clear.h
index f493877..bc035ac 100644
--- a/src/mesa/state_tracker/st_cb_clear.h
+++ b/src/mesa/state_tracker/st_cb_clear.h
@@ -37,6 +37,9 @@ 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);
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 5b24b9f..32bf214 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -494,7 +494,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
       memcpy(map, verts, sizeof(verts));
       pipe_buffer_unmap(pipe->screen, buf);
 
-      util_draw_vertex_buffer(pipe, buf,
+      util_draw_vertex_buffer(pipe, buf, 0,
                               PIPE_PRIM_QUADS,
                               4,  /* verts */
                               3); /* attribs/vert */
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 00076f6..eece7de 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -426,7 +426,7 @@ st_finish_render_texture(GLcontext *ctx,
    if (!strb)
       return;
 
-   ctx->st->pipe->flush(ctx->st->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+   st_flush( ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL );
 
    if (strb->surface)
       screen->tex_surface_release( screen, &strb->surface );
diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c
index cc40467..072f2e9 100644
--- a/src/mesa/state_tracker/st_cb_flush.c
+++ b/src/mesa/state_tracker/st_cb_flush.c
@@ -37,11 +37,14 @@
 #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_public.h"
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_winsys.h"
+#include "util/u_gen_mipmap.h"
+#include "util/u_blit.h"
 
 
 static INLINE GLboolean
@@ -78,7 +81,13 @@ void st_flush( struct st_context *st, uint pipeFlushFlags,
 {
    FLUSH_VERTICES(st->ctx, 0);
 
-   st_flush_bitmap_cache(st);
+   /* 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, pipeFlushFlags, fence );
 }
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index c801532..646eaff 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -317,10 +317,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    if (!dest)
       return;
 
-   st_flush_bitmap_cache(ctx->st);
-
    /* make sure rendering has completed */
-   pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+   st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
 
    if (format == GL_STENCIL_INDEX) {
       st_read_stencil_pixels(ctx, x, y, width, height, type, pack, dest);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 5bcb87c..695ac4a 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -154,6 +154,7 @@ struct st_context
       void *vs;
       float vertices[4][3][4];  /**< vertex pos + color + texcoord */
       struct pipe_buffer *vbuf;
+      unsigned vbuf_slot;       /* next free slot in vbuf */
       struct bitmap_cache *cache;
    } bitmap;
 
@@ -173,6 +174,7 @@ struct st_context
       void *fs;
       float vertices[4][2][4];  /**< vertex pos + color */
       struct pipe_buffer *vbuf;
+      unsigned vbuf_slot;
    } clear;
 
    void *passthrough_fs;  /**< simple pass-through frag shader */



More information about the mesa-commit mailing list