vbo_exec_array.c revision 2708ddfb06a36d8568e2aa130bf1f7d551fcd309
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/api_noop.h" 34#include "main/varray.h" 35#include "main/bufferobj.h" 36#include "glapi/dispatch.h" 37 38#include "vbo_context.h" 39 40 41/** 42 * Compute min and max elements for glDraw[Range]Elements() calls. 43 */ 44void 45vbo_get_minmax_index(GLcontext *ctx, 46 const struct _mesa_prim *prim, 47 const struct _mesa_index_buffer *ib, 48 GLuint *min_index, GLuint *max_index) 49{ 50 GLuint i; 51 GLsizei count = prim->count; 52 const void *indices; 53 54 if (ib->obj->Name) { 55 const GLvoid *map = ctx->Driver.MapBuffer(ctx, 56 GL_ELEMENT_ARRAY_BUFFER_ARB, 57 GL_READ_ONLY, 58 ib->obj); 59 indices = ADD_POINTERS(map, ib->ptr); 60 } else { 61 indices = ib->ptr; 62 } 63 64 switch (ib->type) { 65 case GL_UNSIGNED_INT: { 66 const GLuint *ui_indices = (const GLuint *)ib->ptr; 67 GLuint max_ui = ui_indices[count-1]; 68 GLuint min_ui = ui_indices[0]; 69 for (i = 0; i < count; i++) { 70 if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; 71 if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; 72 } 73 *min_index = min_ui; 74 *max_index = max_ui; 75 break; 76 } 77 case GL_UNSIGNED_SHORT: { 78 const GLushort *us_indices = (const GLushort *)indices; 79 GLuint max_us = us_indices[count-1]; 80 GLuint min_us = us_indices[0]; 81 for (i = 0; i < count; i++) { 82 if (us_indices[i] > max_us) max_us = us_indices[i]; 83 if (us_indices[i] < min_us) min_us = us_indices[i]; 84 } 85 *min_index = min_us; 86 *max_index = max_us; 87 break; 88 } 89 case GL_UNSIGNED_BYTE: { 90 const GLubyte *ub_indices = (const GLubyte *)indices; 91 GLuint max_ub = ub_indices[count-1]; 92 GLuint min_ub = ub_indices[0]; 93 for (i = 0; i < count; i++) { 94 if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; 95 if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; 96 } 97 *min_index = min_ub; 98 *max_index = max_ub; 99 break; 100 } 101 default: 102 assert(0); 103 break; 104 } 105 106 if (ib->obj->Name != 0) { 107 ctx->Driver.UnmapBuffer(ctx, 108 GL_ELEMENT_ARRAY_BUFFER_ARB, 109 ib->obj); 110 } 111} 112 113 114/** 115 * Check that element 'j' of the array has reasonable data. 116 * Map VBO if needed. 117 */ 118static void 119check_array_data(GLcontext *ctx, struct gl_client_array *array, 120 GLuint attrib, GLuint j) 121{ 122 if (array->Enabled) { 123 const void *data = array->Ptr; 124 if (array->BufferObj->Name) { 125 if (!array->BufferObj->Pointer) { 126 /* need to map now */ 127 array->BufferObj->Pointer = ctx->Driver.MapBuffer(ctx, 128 GL_ARRAY_BUFFER_ARB, 129 GL_READ_ONLY, 130 array->BufferObj); 131 } 132 data = ADD_POINTERS(data, array->BufferObj->Pointer); 133 } 134 switch (array->Type) { 135 case GL_FLOAT: 136 { 137 GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j); 138 GLuint k; 139 for (k = 0; k < array->Size; k++) { 140 if (IS_INF_OR_NAN(f[k]) || 141 f[k] >= 1.0e20 || f[k] <= -1.0e10) { 142 _mesa_printf("Bad array data:\n"); 143 _mesa_printf(" Element[%u].%u = %f\n", j, k, f[k]); 144 _mesa_printf(" Array %u at %p\n", attrib, (void* ) array); 145 _mesa_printf(" Type 0x%x, Size %d, Stride %d\n", 146 array->Type, array->Size, array->Stride); 147 _mesa_printf(" Address/offset %p in Buffer Object %u\n", 148 array->Ptr, array->BufferObj->Name); 149 f[k] = 1.0; /* XXX replace the bad value! */ 150 } 151 //assert(!IS_INF_OR_NAN(f[k])); 152 } 153 } 154 break; 155 default: 156 ; 157 } 158 } 159} 160 161 162/** 163 * Unmap the buffer object referenced by given array, if mapped. 164 */ 165static void 166unmap_array_buffer(GLcontext *ctx, struct gl_client_array *array) 167{ 168 if (array->Enabled && 169 array->BufferObj->Name && 170 array->BufferObj->Pointer) { 171 ctx->Driver.UnmapBuffer(ctx, 172 GL_ARRAY_BUFFER_ARB, 173 array->BufferObj); 174 } 175} 176 177 178/** 179 * Examine the array's data for NaNs, etc. 180 */ 181static void 182check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType, 183 const void *elements) 184{ 185 struct gl_array_object *arrayObj = ctx->Array.ArrayObj; 186 const void *elemMap; 187 GLint i, k; 188 189 if (ctx->Array.ElementArrayBufferObj->Name) { 190 elemMap = ctx->Driver.MapBuffer(ctx, 191 GL_ELEMENT_ARRAY_BUFFER_ARB, 192 GL_READ_ONLY, 193 ctx->Array.ElementArrayBufferObj); 194 elements = ADD_POINTERS(elements, elemMap); 195 } 196 197 for (i = 0; i < count; i++) { 198 GLuint j; 199 200 /* j = element[i] */ 201 switch (elemType) { 202 case GL_UNSIGNED_BYTE: 203 j = ((const GLubyte *) elements)[i]; 204 break; 205 case GL_UNSIGNED_SHORT: 206 j = ((const GLushort *) elements)[i]; 207 break; 208 case GL_UNSIGNED_INT: 209 j = ((const GLuint *) elements)[i]; 210 break; 211 default: 212 assert(0); 213 } 214 215 /* check element j of each enabled array */ 216 check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j); 217 check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j); 218 check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j); 219 check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j); 220 for (k = 0; k < Elements(arrayObj->TexCoord); k++) { 221 check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j); 222 } 223 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) { 224 check_array_data(ctx, &arrayObj->VertexAttrib[k], VERT_ATTRIB_GENERIC0 + k, j); 225 } 226 } 227 228 if (ctx->Array.ElementArrayBufferObj->Name) { 229 ctx->Driver.UnmapBuffer(ctx, 230 GL_ELEMENT_ARRAY_BUFFER_ARB, 231 ctx->Array.ElementArrayBufferObj); 232 } 233 234 unmap_array_buffer(ctx, &arrayObj->Vertex); 235 unmap_array_buffer(ctx, &arrayObj->Normal); 236 unmap_array_buffer(ctx, &arrayObj->Color); 237 for (k = 0; k < Elements(arrayObj->TexCoord); k++) { 238 unmap_array_buffer(ctx, &arrayObj->TexCoord[k]); 239 } 240 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) { 241 unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]); 242 } 243} 244 245 246/** 247 * Check array data, looking for NaNs, etc. 248 */ 249static void 250check_draw_arrays_data(GLcontext *ctx, GLint start, GLsizei count) 251{ 252 /* TO DO */ 253} 254 255 256/** 257 * Print info/data for glDrawArrays(). 258 */ 259static void 260print_draw_arrays(GLcontext *ctx, struct vbo_exec_context *exec, 261 GLenum mode, GLint start, GLsizei count) 262{ 263 int i; 264 265 _mesa_printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n", 266 mode, start, count); 267 268 for (i = 0; i < 32; i++) { 269 GLuint bufName = exec->array.inputs[i]->BufferObj->Name; 270 GLint stride = exec->array.inputs[i]->Stride; 271 _mesa_printf("attr %2d: size %d stride %d enabled %d " 272 "ptr %p Bufobj %u\n", 273 i, 274 exec->array.inputs[i]->Size, 275 stride, 276 /*exec->array.inputs[i]->Enabled,*/ 277 exec->array.legacy_array[i]->Enabled, 278 exec->array.inputs[i]->Ptr, 279 bufName); 280 281 if (bufName) { 282 struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName); 283 GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB, 284 GL_READ_ONLY_ARB, buf); 285 int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr; 286 float *f = (float *) (p + offset); 287 int *k = (int *) f; 288 int i; 289 int n = (count * stride) / 4; 290 if (n > 32) 291 n = 32; 292 _mesa_printf(" Data at offset %d:\n", offset); 293 for (i = 0; i < n; i++) { 294 _mesa_printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); 295 } 296 ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf); 297 } 298 } 299} 300 301 302/** 303 * Just translate the arrayobj into a sane layout. 304 */ 305static void 306bind_array_obj(GLcontext *ctx) 307{ 308 struct vbo_context *vbo = vbo_context(ctx); 309 struct vbo_exec_context *exec = &vbo->exec; 310 struct gl_array_object *arrayObj = ctx->Array.ArrayObj; 311 GLuint i; 312 313 /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array 314 * rather than as individual named arrays. Then this function can 315 * go away. 316 */ 317 exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex; 318 exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight; 319 exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal; 320 exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color; 321 exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor; 322 exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord; 323 exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index; 324 if (arrayObj->PointSize.Enabled) { 325 /* this aliases COLOR_INDEX */ 326 exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize; 327 } 328 exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag; 329 330 for (i = 0; i < Elements(arrayObj->TexCoord); i++) 331 exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i]; 332 333 for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) { 334 assert(i < Elements(exec->array.generic_array)); 335 exec->array.generic_array[i] = &arrayObj->VertexAttrib[i]; 336 } 337 338 exec->array.array_obj = arrayObj->Name; 339} 340 341 342static void 343recalculate_input_bindings(GLcontext *ctx) 344{ 345 struct vbo_context *vbo = vbo_context(ctx); 346 struct vbo_exec_context *exec = &vbo->exec; 347 const struct gl_client_array **inputs = &exec->array.inputs[0]; 348 GLbitfield const_inputs = 0x0; 349 GLuint i; 350 351 exec->array.program_mode = get_program_mode(ctx); 352 exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; 353 354 switch (exec->array.program_mode) { 355 case VP_NONE: 356 /* When no vertex program is active (or the vertex program is generated 357 * from fixed-function state). We put the material values into the 358 * generic slots. This is the only situation where material values 359 * are available as per-vertex attributes. 360 */ 361 for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { 362 if (exec->array.legacy_array[i]->Enabled) 363 inputs[i] = exec->array.legacy_array[i]; 364 else { 365 inputs[i] = &vbo->legacy_currval[i]; 366 const_inputs |= 1 << i; 367 } 368 } 369 370 for (i = 0; i < MAT_ATTRIB_MAX; i++) { 371 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i]; 372 const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i); 373 } 374 375 /* Could use just about anything, just to fill in the empty 376 * slots: 377 */ 378 for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) { 379 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; 380 const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i); 381 } 382 break; 383 384 case VP_NV: 385 /* NV_vertex_program - attribute arrays alias and override 386 * conventional, legacy arrays. No materials, and the generic 387 * slots are vacant. 388 */ 389 for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { 390 if (exec->array.generic_array[i]->Enabled) 391 inputs[i] = exec->array.generic_array[i]; 392 else if (exec->array.legacy_array[i]->Enabled) 393 inputs[i] = exec->array.legacy_array[i]; 394 else { 395 inputs[i] = &vbo->legacy_currval[i]; 396 const_inputs |= 1 << i; 397 } 398 } 399 400 /* Could use just about anything, just to fill in the empty 401 * slots: 402 */ 403 for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) { 404 inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0]; 405 const_inputs |= 1 << i; 406 } 407 break; 408 409 case VP_ARB: 410 /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0] 411 * attribute array aliases and overrides the legacy position array. 412 * 413 * Otherwise, legacy attributes available in the legacy slots, 414 * generic attributes in the generic slots and materials are not 415 * available as per-vertex attributes. 416 */ 417 if (exec->array.generic_array[0]->Enabled) 418 inputs[0] = exec->array.generic_array[0]; 419 else if (exec->array.legacy_array[0]->Enabled) 420 inputs[0] = exec->array.legacy_array[0]; 421 else { 422 inputs[0] = &vbo->legacy_currval[0]; 423 const_inputs |= 1 << 0; 424 } 425 426 for (i = 1; i <= VERT_ATTRIB_TEX7; i++) { 427 if (exec->array.legacy_array[i]->Enabled) 428 inputs[i] = exec->array.legacy_array[i]; 429 else { 430 inputs[i] = &vbo->legacy_currval[i]; 431 const_inputs |= 1 << i; 432 } 433 } 434 435 for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) { 436 if (exec->array.generic_array[i]->Enabled) 437 inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; 438 else { 439 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; 440 const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i); 441 } 442 443 } 444 break; 445 } 446 447 _mesa_set_varying_vp_inputs( ctx, ~const_inputs ); 448} 449 450 451static void 452bind_arrays(GLcontext *ctx) 453{ 454#if 0 455 if (ctx->Array.ArrayObj.Name != exec->array.array_obj) { 456 bind_array_obj(ctx); 457 recalculate_input_bindings(ctx); 458 } 459 else if (exec->array.program_mode != get_program_mode(ctx) || 460 exec->array.enabled_flags != ctx->Array.ArrayObj->_Enabled) { 461 462 recalculate_input_bindings(ctx); 463 } 464#else 465 bind_array_obj(ctx); 466 recalculate_input_bindings(ctx); 467#endif 468} 469 470 471 472/*********************************************************************** 473 * API functions. 474 */ 475 476static void GLAPIENTRY 477vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) 478{ 479 GET_CURRENT_CONTEXT(ctx); 480 struct vbo_context *vbo = vbo_context(ctx); 481 struct vbo_exec_context *exec = &vbo->exec; 482 struct _mesa_prim prim[1]; 483 484 if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) 485 return; 486 487 FLUSH_CURRENT( ctx, 0 ); 488 489 if (ctx->NewState) 490 _mesa_update_state( ctx ); 491 492 if (!vbo_validate_shaders(ctx)) { 493 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawArrays(bad shader)"); 494 return; 495 } 496 497#if 0 498 check_draw_arrays_data(ctx, start, count); 499#else 500 (void) check_draw_arrays_data; 501#endif 502 503 bind_arrays( ctx ); 504 505 /* Again... because we may have changed the bitmask of per-vertex varying 506 * attributes. If we regenerate the fixed-function vertex program now 507 * we may be able to prune down the number of vertex attributes which we 508 * need in the shader. 509 */ 510 if (ctx->NewState) 511 _mesa_update_state( ctx ); 512 513 prim[0].begin = 1; 514 prim[0].end = 1; 515 prim[0].weak = 0; 516 prim[0].pad = 0; 517 prim[0].mode = mode; 518 prim[0].start = start; 519 prim[0].count = count; 520 prim[0].indexed = 0; 521 522 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 523 GL_TRUE, start, start + count - 1 ); 524 525#if 0 526 print_draw_arrays(ctx, exec, mode, start, count); 527#else 528 (void) print_draw_arrays; 529#endif 530} 531 532 533/** 534 * Map GL_ELEMENT_ARRAY_BUFFER and print contents. 535 */ 536static void 537dump_element_buffer(GLcontext *ctx, GLenum type) 538{ 539 const GLvoid *map = ctx->Driver.MapBuffer(ctx, 540 GL_ELEMENT_ARRAY_BUFFER_ARB, 541 GL_READ_ONLY, 542 ctx->Array.ElementArrayBufferObj); 543 switch (type) { 544 case GL_UNSIGNED_BYTE: 545 { 546 const GLubyte *us = (const GLubyte *) map; 547 GLuint i; 548 for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) { 549 _mesa_printf("%02x ", us[i]); 550 if (i % 32 == 31) 551 _mesa_printf("\n"); 552 } 553 _mesa_printf("\n"); 554 } 555 break; 556 case GL_UNSIGNED_SHORT: 557 { 558 const GLushort *us = (const GLushort *) map; 559 GLuint i; 560 for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) { 561 _mesa_printf("%04x ", us[i]); 562 if (i % 16 == 15) 563 _mesa_printf("\n"); 564 } 565 _mesa_printf("\n"); 566 } 567 break; 568 case GL_UNSIGNED_INT: 569 { 570 const GLuint *us = (const GLuint *) map; 571 GLuint i; 572 for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) { 573 _mesa_printf("%08x ", us[i]); 574 if (i % 8 == 7) 575 _mesa_printf("\n"); 576 } 577 _mesa_printf("\n"); 578 } 579 break; 580 default: 581 ; 582 } 583 584 ctx->Driver.UnmapBuffer(ctx, 585 GL_ELEMENT_ARRAY_BUFFER_ARB, 586 ctx->Array.ElementArrayBufferObj); 587} 588 589/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */ 590static void 591vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode, 592 GLboolean index_bounds_valid, 593 GLuint start, GLuint end, 594 GLsizei count, GLenum type, 595 const GLvoid *indices) 596{ 597 struct vbo_context *vbo = vbo_context(ctx); 598 struct vbo_exec_context *exec = &vbo->exec; 599 struct _mesa_index_buffer ib; 600 struct _mesa_prim prim[1]; 601 602 FLUSH_CURRENT( ctx, 0 ); 603 604 if (ctx->NewState) 605 _mesa_update_state( ctx ); 606 607 if (!vbo_validate_shaders(ctx)) { 608 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawRangeElements(bad shader)"); 609 return; 610 } 611 612 if (ctx->NewState) 613 _mesa_update_state( ctx ); 614 615 bind_arrays( ctx ); 616 617 ib.count = count; 618 ib.type = type; 619 ib.obj = ctx->Array.ElementArrayBufferObj; 620 ib.ptr = indices; 621 622 prim[0].begin = 1; 623 prim[0].end = 1; 624 prim[0].weak = 0; 625 prim[0].pad = 0; 626 prim[0].mode = mode; 627 prim[0].start = 0; 628 prim[0].count = count; 629 prim[0].indexed = 1; 630 631 /* Need to give special consideration to rendering a range of 632 * indices starting somewhere above zero. Typically the 633 * application is issuing multiple DrawRangeElements() to draw 634 * successive primitives layed out linearly in the vertex arrays. 635 * Unless the vertex arrays are all in a VBO (or locked as with 636 * CVA), the OpenGL semantics imply that we need to re-read or 637 * re-upload the vertex data on each draw call. 638 * 639 * In the case of hardware tnl, we want to avoid starting the 640 * upload at zero, as it will mean every draw call uploads an 641 * increasing amount of not-used vertex data. Worse - in the 642 * software tnl module, all those vertices might be transformed and 643 * lit but never rendered. 644 * 645 * If we just upload or transform the vertices in start..end, 646 * however, the indices will be incorrect. 647 * 648 * At this level, we don't know exactly what the requirements of 649 * the backend are going to be, though it will likely boil down to 650 * either: 651 * 652 * 1) Do nothing, everything is in a VBO and is processed once 653 * only. 654 * 655 * 2) Adjust the indices and vertex arrays so that start becomes 656 * zero. 657 * 658 * Rather than doing anything here, I'll provide a helper function 659 * for the latter case elsewhere. 660 */ 661 662 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, 663 index_bounds_valid, start, end ); 664} 665 666static void GLAPIENTRY 667vbo_exec_DrawRangeElements(GLenum mode, 668 GLuint start, GLuint end, 669 GLsizei count, GLenum type, const GLvoid *indices) 670{ 671 GET_CURRENT_CONTEXT(ctx); 672 673 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, 674 type, indices )) 675 return; 676 677 if (end >= ctx->Array.ArrayObj->_MaxElement) { 678 /* the max element is out of bounds of one or more enabled arrays */ 679 _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, " 680 "type 0x%x, indices=%p)\n" 681 "\tindex=%u is out of bounds (max=%u) " 682 "Element Buffer %u (size %d)", 683 start, end, count, type, indices, end, 684 ctx->Array.ArrayObj->_MaxElement - 1, 685 ctx->Array.ElementArrayBufferObj->Name, 686 ctx->Array.ElementArrayBufferObj->Size); 687 688 if (0) 689 dump_element_buffer(ctx, type); 690 691 if (0) 692 _mesa_print_arrays(ctx); 693 return; 694 } 695 else if (0) { 696 _mesa_printf("glDraw[Range]Elements" 697 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n", 698 start, end, type, count, 699 ctx->Array.ElementArrayBufferObj->Name); 700 } 701 702#if 0 703 check_draw_elements_data(ctx, count, type, indices); 704#else 705 (void) check_draw_elements_data; 706#endif 707 708 vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end, 709 count, type, indices); 710} 711 712 713static void GLAPIENTRY 714vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, 715 const GLvoid *indices) 716{ 717 GET_CURRENT_CONTEXT(ctx); 718 719 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) 720 return; 721 722 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0, 723 count, type, indices); 724} 725 726 727/*********************************************************************** 728 * Initialization 729 */ 730 731void 732vbo_exec_array_init( struct vbo_exec_context *exec ) 733{ 734#if 1 735 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; 736 exec->vtxfmt.DrawElements = vbo_exec_DrawElements; 737 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements; 738#else 739 exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays; 740 exec->vtxfmt.DrawElements = _mesa_noop_DrawElements; 741 exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements; 742#endif 743} 744 745 746void 747vbo_exec_array_destroy( struct vbo_exec_context *exec ) 748{ 749 /* nothing to do */ 750} 751 752 753/* This API entrypoint is not ordinarily used */ 754void GLAPIENTRY 755_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count) 756{ 757 vbo_exec_DrawArrays(mode, first, count); 758} 759 760 761/* This API entrypoint is not ordinarily used */ 762void GLAPIENTRY 763_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, 764 const GLvoid *indices) 765{ 766 vbo_exec_DrawElements(mode, count, type, indices); 767} 768 769 770/* This API entrypoint is not ordinarily used */ 771void GLAPIENTRY 772_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, 773 GLenum type, const GLvoid *indices) 774{ 775 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices); 776} 777