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/mesa_private.h" 33#include "main/dispatch.h" 34#include "glapi/glapi.h" 35 36#include "vbo_private.h" 37 38 39typedef void (*attr_func)(struct gl_context *ctx, GLint index, const GLfloat *); 40 41 42/* This file makes heavy use of the aliasing of NV vertex attributes 43 * with the legacy attributes, and also with ARB and Material 44 * attributes as currently implemented. 45 */ 46static void 47VertexAttrib1fvNV(struct gl_context *ctx, GLint index, const GLfloat *v) 48{ 49 CALL_VertexAttrib1fvNV(ctx->Exec, (index, v)); 50} 51 52 53static void 54VertexAttrib2fvNV(struct gl_context *ctx, GLint index, const GLfloat *v) 55{ 56 CALL_VertexAttrib2fvNV(ctx->Exec, (index, v)); 57} 58 59 60static void 61VertexAttrib3fvNV(struct gl_context *ctx, GLint index, const GLfloat *v) 62{ 63 CALL_VertexAttrib3fvNV(ctx->Exec, (index, v)); 64} 65 66 67static void 68VertexAttrib4fvNV(struct gl_context *ctx, GLint index, const GLfloat *v) 69{ 70 CALL_VertexAttrib4fvNV(ctx->Exec, (index, v)); 71} 72 73 74static attr_func vert_attrfunc[4] = { 75 VertexAttrib1fvNV, 76 VertexAttrib2fvNV, 77 VertexAttrib3fvNV, 78 VertexAttrib4fvNV 79}; 80 81 82struct loopback_attr { 83 enum vbo_attrib index; 84 GLuint offset; 85 attr_func func; 86}; 87 88 89/** 90 * Don't emit ends and begins on wrapped primitives. Don't replay 91 * wrapped vertices. If we get here, it's probably because the 92 * precalculated wrapping is wrong. 93 */ 94static void 95loopback_prim(struct gl_context *ctx, 96 const GLubyte *buffer, 97 const struct _mesa_prim *prim, 98 GLuint wrap_count, 99 GLuint stride, 100 const struct loopback_attr *la, GLuint nr) 101{ 102 GLuint start = prim->start; 103 const GLuint end = start + prim->count; 104 const GLubyte *data; 105 106 if (0) 107 printf("loopback prim %s(%s,%s) verts %d..%d vsize %d\n", 108 _mesa_lookup_prim_by_nr(prim->mode), 109 prim->begin ? "begin" : "..", 110 prim->end ? "end" : "..", 111 start, end, 112 stride); 113 114 if (prim->begin) { 115 CALL_Begin(ctx->Exec, (prim->mode)); 116 } 117 else { 118 start += wrap_count; 119 } 120 121 data = buffer + start * stride; 122 123 for (GLuint j = start; j < end; j++) { 124 for (GLuint k = 0; k < nr; k++) 125 la[k].func(ctx, la[k].index, (const GLfloat *)(data + la[k].offset)); 126 127 data += stride; 128 } 129 130 if (prim->end) { 131 CALL_End(ctx->Exec, ()); 132 } 133} 134 135 136static inline void 137append_attr(GLuint *nr, struct loopback_attr la[], int i, int shift, 138 const struct gl_vertex_array_object *vao) 139{ 140 la[*nr].index = shift + i; 141 la[*nr].offset = vao->VertexAttrib[i].RelativeOffset; 142 la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Format.Size - 1]; 143 (*nr)++; 144} 145 146 147void 148_vbo_loopback_vertex_list(struct gl_context *ctx, 149 const struct vbo_save_vertex_list* node, 150 fi_type *buffer) 151{ 152 struct loopback_attr la[VBO_ATTRIB_MAX]; 153 GLuint nr = 0; 154 155 /* All Legacy, NV, ARB and Material attributes are routed through 156 * the NV attributes entrypoints: 157 */ 158 const struct gl_vertex_array_object *vao = node->VAO[VP_MODE_FF]; 159 GLbitfield mask = vao->Enabled & VERT_BIT_MAT_ALL; 160 while (mask) { 161 const int i = u_bit_scan(&mask); 162 append_attr(&nr, la, i, VBO_MATERIAL_SHIFT, vao); 163 } 164 165 vao = node->VAO[VP_MODE_SHADER]; 166 mask = vao->Enabled & ~(VERT_BIT_POS | VERT_BIT_GENERIC0); 167 while (mask) { 168 const int i = u_bit_scan(&mask); 169 append_attr(&nr, la, i, 0, vao); 170 } 171 172 /* The last in the list should be the vertex provoking attribute */ 173 if (vao->Enabled & VERT_BIT_GENERIC0) { 174 append_attr(&nr, la, VERT_ATTRIB_GENERIC0, 0, vao); 175 } else if (vao->Enabled & VERT_BIT_POS) { 176 append_attr(&nr, la, VERT_ATTRIB_POS, 0, vao); 177 } 178 179 const GLuint wrap_count = node->cold->wrap_count; 180 const GLuint stride = _vbo_save_get_stride(node); 181 182 /* Replay the primitives */ 183 const struct _mesa_prim *prims = node->cold->prims; 184 const GLuint prim_count = node->cold->prim_count; 185 186 for (GLuint i = 0; i < prim_count; i++) { 187 loopback_prim(ctx, (GLubyte*)buffer + vao->BufferBinding[0].Offset, 188 &prims[i], wrap_count, stride, la, nr); 189 } 190} 191