p0->count += p1->count;
p0->end = p1->end;
}
+
+/**
+ * Copy zero, one or two vertices from the current vertex buffer into
+ * the temporary "copy" buffer.
+ * This is used when a single primitive overflows a vertex buffer and
+ * we need to continue the primitive in a new vertex buffer.
+ * The temporary "copy" buffer holds the vertices which need to get
+ * copied from the old buffer to the new one.
+ */
+unsigned
+vbo_copy_vertices(struct gl_context *ctx,
+ GLenum mode,
+ struct _mesa_prim *last_prim,
+ unsigned vertex_size,
+ bool in_dlist,
+ fi_type *dst,
+ const fi_type *src)
+{
+ const unsigned count = last_prim->count;
+ unsigned copy = 0;
+
+ switch (mode) {
+ case GL_POINTS:
+ return 0;
+ case GL_LINES:
+ case GL_TRIANGLES:
+ case GL_QUADS:
+ if (mode == GL_LINES)
+ copy = count % 2;
+ else if (mode == GL_TRIANGLES)
+ copy = count % 3;
+ else if (mode == GL_QUADS)
+ copy = count % 4;
+
+ for (unsigned i = 0; i < copy; i++) {
+ memcpy(dst + i * vertex_size, src + (count - copy + i) * vertex_size,
+ vertex_size * sizeof(GLfloat));
+ }
+ return copy;
+ case GL_LINE_STRIP:
+ if (count == 0)
+ return 0;
+
+ memcpy(dst, src + (count - 1) * vertex_size,
+ vertex_size * sizeof(GLfloat));
+ return 1;
+ case GL_LINE_LOOP:
+ if (!in_dlist && 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 incremented 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.
+ */
+ assert(last_prim->start > 0);
+ src -= vertex_size;
+ }
+ /* fall-through */
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ if (count == 0) {
+ return 0;
+ } else if (count == 1) {
+ memcpy(dst, src + 0, vertex_size * sizeof(GLfloat));
+ return 1;
+ } else {
+ memcpy(dst, src + 0, vertex_size * sizeof(GLfloat));
+ memcpy(dst + vertex_size, src + (count - 1) * vertex_size,
+ vertex_size * sizeof(GLfloat));
+ return 2;
+ }
+ case GL_TRIANGLE_STRIP:
+ /* no parity issue, but need to make sure the tri is not drawn twice */
+ if (count & 1) {
+ last_prim->count--;
+ }
+ /* fallthrough */
+ case GL_QUAD_STRIP:
+ switch (count) {
+ case 0:
+ copy = 0;
+ break;
+ case 1:
+ copy = 1;
+ break;
+ default:
+ copy = 2 + (count & 1);
+ break;
+ }
+ for (unsigned i = 0; i < copy; i++) {
+ memcpy(dst + i * vertex_size, src + (count - copy + i) * vertex_size,
+ vertex_size * sizeof(GLfloat));
+ }
+ return copy;
+ case PRIM_OUTSIDE_BEGIN_END:
+ return 0;
+ default:
+ unreachable("Unexpected primitive type");
+ return 0;
+ }
+}
}
-/**
- * Copy zero, one or two vertices from the current vertex buffer into
- * the temporary "copy" buffer.
- * This is used when a single primitive overflows a vertex buffer and
- * we need to continue the primitive in a new vertex buffer.
- * The temporary "copy" buffer holds the vertices which need to get
- * copied from the old buffer to the new one.
- */
static GLuint
-vbo_copy_vertices(struct vbo_exec_context *exec)
+vbo_exec_copy_vertices(struct vbo_exec_context *exec)
{
struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1];
- const GLuint nr = last_prim->count;
- GLuint ovf, i;
const GLuint sz = exec->vtx.vertex_size;
fi_type *dst = exec->vtx.copied.buffer;
const fi_type *src = exec->vtx.buffer_map + last_prim->start * sz;
- switch (exec->ctx->Driver.CurrentExecPrimitive) {
- case GL_POINTS:
- return 0;
- case GL_LINES:
- ovf = nr&1;
- for (i = 0 ; i < ovf ; i++)
- memcpy(dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat));
- return i;
- case GL_TRIANGLES:
- ovf = nr%3;
- for (i = 0 ; i < ovf ; i++)
- memcpy(dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat));
- return i;
- case GL_QUADS:
- ovf = nr&3;
- for (i = 0 ; i < ovf ; i++)
- memcpy(dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat));
- return i;
- case GL_LINE_STRIP:
- if (nr == 0) {
- return 0;
- }
- else {
- memcpy(dst, src+(nr-1)*sz, sz * sizeof(GLfloat));
- 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.
- */
- assert(last_prim->start > 0);
- src -= sz;
- }
- /* fall-through */
- case GL_TRIANGLE_FAN:
- case GL_POLYGON:
- if (nr == 0) {
- return 0;
- }
- else if (nr == 1) {
- memcpy(dst, src+0, sz * sizeof(GLfloat));
- return 1;
- }
- else {
- memcpy(dst, src+0, sz * sizeof(GLfloat));
- memcpy(dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat));
- return 2;
- }
- case GL_TRIANGLE_STRIP:
- /* no parity issue, but need to make sure the tri is not drawn twice */
- if (nr & 1) {
- last_prim->count--;
- }
- /* fallthrough */
- case GL_QUAD_STRIP:
- switch (nr) {
- case 0:
- ovf = 0;
- break;
- case 1:
- ovf = 1;
- break;
- default:
- ovf = 2 + (nr & 1);
- break;
- }
- for (i = 0 ; i < ovf ; i++)
- memcpy(dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat));
- return i;
- case PRIM_OUTSIDE_BEGIN_END:
- return 0;
- default:
- unreachable("Unexpected primitive type");
- return 0;
- }
+ return vbo_copy_vertices(exec->ctx, exec->ctx->Driver.CurrentExecPrimitive,
+ last_prim, sz, false, dst, src);
}
if (exec->vtx.prim_count &&
exec->vtx.vert_count) {
- exec->vtx.copied.nr = vbo_copy_vertices(exec);
+ exec->vtx.copied.nr = vbo_exec_copy_vertices(exec);
if (exec->vtx.copied.nr != exec->vtx.vert_count) {
struct gl_context *ctx = exec->ctx;
vbo_merge_prims(struct _mesa_prim *p0, const struct _mesa_prim *p1);
+unsigned
+vbo_copy_vertices(struct gl_context *ctx,
+ GLenum mode,
+ struct _mesa_prim *last_prim,
+ unsigned vertex_size,
+ bool in_dlist,
+ fi_type *dst,
+ const fi_type *src);
+
/**
* Get the filter mask for vbo draws depending on the vertex_processing_mode.
*/
const fi_type * src_buffer)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
- const struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
- GLuint nr = prim->count;
+ struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
GLuint sz = save->vertex_size;
const fi_type *src = src_buffer + prim->start * sz;
fi_type *dst = save->copied.buffer;
- GLuint ovf, i;
if (prim->end)
return 0;
- switch (prim->mode) {
- case GL_POINTS:
- return 0;
- case GL_LINES:
- ovf = nr & 1;
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- case GL_TRIANGLES:
- ovf = nr % 3;
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- case GL_QUADS:
- ovf = nr & 3;
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- case GL_LINE_STRIP:
- if (nr == 0)
- return 0;
- else {
- memcpy(dst, src + (nr - 1) * sz, sz * sizeof(GLfloat));
- return 1;
- }
- case GL_LINE_LOOP:
- case GL_TRIANGLE_FAN:
- case GL_POLYGON:
- if (nr == 0)
- return 0;
- else if (nr == 1) {
- memcpy(dst, src + 0, sz * sizeof(GLfloat));
- return 1;
- }
- else {
- memcpy(dst, src + 0, sz * sizeof(GLfloat));
- memcpy(dst + sz, src + (nr - 1) * sz, sz * sizeof(GLfloat));
- return 2;
- }
- case GL_TRIANGLE_STRIP:
- case GL_QUAD_STRIP:
- switch (nr) {
- case 0:
- ovf = 0;
- break;
- case 1:
- ovf = 1;
- break;
- default:
- ovf = 2 + (nr & 1);
- break;
- }
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- default:
- unreachable("Unexpected primitive type");
- return 0;
- }
+ return vbo_copy_vertices(ctx, prim->mode, prim, sz, true, dst, src);
}