diff options
author | Keith Whitwell <[email protected]> | 2003-11-24 15:23:18 +0000 |
---|---|---|
committer | Keith Whitwell <[email protected]> | 2003-11-24 15:23:18 +0000 |
commit | ae0eaf93e092ac8e8b1c98f3e986de96940663fa (patch) | |
tree | 56aae7c4b985f657384df5e088227c4dd08130fb /src/mesa/tnl/t_save_loopback.c | |
parent | 57c9814b9e87924696df4c741861c29d4236d1eb (diff) |
Merge vtx-0-2-branch
Diffstat (limited to 'src/mesa/tnl/t_save_loopback.c')
-rw-r--r-- | src/mesa/tnl/t_save_loopback.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/src/mesa/tnl/t_save_loopback.c b/src/mesa/tnl/t_save_loopback.c new file mode 100644 index 00000000000..b496a784c35 --- /dev/null +++ b/src/mesa/tnl/t_save_loopback.c @@ -0,0 +1,301 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Author: + * Keith Whitwell <[email protected]> + */ + +#include "context.h" +#include "enums.h" +#include "glapi.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "t_context.h" +#include "t_save_api.h" + +/* If someone compiles a display list like: + * glBegin(Triangles) + * glVertex() + * ... lots of vertices ... + * glEnd() + * + * or: + * glDrawArrays(...) + * + * and then tries to execute it like this: + * + * glBegin(Lines) + * glCallList() + * glEnd() + * + * it will wind up in here, as the vertex copying used when wrapping + * buffers in list compilation (Triangles) won't be right for how the + * list is being executed (as Lines). + * + * This could be avoided by not compiling as vertex_lists until after + * the first glEnd() has been seen. However, that would miss an + * important category of display lists, for the sake of a degenerate + * usage. + * + * Further, replaying degenerately-called lists in this fashion is + * probably still faster than the replay using opcodes. + */ + +typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); + + +/* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */ +static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib1fvNV(target, v); +} + +static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib2fvNV(target, v); +} + +static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib3fvNV(target, v); +} + +static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib4fvNV(target, v); +} + +static attr_func vert_attrfunc[4] = { + VertexAttrib1fvNV, + VertexAttrib2fvNV, + VertexAttrib3fvNV, + VertexAttrib4fvNV +}; + + +static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case _TNL_ATTRIB_MAT_FRONT_SHININESS: + ctx->Exec->Materialfv( GL_FRONT, GL_SHININESS, v ); + break; + case _TNL_ATTRIB_MAT_BACK_SHININESS: + ctx->Exec->Materialfv( GL_BACK, GL_SHININESS, v ); + break; + } +} + + +static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case _TNL_ATTRIB_MAT_FRONT_INDEXES: + ctx->Exec->Materialfv( GL_FRONT, GL_COLOR_INDEXES, v ); + break; + case _TNL_ATTRIB_MAT_BACK_INDEXES: + ctx->Exec->Materialfv( GL_BACK, GL_COLOR_INDEXES, v ); + break; + } +} + + +static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case _TNL_ATTRIB_MAT_FRONT_EMISSION: + ctx->Exec->Materialfv( GL_FRONT, GL_EMISSION, v ); + break; + case _TNL_ATTRIB_MAT_BACK_EMISSION: + ctx->Exec->Materialfv( GL_BACK, GL_EMISSION, v ); + break; + case _TNL_ATTRIB_MAT_FRONT_AMBIENT: + ctx->Exec->Materialfv( GL_FRONT, GL_AMBIENT, v ); + break; + case _TNL_ATTRIB_MAT_BACK_AMBIENT: + ctx->Exec->Materialfv( GL_BACK, GL_AMBIENT, v ); + break; + case _TNL_ATTRIB_MAT_FRONT_DIFFUSE: + ctx->Exec->Materialfv( GL_FRONT, GL_DIFFUSE, v ); + break; + case _TNL_ATTRIB_MAT_BACK_DIFFUSE: + ctx->Exec->Materialfv( GL_BACK, GL_DIFFUSE, v ); + break; + case _TNL_ATTRIB_MAT_FRONT_SPECULAR: + ctx->Exec->Materialfv( GL_FRONT, GL_SPECULAR, v ); + break; + case _TNL_ATTRIB_MAT_BACK_SPECULAR: + ctx->Exec->Materialfv( GL_BACK, GL_SPECULAR, v ); + break; + } +} + + +static attr_func mat_attrfunc[4] = { + mat_attr1fv, + 0, + mat_attr3fv, + mat_attr4fv +}; + + +static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->Indexf(v[0]); +} + +static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->EdgeFlag((v[0] == 1.0)); +} + +struct loopback_attr { + GLint target; + GLint sz; + attr_func func; +}; + +/* Don't emit ends and begins on wrapped primitives. Don't replay + * wrapped vertices. If we get here, it's probably because the the + * precalculated wrapping is wrong. + */ +static void loopback_prim( GLcontext *ctx, + struct tnl_vertex_list *list, GLuint i, + struct loopback_attr *la, GLuint nr ) +{ + struct tnl_prim *prim = &list->prim[i]; + GLint begin = prim->start; + GLint end = begin + prim->count; + GLfloat *data; + GLint j, k; + + if (prim->mode & PRIM_BEGIN) { + glBegin( prim->mode & PRIM_MODE_MASK ); + } else { + assert(i == 0); + assert(begin == 0); + begin += list->wrap_count; + } + + data = list->buffer + begin * list->vertex_size; + + for (j = begin ; j < end ; j++) { + GLfloat *tmp = data + la[0].sz; + + for (k = 1 ; k < nr ; k++) { + la[k].func( ctx, la[k].target, tmp ); + tmp += la[k].sz; + } + + /* Fire the vertex + */ + la[0].func( ctx, VERT_ATTRIB_POS, data ); + data = tmp; + } + + if (prim->mode & PRIM_END) { + glEnd(); + } + else { + assert (i == list->prim_count-1); + } +} + +/* Primitives generated by DrawArrays/DrawElements/Rectf may be + * caught here. If there is no primitive in progress, execute them + * normally, otherwise need to track and discard the generated + * primitives. + */ +static void loopback_weak_prim( GLcontext *ctx, + struct tnl_vertex_list *list, GLuint i, + struct loopback_attr *la, GLuint nr ) +{ + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) + loopback_prim( ctx, list, i, la, nr ); + else { + struct tnl_prim *prim = &list->prim[i]; + + /* Use the prim_weak flag to ensure that if this primitive + * wraps, we don't mistake future vertex_lists for part of the + * surrounding primitive. + * + * While this flag is set, we are simply disposing of data + * generated by an operation now known to be a noop. + */ + if (prim->mode & PRIM_BEGIN) + ctx->Driver.CurrentExecPrimitive |= PRIM_WEAK; + if (prim->mode & PRIM_END) + ctx->Driver.CurrentExecPrimitive &= ~PRIM_WEAK; + } +} + + + +void _tnl_loopback_vertex_list( GLcontext *ctx, struct tnl_vertex_list *list ) +{ + struct loopback_attr la[_TNL_ATTRIB_MAX]; + GLuint i, nr = 0; + + for (i = 0 ; i <= _TNL_ATTRIB_TEX7 ; i++) { + if (list->attrsz[i]) { + la[nr].target = i; + la[nr].sz = list->attrsz[i]; + la[nr].func = vert_attrfunc[list->attrsz[i]-1]; + nr++; + } + } + + for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; + i <= _TNL_ATTRIB_MAT_BACK_INDEXES ; + i++) { + if (list->attrsz[i]) { + la[nr].target = i; + la[nr].sz = list->attrsz[i]; + la[nr].func = mat_attrfunc[list->attrsz[i]-1]; + nr++; + } + } + + if (list->attrsz[_TNL_ATTRIB_EDGEFLAG]) { + la[nr].target = _TNL_ATTRIB_EDGEFLAG; + la[nr].sz = list->attrsz[_TNL_ATTRIB_EDGEFLAG]; + la[nr].func = edgeflag_attr1fv; + nr++; + } + + if (list->attrsz[_TNL_ATTRIB_INDEX]) { + la[nr].target = _TNL_ATTRIB_INDEX; + la[nr].sz = list->attrsz[_TNL_ATTRIB_INDEX]; + la[nr].func = index_attr1fv; + nr++; + } + + for (i = 0 ; i < list->prim_count ; i++) { + if (list->prim[i].mode & PRIM_WEAK) + loopback_weak_prim( ctx, list, i, la, nr ); + else + loopback_prim( ctx, list, i, la, nr ); + } +} |