vbo: deduplicate copy_vertices functions

There are some differences in exec, but those look like bug fixes not ported
to vbo_save.

Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4052>
This commit is contained in:
Marek Olšák 2020-02-18 18:37:36 -05:00
parent fd8eb634fd
commit 1be1ea0b8e
4 changed files with 117 additions and 158 deletions

View file

@ -225,3 +225,105 @@ vbo_merge_prims(struct _mesa_prim *p0, const struct _mesa_prim *p1)
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;
}
}

View file

@ -65,104 +65,16 @@ vbo_exec_debug_verts(struct vbo_exec_context *exec)
}
/**
* 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);
}
@ -392,7 +304,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec)
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;

View file

@ -185,6 +185,15 @@ void
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.
*/

View file

@ -111,79 +111,15 @@ copy_vertices(struct gl_context *ctx,
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);
}