| /************************************************************************** |
| * |
| * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. |
| * 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, sub license, 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 (including the |
| * next paragraph) 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 NON-INFRINGEMENT. |
| * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. |
| * |
| **************************************************************************/ |
| |
| #include "main/context.h" |
| #include "main/glheader.h" |
| #include "main/enums.h" |
| #include "main/imports.h" |
| #include "main/macros.h" |
| #include "main/mtypes.h" |
| #include "glapi/dispatch.h" |
| #include "glapi/glapi.h" |
| |
| #include "vbo_context.h" |
| |
| |
| |
| typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); |
| |
| |
| /* This file makes heavy use of the aliasing of NV vertex attributes |
| * with the legacy attributes, and also with ARB and Material |
| * attributes as currently implemented. |
| */ |
| 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; |
| }; |
| |
| /* 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, |
| 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; |
| } |
| |
| /* Fire the vertex |
| */ |
| la[0].func( ctx, VBO_ATTRIB_POS, data ); |
| data = tmp; |
| } |
| |
| if (prim->end) { |
| CALL_End(GET_DISPATCH(), ()); |
| } |
| } |
| |
| /* 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, |
| const struct _mesa_prim *prim ) |
| { |
| /* 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->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; |
| |
| /* All Legacy, NV, ARB and Material attributes are routed through |
| * the NV attributes entrypoints: |
| */ |
| 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 ); |
| } |
| } |
| } |