summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/vbo/vbo_context.h10
-rw-r--r--src/mesa/vbo/vbo_exec_api.c38
-rw-r--r--src/mesa/vbo/vbo_exec_draw.c11
3 files changed, 56 insertions, 3 deletions
diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h
index 1e85335c107..e6b9d890d5f 100644
--- a/src/mesa/vbo/vbo_context.h
+++ b/src/mesa/vbo/vbo_context.h
@@ -205,8 +205,14 @@ vbo_get_default_vals_as_union(GLenum format)
static inline unsigned
vbo_compute_max_verts(const struct vbo_exec_context *exec)
{
- return (VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
- (exec->vtx.vertex_size * sizeof(GLfloat));
+ unsigned n = (VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
+ (exec->vtx.vertex_size * sizeof(GLfloat));
+ assert(n > 0);
+ /* Subtract one so we're always sure to have room for an extra
+ * vertex for GL_LINE_LOOP -> GL_LINE_STRIP conversion.
+ */
+ n--;
+ return n;
}
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index f26bf405d56..a23d5aa08aa 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -61,7 +61,8 @@ static void reset_attrfv( struct vbo_exec_context *exec );
/**
* Close off the last primitive, execute the buffer, restart the
- * primitive.
+ * primitive. This is called when we fill a vertex buffer before
+ * hitting glEnd.
*/
static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
{
@@ -81,6 +82,22 @@ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
last_count = last_prim->count;
+ /* Special handling for wrapping GL_LINE_LOOP */
+ if (last_prim->mode == GL_LINE_LOOP &&
+ last_count > 0 &&
+ !last_prim->end) {
+ /* draw this section of the incomplete line loop as a line strip */
+ last_prim->mode = GL_LINE_STRIP;
+ if (!last_prim->begin) {
+ /* This is not the first section of the line loop, so don't
+ * draw the 0th vertex. We're saving it until we draw the
+ * very last section of the loop.
+ */
+ last_prim->start++;
+ last_prim->count--;
+ }
+ }
+
/* Execute the buffer and save copied vertices.
*/
if (exec->vtx.vert_count)
@@ -96,6 +113,7 @@ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
if (_mesa_inside_begin_end(exec->ctx)) {
exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
+ exec->vtx.prim[0].begin = 0;
exec->vtx.prim[0].start = 0;
exec->vtx.prim[0].count = 0;
exec->vtx.prim_count++;
@@ -825,6 +843,24 @@ static void GLAPIENTRY vbo_exec_End( void )
last_prim->end = 1;
last_prim->count = exec->vtx.vert_count - last_prim->start;
+ /* Special handling for GL_LINE_LOOP */
+ if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) {
+ /* We're finishing drawing a line loop. Append 0th vertex onto
+ * end of vertex buffer so we can draw it as a line strip.
+ */
+ const fi_type *src = exec->vtx.buffer_map;
+ fi_type *dst = exec->vtx.buffer_map +
+ exec->vtx.vert_count * exec->vtx.vertex_size;
+
+ /* copy 0th vertex to end of buffer */
+ memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type));
+
+ assert(last_prim->start == 0);
+ last_prim->start++; /* skip vertex0 */
+ /* note that last_prim->count stays unchanged */
+ last_prim->mode = GL_LINE_STRIP;
+ }
+
try_vbo_merge(exec);
}
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index f6a1e4bdfad..ed5d9e947b0 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -109,6 +109,17 @@ vbo_copy_vertices( struct vbo_exec_context *exec )
return 1;
}
case GL_LINE_LOOP:
+ if (last_prim->begin == 0) {
+ /* We're dealing with the second or later section of a split/wrapped
+ * GL_LINE_LOOP. Since we're converting line loops to line strips,
+ * we've already increment the last_prim->start counter by one to
+ * skip the 0th vertex in the loop. We need to undo that (effectively
+ * subtract one from last_prim->start) so that we copy the 0th vertex
+ * to the next vertex buffer.
+ */
+ src -= sz;
+ }
+ /* fall-through */
case GL_TRIANGLE_FAN:
case GL_POLYGON:
if (nr == 0) {