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