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