vbo_save_loopback.c [plain text]
#include "swrast_setup/swrast_setup.h"
#include "swrast/swrast.h"
#include "tnl/tnl.h"
#include "context.h"
#include "vbo_context.h"
#include "glheader.h"
#include "enums.h"
#include "glapi.h"
#include "imports.h"
#include "macros.h"
#include "mtypes.h"
#include "dispatch.h"
typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
}
static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
}
static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
}
static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
}
static attr_func vert_attrfunc[4] = {
VertexAttrib1fvNV,
VertexAttrib2fvNV,
VertexAttrib3fvNV,
VertexAttrib4fvNV
};
struct loopback_attr {
GLint target;
GLint sz;
attr_func func;
};
static void loopback_prim( GLcontext *ctx,
const GLfloat *buffer,
const struct _mesa_prim *prim,
GLuint wrap_count,
GLuint vertex_size,
const struct loopback_attr *la, GLuint nr )
{
GLint start = prim->start;
GLint end = start + prim->count;
const GLfloat *data;
GLint j;
GLuint k;
if (0)
_mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
_mesa_lookup_enum_by_nr(prim->mode),
prim->begin ? "begin" : "..",
prim->end ? "end" : "..",
start,
end);
if (prim->begin) {
CALL_Begin(GET_DISPATCH(), ( prim->mode ));
}
else {
assert(start == 0);
start += wrap_count;
}
data = buffer + start * vertex_size;
for (j = start ; j < end ; j++) {
const GLfloat *tmp = data + la[0].sz;
for (k = 1 ; k < nr ; k++) {
la[k].func( ctx, la[k].target, tmp );
tmp += la[k].sz;
}
la[0].func( ctx, VBO_ATTRIB_POS, data );
data = tmp;
}
if (prim->end) {
CALL_End(GET_DISPATCH(), ());
}
}
static void loopback_weak_prim( GLcontext *ctx,
const struct _mesa_prim *prim )
{
if (prim->begin)
ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
if (prim->end)
ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
}
void vbo_loopback_vertex_list( GLcontext *ctx,
const GLfloat *buffer,
const GLubyte *attrsz,
const struct _mesa_prim *prim,
GLuint prim_count,
GLuint wrap_count,
GLuint vertex_size)
{
struct loopback_attr la[VBO_ATTRIB_MAX];
GLuint i, nr = 0;
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
if (attrsz[i]) {
la[nr].target = i;
la[nr].sz = attrsz[i];
la[nr].func = vert_attrfunc[attrsz[i]-1];
nr++;
}
}
for (i = 0 ; i < prim_count ; i++) {
if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
(ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
{
loopback_weak_prim( ctx, &prim[i] );
}
else
{
loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
}
}
}