vbo_exec_array.c revision fd4a3d463c103192311aacc04f5f871f4a1035df
1/************************************************************************** 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * Copyright 2009 VMware, Inc. 5 * 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 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29#include "main/glheader.h" 30#include "main/context.h" 31#include "main/state.h" 32#include "main/api_validate.h" 33#include "main/varray.h" 34#include "main/bufferobj.h" 35#include "main/enums.h" 36#include "main/macros.h" 37#include "main/transformfeedback.h" 38 39#include "vbo_context.h" 40 41 42/** 43 * All vertex buffers should be in an unmapped state when we're about 44 * to draw. This debug function checks that. 45 */ 46static void 47check_buffers_are_unmapped(const struct gl_client_array **inputs) 48{ 49#ifdef DEBUG 50 GLuint i; 51 52 for (i = 0; i < VERT_ATTRIB_MAX; i++) { 53 if (inputs[i]) { 54 struct gl_buffer_object *obj = inputs[i]->BufferObj; 55 assert(!_mesa_bufferobj_mapped(obj)); 56 (void) obj; 57 } 58 } 59#endif 60} 61 62 63/** 64 * A debug function that may be called from other parts of Mesa as 65 * needed during debugging. 66 */ 67void 68vbo_check_buffers_are_unmapped(struct gl_context *ctx) 69{ 70 struct vbo_context *vbo = vbo_context(ctx); 71 struct vbo_exec_context *exec = &vbo->exec; 72 /* check the current vertex arrays */ 73 check_buffers_are_unmapped(exec->array.inputs); 74 /* check the current glBegin/glVertex/glEnd-style VBO */ 75 assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj)); 76} 77 78 79 80/** 81 * Compute min and max elements by scanning the index buffer for 82 * glDraw[Range]Elements() calls. 83 * If primitive restart is enabled, we need to ignore restart 84 * indexes when computing min/max. 85 */ 86static void 87vbo_get_minmax_index(struct gl_context *ctx, 88 const struct _mesa_prim *prim, 89 const struct _mesa_index_buffer *ib, 90 GLuint *min_index, GLuint *max_index, 91 const GLuint count) 92{ 93 const GLboolean restart = ctx->Array.PrimitiveRestart; 94 const GLuint restartIndex = ctx->Array.RestartIndex; 95 const int index_size = vbo_sizeof_ib_type(ib->type); 96 const char *indices; 97 GLuint i; 98 99 indices = (char *) ib->ptr + prim->start * index_size; 100 if (_mesa_is_bufferobj(ib->obj)) { 101 GLsizeiptr size = MIN2(count * index_size, ib->obj->Size); 102 indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size, 103 GL_MAP_READ_BIT, ib->obj); 104 } 105 106 switch (ib->type) { 107 case GL_UNSIGNED_INT: { 108 const GLuint *ui_indices = (const GLuint *)indices; 109 GLuint max_ui = 0; 110 GLuint min_ui = ~0U; 111 if (restart) { 112 for (i = 0; i < count; i++) { 113 if (ui_indices[i] != restartIndex) { 114 if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; 115 if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; 116 } 117 } 118 } 119 else { 120 for (i = 0; i < count; i++) { 121 if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; 122 if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; 123 } 124 } 125 *min_index = min_ui; 126 *max_index = max_ui; 127 break; 128 } 129 case GL_UNSIGNED_SHORT: { 130 const GLushort *us_indices = (const GLushort *)indices; 131 GLuint max_us = 0; 132 GLuint min_us = ~0U; 133 if (restart) { 134 for (i = 0; i < count; i++) { 135 if (us_indices[i] != restartIndex) { 136 if (us_indices[i] > max_us) max_us = us_indices[i]; 137 if (us_indices[i] < min_us) min_us = us_indices[i]; 138 } 139 } 140 } 141 else { 142 for (i = 0; i < count; i++) { 143 if (us_indices[i] > max_us) max_us = us_indices[i]; 144 if (us_indices[i] < min_us) min_us = us_indices[i]; 145 } 146 } 147 *min_index = min_us; 148 *max_index = max_us; 149 break; 150 } 151 case GL_UNSIGNED_BYTE: { 152 const GLubyte *ub_indices = (const GLubyte *)indices; 153 GLuint max_ub = 0; 154 GLuint min_ub = ~0U; 155 if (restart) { 156 for (i = 0; i < count; i++) { 157 if (ub_indices[i] != restartIndex) { 158 if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; 159 if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; 160 } 161 } 162 } 163 else { 164 for (i = 0; i < count; i++) { 165 if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; 166 if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; 167 } 168 } 169 *min_index = min_ub; 170 *max_index = max_ub; 171 break; 172 } 173 default: 174 assert(0); 175 break; 176 } 177 178 if (_mesa_is_bufferobj(ib->obj)) { 179 ctx->Driver.UnmapBuffer(ctx, ib->obj); 180 } 181} 182 183/** 184 * Compute min and max elements for nr_prims 185 */ 186void 187vbo_get_minmax_indices(struct gl_context *ctx, 188 const struct _mesa_prim *prims, 189 const struct _mesa_index_buffer *ib, 190 GLuint *min_index, 191 GLuint *max_index, 192 GLuint nr_prims) 193{ 194 GLuint tmp_min, tmp_max; 195 GLuint i; 196 GLuint count; 197 198 *min_index = ~0; 199 *max_index = 0; 200 201 for (i = 0; i < nr_prims; i++) { 202 const struct _mesa_prim *start_prim; 203 204 start_prim = &prims[i]; 205 count = start_prim->count; 206 /* Do combination if possible to reduce map/unmap count */ 207 while ((i + 1 < nr_prims) && 208 (prims[i].start + prims[i].count == prims[i+1].start)) { 209 count += prims[i+1].count; 210 i++; 211 } 212 vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count); 213 *min_index = MIN2(*min_index, tmp_min); 214 *max_index = MAX2(*max_index, tmp_max); 215 } 216} 217 218 219/** 220 * Check that element 'j' of the array has reasonable data. 221 * Map VBO if needed. 222 * For debugging purposes; not normally used. 223 */ 224static void 225check_array_data(struct gl_context *ctx, struct gl_client_array *array, 226 GLuint attrib, GLuint j) 227{ 228 if (array->Enabled) { 229 const void *data = array->Ptr; 230 if (_mesa_is_bufferobj(array->BufferObj)) { 231 if (!array->BufferObj->Pointer) { 232 /* need to map now */ 233 array->BufferObj->Pointer = 234 ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size, 235 GL_MAP_READ_BIT, array->BufferObj); 236 } 237 data = ADD_POINTERS(data, array->BufferObj->Pointer); 238 } 239 switch (array->Type) { 240 case GL_FLOAT: 241 { 242 GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j); 243 GLint k; 244 for (k = 0; k < array->Size; k++) { 245 if (IS_INF_OR_NAN(f[k]) || 246 f[k] >= 1.0e20 || f[k] <= -1.0e10) { 247 printf("Bad array data:\n"); 248 printf(" Element[%u].%u = %f\n", j, k, f[k]); 249 printf(" Array %u at %p\n", attrib, (void* ) array); 250 printf(" Type 0x%x, Size %d, Stride %d\n", 251 array->Type, array->Size, array->Stride); 252 printf(" Address/offset %p in Buffer Object %u\n", 253 array->Ptr, array->BufferObj->Name); 254 f[k] = 1.0; /* XXX replace the bad value! */ 255 } 256 /*assert(!IS_INF_OR_NAN(f[k]));*/ 257 } 258 } 259 break; 260 default: 261 ; 262 } 263 } 264} 265 266 267/** 268 * Unmap the buffer object referenced by given array, if mapped. 269 */ 270static void 271unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array) 272{ 273 if (array->Enabled && 274 _mesa_is_bufferobj(array->BufferObj) && 275 _mesa_bufferobj_mapped(array->BufferObj)) { 276 ctx->Driver.UnmapBuffer(ctx, array->BufferObj); 277 } 278} 279 280 281/** 282 * Examine the array's data for NaNs, etc. 283 * For debug purposes; not normally used. 284 */ 285static void 286check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType, 287 const void *elements, GLint basevertex) 288{ 289 struct gl_array_object *arrayObj = ctx->Array.ArrayObj; 290 const void *elemMap; 291 GLint i, k; 292 293 if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) { 294 elemMap = ctx->Driver.MapBufferRange(ctx, 0, 295 ctx->Array.ArrayObj->ElementArrayBufferObj->Size, 296 GL_MAP_READ_BIT, 297 ctx->Array.ArrayObj->ElementArrayBufferObj); 298 elements = ADD_POINTERS(elements, elemMap); 299 } 300 301 for (i = 0; i < count; i++) { 302 GLuint j; 303 304 /* j = element[i] */ 305 switch (elemType) { 306 case GL_UNSIGNED_BYTE: 307 j = ((const GLubyte *) elements)[i]; 308 break; 309 case GL_UNSIGNED_SHORT: 310 j = ((const GLushort *) elements)[i]; 311 break; 312 case GL_UNSIGNED_INT: 313 j = ((const GLuint *) elements)[i]; 314 break; 315 default: 316 assert(0); 317 } 318 319 /* check element j of each enabled array */ 320 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) { 321 check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j); 322 } 323 } 324 325 if (_mesa_is_bufferobj(arrayObj->ElementArrayBufferObj)) { 326 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj); 327 } 328 329 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) { 330 unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]); 331 } 332} 333 334 335/** 336 * Check array data, looking for NaNs, etc. 337 */ 338static void 339check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count) 340{ 341 /* TO DO */ 342} 343 344 345/** 346 * Print info/data for glDrawArrays(), for debugging. 347 */ 348static void 349print_draw_arrays(struct gl_context *ctx, 350 GLenum mode, GLint start, GLsizei count) 351{ 352 struct vbo_context *vbo = vbo_context(ctx); 353 struct vbo_exec_context *exec = &vbo->exec; 354 struct gl_array_object *arrayObj = ctx->Array.ArrayObj; 355 int i; 356 357 printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n", 358 mode, start, count); 359 360 for (i = 0; i < 32; i++) { 361 struct gl_buffer_object *bufObj = exec->array.inputs[i]->BufferObj; 362 GLuint bufName = bufObj->Name; 363 GLint stride = exec->array.inputs[i]->Stride; 364 printf("attr %2d: size %d stride %d enabled %d " 365 "ptr %p Bufobj %u\n", 366 i, 367 exec->array.inputs[i]->Size, 368 stride, 369 /*exec->array.inputs[i]->Enabled,*/ 370 arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)].Enabled, 371 exec->array.inputs[i]->Ptr, 372 bufName); 373 374 if (bufName) { 375 GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, 376 GL_MAP_READ_BIT, bufObj); 377 int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr; 378 float *f = (float *) (p + offset); 379 int *k = (int *) f; 380 int i; 381 int n = (count * stride) / 4; 382 if (n > 32) 383 n = 32; 384 printf(" Data at offset %d:\n", offset); 385 for (i = 0; i < n; i++) { 386 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); 387 } 388 ctx->Driver.UnmapBuffer(ctx, bufObj); 389 } 390 } 391} 392 393 394/** 395 * Set the vbo->exec->inputs[] pointers to point to the enabled 396 * vertex arrays. This depends on the current vertex program/shader 397 * being executed because of whether or not generic vertex arrays 398 * alias the conventional vertex arrays. 399 * For arrays that aren't enabled, we set the input[attrib] pointer 400 * to point at a zero-stride current value "array". 401 */ 402static void 403recalculate_input_bindings(struct gl_context *ctx) 404{ 405 struct vbo_context *vbo = vbo_context(ctx); 406 struct vbo_exec_context *exec = &vbo->exec; 407 struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib; 408 const struct gl_client_array **inputs = &exec->array.inputs[0]; 409 GLbitfield64 const_inputs = 0x0; 410 GLuint i; 411 412 switch (get_program_mode(ctx)) { 413 case VP_NONE: 414 /* When no vertex program is active (or the vertex program is generated 415 * from fixed-function state). We put the material values into the 416 * generic slots. This is the only situation where material values 417 * are available as per-vertex attributes. 418 */ 419 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) { 420 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) 421 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; 422 else { 423 inputs[i] = &vbo->legacy_currval[i]; 424 const_inputs |= VERT_BIT(i); 425 } 426 } 427 428 for (i = 0; i < MAT_ATTRIB_MAX; i++) { 429 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->mat_currval[i]; 430 const_inputs |= VERT_BIT_GENERIC(i); 431 } 432 433 /* Could use just about anything, just to fill in the empty 434 * slots: 435 */ 436 for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) { 437 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i]; 438 const_inputs |= VERT_BIT_GENERIC(i); 439 } 440 441 /* There is no need to make _NEW_ARRAY dirty here for the TnL program, 442 * because it already takes care of invalidating the state necessary 443 * to revalidate vertex arrays. Not marking the state as dirty also 444 * improves performance (quite significantly in some apps). 445 */ 446 if (!ctx->VertexProgram._MaintainTnlProgram) 447 ctx->NewState |= _NEW_ARRAY; 448 break; 449 450 case VP_NV: 451 /* NV_vertex_program - attribute arrays alias and override 452 * conventional, legacy arrays. No materials, and the generic 453 * slots are vacant. 454 */ 455 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) { 456 if (i < VERT_ATTRIB_GENERIC_MAX 457 && vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) 458 inputs[i] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; 459 else if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) 460 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; 461 else { 462 inputs[i] = &vbo->legacy_currval[i]; 463 const_inputs |= VERT_BIT_FF(i); 464 } 465 } 466 467 /* Could use just about anything, just to fill in the empty 468 * slots: 469 */ 470 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) { 471 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i]; 472 const_inputs |= VERT_BIT_GENERIC(i); 473 } 474 475 ctx->NewState |= _NEW_ARRAY; 476 break; 477 478 case VP_ARB: 479 /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0] 480 * attribute array aliases and overrides the legacy position array. 481 * 482 * Otherwise, legacy attributes available in the legacy slots, 483 * generic attributes in the generic slots and materials are not 484 * available as per-vertex attributes. 485 */ 486 if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) 487 inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0]; 488 else if (vertexAttrib[VERT_ATTRIB_POS].Enabled) 489 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS]; 490 else { 491 inputs[0] = &vbo->legacy_currval[0]; 492 const_inputs |= VERT_BIT_POS; 493 } 494 495 for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) { 496 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) 497 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; 498 else { 499 inputs[i] = &vbo->legacy_currval[i]; 500 const_inputs |= VERT_BIT_FF(i); 501 } 502 } 503 504 for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { 505 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) 506 inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; 507 else { 508 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i]; 509 const_inputs |= VERT_BIT_GENERIC(i); 510 } 511 } 512 513 inputs[VERT_ATTRIB_GENERIC0] = inputs[0]; 514 ctx->NewState |= _NEW_ARRAY; 515 break; 516 } 517 518 _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) ); 519} 520 521 522/** 523 * Examine the enabled vertex arrays to set the exec->array.inputs[] values. 524 * These will point to the arrays to actually use for drawing. Some will 525 * be user-provided arrays, other will be zero-stride const-valued arrays. 526 * Note that this might set the _NEW_ARRAY dirty flag so state validation 527 * must be done after this call. 528 */ 529void 530vbo_bind_arrays(struct gl_context *ctx) 531{ 532 if (!ctx->Array.RebindArrays) { 533 return; 534 } 535 536 recalculate_input_bindings(ctx); 537 ctx->Array.RebindArrays = GL_FALSE; 538} 539 540 541/** 542 * Helper function called by the other DrawArrays() functions below. 543 * This is where we handle primitive restart for drawing non-indexed 544 * arrays. If primitive restart is enabled, it typically means 545 * splitting one DrawArrays() into two. 546 */ 547static void 548vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, 549 GLsizei count, GLuint numInstances) 550{ 551 struct vbo_context *vbo = vbo_context(ctx); 552 struct vbo_exec_context *exec = &vbo->exec; 553 struct _mesa_prim prim[2]; 554 555 vbo_bind_arrays(ctx); 556 557 vbo_draw_method(exec, DRAW_ARRAYS); 558 559 /* Again... because we may have changed the bitmask of per-vertex varying 560 * attributes. If we regenerate the fixed-function vertex program now 561 * we may be able to prune down the number of vertex attributes which we 562 * need in the shader. 563 */ 564 if (ctx->NewState) 565 _mesa_update_state(ctx); 566 567 /* init most fields to zero */ 568 memset(prim, 0, sizeof(prim)); 569 prim[0].begin = 1; 570 prim[0].end = 1; 571 prim[0].mode = mode; 572 prim[0].num_instances = numInstances; 573 574 /* Implement the primitive restart index */ 575 if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) { 576 GLuint primCount = 0; 577 578 if (ctx->Array.RestartIndex == start) { 579 /* special case: RestartIndex at beginning */ 580 if (count > 1) { 581 prim[0].start = start + 1; 582 prim[0].count = count - 1; 583 primCount = 1; 584 } 585 } 586 else if (ctx->Array.RestartIndex == start + count - 1) { 587 /* special case: RestartIndex at end */ 588 if (count > 1) { 589 prim[0].start = start; 590 prim[0].count = count - 1; 591 primCount = 1; 592 } 593 } 594 else { 595 /* general case: RestartIndex in middle, split into two prims */ 596 prim[0].start = start; 597 prim[0].count = ctx->Array.RestartIndex - start; 598 599 prim[1] = prim[0]; 600 prim[1].start = ctx->Array.RestartIndex + 1; 601 prim[1].count = count - prim[1].start; 602 603 primCount = 2; 604 } 605 606 if (primCount > 0) { 607 /* draw one or two prims */ 608 check_buffers_are_unmapped(exec->array.inputs); 609 vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL, 610 GL_TRUE, start, start + count - 1, NULL); 611 } 612 } 613 else { 614 /* no prim restart */ 615 prim[0].start = start; 616 prim[0].count = count; 617 618 check_buffers_are_unmapped(exec->array.inputs); 619 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL, 620 GL_TRUE, start, start + count - 1, 621 NULL); 622 } 623} 624 625 626 627/** 628 * Called from glDrawArrays when in immediate mode (not display list mode). 629 */ 630static void GLAPIENTRY 631vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) 632{ 633 GET_CURRENT_CONTEXT(ctx); 634 635 if (MESA_VERBOSE & VERBOSE_DRAW) 636 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n", 637 _mesa_lookup_enum_by_nr(mode), start, count); 638 639 if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) 640 return; 641 642 FLUSH_CURRENT( ctx, 0 ); 643 644 if (!_mesa_valid_to_render(ctx, "glDrawArrays")) { 645 return; 646 } 647 648 if (0) 649 check_draw_arrays_data(ctx, start, count); 650 651 vbo_draw_arrays(ctx, mode, start, count, 1); 652 653 if (0) 654 print_draw_arrays(ctx, mode, start, count); 655} 656 657 658/** 659 * Called from glDrawArraysInstanced when in immediate mode (not 660 * display list mode). 661 */ 662static void GLAPIENTRY 663vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count, 664 GLsizei numInstances) 665{ 666 GET_CURRENT_CONTEXT(ctx); 667 668 if (MESA_VERBOSE & VERBOSE_DRAW) 669 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n", 670 _mesa_lookup_enum_by_nr(mode), start, count, numInstances); 671 672 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances)) 673 return; 674 675 FLUSH_CURRENT( ctx, 0 ); 676 677 if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) { 678 return; 679 } 680 681 if (0) 682 check_draw_arrays_data(ctx, start, count); 683 684 vbo_draw_arrays(ctx, mode, start, count, numInstances); 685 686 if (0) 687 print_draw_arrays(ctx, mode, start, count); 688} 689 690 691/** 692 * Map GL_ELEMENT_ARRAY_BUFFER and print contents. 693 * For debugging. 694 */ 695#if 0 696static void 697dump_element_buffer(struct gl_context *ctx, GLenum type) 698{ 699 const GLvoid *map = 700 ctx->Driver.MapBufferRange(ctx, 0, 701 ctx->Array.ArrayObj->ElementArrayBufferObj->Size, 702 GL_MAP_READ_BIT, 703 ctx->Array.ArrayObj->ElementArrayBufferObj); 704 switch (type) { 705 case GL_UNSIGNED_BYTE: 706 { 707 const GLubyte *us = (const GLubyte *) map; 708 GLint i; 709 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) { 710 printf("%02x ", us[i]); 711 if (i % 32 == 31) 712 printf("\n"); 713 } 714 printf("\n"); 715 } 716 break; 717 case GL_UNSIGNED_SHORT: 718 { 719 const GLushort *us = (const GLushort *) map; 720 GLint i; 721 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) { 722 printf("%04x ", us[i]); 723 if (i % 16 == 15) 724 printf("\n"); 725 } 726 printf("\n"); 727 } 728 break; 729 case GL_UNSIGNED_INT: 730 { 731 const GLuint *us = (const GLuint *) map; 732 GLint i; 733 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) { 734 printf("%08x ", us[i]); 735 if (i % 8 == 7) 736 printf("\n"); 737 } 738 printf("\n"); 739 } 740 break; 741 default: 742 ; 743 } 744 745 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj); 746} 747#endif 748 749 750/** 751 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements. 752 * Do the rendering for a glDrawElements or glDrawRangeElements call after 753 * we've validated buffer bounds, etc. 754 */ 755static void 756vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, 757 GLboolean index_bounds_valid, 758 GLuint start, GLuint end, 759 GLsizei count, GLenum type, 760 const GLvoid *indices, 761 GLint basevertex, GLint numInstances) 762{ 763 struct vbo_context *vbo = vbo_context(ctx); 764 struct vbo_exec_context *exec = &vbo->exec; 765 struct _mesa_index_buffer ib; 766 struct _mesa_prim prim[1]; 767 768 FLUSH_CURRENT( ctx, 0 ); 769 770 if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) { 771 return; 772 } 773 774 vbo_bind_arrays( ctx ); 775 776 vbo_draw_method(exec, DRAW_ARRAYS); 777 778 /* check for dirty state again */ 779 if (ctx->NewState) 780 _mesa_update_state( ctx ); 781 782 ib.count = count; 783 ib.type = type; 784 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; 785 ib.ptr = indices; 786 787 prim[0].begin = 1; 788 prim[0].end = 1; 789 prim[0].weak = 0; 790 prim[0].pad = 0; 791 prim[0].mode = mode; 792 prim[0].start = 0; 793 prim[0].count = count; 794 prim[0].indexed = 1; 795 prim[0].basevertex = basevertex; 796 prim[0].num_instances = numInstances; 797 798 /* Need to give special consideration to rendering a range of 799 * indices starting somewhere above zero. Typically the 800 * application is issuing multiple DrawRangeElements() to draw 801 * successive primitives layed out linearly in the vertex arrays. 802 * Unless the vertex arrays are all in a VBO (or locked as with 803 * CVA), the OpenGL semantics imply that we need to re-read or 804 * re-upload the vertex data on each draw call. 805 * 806 * In the case of hardware tnl, we want to avoid starting the 807 * upload at zero, as it will mean every draw call uploads an 808 * increasing amount of not-used vertex data. Worse - in the 809 * software tnl module, all those vertices might be transformed and 810 * lit but never rendered. 811 * 812 * If we just upload or transform the vertices in start..end, 813 * however, the indices will be incorrect. 814 * 815 * At this level, we don't know exactly what the requirements of 816 * the backend are going to be, though it will likely boil down to 817 * either: 818 * 819 * 1) Do nothing, everything is in a VBO and is processed once 820 * only. 821 * 822 * 2) Adjust the indices and vertex arrays so that start becomes 823 * zero. 824 * 825 * Rather than doing anything here, I'll provide a helper function 826 * for the latter case elsewhere. 827 */ 828 829 check_buffers_are_unmapped(exec->array.inputs); 830 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, 831 index_bounds_valid, start, end, NULL ); 832} 833 834 835/** 836 * Called by glDrawRangeElementsBaseVertex() in immediate mode. 837 */ 838static void GLAPIENTRY 839vbo_exec_DrawRangeElementsBaseVertex(GLenum mode, 840 GLuint start, GLuint end, 841 GLsizei count, GLenum type, 842 const GLvoid *indices, 843 GLint basevertex) 844{ 845 static GLuint warnCount = 0; 846 GLboolean index_bounds_valid = GL_TRUE; 847 GET_CURRENT_CONTEXT(ctx); 848 849 if (MESA_VERBOSE & VERBOSE_DRAW) 850 _mesa_debug(ctx, 851 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n", 852 _mesa_lookup_enum_by_nr(mode), start, end, count, 853 _mesa_lookup_enum_by_nr(type), indices, basevertex); 854 855 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, 856 type, indices, basevertex )) 857 return; 858 859 if ((int) end + basevertex < 0 || 860 start + basevertex >= ctx->Array.ArrayObj->_MaxElement) { 861 /* The application requested we draw using a range of indices that's 862 * outside the bounds of the current VBO. This is invalid and appears 863 * to give undefined results. The safest thing to do is to simply 864 * ignore the range, in case the application botched their range tracking 865 * but did provide valid indices. Also issue a warning indicating that 866 * the application is broken. 867 */ 868 if (warnCount++ < 10) { 869 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, " 870 "basevertex %d, count %d, type 0x%x, indices=%p):\n" 871 "\trange is outside VBO bounds (max=%u); ignoring.\n" 872 "\tThis should be fixed in the application.", 873 start, end, basevertex, count, type, indices, 874 ctx->Array.ArrayObj->_MaxElement - 1); 875 } 876 index_bounds_valid = GL_FALSE; 877 } 878 879 /* NOTE: It's important that 'end' is a reasonable value. 880 * in _tnl_draw_prims(), we use end to determine how many vertices 881 * to transform. If it's too large, we can unnecessarily split prims 882 * or we can read/write out of memory in several different places! 883 */ 884 885 /* Catch/fix some potential user errors */ 886 if (type == GL_UNSIGNED_BYTE) { 887 start = MIN2(start, 0xff); 888 end = MIN2(end, 0xff); 889 } 890 else if (type == GL_UNSIGNED_SHORT) { 891 start = MIN2(start, 0xffff); 892 end = MIN2(end, 0xffff); 893 } 894 895 if (0) { 896 printf("glDraw[Range]Elements{,BaseVertex}" 897 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, " 898 "base %d\n", 899 start, end, type, count, 900 ctx->Array.ArrayObj->ElementArrayBufferObj->Name, 901 basevertex); 902 } 903 904 if ((int) start + basevertex < 0 || 905 end + basevertex >= ctx->Array.ArrayObj->_MaxElement) 906 index_bounds_valid = GL_FALSE; 907 908#if 0 909 check_draw_elements_data(ctx, count, type, indices); 910#else 911 (void) check_draw_elements_data; 912#endif 913 914 vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end, 915 count, type, indices, basevertex, 1); 916} 917 918 919/** 920 * Called by glDrawRangeElements() in immediate mode. 921 */ 922static void GLAPIENTRY 923vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end, 924 GLsizei count, GLenum type, const GLvoid *indices) 925{ 926 if (MESA_VERBOSE & VERBOSE_DRAW) { 927 GET_CURRENT_CONTEXT(ctx); 928 _mesa_debug(ctx, 929 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n", 930 _mesa_lookup_enum_by_nr(mode), start, end, count, 931 _mesa_lookup_enum_by_nr(type), indices); 932 } 933 934 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type, 935 indices, 0); 936} 937 938 939/** 940 * Called by glDrawElements() in immediate mode. 941 */ 942static void GLAPIENTRY 943vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, 944 const GLvoid *indices) 945{ 946 GET_CURRENT_CONTEXT(ctx); 947 948 if (MESA_VERBOSE & VERBOSE_DRAW) 949 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n", 950 _mesa_lookup_enum_by_nr(mode), count, 951 _mesa_lookup_enum_by_nr(type), indices); 952 953 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 )) 954 return; 955 956 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 957 count, type, indices, 0, 1); 958} 959 960 961/** 962 * Called by glDrawElementsBaseVertex() in immediate mode. 963 */ 964static void GLAPIENTRY 965vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 966 const GLvoid *indices, GLint basevertex) 967{ 968 GET_CURRENT_CONTEXT(ctx); 969 970 if (MESA_VERBOSE & VERBOSE_DRAW) 971 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n", 972 _mesa_lookup_enum_by_nr(mode), count, 973 _mesa_lookup_enum_by_nr(type), indices, basevertex); 974 975 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 976 basevertex )) 977 return; 978 979 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 980 count, type, indices, basevertex, 1); 981} 982 983 984/** 985 * Called by glDrawElementsInstanced() in immediate mode. 986 */ 987static void GLAPIENTRY 988vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, 989 const GLvoid *indices, GLsizei numInstances) 990{ 991 GET_CURRENT_CONTEXT(ctx); 992 993 if (MESA_VERBOSE & VERBOSE_DRAW) 994 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n", 995 _mesa_lookup_enum_by_nr(mode), count, 996 _mesa_lookup_enum_by_nr(type), indices, numInstances); 997 998 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, 999 numInstances, 0)) 1000 return; 1001 1002 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 1003 count, type, indices, 0, numInstances); 1004} 1005 1006/** 1007 * Called by glDrawElementsInstancedBaseVertex() in immediate mode. 1008 */ 1009static void GLAPIENTRY 1010vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, 1011 const GLvoid *indices, GLsizei numInstances, 1012 GLint basevertex) 1013{ 1014 GET_CURRENT_CONTEXT(ctx); 1015 1016 if (MESA_VERBOSE & VERBOSE_DRAW) 1017 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n", 1018 _mesa_lookup_enum_by_nr(mode), count, 1019 _mesa_lookup_enum_by_nr(type), indices, 1020 numInstances, basevertex); 1021 1022 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, 1023 numInstances, basevertex)) 1024 return; 1025 1026 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 1027 count, type, indices, basevertex, numInstances); 1028} 1029 1030 1031/** 1032 * Inner support for both _mesa_MultiDrawElements() and 1033 * _mesa_MultiDrawRangeElements(). 1034 * This does the actual rendering after we've checked array indexes, etc. 1035 */ 1036static void 1037vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, 1038 const GLsizei *count, GLenum type, 1039 const GLvoid **indices, GLsizei primcount, 1040 const GLint *basevertex) 1041{ 1042 struct vbo_context *vbo = vbo_context(ctx); 1043 struct vbo_exec_context *exec = &vbo->exec; 1044 struct _mesa_index_buffer ib; 1045 struct _mesa_prim *prim; 1046 unsigned int index_type_size = vbo_sizeof_ib_type(type); 1047 uintptr_t min_index_ptr, max_index_ptr; 1048 GLboolean fallback = GL_FALSE; 1049 int i; 1050 1051 if (primcount == 0) 1052 return; 1053 1054 FLUSH_CURRENT( ctx, 0 ); 1055 1056 if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) { 1057 return; 1058 } 1059 1060 prim = calloc(1, primcount * sizeof(*prim)); 1061 if (prim == NULL) { 1062 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements"); 1063 return; 1064 } 1065 1066 /* Decide if we can do this all as one set of primitives sharing the 1067 * same index buffer, or if we have to reset the index pointer per 1068 * primitive. 1069 */ 1070 vbo_bind_arrays( ctx ); 1071 1072 /* check for dirty state again */ 1073 if (ctx->NewState) 1074 _mesa_update_state( ctx ); 1075 1076 min_index_ptr = (uintptr_t)indices[0]; 1077 max_index_ptr = 0; 1078 for (i = 0; i < primcount; i++) { 1079 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]); 1080 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] + 1081 index_type_size * count[i]); 1082 } 1083 1084 /* Check if we can handle this thing as a bunch of index offsets from the 1085 * same index pointer. If we can't, then we have to fall back to doing 1086 * a draw_prims per primitive. 1087 * Check that the difference between each prim's indexes is a multiple of 1088 * the index/element size. 1089 */ 1090 if (index_type_size != 1) { 1091 for (i = 0; i < primcount; i++) { 1092 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) { 1093 fallback = GL_TRUE; 1094 break; 1095 } 1096 } 1097 } 1098 1099 /* If the index buffer isn't in a VBO, then treating the application's 1100 * subranges of the index buffer as one large index buffer may lead to 1101 * us reading unmapped memory. 1102 */ 1103 if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) 1104 fallback = GL_TRUE; 1105 1106 if (!fallback) { 1107 ib.count = (max_index_ptr - min_index_ptr) / index_type_size; 1108 ib.type = type; 1109 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; 1110 ib.ptr = (void *)min_index_ptr; 1111 1112 for (i = 0; i < primcount; i++) { 1113 prim[i].begin = (i == 0); 1114 prim[i].end = (i == primcount - 1); 1115 prim[i].weak = 0; 1116 prim[i].pad = 0; 1117 prim[i].mode = mode; 1118 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size; 1119 prim[i].count = count[i]; 1120 prim[i].indexed = 1; 1121 prim[i].num_instances = 1; 1122 if (basevertex != NULL) 1123 prim[i].basevertex = basevertex[i]; 1124 else 1125 prim[i].basevertex = 0; 1126 } 1127 1128 check_buffers_are_unmapped(exec->array.inputs); 1129 vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib, 1130 GL_FALSE, ~0, ~0, NULL); 1131 } else { 1132 /* render one prim at a time */ 1133 for (i = 0; i < primcount; i++) { 1134 ib.count = count[i]; 1135 ib.type = type; 1136 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; 1137 ib.ptr = indices[i]; 1138 1139 prim[0].begin = 1; 1140 prim[0].end = 1; 1141 prim[0].weak = 0; 1142 prim[0].pad = 0; 1143 prim[0].mode = mode; 1144 prim[0].start = 0; 1145 prim[0].count = count[i]; 1146 prim[0].indexed = 1; 1147 prim[0].num_instances = 1; 1148 if (basevertex != NULL) 1149 prim[0].basevertex = basevertex[i]; 1150 else 1151 prim[0].basevertex = 0; 1152 1153 check_buffers_are_unmapped(exec->array.inputs); 1154 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib, 1155 GL_FALSE, ~0, ~0, NULL); 1156 } 1157 } 1158 1159 free(prim); 1160} 1161 1162 1163static void GLAPIENTRY 1164vbo_exec_MultiDrawElements(GLenum mode, 1165 const GLsizei *count, GLenum type, 1166 const GLvoid **indices, 1167 GLsizei primcount) 1168{ 1169 GET_CURRENT_CONTEXT(ctx); 1170 GLint i; 1171 1172 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1173 1174 for (i = 0; i < primcount; i++) { 1175 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i], 1176 0)) 1177 return; 1178 } 1179 1180 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 1181 NULL); 1182} 1183 1184 1185static void GLAPIENTRY 1186vbo_exec_MultiDrawElementsBaseVertex(GLenum mode, 1187 const GLsizei *count, GLenum type, 1188 const GLvoid **indices, 1189 GLsizei primcount, 1190 const GLsizei *basevertex) 1191{ 1192 GET_CURRENT_CONTEXT(ctx); 1193 GLint i; 1194 1195 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1196 1197 for (i = 0; i < primcount; i++) { 1198 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i], 1199 basevertex[i])) 1200 return; 1201 } 1202 1203 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 1204 basevertex); 1205} 1206 1207#if FEATURE_EXT_transform_feedback 1208 1209static void 1210vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, 1211 struct gl_transform_feedback_object *obj, 1212 GLuint numInstances) 1213{ 1214 struct vbo_context *vbo = vbo_context(ctx); 1215 struct vbo_exec_context *exec = &vbo->exec; 1216 struct _mesa_prim prim[2]; 1217 1218 vbo_bind_arrays(ctx); 1219 1220 /* Again... because we may have changed the bitmask of per-vertex varying 1221 * attributes. If we regenerate the fixed-function vertex program now 1222 * we may be able to prune down the number of vertex attributes which we 1223 * need in the shader. 1224 */ 1225 if (ctx->NewState) 1226 _mesa_update_state(ctx); 1227 1228 /* init most fields to zero */ 1229 memset(prim, 0, sizeof(prim)); 1230 prim[0].begin = 1; 1231 prim[0].end = 1; 1232 prim[0].mode = mode; 1233 prim[0].num_instances = numInstances; 1234 1235 /* Maybe we should do some primitive splitting for primitive restart 1236 * (like in DrawArrays), but we have no way to know how many vertices 1237 * will be rendered. */ 1238 1239 check_buffers_are_unmapped(exec->array.inputs); 1240 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL, 1241 GL_TRUE, 0, 0, obj); 1242} 1243 1244/** 1245 * Like DrawArrays, but take the count from a transform feedback object. 1246 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc. 1247 * \param name the transform feedback object 1248 * User still has to setup of the vertex attribute info with 1249 * glVertexPointer, glColorPointer, etc. 1250 * Part of GL_ARB_transform_feedback2. 1251 */ 1252static void GLAPIENTRY 1253vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name) 1254{ 1255 GET_CURRENT_CONTEXT(ctx); 1256 struct gl_transform_feedback_object *obj = 1257 _mesa_lookup_transform_feedback_object(ctx, name); 1258 1259 if (MESA_VERBOSE & VERBOSE_DRAW) 1260 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n", 1261 _mesa_lookup_enum_by_nr(mode), name); 1262 1263 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) { 1264 return; 1265 } 1266 1267 FLUSH_CURRENT(ctx, 0); 1268 1269 if (!_mesa_valid_to_render(ctx, "glDrawTransformFeedback")) { 1270 return; 1271 } 1272 1273 vbo_draw_transform_feedback(ctx, mode, obj, 1); 1274} 1275 1276#endif 1277 1278/** 1279 * Plug in the immediate-mode vertex array drawing commands into the 1280 * givven vbo_exec_context object. 1281 */ 1282void 1283vbo_exec_array_init( struct vbo_exec_context *exec ) 1284{ 1285 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; 1286 exec->vtxfmt.DrawElements = vbo_exec_DrawElements; 1287 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements; 1288 exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements; 1289 exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex; 1290 exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex; 1291 exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex; 1292 exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced; 1293 exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced; 1294 exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex; 1295#if FEATURE_EXT_transform_feedback 1296 exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback; 1297#endif 1298} 1299 1300 1301void 1302vbo_exec_array_destroy( struct vbo_exec_context *exec ) 1303{ 1304 /* nothing to do */ 1305} 1306 1307 1308 1309/** 1310 * The following functions are only used for OpenGL ES 1/2 support. 1311 * And some aren't even supported (yet) in ES 1/2. 1312 */ 1313 1314 1315void GLAPIENTRY 1316_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count) 1317{ 1318 vbo_exec_DrawArrays(mode, first, count); 1319} 1320 1321 1322void GLAPIENTRY 1323_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, 1324 const GLvoid *indices) 1325{ 1326 vbo_exec_DrawElements(mode, count, type, indices); 1327} 1328 1329 1330void GLAPIENTRY 1331_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 1332 const GLvoid *indices, GLint basevertex) 1333{ 1334 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex); 1335} 1336 1337 1338void GLAPIENTRY 1339_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, 1340 GLenum type, const GLvoid *indices) 1341{ 1342 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices); 1343} 1344 1345 1346void GLAPIENTRY 1347_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, 1348 GLsizei count, GLenum type, 1349 const GLvoid *indices, GLint basevertex) 1350{ 1351 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type, 1352 indices, basevertex); 1353} 1354 1355 1356void GLAPIENTRY 1357_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, 1358 const GLvoid **indices, GLsizei primcount) 1359{ 1360 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount); 1361} 1362 1363 1364void GLAPIENTRY 1365_mesa_MultiDrawElementsBaseVertex(GLenum mode, 1366 const GLsizei *count, GLenum type, 1367 const GLvoid **indices, GLsizei primcount, 1368 const GLint *basevertex) 1369{ 1370 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices, 1371 primcount, basevertex); 1372} 1373 1374#if FEATURE_EXT_transform_feedback 1375 1376void GLAPIENTRY 1377_mesa_DrawTransformFeedback(GLenum mode, GLuint name) 1378{ 1379 vbo_exec_DrawTransformFeedback(mode, name); 1380} 1381 1382#endif 1383