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