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/mfeatures.h" 33#include "main/mtypes.h" 34#include "main/dispatch.h" 35#include "glapi/glapi.h" 36 37#include "vbo_context.h" 38 39 40#if FEATURE_dlist 41 42 43typedef void (*attr_func)( struct gl_context *ctx, GLint target, const GLfloat * ); 44 45 46/* This file makes heavy use of the aliasing of NV vertex attributes 47 * with the legacy attributes, and also with ARB and Material 48 * attributes as currently implemented. 49 */ 50static void VertexAttrib1fvNV(struct gl_context *ctx, GLint target, const GLfloat *v) 51{ 52 CALL_VertexAttrib1fvNV(ctx->Exec, (target, v)); 53} 54 55static void VertexAttrib2fvNV(struct gl_context *ctx, GLint target, const GLfloat *v) 56{ 57 CALL_VertexAttrib2fvNV(ctx->Exec, (target, v)); 58} 59 60static void VertexAttrib3fvNV(struct gl_context *ctx, GLint target, const GLfloat *v) 61{ 62 CALL_VertexAttrib3fvNV(ctx->Exec, (target, v)); 63} 64 65static void VertexAttrib4fvNV(struct gl_context *ctx, GLint target, const GLfloat *v) 66{ 67 CALL_VertexAttrib4fvNV(ctx->Exec, (target, v)); 68} 69 70static attr_func vert_attrfunc[4] = { 71 VertexAttrib1fvNV, 72 VertexAttrib2fvNV, 73 VertexAttrib3fvNV, 74 VertexAttrib4fvNV 75}; 76 77struct loopback_attr { 78 GLint target; 79 GLint sz; 80 attr_func func; 81}; 82 83/* Don't emit ends and begins on wrapped primitives. Don't replay 84 * wrapped vertices. If we get here, it's probably because the 85 * precalculated wrapping is wrong. 86 */ 87static void loopback_prim( struct gl_context *ctx, 88 const GLfloat *buffer, 89 const struct _mesa_prim *prim, 90 GLuint wrap_count, 91 GLuint vertex_size, 92 const struct loopback_attr *la, GLuint nr ) 93{ 94 GLint start = prim->start; 95 GLint end = start + prim->count; 96 const GLfloat *data; 97 GLint j; 98 GLuint k; 99 100 if (0) 101 printf("loopback prim %s(%s,%s) verts %d..%d\n", 102 _mesa_lookup_prim_by_nr(prim->mode), 103 prim->begin ? "begin" : "..", 104 prim->end ? "end" : "..", 105 start, 106 end); 107 108 if (prim->begin) { 109 CALL_Begin(GET_DISPATCH(), ( prim->mode )); 110 } 111 else { 112 assert(start == 0); 113 start += wrap_count; 114 } 115 116 data = buffer + start * vertex_size; 117 118 for (j = start ; j < end ; j++) { 119 const GLfloat *tmp = data + la[0].sz; 120 121 for (k = 1 ; k < nr ; k++) { 122 la[k].func( ctx, la[k].target, tmp ); 123 tmp += la[k].sz; 124 } 125 126 /* Fire the vertex 127 */ 128 la[0].func( ctx, VBO_ATTRIB_POS, data ); 129 data = tmp; 130 } 131 132 if (prim->end) { 133 CALL_End(GET_DISPATCH(), ()); 134 } 135} 136 137/* Primitives generated by DrawArrays/DrawElements/Rectf may be 138 * caught here. If there is no primitive in progress, execute them 139 * normally, otherwise need to track and discard the generated 140 * primitives. 141 */ 142static void loopback_weak_prim( struct gl_context *ctx, 143 const struct _mesa_prim *prim ) 144{ 145 /* Use the prim_weak flag to ensure that if this primitive 146 * wraps, we don't mistake future vertex_lists for part of the 147 * surrounding primitive. 148 * 149 * While this flag is set, we are simply disposing of data 150 * generated by an operation now known to be a noop. 151 */ 152 if (prim->begin) 153 ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK; 154 if (prim->end) 155 ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK; 156} 157 158 159void vbo_loopback_vertex_list( struct gl_context *ctx, 160 const GLfloat *buffer, 161 const GLubyte *attrsz, 162 const struct _mesa_prim *prim, 163 GLuint prim_count, 164 GLuint wrap_count, 165 GLuint vertex_size) 166{ 167 struct loopback_attr la[VBO_ATTRIB_MAX]; 168 GLuint i, nr = 0; 169 170 /* All Legacy, NV, ARB and Material attributes are routed through 171 * the NV attributes entrypoints: 172 */ 173 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { 174 if (attrsz[i]) { 175 la[nr].target = i; 176 la[nr].sz = attrsz[i]; 177 la[nr].func = vert_attrfunc[attrsz[i]-1]; 178 nr++; 179 } 180 } 181 182 for (i = 0 ; i < prim_count ; i++) { 183 if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) && 184 (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)) 185 { 186 loopback_weak_prim( ctx, &prim[i] ); 187 } 188 else 189 { 190 loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr ); 191 } 192 } 193} 194 195 196#endif /* FEATURE_dlist */ 197