vbo_exec_draw.c revision 7117f1b4
1/* 2 * Mesa 3-D graphics library 3 * Version: 5.1 4 * 5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Keith Whitwell <keith@tungstengraphics.com> 26 */ 27 28#include "glheader.h" 29#include "context.h" 30#include "enums.h" 31#include "state.h" 32#include "macros.h" 33 34#include "vbo_context.h" 35 36 37static void vbo_exec_debug_verts( struct vbo_exec_context *exec ) 38{ 39 GLuint count = exec->vtx.vert_count; 40 GLuint i; 41 42 _mesa_printf("%s: %u vertices %d primitives, %d vertsize\n", 43 __FUNCTION__, 44 count, 45 exec->vtx.prim_count, 46 exec->vtx.vertex_size); 47 48 for (i = 0 ; i < exec->vtx.prim_count ; i++) { 49 struct _mesa_prim *prim = &exec->vtx.prim[i]; 50 _mesa_printf(" prim %d: %s%s %d..%d %s %s\n", 51 i, 52 _mesa_lookup_enum_by_nr(prim->mode), 53 prim->weak ? " (weak)" : "", 54 prim->start, 55 prim->start + prim->count, 56 prim->begin ? "BEGIN" : "(wrap)", 57 prim->end ? "END" : "(wrap)"); 58 } 59} 60 61 62/* 63 * NOTE: Need to have calculated primitives by this point -- do it on the fly. 64 * NOTE: Old 'parity' issue is gone. 65 */ 66static GLuint vbo_copy_vertices( struct vbo_exec_context *exec ) 67{ 68 GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count; 69 GLuint ovf, i; 70 GLuint sz = exec->vtx.vertex_size; 71 GLfloat *dst = exec->vtx.copied.buffer; 72 GLfloat *src = ((GLfloat *)exec->vtx.buffer_map + 73 exec->vtx.prim[exec->vtx.prim_count-1].start * 74 exec->vtx.vertex_size); 75 76 77 switch( exec->ctx->Driver.CurrentExecPrimitive ) 78 { 79 case GL_POINTS: 80 return 0; 81 case GL_LINES: 82 ovf = nr&1; 83 for (i = 0 ; i < ovf ; i++) 84 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); 85 return i; 86 case GL_TRIANGLES: 87 ovf = nr%3; 88 for (i = 0 ; i < ovf ; i++) 89 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); 90 return i; 91 case GL_QUADS: 92 ovf = nr&3; 93 for (i = 0 ; i < ovf ; i++) 94 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); 95 return i; 96 case GL_LINE_STRIP: 97 if (nr == 0) 98 return 0; 99 else { 100 _mesa_memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) ); 101 return 1; 102 } 103 case GL_LINE_LOOP: 104 case GL_TRIANGLE_FAN: 105 case GL_POLYGON: 106 if (nr == 0) 107 return 0; 108 else if (nr == 1) { 109 _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) ); 110 return 1; 111 } else { 112 _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) ); 113 _mesa_memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) ); 114 return 2; 115 } 116 case GL_TRIANGLE_STRIP: 117 /* no parity issue, but need to make sure the tri is not drawn twice */ 118 if (nr & 1) { 119 exec->vtx.prim[exec->vtx.prim_count-1].count--; 120 } 121 /* fallthrough */ 122 case GL_QUAD_STRIP: 123 switch (nr) { 124 case 0: ovf = 0; break; 125 case 1: ovf = 1; break; 126 default: ovf = 2 + (nr&1); break; 127 } 128 for (i = 0 ; i < ovf ; i++) 129 _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); 130 return i; 131 case GL_POLYGON+1: 132 return 0; 133 default: 134 assert(0); 135 return 0; 136 } 137} 138 139 140 141/* TODO: populate these as the vertex is defined: 142 */ 143static void vbo_exec_bind_arrays( GLcontext *ctx ) 144{ 145 struct vbo_context *vbo = vbo_context(ctx); 146 struct vbo_exec_context *exec = &vbo->exec; 147 struct gl_client_array *arrays = exec->vtx.arrays; 148 GLuint count = exec->vtx.vert_count; 149 GLubyte *data = exec->vtx.buffer_map; 150 const GLuint *map; 151 GLuint attr; 152 153 /* Install the default (ie Current) attributes first, then overlay 154 * all active ones. 155 */ 156 switch (get_program_mode(exec->ctx)) { 157 case VP_NONE: 158 memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); 159 memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); 160 map = vbo->map_vp_none; 161 break; 162 case VP_NV: 163 case VP_ARB: 164 /* The aliasing of attributes for NV vertex programs has already 165 * occurred. NV vertex programs cannot access material values, 166 * nor attributes greater than VERT_ATTRIB_TEX7. 167 */ 168 memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); 169 memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); 170 map = vbo->map_vp_arb; 171 break; 172 } 173 174 /* Make all active attributes (including edgeflag) available as 175 * arrays of floats. 176 */ 177 for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) { 178 GLuint src = map[attr]; 179 180 if (exec->vtx.attrsz[src]) { 181 arrays[attr].Ptr = (void *)data; 182 arrays[attr].Size = exec->vtx.attrsz[src]; 183 arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); 184 arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); 185 arrays[attr].Type = GL_FLOAT; 186 arrays[attr].Enabled = 1; 187 arrays[attr].BufferObj = exec->vtx.bufferobj; /* NullBufferObj */ 188 arrays[attr]._MaxElement = count; /* ??? */ 189 190 data += exec->vtx.attrsz[attr] * sizeof(GLfloat); 191 } 192 } 193} 194 195 196/** 197 * Execute the buffer and save copied verts. 198 */ 199void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) 200{ 201 if (0) 202 vbo_exec_debug_verts( exec ); 203 204 205 if (exec->vtx.prim_count && 206 exec->vtx.vert_count) { 207 208 exec->vtx.copied.nr = vbo_copy_vertices( exec ); 209 210 if (exec->vtx.copied.nr != exec->vtx.vert_count) { 211 GLcontext *ctx = exec->ctx; 212 213 vbo_exec_bind_arrays( ctx ); 214 215 vbo_context(ctx)->draw_prims( ctx, 216 exec->vtx.inputs, 217 exec->vtx.prim, 218 exec->vtx.prim_count, 219 NULL, 220 0, 221 exec->vtx.vert_count - 1); 222 } 223 } 224 225 exec->vtx.prim_count = 0; 226 exec->vtx.vert_count = 0; 227 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; 228} 229