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