vbo_save_loopback.c revision 0846c88ec3a63ac5e4096aedcdc107cbe71f306b
1/************************************************************************** 2 * 3 * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "main/context.h" 29#include "main/glheader.h" 30#include "main/enums.h" 31#include "main/imports.h" 32#include "main/macros.h" 33#include "main/mtypes.h" 34#include "glapi/dispatch.h" 35#include "glapi/glapi.h" 36 37#include "vbo_context.h" 38 39 40 41typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); 42 43 44/* This file makes heavy use of the aliasing of NV vertex attributes 45 * with the legacy attributes, and also with ARB and Material 46 * attributes as currently implemented. 47 */ 48static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v) 49{ 50 CALL_VertexAttrib1fvNV(ctx->Exec, (target, v)); 51} 52 53static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v) 54{ 55 CALL_VertexAttrib2fvNV(ctx->Exec, (target, v)); 56} 57 58static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v) 59{ 60 CALL_VertexAttrib3fvNV(ctx->Exec, (target, v)); 61} 62 63static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v) 64{ 65 CALL_VertexAttrib4fvNV(ctx->Exec, (target, v)); 66} 67 68static attr_func vert_attrfunc[4] = { 69 VertexAttrib1fvNV, 70 VertexAttrib2fvNV, 71 VertexAttrib3fvNV, 72 VertexAttrib4fvNV 73}; 74 75struct loopback_attr { 76 GLint target; 77 GLint sz; 78 attr_func func; 79}; 80 81/* Don't emit ends and begins on wrapped primitives. Don't replay 82 * wrapped vertices. If we get here, it's probably because the the 83 * precalculated wrapping is wrong. 84 */ 85static void loopback_prim( GLcontext *ctx, 86 const GLfloat *buffer, 87 const struct _mesa_prim *prim, 88 GLuint wrap_count, 89 GLuint vertex_size, 90 const struct loopback_attr *la, GLuint nr ) 91{ 92 GLint start = prim->start; 93 GLint end = start + prim->count; 94 const GLfloat *data; 95 GLint j; 96 GLuint k; 97 98 if (0) 99 _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n", 100 _mesa_lookup_prim_by_nr(prim->mode), 101 prim->begin ? "begin" : "..", 102 prim->end ? "end" : "..", 103 start, 104 end); 105 106 if (prim->begin) { 107 CALL_Begin(GET_DISPATCH(), ( prim->mode )); 108 } 109 else { 110 assert(start == 0); 111 start += wrap_count; 112 } 113 114 data = buffer + start * vertex_size; 115 116 for (j = start ; j < end ; j++) { 117 const GLfloat *tmp = data + la[0].sz; 118 119 for (k = 1 ; k < nr ; k++) { 120 la[k].func( ctx, la[k].target, tmp ); 121 tmp += la[k].sz; 122 } 123 124 /* Fire the vertex 125 */ 126 la[0].func( ctx, VBO_ATTRIB_POS, data ); 127 data = tmp; 128 } 129 130 if (prim->end) { 131 CALL_End(GET_DISPATCH(), ()); 132 } 133} 134 135/* Primitives generated by DrawArrays/DrawElements/Rectf may be 136 * caught here. If there is no primitive in progress, execute them 137 * normally, otherwise need to track and discard the generated 138 * primitives. 139 */ 140static void loopback_weak_prim( GLcontext *ctx, 141 const struct _mesa_prim *prim ) 142{ 143 /* Use the prim_weak flag to ensure that if this primitive 144 * wraps, we don't mistake future vertex_lists for part of the 145 * surrounding primitive. 146 * 147 * While this flag is set, we are simply disposing of data 148 * generated by an operation now known to be a noop. 149 */ 150 if (prim->begin) 151 ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK; 152 if (prim->end) 153 ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK; 154} 155 156 157void vbo_loopback_vertex_list( GLcontext *ctx, 158 const GLfloat *buffer, 159 const GLubyte *attrsz, 160 const struct _mesa_prim *prim, 161 GLuint prim_count, 162 GLuint wrap_count, 163 GLuint vertex_size) 164{ 165 struct loopback_attr la[VBO_ATTRIB_MAX]; 166 GLuint i, nr = 0; 167 168 /* All Legacy, NV, ARB and Material attributes are routed through 169 * the NV attributes entrypoints: 170 */ 171 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { 172 if (attrsz[i]) { 173 la[nr].target = i; 174 la[nr].sz = attrsz[i]; 175 la[nr].func = vert_attrfunc[attrsz[i]-1]; 176 nr++; 177 } 178 } 179 180 for (i = 0 ; i < prim_count ; i++) { 181 if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) && 182 (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)) 183 { 184 loopback_weak_prim( ctx, &prim[i] ); 185 } 186 else 187 { 188 loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr ); 189 } 190 } 191} 192