vbo_exec_array.c revision c5e473fbe25b20cb27aac44ff6e269701abd33a8
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->currval[VBO_ATTRIB_POS+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)] = 430 &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i]; 431 const_inputs |= VERT_BIT_GENERIC(i); 432 } 433 434 /* Could use just about anything, just to fill in the empty 435 * slots: 436 */ 437 for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) { 438 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; 439 const_inputs |= VERT_BIT_GENERIC(i); 440 } 441 break; 442 443 case VP_NV: 444 /* NV_vertex_program - attribute arrays alias and override 445 * conventional, legacy arrays. No materials, and the generic 446 * slots are vacant. 447 */ 448 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) { 449 if (i < VERT_ATTRIB_GENERIC_MAX 450 && vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) 451 inputs[i] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; 452 else if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) 453 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; 454 else { 455 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i]; 456 const_inputs |= VERT_BIT_FF(i); 457 } 458 } 459 460 /* Could use just about anything, just to fill in the empty 461 * slots: 462 */ 463 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) { 464 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; 465 const_inputs |= VERT_BIT_GENERIC(i); 466 } 467 break; 468 469 case VP_ARB: 470 /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0] 471 * attribute array aliases and overrides the legacy position array. 472 * 473 * Otherwise, legacy attributes available in the legacy slots, 474 * generic attributes in the generic slots and materials are not 475 * available as per-vertex attributes. 476 */ 477 if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) 478 inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0]; 479 else if (vertexAttrib[VERT_ATTRIB_POS].Enabled) 480 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS]; 481 else { 482 inputs[0] = &vbo->currval[VBO_ATTRIB_POS]; 483 const_inputs |= VERT_BIT_POS; 484 } 485 486 for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) { 487 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) 488 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; 489 else { 490 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i]; 491 const_inputs |= VERT_BIT_FF(i); 492 } 493 } 494 495 for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { 496 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) 497 inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; 498 else { 499 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; 500 const_inputs |= VERT_BIT_GENERIC(i); 501 } 502 } 503 504 inputs[VERT_ATTRIB_GENERIC0] = inputs[0]; 505 break; 506 } 507 508 _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) ); 509 ctx->NewDriverState |= ctx->DriverFlags.NewArray; 510} 511 512 513/** 514 * Examine the enabled vertex arrays to set the exec->array.inputs[] values. 515 * These will point to the arrays to actually use for drawing. Some will 516 * be user-provided arrays, other will be zero-stride const-valued arrays. 517 * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state 518 * validation must be done after this call. 519 */ 520void 521vbo_bind_arrays(struct gl_context *ctx) 522{ 523 struct vbo_context *vbo = vbo_context(ctx); 524 struct vbo_exec_context *exec = &vbo->exec; 525 526 vbo_draw_method(vbo, DRAW_ARRAYS); 527 528 if (exec->array.recalculate_inputs) { 529 recalculate_input_bindings(ctx); 530 531 /* Again... because we may have changed the bitmask of per-vertex varying 532 * attributes. If we regenerate the fixed-function vertex program now 533 * we may be able to prune down the number of vertex attributes which we 534 * need in the shader. 535 */ 536 if (ctx->NewState) { 537 _mesa_update_state(ctx); 538 } 539 540 exec->array.recalculate_inputs = GL_FALSE; 541 } 542} 543 544 545/** 546 * Helper function called by the other DrawArrays() functions below. 547 * This is where we handle primitive restart for drawing non-indexed 548 * arrays. If primitive restart is enabled, it typically means 549 * splitting one DrawArrays() into two. 550 */ 551static void 552vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, 553 GLsizei count, GLuint numInstances) 554{ 555 struct vbo_context *vbo = vbo_context(ctx); 556 struct vbo_exec_context *exec = &vbo->exec; 557 struct _mesa_prim prim[2]; 558 559 vbo_bind_arrays(ctx); 560 561 /* init most fields to zero */ 562 memset(prim, 0, sizeof(prim)); 563 prim[0].begin = 1; 564 prim[0].end = 1; 565 prim[0].mode = mode; 566 prim[0].num_instances = numInstances; 567 568 /* Implement the primitive restart index */ 569 if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) { 570 GLuint primCount = 0; 571 572 if (ctx->Array.RestartIndex == start) { 573 /* special case: RestartIndex at beginning */ 574 if (count > 1) { 575 prim[0].start = start + 1; 576 prim[0].count = count - 1; 577 primCount = 1; 578 } 579 } 580 else if (ctx->Array.RestartIndex == start + count - 1) { 581 /* special case: RestartIndex at end */ 582 if (count > 1) { 583 prim[0].start = start; 584 prim[0].count = count - 1; 585 primCount = 1; 586 } 587 } 588 else { 589 /* general case: RestartIndex in middle, split into two prims */ 590 prim[0].start = start; 591 prim[0].count = ctx->Array.RestartIndex - start; 592 593 prim[1] = prim[0]; 594 prim[1].start = ctx->Array.RestartIndex + 1; 595 prim[1].count = count - prim[1].start; 596 597 primCount = 2; 598 } 599 600 if (primCount > 0) { 601 /* draw one or two prims */ 602 check_buffers_are_unmapped(exec->array.inputs); 603 vbo->draw_prims(ctx, prim, primCount, NULL, 604 GL_TRUE, start, start + count - 1, NULL); 605 } 606 } 607 else { 608 /* no prim restart */ 609 prim[0].start = start; 610 prim[0].count = count; 611 612 check_buffers_are_unmapped(exec->array.inputs); 613 vbo->draw_prims(ctx, prim, 1, NULL, 614 GL_TRUE, start, start + count - 1, 615 NULL); 616 } 617} 618 619 620 621/** 622 * Called from glDrawArrays when in immediate mode (not display list mode). 623 */ 624static void GLAPIENTRY 625vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) 626{ 627 GET_CURRENT_CONTEXT(ctx); 628 629 if (MESA_VERBOSE & VERBOSE_DRAW) 630 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n", 631 _mesa_lookup_enum_by_nr(mode), start, count); 632 633 FLUSH_CURRENT(ctx, 0); 634 635 if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) 636 return; 637 638 if (0) 639 check_draw_arrays_data(ctx, start, count); 640 641 vbo_draw_arrays(ctx, mode, start, count, 1); 642 643 if (0) 644 print_draw_arrays(ctx, mode, start, count); 645} 646 647 648/** 649 * Called from glDrawArraysInstanced when in immediate mode (not 650 * display list mode). 651 */ 652static void GLAPIENTRY 653vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count, 654 GLsizei numInstances) 655{ 656 GET_CURRENT_CONTEXT(ctx); 657 658 if (MESA_VERBOSE & VERBOSE_DRAW) 659 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n", 660 _mesa_lookup_enum_by_nr(mode), start, count, numInstances); 661 662 FLUSH_CURRENT(ctx, 0); 663 664 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances)) 665 return; 666 667 if (0) 668 check_draw_arrays_data(ctx, start, count); 669 670 vbo_draw_arrays(ctx, mode, start, count, numInstances); 671 672 if (0) 673 print_draw_arrays(ctx, mode, start, count); 674} 675 676 677/** 678 * Map GL_ELEMENT_ARRAY_BUFFER and print contents. 679 * For debugging. 680 */ 681#if 0 682static void 683dump_element_buffer(struct gl_context *ctx, GLenum type) 684{ 685 const GLvoid *map = 686 ctx->Driver.MapBufferRange(ctx, 0, 687 ctx->Array.ArrayObj->ElementArrayBufferObj->Size, 688 GL_MAP_READ_BIT, 689 ctx->Array.ArrayObj->ElementArrayBufferObj); 690 switch (type) { 691 case GL_UNSIGNED_BYTE: 692 { 693 const GLubyte *us = (const GLubyte *) map; 694 GLint i; 695 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) { 696 printf("%02x ", us[i]); 697 if (i % 32 == 31) 698 printf("\n"); 699 } 700 printf("\n"); 701 } 702 break; 703 case GL_UNSIGNED_SHORT: 704 { 705 const GLushort *us = (const GLushort *) map; 706 GLint i; 707 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) { 708 printf("%04x ", us[i]); 709 if (i % 16 == 15) 710 printf("\n"); 711 } 712 printf("\n"); 713 } 714 break; 715 case GL_UNSIGNED_INT: 716 { 717 const GLuint *us = (const GLuint *) map; 718 GLint i; 719 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) { 720 printf("%08x ", us[i]); 721 if (i % 8 == 7) 722 printf("\n"); 723 } 724 printf("\n"); 725 } 726 break; 727 default: 728 ; 729 } 730 731 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj); 732} 733#endif 734 735 736/** 737 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements. 738 * Do the rendering for a glDrawElements or glDrawRangeElements call after 739 * we've validated buffer bounds, etc. 740 */ 741static void 742vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, 743 GLboolean index_bounds_valid, 744 GLuint start, GLuint end, 745 GLsizei count, GLenum type, 746 const GLvoid *indices, 747 GLint basevertex, GLint numInstances) 748{ 749 struct vbo_context *vbo = vbo_context(ctx); 750 struct vbo_exec_context *exec = &vbo->exec; 751 struct _mesa_index_buffer ib; 752 struct _mesa_prim prim[1]; 753 754 vbo_bind_arrays(ctx); 755 756 ib.count = count; 757 ib.type = type; 758 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; 759 ib.ptr = indices; 760 761 prim[0].begin = 1; 762 prim[0].end = 1; 763 prim[0].weak = 0; 764 prim[0].pad = 0; 765 prim[0].mode = mode; 766 prim[0].start = 0; 767 prim[0].count = count; 768 prim[0].indexed = 1; 769 prim[0].basevertex = basevertex; 770 prim[0].num_instances = numInstances; 771 772 /* Need to give special consideration to rendering a range of 773 * indices starting somewhere above zero. Typically the 774 * application is issuing multiple DrawRangeElements() to draw 775 * successive primitives layed out linearly in the vertex arrays. 776 * Unless the vertex arrays are all in a VBO (or locked as with 777 * CVA), the OpenGL semantics imply that we need to re-read or 778 * re-upload the vertex data on each draw call. 779 * 780 * In the case of hardware tnl, we want to avoid starting the 781 * upload at zero, as it will mean every draw call uploads an 782 * increasing amount of not-used vertex data. Worse - in the 783 * software tnl module, all those vertices might be transformed and 784 * lit but never rendered. 785 * 786 * If we just upload or transform the vertices in start..end, 787 * however, the indices will be incorrect. 788 * 789 * At this level, we don't know exactly what the requirements of 790 * the backend are going to be, though it will likely boil down to 791 * either: 792 * 793 * 1) Do nothing, everything is in a VBO and is processed once 794 * only. 795 * 796 * 2) Adjust the indices and vertex arrays so that start becomes 797 * zero. 798 * 799 * Rather than doing anything here, I'll provide a helper function 800 * for the latter case elsewhere. 801 */ 802 803 check_buffers_are_unmapped(exec->array.inputs); 804 vbo->draw_prims( ctx, prim, 1, &ib, 805 index_bounds_valid, start, end, NULL ); 806} 807 808 809/** 810 * Called by glDrawRangeElementsBaseVertex() in immediate mode. 811 */ 812static void GLAPIENTRY 813vbo_exec_DrawRangeElementsBaseVertex(GLenum mode, 814 GLuint start, GLuint end, 815 GLsizei count, GLenum type, 816 const GLvoid *indices, 817 GLint basevertex) 818{ 819 static GLuint warnCount = 0; 820 GLboolean index_bounds_valid = GL_TRUE; 821 GET_CURRENT_CONTEXT(ctx); 822 823 if (MESA_VERBOSE & VERBOSE_DRAW) 824 _mesa_debug(ctx, 825 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n", 826 _mesa_lookup_enum_by_nr(mode), start, end, count, 827 _mesa_lookup_enum_by_nr(type), indices, basevertex); 828 829 FLUSH_CURRENT(ctx, 0); 830 831 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, 832 type, indices, basevertex )) 833 return; 834 835 if ((int) end + basevertex < 0 || 836 start + basevertex >= ctx->Array.ArrayObj->_MaxElement) { 837 /* The application requested we draw using a range of indices that's 838 * outside the bounds of the current VBO. This is invalid and appears 839 * to give undefined results. The safest thing to do is to simply 840 * ignore the range, in case the application botched their range tracking 841 * but did provide valid indices. Also issue a warning indicating that 842 * the application is broken. 843 */ 844 if (warnCount++ < 10) { 845 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, " 846 "basevertex %d, count %d, type 0x%x, indices=%p):\n" 847 "\trange is outside VBO bounds (max=%u); ignoring.\n" 848 "\tThis should be fixed in the application.", 849 start, end, basevertex, count, type, indices, 850 ctx->Array.ArrayObj->_MaxElement - 1); 851 } 852 index_bounds_valid = GL_FALSE; 853 } 854 855 /* NOTE: It's important that 'end' is a reasonable value. 856 * in _tnl_draw_prims(), we use end to determine how many vertices 857 * to transform. If it's too large, we can unnecessarily split prims 858 * or we can read/write out of memory in several different places! 859 */ 860 861 /* Catch/fix some potential user errors */ 862 if (type == GL_UNSIGNED_BYTE) { 863 start = MIN2(start, 0xff); 864 end = MIN2(end, 0xff); 865 } 866 else if (type == GL_UNSIGNED_SHORT) { 867 start = MIN2(start, 0xffff); 868 end = MIN2(end, 0xffff); 869 } 870 871 if (0) { 872 printf("glDraw[Range]Elements{,BaseVertex}" 873 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, " 874 "base %d\n", 875 start, end, type, count, 876 ctx->Array.ArrayObj->ElementArrayBufferObj->Name, 877 basevertex); 878 } 879 880 if ((int) start + basevertex < 0 || 881 end + basevertex >= ctx->Array.ArrayObj->_MaxElement) 882 index_bounds_valid = GL_FALSE; 883 884#if 0 885 check_draw_elements_data(ctx, count, type, indices); 886#else 887 (void) check_draw_elements_data; 888#endif 889 890 vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end, 891 count, type, indices, basevertex, 1); 892} 893 894 895/** 896 * Called by glDrawRangeElements() in immediate mode. 897 */ 898static void GLAPIENTRY 899vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end, 900 GLsizei count, GLenum type, const GLvoid *indices) 901{ 902 if (MESA_VERBOSE & VERBOSE_DRAW) { 903 GET_CURRENT_CONTEXT(ctx); 904 _mesa_debug(ctx, 905 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n", 906 _mesa_lookup_enum_by_nr(mode), start, end, count, 907 _mesa_lookup_enum_by_nr(type), indices); 908 } 909 910 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type, 911 indices, 0); 912} 913 914 915/** 916 * Called by glDrawElements() in immediate mode. 917 */ 918static void GLAPIENTRY 919vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, 920 const GLvoid *indices) 921{ 922 GET_CURRENT_CONTEXT(ctx); 923 924 if (MESA_VERBOSE & VERBOSE_DRAW) 925 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n", 926 _mesa_lookup_enum_by_nr(mode), count, 927 _mesa_lookup_enum_by_nr(type), indices); 928 929 FLUSH_CURRENT(ctx, 0); 930 931 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 )) 932 return; 933 934 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 935 count, type, indices, 0, 1); 936} 937 938 939/** 940 * Called by glDrawElementsBaseVertex() in immediate mode. 941 */ 942static void GLAPIENTRY 943vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 944 const GLvoid *indices, GLint basevertex) 945{ 946 GET_CURRENT_CONTEXT(ctx); 947 948 if (MESA_VERBOSE & VERBOSE_DRAW) 949 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n", 950 _mesa_lookup_enum_by_nr(mode), count, 951 _mesa_lookup_enum_by_nr(type), indices, basevertex); 952 953 FLUSH_CURRENT(ctx, 0); 954 955 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 956 basevertex )) 957 return; 958 959 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 960 count, type, indices, basevertex, 1); 961} 962 963 964/** 965 * Called by glDrawElementsInstanced() in immediate mode. 966 */ 967static void GLAPIENTRY 968vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, 969 const GLvoid *indices, GLsizei numInstances) 970{ 971 GET_CURRENT_CONTEXT(ctx); 972 973 if (MESA_VERBOSE & VERBOSE_DRAW) 974 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n", 975 _mesa_lookup_enum_by_nr(mode), count, 976 _mesa_lookup_enum_by_nr(type), indices, numInstances); 977 978 FLUSH_CURRENT(ctx, 0); 979 980 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, 981 numInstances, 0)) 982 return; 983 984 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 985 count, type, indices, 0, numInstances); 986} 987 988/** 989 * Called by glDrawElementsInstancedBaseVertex() in immediate mode. 990 */ 991static void GLAPIENTRY 992vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, 993 const GLvoid *indices, GLsizei numInstances, 994 GLint basevertex) 995{ 996 GET_CURRENT_CONTEXT(ctx); 997 998 if (MESA_VERBOSE & VERBOSE_DRAW) 999 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n", 1000 _mesa_lookup_enum_by_nr(mode), count, 1001 _mesa_lookup_enum_by_nr(type), indices, 1002 numInstances, basevertex); 1003 1004 FLUSH_CURRENT(ctx, 0); 1005 1006 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, 1007 numInstances, basevertex)) 1008 return; 1009 1010 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 1011 count, type, indices, basevertex, numInstances); 1012} 1013 1014 1015/** 1016 * Inner support for both _mesa_MultiDrawElements() and 1017 * _mesa_MultiDrawRangeElements(). 1018 * This does the actual rendering after we've checked array indexes, etc. 1019 */ 1020static void 1021vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, 1022 const GLsizei *count, GLenum type, 1023 const GLvoid **indices, GLsizei primcount, 1024 const GLint *basevertex) 1025{ 1026 struct vbo_context *vbo = vbo_context(ctx); 1027 struct vbo_exec_context *exec = &vbo->exec; 1028 struct _mesa_index_buffer ib; 1029 struct _mesa_prim *prim; 1030 unsigned int index_type_size = vbo_sizeof_ib_type(type); 1031 uintptr_t min_index_ptr, max_index_ptr; 1032 GLboolean fallback = GL_FALSE; 1033 int i; 1034 1035 if (primcount == 0) 1036 return; 1037 1038 prim = calloc(1, primcount * sizeof(*prim)); 1039 if (prim == NULL) { 1040 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements"); 1041 return; 1042 } 1043 1044 vbo_bind_arrays(ctx); 1045 1046 min_index_ptr = (uintptr_t)indices[0]; 1047 max_index_ptr = 0; 1048 for (i = 0; i < primcount; i++) { 1049 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]); 1050 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] + 1051 index_type_size * count[i]); 1052 } 1053 1054 /* Check if we can handle this thing as a bunch of index offsets from the 1055 * same index pointer. If we can't, then we have to fall back to doing 1056 * a draw_prims per primitive. 1057 * Check that the difference between each prim's indexes is a multiple of 1058 * the index/element size. 1059 */ 1060 if (index_type_size != 1) { 1061 for (i = 0; i < primcount; i++) { 1062 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) { 1063 fallback = GL_TRUE; 1064 break; 1065 } 1066 } 1067 } 1068 1069 /* If the index buffer isn't in a VBO, then treating the application's 1070 * subranges of the index buffer as one large index buffer may lead to 1071 * us reading unmapped memory. 1072 */ 1073 if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) 1074 fallback = GL_TRUE; 1075 1076 if (!fallback) { 1077 ib.count = (max_index_ptr - min_index_ptr) / index_type_size; 1078 ib.type = type; 1079 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; 1080 ib.ptr = (void *)min_index_ptr; 1081 1082 for (i = 0; i < primcount; i++) { 1083 prim[i].begin = (i == 0); 1084 prim[i].end = (i == primcount - 1); 1085 prim[i].weak = 0; 1086 prim[i].pad = 0; 1087 prim[i].mode = mode; 1088 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size; 1089 prim[i].count = count[i]; 1090 prim[i].indexed = 1; 1091 prim[i].num_instances = 1; 1092 if (basevertex != NULL) 1093 prim[i].basevertex = basevertex[i]; 1094 else 1095 prim[i].basevertex = 0; 1096 } 1097 1098 check_buffers_are_unmapped(exec->array.inputs); 1099 vbo->draw_prims(ctx, prim, primcount, &ib, 1100 GL_FALSE, ~0, ~0, NULL); 1101 } else { 1102 /* render one prim at a time */ 1103 for (i = 0; i < primcount; i++) { 1104 ib.count = count[i]; 1105 ib.type = type; 1106 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; 1107 ib.ptr = indices[i]; 1108 1109 prim[0].begin = 1; 1110 prim[0].end = 1; 1111 prim[0].weak = 0; 1112 prim[0].pad = 0; 1113 prim[0].mode = mode; 1114 prim[0].start = 0; 1115 prim[0].count = count[i]; 1116 prim[0].indexed = 1; 1117 prim[0].num_instances = 1; 1118 if (basevertex != NULL) 1119 prim[0].basevertex = basevertex[i]; 1120 else 1121 prim[0].basevertex = 0; 1122 1123 check_buffers_are_unmapped(exec->array.inputs); 1124 vbo->draw_prims(ctx, prim, 1, &ib, 1125 GL_FALSE, ~0, ~0, NULL); 1126 } 1127 } 1128 1129 free(prim); 1130} 1131 1132 1133static void GLAPIENTRY 1134vbo_exec_MultiDrawElements(GLenum mode, 1135 const GLsizei *count, GLenum type, 1136 const GLvoid **indices, 1137 GLsizei primcount) 1138{ 1139 GET_CURRENT_CONTEXT(ctx); 1140 GLint i; 1141 1142 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1143 1144 for (i = 0; i < primcount; i++) { 1145 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i], 1146 0)) 1147 return; 1148 } 1149 1150 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 1151 NULL); 1152} 1153 1154 1155static void GLAPIENTRY 1156vbo_exec_MultiDrawElementsBaseVertex(GLenum mode, 1157 const GLsizei *count, GLenum type, 1158 const GLvoid **indices, 1159 GLsizei primcount, 1160 const GLsizei *basevertex) 1161{ 1162 GET_CURRENT_CONTEXT(ctx); 1163 GLint i; 1164 1165 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1166 1167 for (i = 0; i < primcount; i++) { 1168 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i], 1169 basevertex[i])) 1170 return; 1171 } 1172 1173 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 1174 basevertex); 1175} 1176 1177#if FEATURE_EXT_transform_feedback 1178 1179static void 1180vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, 1181 struct gl_transform_feedback_object *obj, 1182 GLuint numInstances) 1183{ 1184 struct vbo_context *vbo = vbo_context(ctx); 1185 struct vbo_exec_context *exec = &vbo->exec; 1186 struct _mesa_prim prim[2]; 1187 1188 vbo_bind_arrays(ctx); 1189 1190 /* init most fields to zero */ 1191 memset(prim, 0, sizeof(prim)); 1192 prim[0].begin = 1; 1193 prim[0].end = 1; 1194 prim[0].mode = mode; 1195 prim[0].num_instances = numInstances; 1196 1197 /* Maybe we should do some primitive splitting for primitive restart 1198 * (like in DrawArrays), but we have no way to know how many vertices 1199 * will be rendered. */ 1200 1201 check_buffers_are_unmapped(exec->array.inputs); 1202 vbo->draw_prims(ctx, prim, 1, NULL, 1203 GL_TRUE, 0, 0, obj); 1204} 1205 1206/** 1207 * Like DrawArrays, but take the count from a transform feedback object. 1208 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc. 1209 * \param name the transform feedback object 1210 * User still has to setup of the vertex attribute info with 1211 * glVertexPointer, glColorPointer, etc. 1212 * Part of GL_ARB_transform_feedback2. 1213 */ 1214static void GLAPIENTRY 1215vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name) 1216{ 1217 GET_CURRENT_CONTEXT(ctx); 1218 struct gl_transform_feedback_object *obj = 1219 _mesa_lookup_transform_feedback_object(ctx, name); 1220 1221 if (MESA_VERBOSE & VERBOSE_DRAW) 1222 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n", 1223 _mesa_lookup_enum_by_nr(mode), name); 1224 1225 FLUSH_CURRENT(ctx, 0); 1226 1227 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) { 1228 return; 1229 } 1230 1231 vbo_draw_transform_feedback(ctx, mode, obj, 1); 1232} 1233 1234#endif 1235 1236/** 1237 * Plug in the immediate-mode vertex array drawing commands into the 1238 * givven vbo_exec_context object. 1239 */ 1240void 1241vbo_exec_array_init( struct vbo_exec_context *exec ) 1242{ 1243 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; 1244 exec->vtxfmt.DrawElements = vbo_exec_DrawElements; 1245 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements; 1246 exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements; 1247 exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex; 1248 exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex; 1249 exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex; 1250 exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced; 1251 exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced; 1252 exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex; 1253#if FEATURE_EXT_transform_feedback 1254 exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback; 1255#endif 1256} 1257 1258 1259void 1260vbo_exec_array_destroy( struct vbo_exec_context *exec ) 1261{ 1262 /* nothing to do */ 1263} 1264 1265 1266 1267/** 1268 * The following functions are only used for OpenGL ES 1/2 support. 1269 * And some aren't even supported (yet) in ES 1/2. 1270 */ 1271 1272 1273void GLAPIENTRY 1274_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count) 1275{ 1276 vbo_exec_DrawArrays(mode, first, count); 1277} 1278 1279 1280void GLAPIENTRY 1281_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, 1282 const GLvoid *indices) 1283{ 1284 vbo_exec_DrawElements(mode, count, type, indices); 1285} 1286 1287 1288void GLAPIENTRY 1289_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 1290 const GLvoid *indices, GLint basevertex) 1291{ 1292 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex); 1293} 1294 1295 1296void GLAPIENTRY 1297_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, 1298 GLenum type, const GLvoid *indices) 1299{ 1300 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices); 1301} 1302 1303 1304void GLAPIENTRY 1305_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, 1306 GLsizei count, GLenum type, 1307 const GLvoid *indices, GLint basevertex) 1308{ 1309 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type, 1310 indices, basevertex); 1311} 1312 1313 1314void GLAPIENTRY 1315_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, 1316 const GLvoid **indices, GLsizei primcount) 1317{ 1318 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount); 1319} 1320 1321 1322void GLAPIENTRY 1323_mesa_MultiDrawElementsBaseVertex(GLenum mode, 1324 const GLsizei *count, GLenum type, 1325 const GLvoid **indices, GLsizei primcount, 1326 const GLint *basevertex) 1327{ 1328 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices, 1329 primcount, basevertex); 1330} 1331 1332#if FEATURE_EXT_transform_feedback 1333 1334void GLAPIENTRY 1335_mesa_DrawTransformFeedback(GLenum mode, GLuint name) 1336{ 1337 vbo_exec_DrawTransformFeedback(mode, name); 1338} 1339 1340#endif 1341