vbo_exec_api.c revision 4e9c8166b064de4eed38e385880cd491e6d8d9c4
1/************************************************************************** 2 3Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. 4 5All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a 8copy of this software and associated documentation files (the "Software"), 9to deal in the Software without restriction, including without limitation 10on the rights to use, copy, modify, merge, publish, distribute, sub 11license, and/or sell copies of the Software, and to permit persons to whom 12the Software is furnished to do so, subject to the following conditions: 13 14The above copyright notice and this permission notice (including the next 15paragraph) shall be included in all copies or substantial portions of the 16Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24USE OR OTHER DEALINGS IN THE SOFTWARE. 25 26**************************************************************************/ 27 28/* 29 * Authors: 30 * Keith Whitwell <keith@tungstengraphics.com> 31 */ 32 33#include "main/glheader.h" 34#include "main/context.h" 35#include "main/macros.h" 36#include "main/vtxfmt.h" 37#include "main/dlist.h" 38#include "main/state.h" 39#include "main/light.h" 40#include "main/api_arrayelt.h" 41#include "main/api_noop.h" 42#include "glapi/dispatch.h" 43 44#include "vbo_context.h" 45 46#ifdef ERROR 47#undef ERROR 48#endif 49 50 51static void reset_attrfv( struct vbo_exec_context *exec ); 52 53 54/* Close off the last primitive, execute the buffer, restart the 55 * primitive. 56 */ 57static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) 58{ 59 if (exec->vtx.prim_count == 0) { 60 exec->vtx.copied.nr = 0; 61 exec->vtx.vert_count = 0; 62 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; 63 } 64 else { 65 GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin; 66 GLuint last_count; 67 68 if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { 69 GLint i = exec->vtx.prim_count - 1; 70 assert(i >= 0); 71 exec->vtx.prim[i].count = (exec->vtx.vert_count - 72 exec->vtx.prim[i].start); 73 } 74 75 last_count = exec->vtx.prim[exec->vtx.prim_count-1].count; 76 77 /* Execute the buffer and save copied vertices. 78 */ 79 if (exec->vtx.vert_count) 80 vbo_exec_vtx_flush( exec ); 81 else { 82 exec->vtx.prim_count = 0; 83 exec->vtx.copied.nr = 0; 84 } 85 86 /* Emit a glBegin to start the new list. 87 */ 88 assert(exec->vtx.prim_count == 0); 89 90 if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { 91 exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive; 92 exec->vtx.prim[0].start = 0; 93 exec->vtx.prim[0].count = 0; 94 exec->vtx.prim_count++; 95 96 if (exec->vtx.copied.nr == last_count) 97 exec->vtx.prim[0].begin = last_begin; 98 } 99 } 100} 101 102 103/* Deal with buffer wrapping where provoked by the vertex buffer 104 * filling up, as opposed to upgrade_vertex(). 105 */ 106void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) 107{ 108 GLfloat *data = exec->vtx.copied.buffer; 109 GLuint i; 110 111 /* Run pipeline on current vertices, copy wrapped vertices 112 * to exec->vtx.copied. 113 */ 114 vbo_exec_wrap_buffers( exec ); 115 116 /* Copy stored stored vertices to start of new list. 117 */ 118 assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); 119 120 for (i = 0 ; i < exec->vtx.copied.nr ; i++) { 121 _mesa_memcpy( exec->vtx.vbptr, data, 122 exec->vtx.vertex_size * sizeof(GLfloat)); 123 exec->vtx.vbptr += exec->vtx.vertex_size; 124 data += exec->vtx.vertex_size; 125 exec->vtx.vert_count++; 126 } 127 128 exec->vtx.copied.nr = 0; 129} 130 131 132/* 133 * Copy the active vertex's values to the ctx->Current fields. 134 */ 135static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) 136{ 137 GLcontext *ctx = exec->ctx; 138 struct vbo_context *vbo = vbo_context(ctx); 139 GLuint i; 140 141 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { 142 if (exec->vtx.attrsz[i]) { 143 GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; 144 145 /* Note: the exec->vtx.current[i] pointers point into the 146 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. 147 */ 148 COPY_CLEAN_4V(current, 149 exec->vtx.attrsz[i], 150 exec->vtx.attrptr[i]); 151 152 153 /* Given that we explicitly state size here, there is no need 154 * for the COPY_CLEAN above, could just copy 16 bytes and be 155 * done. The only problem is when Mesa accesses ctx->Current 156 * directly. 157 */ 158 vbo->currval[i].Size = exec->vtx.attrsz[i]; 159 160 /* This triggers rather too much recalculation of Mesa state 161 * that doesn't get used (eg light positions). 162 */ 163 if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && 164 i <= VBO_ATTRIB_MAT_BACK_INDEXES) 165 ctx->NewState |= _NEW_LIGHT; 166 } 167 } 168 169 /* Colormaterial -- this kindof sucks. 170 */ 171 if (ctx->Light.ColorMaterialEnabled && 172 exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) { 173 _mesa_update_color_material(ctx, 174 ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); 175 } 176 177 ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; 178} 179 180 181static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) 182{ 183 GLcontext *ctx = exec->ctx; 184 struct vbo_context *vbo = vbo_context(ctx); 185 GLint i; 186 187 for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { 188 const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; 189 switch (exec->vtx.attrsz[i]) { 190 case 4: exec->vtx.attrptr[i][3] = current[3]; 191 case 3: exec->vtx.attrptr[i][2] = current[2]; 192 case 2: exec->vtx.attrptr[i][1] = current[1]; 193 case 1: exec->vtx.attrptr[i][0] = current[0]; 194 break; 195 } 196 } 197 198 ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; 199} 200 201 202/* Flush existing data, set new attrib size, replay copied vertices. 203 */ 204static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, 205 GLuint attr, 206 GLuint newsz ) 207{ 208 GLcontext *ctx = exec->ctx; 209 struct vbo_context *vbo = vbo_context(ctx); 210 GLint lastcount = exec->vtx.vert_count; 211 GLfloat *tmp; 212 GLuint oldsz; 213 GLuint i; 214 215 /* Run pipeline on current vertices, copy wrapped vertices 216 * to exec->vtx.copied. 217 */ 218 vbo_exec_wrap_buffers( exec ); 219 220 221 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case 222 * when the attribute already exists in the vertex and is having 223 * its size increased. 224 */ 225 vbo_exec_copy_to_current( exec ); 226 227 228 /* Heuristic: Attempt to isolate attributes received outside 229 * begin/end so that they don't bloat the vertices. 230 */ 231 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && 232 exec->vtx.attrsz[attr] == 0 && 233 lastcount > 8 && 234 exec->vtx.vertex_size) { 235 reset_attrfv( exec ); 236 } 237 238 /* Fix up sizes: 239 */ 240 oldsz = exec->vtx.attrsz[attr]; 241 exec->vtx.attrsz[attr] = newsz; 242 243 exec->vtx.vertex_size += newsz - oldsz; 244 exec->vtx.max_vert = VBO_VERT_BUFFER_SIZE / exec->vtx.vertex_size; 245 exec->vtx.vert_count = 0; 246 exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; 247 248 249 /* Recalculate all the attrptr[] values 250 */ 251 for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) { 252 if (exec->vtx.attrsz[i]) { 253 exec->vtx.attrptr[i] = tmp; 254 tmp += exec->vtx.attrsz[i]; 255 } 256 else 257 exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ 258 } 259 260 /* Copy from current to repopulate the vertex with correct values. 261 */ 262 vbo_exec_copy_from_current( exec ); 263 264 /* Replay stored vertices to translate them 265 * to new format here. 266 * 267 * -- No need to replay - just copy piecewise 268 */ 269 if (exec->vtx.copied.nr) 270 { 271 GLfloat *data = exec->vtx.copied.buffer; 272 GLfloat *dest = exec->vtx.vbptr; 273 GLuint j; 274 275 assert(exec->vtx.vbptr == (GLfloat *)exec->vtx.buffer_map); 276 277 for (i = 0 ; i < exec->vtx.copied.nr ; i++) { 278 for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { 279 if (exec->vtx.attrsz[j]) { 280 if (j == attr) { 281 if (oldsz) { 282 COPY_CLEAN_4V( dest, oldsz, data ); 283 data += oldsz; 284 dest += newsz; 285 } else { 286 const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr; 287 COPY_SZ_4V( dest, newsz, current ); 288 dest += newsz; 289 } 290 } 291 else { 292 GLuint sz = exec->vtx.attrsz[j]; 293 COPY_SZ_4V( dest, sz, data ); 294 dest += sz; 295 data += sz; 296 } 297 } 298 } 299 } 300 301 exec->vtx.vbptr = dest; 302 exec->vtx.vert_count += exec->vtx.copied.nr; 303 exec->vtx.copied.nr = 0; 304 } 305} 306 307 308static void vbo_exec_fixup_vertex( GLcontext *ctx, 309 GLuint attr, GLuint sz ) 310{ 311 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 312 int i; 313 314 if (sz > exec->vtx.attrsz[attr]) { 315 /* New size is larger. Need to flush existing vertices and get 316 * an enlarged vertex format. 317 */ 318 vbo_exec_wrap_upgrade_vertex( exec, attr, sz ); 319 } 320 else if (sz < exec->vtx.active_sz[attr]) { 321 static const GLfloat id[4] = { 0, 0, 0, 1 }; 322 323 /* New size is smaller - just need to fill in some 324 * zeros. Don't need to flush or wrap. 325 */ 326 for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++) 327 exec->vtx.attrptr[attr][i-1] = id[i-1]; 328 } 329 330 exec->vtx.active_sz[attr] = sz; 331 332 /* Does setting NeedFlush belong here? Necessitates resetting 333 * vtxfmt on each flush (otherwise flags won't get reset 334 * afterwards). 335 */ 336 if (attr == 0) 337 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; 338 else 339 exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; 340} 341 342 343 344 345/* 346 */ 347#define ATTR( A, N, V0, V1, V2, V3 ) \ 348do { \ 349 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ 350 \ 351 if (exec->vtx.active_sz[A] != N) \ 352 vbo_exec_fixup_vertex(ctx, A, N); \ 353 \ 354 { \ 355 GLfloat *dest = exec->vtx.attrptr[A]; \ 356 if (N>0) dest[0] = V0; \ 357 if (N>1) dest[1] = V1; \ 358 if (N>2) dest[2] = V2; \ 359 if (N>3) dest[3] = V3; \ 360 } \ 361 \ 362 if ((A) == 0) { \ 363 GLuint i; \ 364 \ 365 for (i = 0; i < exec->vtx.vertex_size; i++) \ 366 exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \ 367 \ 368 exec->vtx.vbptr += exec->vtx.vertex_size; \ 369 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ 370 \ 371 if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ 372 vbo_exec_vtx_wrap( exec ); \ 373 } \ 374} while (0) 375 376 377#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ) 378#define TAG(x) vbo_##x 379 380#include "vbo_attrib_tmp.h" 381 382 383 384 385 386/* Eval 387 */ 388static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u ) 389{ 390 GET_CURRENT_CONTEXT( ctx ); 391 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 392 393 { 394 GLint i; 395 if (exec->eval.recalculate_maps) 396 vbo_exec_eval_update( exec ); 397 398 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { 399 if (exec->eval.map1[i].map) 400 if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz) 401 vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz ); 402 } 403 } 404 405 406 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, 407 exec->vtx.vertex_size * sizeof(GLfloat)); 408 409 vbo_exec_do_EvalCoord1f( exec, u ); 410 411 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, 412 exec->vtx.vertex_size * sizeof(GLfloat)); 413} 414 415static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v ) 416{ 417 GET_CURRENT_CONTEXT( ctx ); 418 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 419 420 { 421 GLint i; 422 if (exec->eval.recalculate_maps) 423 vbo_exec_eval_update( exec ); 424 425 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { 426 if (exec->eval.map2[i].map) 427 if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz) 428 vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz ); 429 } 430 431 if (ctx->Eval.AutoNormal) 432 if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3) 433 vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 ); 434 } 435 436 _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, 437 exec->vtx.vertex_size * sizeof(GLfloat)); 438 439 vbo_exec_do_EvalCoord2f( exec, u, v ); 440 441 _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, 442 exec->vtx.vertex_size * sizeof(GLfloat)); 443} 444 445static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u ) 446{ 447 vbo_exec_EvalCoord1f( u[0] ); 448} 449 450static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u ) 451{ 452 vbo_exec_EvalCoord2f( u[0], u[1] ); 453} 454 455static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i ) 456{ 457 GET_CURRENT_CONTEXT( ctx ); 458 GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) / 459 (GLfloat) ctx->Eval.MapGrid1un); 460 GLfloat u = i * du + ctx->Eval.MapGrid1u1; 461 462 vbo_exec_EvalCoord1f( u ); 463} 464 465 466static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) 467{ 468 GET_CURRENT_CONTEXT( ctx ); 469 GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / 470 (GLfloat) ctx->Eval.MapGrid2un); 471 GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / 472 (GLfloat) ctx->Eval.MapGrid2vn); 473 GLfloat u = i * du + ctx->Eval.MapGrid2u1; 474 GLfloat v = j * dv + ctx->Eval.MapGrid2v1; 475 476 vbo_exec_EvalCoord2f( u, v ); 477} 478 479 480/** 481 * Check if programs/shaders are enabled and valid at glBegin time. 482 */ 483GLboolean 484vbo_validate_shaders(GLcontext *ctx) 485{ 486 if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) || 487 (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) { 488 return GL_FALSE; 489 } 490 if (ctx->Shader.CurrentProgram && !ctx->Shader.CurrentProgram->LinkStatus) { 491 return GL_FALSE; 492 } 493 return GL_TRUE; 494} 495 496 497/* Build a list of primitives on the fly. Keep 498 * ctx->Driver.CurrentExecPrimitive uptodate as well. 499 */ 500static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) 501{ 502 GET_CURRENT_CONTEXT( ctx ); 503 504 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { 505 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 506 int i; 507 508 if (ctx->NewState) { 509 _mesa_update_state( ctx ); 510 511 CALL_Begin(ctx->Exec, (mode)); 512 return; 513 } 514 515 if (!vbo_validate_shaders(ctx)) { 516 _mesa_error(ctx, GL_INVALID_OPERATION, 517 "glBegin (invalid vertex/fragment program)"); 518 return; 519 } 520 521 /* Heuristic: attempt to isolate attributes occuring outside 522 * begin/end pairs. 523 */ 524 if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) 525 vbo_exec_FlushVertices( ctx, ~0 ); 526 527 i = exec->vtx.prim_count++; 528 exec->vtx.prim[i].mode = mode; 529 exec->vtx.prim[i].begin = 1; 530 exec->vtx.prim[i].end = 0; 531 exec->vtx.prim[i].indexed = 0; 532 exec->vtx.prim[i].weak = 0; 533 exec->vtx.prim[i].pad = 0; 534 exec->vtx.prim[i].start = exec->vtx.vert_count; 535 exec->vtx.prim[i].count = 0; 536 537 ctx->Driver.CurrentExecPrimitive = mode; 538 } 539 else 540 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); 541 542} 543 544static void GLAPIENTRY vbo_exec_End( void ) 545{ 546 GET_CURRENT_CONTEXT( ctx ); 547 548 if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { 549 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 550 int idx = exec->vtx.vert_count; 551 int i = exec->vtx.prim_count - 1; 552 553 exec->vtx.prim[i].end = 1; 554 exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; 555 556 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; 557 558 if (exec->vtx.prim_count == VBO_MAX_PRIM) 559 vbo_exec_vtx_flush( exec ); 560 } 561 else 562 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); 563} 564 565 566static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) 567{ 568 GLvertexformat *vfmt = &exec->vtxfmt; 569 570 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ 571 vfmt->Begin = vbo_exec_Begin; 572 vfmt->CallList = _mesa_CallList; 573 vfmt->CallLists = _mesa_CallLists; 574 vfmt->End = vbo_exec_End; 575 vfmt->EvalCoord1f = vbo_exec_EvalCoord1f; 576 vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv; 577 vfmt->EvalCoord2f = vbo_exec_EvalCoord2f; 578 vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv; 579 vfmt->EvalPoint1 = vbo_exec_EvalPoint1; 580 vfmt->EvalPoint2 = vbo_exec_EvalPoint2; 581 582 vfmt->Rectf = _mesa_noop_Rectf; 583 vfmt->EvalMesh1 = _mesa_noop_EvalMesh1; 584 vfmt->EvalMesh2 = _mesa_noop_EvalMesh2; 585 586 587 /* from attrib_tmp.h: 588 */ 589 vfmt->Color3f = vbo_Color3f; 590 vfmt->Color3fv = vbo_Color3fv; 591 vfmt->Color4f = vbo_Color4f; 592 vfmt->Color4fv = vbo_Color4fv; 593 vfmt->FogCoordfEXT = vbo_FogCoordfEXT; 594 vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT; 595 vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f; 596 vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv; 597 vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f; 598 vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv; 599 vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f; 600 vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv; 601 vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f; 602 vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv; 603 vfmt->Normal3f = vbo_Normal3f; 604 vfmt->Normal3fv = vbo_Normal3fv; 605 vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT; 606 vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT; 607 vfmt->TexCoord1f = vbo_TexCoord1f; 608 vfmt->TexCoord1fv = vbo_TexCoord1fv; 609 vfmt->TexCoord2f = vbo_TexCoord2f; 610 vfmt->TexCoord2fv = vbo_TexCoord2fv; 611 vfmt->TexCoord3f = vbo_TexCoord3f; 612 vfmt->TexCoord3fv = vbo_TexCoord3fv; 613 vfmt->TexCoord4f = vbo_TexCoord4f; 614 vfmt->TexCoord4fv = vbo_TexCoord4fv; 615 vfmt->Vertex2f = vbo_Vertex2f; 616 vfmt->Vertex2fv = vbo_Vertex2fv; 617 vfmt->Vertex3f = vbo_Vertex3f; 618 vfmt->Vertex3fv = vbo_Vertex3fv; 619 vfmt->Vertex4f = vbo_Vertex4f; 620 vfmt->Vertex4fv = vbo_Vertex4fv; 621 622 vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB; 623 vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB; 624 vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB; 625 vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB; 626 vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB; 627 vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB; 628 vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB; 629 vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB; 630 631 vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV; 632 vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV; 633 vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV; 634 vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV; 635 vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV; 636 vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV; 637 vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV; 638 vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV; 639 640 vfmt->Materialfv = vbo_Materialfv; 641 642 vfmt->EdgeFlag = vbo_EdgeFlag; 643 vfmt->Indexf = vbo_Indexf; 644 vfmt->Indexfv = vbo_Indexfv; 645 646} 647 648 649void vbo_exec_vtx_init( struct vbo_exec_context *exec ) 650{ 651 GLcontext *ctx = exec->ctx; 652 struct vbo_context *vbo = vbo_context(ctx); 653 GLuint i; 654 655 /* Allocate a buffer object. Will just reuse this object 656 * continuously. 657 */ 658 exec->vtx.bufferobj = ctx->Array.NullBufferObj; 659 exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64); 660 661 vbo_exec_vtxfmt_init( exec ); 662 663 /* Hook our functions into the dispatch table. 664 */ 665 _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); 666 667 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { 668 exec->vtx.attrsz[i] = 0; 669 exec->vtx.active_sz[i] = 0; 670 exec->vtx.inputs[i] = &exec->vtx.arrays[i]; 671 } 672 673 { 674 struct gl_client_array *arrays = exec->vtx.arrays; 675 memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); 676 memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); 677 } 678 679 exec->vtx.vertex_size = 0; 680} 681 682 683void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) 684{ 685 if (exec->vtx.buffer_map) { 686 ALIGN_FREE(exec->vtx.buffer_map); 687 exec->vtx.buffer_map = NULL; 688 } 689} 690 691 692void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) 693{ 694 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 695 696 if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) 697 return; 698 699 if (exec->vtx.vert_count) { 700 vbo_exec_vtx_flush( exec ); 701 } 702 703 if (exec->vtx.vertex_size) { 704 vbo_exec_copy_to_current( exec ); 705 reset_attrfv( exec ); 706 } 707 708 exec->ctx->Driver.NeedFlush = 0; 709} 710 711 712static void reset_attrfv( struct vbo_exec_context *exec ) 713{ 714 GLuint i; 715 716 for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { 717 exec->vtx.attrsz[i] = 0; 718 exec->vtx.active_sz[i] = 0; 719 } 720 721 exec->vtx.vertex_size = 0; 722} 723 724