draw.c revision 01e04c3f
1/************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 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 VMWARE 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 <stdio.h> 30#include "arrayobj.h" 31#include "glheader.h" 32#include "c99_alloca.h" 33#include "context.h" 34#include "state.h" 35#include "draw.h" 36#include "draw_validate.h" 37#include "dispatch.h" 38#include "varray.h" 39#include "bufferobj.h" 40#include "enums.h" 41#include "macros.h" 42#include "transformfeedback.h" 43 44typedef struct { 45 GLuint count; 46 GLuint primCount; 47 GLuint first; 48 GLuint baseInstance; 49} DrawArraysIndirectCommand; 50 51typedef struct { 52 GLuint count; 53 GLuint primCount; 54 GLuint firstIndex; 55 GLint baseVertex; 56 GLuint baseInstance; 57} DrawElementsIndirectCommand; 58 59 60/** 61 * Check that element 'j' of the array has reasonable data. 62 * Map VBO if needed. 63 * For debugging purposes; not normally used. 64 */ 65static void 66check_array_data(struct gl_context *ctx, struct gl_vertex_array_object *vao, 67 GLuint attrib, GLuint j) 68{ 69 const struct gl_array_attributes *array = &vao->VertexAttrib[attrib]; 70 if (array->Enabled) { 71 const struct gl_vertex_buffer_binding *binding = 72 &vao->BufferBinding[array->BufferBindingIndex]; 73 struct gl_buffer_object *bo = binding->BufferObj; 74 const void *data = array->Ptr; 75 if (_mesa_is_bufferobj(bo)) { 76 if (!bo->Mappings[MAP_INTERNAL].Pointer) { 77 /* need to map now */ 78 bo->Mappings[MAP_INTERNAL].Pointer = 79 ctx->Driver.MapBufferRange(ctx, 0, bo->Size, 80 GL_MAP_READ_BIT, bo, MAP_INTERNAL); 81 } 82 data = ADD_POINTERS(_mesa_vertex_attrib_address(array, binding), 83 bo->Mappings[MAP_INTERNAL].Pointer); 84 } 85 switch (array->Type) { 86 case GL_FLOAT: 87 { 88 GLfloat *f = (GLfloat *) ((GLubyte *) data + binding->Stride * j); 89 GLint k; 90 for (k = 0; k < array->Size; k++) { 91 if (IS_INF_OR_NAN(f[k]) || f[k] >= 1.0e20F || f[k] <= -1.0e10F) { 92 printf("Bad array data:\n"); 93 printf(" Element[%u].%u = %f\n", j, k, f[k]); 94 printf(" Array %u at %p\n", attrib, (void *) array); 95 printf(" Type 0x%x, Size %d, Stride %d\n", 96 array->Type, array->Size, binding->Stride); 97 printf(" Address/offset %p in Buffer Object %u\n", 98 array->Ptr, bo->Name); 99 f[k] = 1.0F; /* XXX replace the bad value! */ 100 } 101 /*assert(!IS_INF_OR_NAN(f[k])); */ 102 } 103 } 104 break; 105 default: 106 ; 107 } 108 } 109} 110 111 112/** 113 * Unmap the buffer object referenced by given array, if mapped. 114 */ 115static void 116unmap_array_buffer(struct gl_context *ctx, struct gl_vertex_array_object *vao, 117 GLuint attrib) 118{ 119 const struct gl_array_attributes *array = &vao->VertexAttrib[attrib]; 120 if (array->Enabled) { 121 const struct gl_vertex_buffer_binding *binding = 122 &vao->BufferBinding[array->BufferBindingIndex]; 123 struct gl_buffer_object *bo = binding->BufferObj; 124 if (_mesa_is_bufferobj(bo) && _mesa_bufferobj_mapped(bo, MAP_INTERNAL)) { 125 ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL); 126 } 127 } 128} 129 130 131static inline int 132sizeof_ib_type(GLenum type) 133{ 134 switch (type) { 135 case GL_UNSIGNED_INT: 136 return sizeof(GLuint); 137 case GL_UNSIGNED_SHORT: 138 return sizeof(GLushort); 139 case GL_UNSIGNED_BYTE: 140 return sizeof(GLubyte); 141 default: 142 assert(!"unsupported index data type"); 143 /* In case assert is turned off */ 144 return 0; 145 } 146} 147 148/** 149 * Examine the array's data for NaNs, etc. 150 * For debug purposes; not normally used. 151 */ 152static void 153check_draw_elements_data(struct gl_context *ctx, GLsizei count, 154 GLenum elemType, const void *elements, 155 GLint basevertex) 156{ 157 struct gl_vertex_array_object *vao = ctx->Array.VAO; 158 const void *elemMap; 159 GLint i; 160 GLuint k; 161 162 if (_mesa_is_bufferobj(vao->IndexBufferObj)) { 163 elemMap = ctx->Driver.MapBufferRange(ctx, 0, 164 vao->IndexBufferObj->Size, 165 GL_MAP_READ_BIT, 166 vao->IndexBufferObj, MAP_INTERNAL); 167 elements = ADD_POINTERS(elements, elemMap); 168 } 169 170 for (i = 0; i < count; i++) { 171 GLuint j; 172 173 /* j = element[i] */ 174 switch (elemType) { 175 case GL_UNSIGNED_BYTE: 176 j = ((const GLubyte *) elements)[i]; 177 break; 178 case GL_UNSIGNED_SHORT: 179 j = ((const GLushort *) elements)[i]; 180 break; 181 case GL_UNSIGNED_INT: 182 j = ((const GLuint *) elements)[i]; 183 break; 184 default: 185 unreachable("Unexpected index buffer type"); 186 } 187 188 /* check element j of each enabled array */ 189 for (k = 0; k < VERT_ATTRIB_MAX; k++) { 190 check_array_data(ctx, vao, k, j); 191 } 192 } 193 194 if (_mesa_is_bufferobj(vao->IndexBufferObj)) { 195 ctx->Driver.UnmapBuffer(ctx, vao->IndexBufferObj, MAP_INTERNAL); 196 } 197 198 for (k = 0; k < VERT_ATTRIB_MAX; k++) { 199 unmap_array_buffer(ctx, vao, k); 200 } 201} 202 203 204/** 205 * Check array data, looking for NaNs, etc. 206 */ 207static void 208check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count) 209{ 210 /* TO DO */ 211} 212 213 214/** 215 * Check if we should skip the draw call even after validation was successful. 216 */ 217static bool 218skip_validated_draw(struct gl_context *ctx) 219{ 220 switch (ctx->API) { 221 case API_OPENGLES2: 222 /* For ES2, we can draw if we have a vertex program/shader). */ 223 return ctx->VertexProgram._Current == NULL; 224 225 case API_OPENGLES: 226 /* For OpenGL ES, only draw if we have vertex positions 227 */ 228 if (!ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled) 229 return true; 230 break; 231 232 case API_OPENGL_CORE: 233 /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec 234 * says: 235 * 236 * "If there is no active program for the vertex or fragment shader 237 * stages, the results of vertex and/or fragment processing will be 238 * undefined. However, this is not an error." 239 * 240 * The fragment shader is not tested here because other state (e.g., 241 * GL_RASTERIZER_DISCARD) affects whether or not we actually care. 242 */ 243 return ctx->VertexProgram._Current == NULL; 244 245 case API_OPENGL_COMPAT: 246 if (ctx->VertexProgram._Current != NULL) { 247 /* Draw regardless of whether or not we have any vertex arrays. 248 * (Ex: could draw a point using a constant vertex pos) 249 */ 250 return false; 251 } else { 252 /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic 253 * array [0]). 254 */ 255 return (!ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled && 256 !ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled); 257 } 258 break; 259 260 default: 261 unreachable("Invalid API value in check_valid_to_render()"); 262 } 263 264 return false; 265} 266 267 268/** 269 * Print info/data for glDrawArrays(), for debugging. 270 */ 271static void 272print_draw_arrays(struct gl_context *ctx, 273 GLenum mode, GLint start, GLsizei count) 274{ 275 const struct gl_vertex_array_object *vao = ctx->Array.VAO; 276 277 printf("_mesa_exec_DrawArrays(mode 0x%x, start %d, count %d):\n", 278 mode, start, count); 279 280 unsigned i; 281 for (i = 0; i < VERT_ATTRIB_MAX; ++i) { 282 const struct gl_array_attributes *array = &vao->VertexAttrib[i]; 283 if (!array->Enabled) 284 continue; 285 286 const struct gl_vertex_buffer_binding *binding = 287 &vao->BufferBinding[array->BufferBindingIndex]; 288 struct gl_buffer_object *bufObj = binding->BufferObj; 289 290 printf("attr %s: size %d stride %d enabled %d " 291 "ptr %p Bufobj %u\n", 292 gl_vert_attrib_name((gl_vert_attrib) i), 293 array->Size, binding->Stride, array->Enabled, 294 array->Ptr, bufObj->Name); 295 296 if (_mesa_is_bufferobj(bufObj)) { 297 GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, 298 GL_MAP_READ_BIT, bufObj, 299 MAP_INTERNAL); 300 int offset = (int) (GLintptr) 301 _mesa_vertex_attrib_address(array, binding); 302 303 unsigned multiplier; 304 switch (array->Type) { 305 case GL_DOUBLE: 306 case GL_INT64_ARB: 307 case GL_UNSIGNED_INT64_ARB: 308 multiplier = 2; 309 break; 310 default: 311 multiplier = 1; 312 } 313 314 float *f = (float *) (p + offset); 315 int *k = (int *) f; 316 int i = 0; 317 int n = (count - 1) * (binding->Stride / (4 * multiplier)) 318 + array->Size; 319 if (n > 32) 320 n = 32; 321 printf(" Data at offset %d:\n", offset); 322 do { 323 if (multiplier == 2) 324 printf(" double[%d] = 0x%016llx %lf\n", i, 325 ((unsigned long long *) k)[i], ((double *) f)[i]); 326 else 327 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); 328 i++; 329 } while (i < n); 330 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); 331 } 332 } 333} 334 335 336/** 337 * Return a filter mask for the net enabled vao arrays. 338 * This is to mask out arrays that would otherwise supersed required current 339 * values for the fixed function shaders for example. 340 */ 341static GLbitfield 342enabled_filter(const struct gl_context *ctx) 343{ 344 switch (ctx->VertexProgram._VPMode) { 345 case VP_MODE_FF: 346 /* When no vertex program is active (or the vertex program is generated 347 * from fixed-function state). We put the material values into the 348 * generic slots. Since the vao has no material arrays, mute these 349 * slots from the enabled arrays so that the current material values 350 * are pulled instead of the vao arrays. 351 */ 352 return VERT_BIT_FF_ALL; 353 354 case VP_MODE_SHADER: 355 /* There are no shaders in OpenGL ES 1.x, so this code path should be 356 * impossible to reach. The meta code is careful to not use shaders in 357 * ES1. 358 */ 359 assert(ctx->API != API_OPENGLES); 360 361 /* Other parts of the code assume that inputs[VERT_ATTRIB_POS] through 362 * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL. However, in OpenGL 363 * ES 2.0+ or OpenGL core profile, none of these arrays should ever 364 * be enabled. 365 */ 366 if (ctx->API != API_OPENGL_COMPAT) 367 return VERT_BIT_GENERIC_ALL; 368 369 return VERT_BIT_ALL; 370 371 default: 372 assert(0); 373 return 0; 374 } 375} 376 377 378/** 379 * Helper function called by the other DrawArrays() functions below. 380 * This is where we handle primitive restart for drawing non-indexed 381 * arrays. If primitive restart is enabled, it typically means 382 * splitting one DrawArrays() into two. 383 */ 384static void 385_mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, 386 GLsizei count, GLuint numInstances, GLuint baseInstance, 387 GLuint drawID) 388{ 389 struct _mesa_prim prim; 390 391 if (skip_validated_draw(ctx)) 392 return; 393 394 /* OpenGL 4.5 says that primitive restart is ignored with non-indexed 395 * draws. 396 */ 397 memset(&prim, 0, sizeof(prim)); 398 prim.begin = 1; 399 prim.end = 1; 400 prim.mode = mode; 401 prim.num_instances = numInstances; 402 prim.base_instance = baseInstance; 403 prim.draw_id = drawID; 404 prim.is_indirect = 0; 405 prim.start = start; 406 prim.count = count; 407 408 ctx->Driver.Draw(ctx, &prim, 1, NULL, 409 GL_TRUE, start, start + count - 1, NULL, 0, NULL); 410 411 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 412 _mesa_flush(ctx); 413 } 414} 415 416 417/** 418 * Execute a glRectf() function. 419 */ 420static void GLAPIENTRY 421_mesa_exec_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) 422{ 423 GET_CURRENT_CONTEXT(ctx); 424 ASSERT_OUTSIDE_BEGIN_END(ctx); 425 426 CALL_Begin(GET_DISPATCH(), (GL_QUADS)); 427 CALL_Vertex2f(GET_DISPATCH(), (x1, y1)); 428 CALL_Vertex2f(GET_DISPATCH(), (x2, y1)); 429 CALL_Vertex2f(GET_DISPATCH(), (x2, y2)); 430 CALL_Vertex2f(GET_DISPATCH(), (x1, y2)); 431 CALL_End(GET_DISPATCH(), ()); 432} 433 434 435static void GLAPIENTRY 436_mesa_exec_EvalMesh1(GLenum mode, GLint i1, GLint i2) 437{ 438 GET_CURRENT_CONTEXT(ctx); 439 GLint i; 440 GLfloat u, du; 441 GLenum prim; 442 443 switch (mode) { 444 case GL_POINT: 445 prim = GL_POINTS; 446 break; 447 case GL_LINE: 448 prim = GL_LINE_STRIP; 449 break; 450 default: 451 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)"); 452 return; 453 } 454 455 /* No effect if vertex maps disabled. 456 */ 457 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3) 458 return; 459 460 du = ctx->Eval.MapGrid1du; 461 u = ctx->Eval.MapGrid1u1 + i1 * du; 462 463 CALL_Begin(GET_DISPATCH(), (prim)); 464 for (i = i1; i <= i2; i++, u += du) { 465 CALL_EvalCoord1f(GET_DISPATCH(), (u)); 466 } 467 CALL_End(GET_DISPATCH(), ()); 468} 469 470 471static void GLAPIENTRY 472_mesa_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) 473{ 474 GET_CURRENT_CONTEXT(ctx); 475 GLfloat u, du, v, dv, v1, u1; 476 GLint i, j; 477 478 switch (mode) { 479 case GL_POINT: 480 case GL_LINE: 481 case GL_FILL: 482 break; 483 default: 484 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)"); 485 return; 486 } 487 488 /* No effect if vertex maps disabled. 489 */ 490 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3) 491 return; 492 493 du = ctx->Eval.MapGrid2du; 494 dv = ctx->Eval.MapGrid2dv; 495 v1 = ctx->Eval.MapGrid2v1 + j1 * dv; 496 u1 = ctx->Eval.MapGrid2u1 + i1 * du; 497 498 switch (mode) { 499 case GL_POINT: 500 CALL_Begin(GET_DISPATCH(), (GL_POINTS)); 501 for (v = v1, j = j1; j <= j2; j++, v += dv) { 502 for (u = u1, i = i1; i <= i2; i++, u += du) { 503 CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); 504 } 505 } 506 CALL_End(GET_DISPATCH(), ()); 507 break; 508 case GL_LINE: 509 for (v = v1, j = j1; j <= j2; j++, v += dv) { 510 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP)); 511 for (u = u1, i = i1; i <= i2; i++, u += du) { 512 CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); 513 } 514 CALL_End(GET_DISPATCH(), ()); 515 } 516 for (u = u1, i = i1; i <= i2; i++, u += du) { 517 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP)); 518 for (v = v1, j = j1; j <= j2; j++, v += dv) { 519 CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); 520 } 521 CALL_End(GET_DISPATCH(), ()); 522 } 523 break; 524 case GL_FILL: 525 for (v = v1, j = j1; j < j2; j++, v += dv) { 526 CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP)); 527 for (u = u1, i = i1; i <= i2; i++, u += du) { 528 CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); 529 CALL_EvalCoord2f(GET_DISPATCH(), (u, v + dv)); 530 } 531 CALL_End(GET_DISPATCH(), ()); 532 } 533 break; 534 } 535} 536 537 538/** 539 * Called from glDrawArrays when in immediate mode (not display list mode). 540 */ 541static void GLAPIENTRY 542_mesa_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) 543{ 544 GET_CURRENT_CONTEXT(ctx); 545 546 if (MESA_VERBOSE & VERBOSE_DRAW) 547 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n", 548 _mesa_enum_to_string(mode), start, count); 549 550 FLUSH_FOR_DRAW(ctx); 551 552 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 553 554 if (_mesa_is_no_error_enabled(ctx)) { 555 if (ctx->NewState) 556 _mesa_update_state(ctx); 557 } else { 558 if (!_mesa_validate_DrawArrays(ctx, mode, count)) 559 return; 560 } 561 562 if (0) 563 check_draw_arrays_data(ctx, start, count); 564 565 _mesa_draw_arrays(ctx, mode, start, count, 1, 0, 0); 566 567 if (0) 568 print_draw_arrays(ctx, mode, start, count); 569} 570 571 572/** 573 * Called from glDrawArraysInstanced when in immediate mode (not 574 * display list mode). 575 */ 576static void GLAPIENTRY 577_mesa_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count, 578 GLsizei numInstances) 579{ 580 GET_CURRENT_CONTEXT(ctx); 581 582 if (MESA_VERBOSE & VERBOSE_DRAW) 583 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n", 584 _mesa_enum_to_string(mode), start, count, numInstances); 585 586 FLUSH_FOR_DRAW(ctx); 587 588 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 589 590 if (_mesa_is_no_error_enabled(ctx)) { 591 if (ctx->NewState) 592 _mesa_update_state(ctx); 593 } else { 594 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, 595 numInstances)) 596 return; 597 } 598 599 if (0) 600 check_draw_arrays_data(ctx, start, count); 601 602 _mesa_draw_arrays(ctx, mode, start, count, numInstances, 0, 0); 603 604 if (0) 605 print_draw_arrays(ctx, mode, start, count); 606} 607 608 609/** 610 * Called from glDrawArraysInstancedBaseInstance when in immediate mode. 611 */ 612static void GLAPIENTRY 613_mesa_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, 614 GLsizei count, GLsizei numInstances, 615 GLuint baseInstance) 616{ 617 GET_CURRENT_CONTEXT(ctx); 618 619 if (MESA_VERBOSE & VERBOSE_DRAW) 620 _mesa_debug(ctx, 621 "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n", 622 _mesa_enum_to_string(mode), first, count, 623 numInstances, baseInstance); 624 625 FLUSH_FOR_DRAW(ctx); 626 627 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 628 629 if (_mesa_is_no_error_enabled(ctx)) { 630 if (ctx->NewState) 631 _mesa_update_state(ctx); 632 } else { 633 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count, 634 numInstances)) 635 return; 636 } 637 638 if (0) 639 check_draw_arrays_data(ctx, first, count); 640 641 _mesa_draw_arrays(ctx, mode, first, count, numInstances, baseInstance, 0); 642 643 if (0) 644 print_draw_arrays(ctx, mode, first, count); 645} 646 647 648/** 649 * Called from glMultiDrawArrays when in immediate mode. 650 */ 651static void GLAPIENTRY 652_mesa_exec_MultiDrawArrays(GLenum mode, const GLint *first, 653 const GLsizei *count, GLsizei primcount) 654{ 655 GET_CURRENT_CONTEXT(ctx); 656 GLint i; 657 658 if (MESA_VERBOSE & VERBOSE_DRAW) 659 _mesa_debug(ctx, 660 "glMultiDrawArrays(%s, %p, %p, %d)\n", 661 _mesa_enum_to_string(mode), first, count, primcount); 662 663 FLUSH_FOR_DRAW(ctx); 664 665 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 666 667 if (_mesa_is_no_error_enabled(ctx)) { 668 if (ctx->NewState) 669 _mesa_update_state(ctx); 670 } else { 671 if (!_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount)) 672 return; 673 } 674 675 for (i = 0; i < primcount; i++) { 676 if (count[i] > 0) { 677 if (0) 678 check_draw_arrays_data(ctx, first[i], count[i]); 679 680 /* The GL_ARB_shader_draw_parameters spec adds the following after the 681 * pseudo-code describing glMultiDrawArrays: 682 * 683 * "The index of the draw (<i> in the above pseudo-code) may be 684 * read by a vertex shader as <gl_DrawIDARB>, as described in 685 * Section 11.1.3.9." 686 */ 687 _mesa_draw_arrays(ctx, mode, first[i], count[i], 1, 0, i); 688 689 if (0) 690 print_draw_arrays(ctx, mode, first[i], count[i]); 691 } 692 } 693} 694 695 696 697/** 698 * Map GL_ELEMENT_ARRAY_BUFFER and print contents. 699 * For debugging. 700 */ 701#if 0 702static void 703dump_element_buffer(struct gl_context *ctx, GLenum type) 704{ 705 const GLvoid *map = 706 ctx->Driver.MapBufferRange(ctx, 0, 707 ctx->Array.VAO->IndexBufferObj->Size, 708 GL_MAP_READ_BIT, 709 ctx->Array.VAO->IndexBufferObj, 710 MAP_INTERNAL); 711 switch (type) { 712 case GL_UNSIGNED_BYTE: 713 { 714 const GLubyte *us = (const GLubyte *) map; 715 GLint i; 716 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) { 717 printf("%02x ", us[i]); 718 if (i % 32 == 31) 719 printf("\n"); 720 } 721 printf("\n"); 722 } 723 break; 724 case GL_UNSIGNED_SHORT: 725 { 726 const GLushort *us = (const GLushort *) map; 727 GLint i; 728 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) { 729 printf("%04x ", us[i]); 730 if (i % 16 == 15) 731 printf("\n"); 732 } 733 printf("\n"); 734 } 735 break; 736 case GL_UNSIGNED_INT: 737 { 738 const GLuint *us = (const GLuint *) map; 739 GLint i; 740 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) { 741 printf("%08x ", us[i]); 742 if (i % 8 == 7) 743 printf("\n"); 744 } 745 printf("\n"); 746 } 747 break; 748 default: 749 ; 750 } 751 752 ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL); 753} 754#endif 755 756 757static bool 758skip_draw_elements(struct gl_context *ctx, GLsizei count, 759 const GLvoid *indices) 760{ 761 if (count == 0) 762 return true; 763 764 /* Not using a VBO for indices, so avoid NULL pointer derefs later. 765 */ 766 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL) 767 return true; 768 769 if (skip_validated_draw(ctx)) 770 return true; 771 772 return false; 773} 774 775 776/** 777 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements. 778 * Do the rendering for a glDrawElements or glDrawRangeElements call after 779 * we've validated buffer bounds, etc. 780 */ 781static void 782_mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, 783 GLboolean index_bounds_valid, 784 GLuint start, GLuint end, 785 GLsizei count, GLenum type, 786 const GLvoid * indices, 787 GLint basevertex, GLuint numInstances, 788 GLuint baseInstance) 789{ 790 struct _mesa_index_buffer ib; 791 struct _mesa_prim prim; 792 793 if (!index_bounds_valid) { 794 assert(start == 0u); 795 assert(end == ~0u); 796 } 797 798 if (skip_draw_elements(ctx, count, indices)) 799 return; 800 801 ib.count = count; 802 ib.index_size = sizeof_ib_type(type); 803 ib.obj = ctx->Array.VAO->IndexBufferObj; 804 ib.ptr = indices; 805 806 prim.begin = 1; 807 prim.end = 1; 808 prim.pad = 0; 809 prim.mode = mode; 810 prim.start = 0; 811 prim.count = count; 812 prim.indexed = 1; 813 prim.is_indirect = 0; 814 prim.basevertex = basevertex; 815 prim.num_instances = numInstances; 816 prim.base_instance = baseInstance; 817 prim.draw_id = 0; 818 819 /* Need to give special consideration to rendering a range of 820 * indices starting somewhere above zero. Typically the 821 * application is issuing multiple DrawRangeElements() to draw 822 * successive primitives layed out linearly in the vertex arrays. 823 * Unless the vertex arrays are all in a VBO (or locked as with 824 * CVA), the OpenGL semantics imply that we need to re-read or 825 * re-upload the vertex data on each draw call. 826 * 827 * In the case of hardware tnl, we want to avoid starting the 828 * upload at zero, as it will mean every draw call uploads an 829 * increasing amount of not-used vertex data. Worse - in the 830 * software tnl module, all those vertices might be transformed and 831 * lit but never rendered. 832 * 833 * If we just upload or transform the vertices in start..end, 834 * however, the indices will be incorrect. 835 * 836 * At this level, we don't know exactly what the requirements of 837 * the backend are going to be, though it will likely boil down to 838 * either: 839 * 840 * 1) Do nothing, everything is in a VBO and is processed once 841 * only. 842 * 843 * 2) Adjust the indices and vertex arrays so that start becomes 844 * zero. 845 * 846 * Rather than doing anything here, I'll provide a helper function 847 * for the latter case elsewhere. 848 */ 849 850 ctx->Driver.Draw(ctx, &prim, 1, &ib, 851 index_bounds_valid, start, end, NULL, 0, NULL); 852 853 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 854 _mesa_flush(ctx); 855 } 856} 857 858 859/** 860 * Called by glDrawRangeElementsBaseVertex() in immediate mode. 861 */ 862static void GLAPIENTRY 863_mesa_exec_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, 864 GLsizei count, GLenum type, 865 const GLvoid * indices, GLint basevertex) 866{ 867 static GLuint warnCount = 0; 868 GLboolean index_bounds_valid = GL_TRUE; 869 870 /* This is only useful to catch invalid values in the "end" parameter 871 * like ~0. 872 */ 873 GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */ 874 875 GET_CURRENT_CONTEXT(ctx); 876 877 if (MESA_VERBOSE & VERBOSE_DRAW) 878 _mesa_debug(ctx, 879 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n", 880 _mesa_enum_to_string(mode), start, end, count, 881 _mesa_enum_to_string(type), indices, basevertex); 882 883 FLUSH_FOR_DRAW(ctx); 884 885 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 886 887 if (_mesa_is_no_error_enabled(ctx)) { 888 if (ctx->NewState) 889 _mesa_update_state(ctx); 890 } else { 891 if (!_mesa_validate_DrawRangeElements(ctx, mode, start, end, count, 892 type, indices)) 893 return; 894 } 895 896 if ((int) end + basevertex < 0 || start + basevertex >= max_element) { 897 /* The application requested we draw using a range of indices that's 898 * outside the bounds of the current VBO. This is invalid and appears 899 * to give undefined results. The safest thing to do is to simply 900 * ignore the range, in case the application botched their range tracking 901 * but did provide valid indices. Also issue a warning indicating that 902 * the application is broken. 903 */ 904 if (warnCount++ < 10) { 905 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, " 906 "basevertex %d, count %d, type 0x%x, indices=%p):\n" 907 "\trange is outside VBO bounds (max=%u); ignoring.\n" 908 "\tThis should be fixed in the application.", 909 start, end, basevertex, count, type, indices, 910 max_element - 1); 911 } 912 index_bounds_valid = GL_FALSE; 913 } 914 915 /* NOTE: It's important that 'end' is a reasonable value. 916 * in _tnl_draw_prims(), we use end to determine how many vertices 917 * to transform. If it's too large, we can unnecessarily split prims 918 * or we can read/write out of memory in several different places! 919 */ 920 921 /* Catch/fix some potential user errors */ 922 if (type == GL_UNSIGNED_BYTE) { 923 start = MIN2(start, 0xff); 924 end = MIN2(end, 0xff); 925 } 926 else if (type == GL_UNSIGNED_SHORT) { 927 start = MIN2(start, 0xffff); 928 end = MIN2(end, 0xffff); 929 } 930 931 if (0) { 932 printf("glDraw[Range]Elements{,BaseVertex}" 933 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, " 934 "base %d\n", 935 start, end, type, count, 936 ctx->Array.VAO->IndexBufferObj->Name, basevertex); 937 } 938 939 if ((int) start + basevertex < 0 || end + basevertex >= max_element) 940 index_bounds_valid = GL_FALSE; 941 942#if 0 943 check_draw_elements_data(ctx, count, type, indices, basevertex); 944#else 945 (void) check_draw_elements_data; 946#endif 947 948 if (!index_bounds_valid) { 949 start = 0; 950 end = ~0; 951 } 952 953 _mesa_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end, 954 count, type, indices, basevertex, 1, 0); 955} 956 957 958/** 959 * Called by glDrawRangeElements() in immediate mode. 960 */ 961static void GLAPIENTRY 962_mesa_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end, 963 GLsizei count, GLenum type, const GLvoid * indices) 964{ 965 if (MESA_VERBOSE & VERBOSE_DRAW) { 966 GET_CURRENT_CONTEXT(ctx); 967 _mesa_debug(ctx, 968 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n", 969 _mesa_enum_to_string(mode), start, end, count, 970 _mesa_enum_to_string(type), indices); 971 } 972 973 _mesa_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type, 974 indices, 0); 975} 976 977 978/** 979 * Called by glDrawElements() in immediate mode. 980 */ 981static void GLAPIENTRY 982_mesa_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, 983 const GLvoid * indices) 984{ 985 GET_CURRENT_CONTEXT(ctx); 986 987 if (MESA_VERBOSE & VERBOSE_DRAW) 988 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n", 989 _mesa_enum_to_string(mode), count, 990 _mesa_enum_to_string(type), indices); 991 992 FLUSH_FOR_DRAW(ctx); 993 994 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 995 996 if (_mesa_is_no_error_enabled(ctx)) { 997 if (ctx->NewState) 998 _mesa_update_state(ctx); 999 } else { 1000 if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices)) 1001 return; 1002 } 1003 1004 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0, 1005 count, type, indices, 0, 1, 0); 1006} 1007 1008 1009/** 1010 * Called by glDrawElementsBaseVertex() in immediate mode. 1011 */ 1012static void GLAPIENTRY 1013_mesa_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 1014 const GLvoid * indices, GLint basevertex) 1015{ 1016 GET_CURRENT_CONTEXT(ctx); 1017 1018 if (MESA_VERBOSE & VERBOSE_DRAW) 1019 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n", 1020 _mesa_enum_to_string(mode), count, 1021 _mesa_enum_to_string(type), indices); 1022 1023 FLUSH_FOR_DRAW(ctx); 1024 1025 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1026 1027 if (_mesa_is_no_error_enabled(ctx)) { 1028 if (ctx->NewState) 1029 _mesa_update_state(ctx); 1030 } else { 1031 if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices)) 1032 return; 1033 } 1034 1035 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0, 1036 count, type, indices, basevertex, 1, 0); 1037} 1038 1039 1040/** 1041 * Called by glDrawElementsInstanced() in immediate mode. 1042 */ 1043static void GLAPIENTRY 1044_mesa_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, 1045 const GLvoid * indices, GLsizei numInstances) 1046{ 1047 GET_CURRENT_CONTEXT(ctx); 1048 1049 if (MESA_VERBOSE & VERBOSE_DRAW) 1050 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n", 1051 _mesa_enum_to_string(mode), count, 1052 _mesa_enum_to_string(type), indices); 1053 1054 FLUSH_FOR_DRAW(ctx); 1055 1056 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1057 1058 if (_mesa_is_no_error_enabled(ctx)) { 1059 if (ctx->NewState) 1060 _mesa_update_state(ctx); 1061 } else { 1062 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 1063 indices, numInstances)) 1064 return; 1065 } 1066 1067 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0, 1068 count, type, indices, 0, numInstances, 0); 1069} 1070 1071 1072/** 1073 * Called by glDrawElementsInstancedBaseVertex() in immediate mode. 1074 */ 1075static void GLAPIENTRY 1076_mesa_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, 1077 GLenum type, const GLvoid * indices, 1078 GLsizei numInstances, 1079 GLint basevertex) 1080{ 1081 GET_CURRENT_CONTEXT(ctx); 1082 1083 if (MESA_VERBOSE & VERBOSE_DRAW) 1084 _mesa_debug(ctx, 1085 "glDrawElementsInstancedBaseVertex" 1086 "(%s, %d, %s, %p, %d; %d)\n", 1087 _mesa_enum_to_string(mode), count, 1088 _mesa_enum_to_string(type), indices, 1089 numInstances, basevertex); 1090 1091 FLUSH_FOR_DRAW(ctx); 1092 1093 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1094 1095 if (_mesa_is_no_error_enabled(ctx)) { 1096 if (ctx->NewState) 1097 _mesa_update_state(ctx); 1098 } else { 1099 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 1100 indices, numInstances)) 1101 return; 1102 } 1103 1104 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0, 1105 count, type, indices, 1106 basevertex, numInstances, 0); 1107} 1108 1109 1110/** 1111 * Called by glDrawElementsInstancedBaseInstance() in immediate mode. 1112 */ 1113static void GLAPIENTRY 1114_mesa_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, 1115 GLenum type, 1116 const GLvoid *indices, 1117 GLsizei numInstances, 1118 GLuint baseInstance) 1119{ 1120 GET_CURRENT_CONTEXT(ctx); 1121 1122 if (MESA_VERBOSE & VERBOSE_DRAW) 1123 _mesa_debug(ctx, 1124 "glDrawElementsInstancedBaseInstance" 1125 "(%s, %d, %s, %p, %d, %d)\n", 1126 _mesa_enum_to_string(mode), count, 1127 _mesa_enum_to_string(type), indices, 1128 numInstances, baseInstance); 1129 1130 FLUSH_FOR_DRAW(ctx); 1131 1132 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1133 1134 if (_mesa_is_no_error_enabled(ctx)) { 1135 if (ctx->NewState) 1136 _mesa_update_state(ctx); 1137 } else { 1138 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 1139 indices, numInstances)) 1140 return; 1141 } 1142 1143 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0, 1144 count, type, indices, 0, numInstances, 1145 baseInstance); 1146} 1147 1148 1149/** 1150 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode. 1151 */ 1152static void GLAPIENTRY 1153_mesa_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, 1154 GLsizei count, 1155 GLenum type, 1156 const GLvoid *indices, 1157 GLsizei numInstances, 1158 GLint basevertex, 1159 GLuint baseInstance) 1160{ 1161 GET_CURRENT_CONTEXT(ctx); 1162 1163 if (MESA_VERBOSE & VERBOSE_DRAW) 1164 _mesa_debug(ctx, 1165 "glDrawElementsInstancedBaseVertexBaseInstance" 1166 "(%s, %d, %s, %p, %d, %d, %d)\n", 1167 _mesa_enum_to_string(mode), count, 1168 _mesa_enum_to_string(type), indices, 1169 numInstances, basevertex, baseInstance); 1170 1171 FLUSH_FOR_DRAW(ctx); 1172 1173 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1174 1175 if (_mesa_is_no_error_enabled(ctx)) { 1176 if (ctx->NewState) 1177 _mesa_update_state(ctx); 1178 } else { 1179 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, 1180 indices, numInstances)) 1181 return; 1182 } 1183 1184 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0, 1185 count, type, indices, basevertex, 1186 numInstances, baseInstance); 1187} 1188 1189 1190/** 1191 * Inner support for both _mesa_MultiDrawElements() and 1192 * _mesa_MultiDrawRangeElements(). 1193 * This does the actual rendering after we've checked array indexes, etc. 1194 */ 1195static void 1196_mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode, 1197 const GLsizei *count, GLenum type, 1198 const GLvoid * const *indices, 1199 GLsizei primcount, const GLint *basevertex) 1200{ 1201 struct _mesa_index_buffer ib; 1202 struct _mesa_prim *prim; 1203 unsigned int index_type_size = sizeof_ib_type(type); 1204 uintptr_t min_index_ptr, max_index_ptr; 1205 GLboolean fallback = GL_FALSE; 1206 int i; 1207 1208 if (primcount == 0) 1209 return; 1210 1211 prim = calloc(primcount, sizeof(*prim)); 1212 if (prim == NULL) { 1213 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements"); 1214 return; 1215 } 1216 1217 min_index_ptr = (uintptr_t) indices[0]; 1218 max_index_ptr = 0; 1219 for (i = 0; i < primcount; i++) { 1220 min_index_ptr = MIN2(min_index_ptr, (uintptr_t) indices[i]); 1221 max_index_ptr = MAX2(max_index_ptr, (uintptr_t) indices[i] + 1222 index_type_size * count[i]); 1223 } 1224 1225 /* Check if we can handle this thing as a bunch of index offsets from the 1226 * same index pointer. If we can't, then we have to fall back to doing 1227 * a draw_prims per primitive. 1228 * Check that the difference between each prim's indexes is a multiple of 1229 * the index/element size. 1230 */ 1231 if (index_type_size != 1) { 1232 for (i = 0; i < primcount; i++) { 1233 if ((((uintptr_t) indices[i] - min_index_ptr) % index_type_size) != 1234 0) { 1235 fallback = GL_TRUE; 1236 break; 1237 } 1238 } 1239 } 1240 1241 /* Draw primitives individually if one count is zero, so we can easily skip 1242 * that primitive. 1243 */ 1244 for (i = 0; i < primcount; i++) { 1245 if (count[i] == 0) { 1246 fallback = GL_TRUE; 1247 break; 1248 } 1249 } 1250 1251 /* If the index buffer isn't in a VBO, then treating the application's 1252 * subranges of the index buffer as one large index buffer may lead to 1253 * us reading unmapped memory. 1254 */ 1255 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) 1256 fallback = GL_TRUE; 1257 1258 if (!fallback) { 1259 ib.count = (max_index_ptr - min_index_ptr) / index_type_size; 1260 ib.index_size = sizeof_ib_type(type); 1261 ib.obj = ctx->Array.VAO->IndexBufferObj; 1262 ib.ptr = (void *) min_index_ptr; 1263 1264 for (i = 0; i < primcount; i++) { 1265 prim[i].begin = (i == 0); 1266 prim[i].end = (i == primcount - 1); 1267 prim[i].pad = 0; 1268 prim[i].mode = mode; 1269 prim[i].start = 1270 ((uintptr_t) indices[i] - min_index_ptr) / index_type_size; 1271 prim[i].count = count[i]; 1272 prim[i].indexed = 1; 1273 prim[i].num_instances = 1; 1274 prim[i].base_instance = 0; 1275 prim[i].draw_id = i; 1276 prim[i].is_indirect = 0; 1277 if (basevertex != NULL) 1278 prim[i].basevertex = basevertex[i]; 1279 else 1280 prim[i].basevertex = 0; 1281 } 1282 1283 ctx->Driver.Draw(ctx, prim, primcount, &ib, 1284 false, 0, ~0, NULL, 0, NULL); 1285 } 1286 else { 1287 /* render one prim at a time */ 1288 for (i = 0; i < primcount; i++) { 1289 if (count[i] == 0) 1290 continue; 1291 ib.count = count[i]; 1292 ib.index_size = sizeof_ib_type(type); 1293 ib.obj = ctx->Array.VAO->IndexBufferObj; 1294 ib.ptr = indices[i]; 1295 1296 prim[0].begin = 1; 1297 prim[0].end = 1; 1298 prim[0].pad = 0; 1299 prim[0].mode = mode; 1300 prim[0].start = 0; 1301 prim[0].count = count[i]; 1302 prim[0].indexed = 1; 1303 prim[0].num_instances = 1; 1304 prim[0].base_instance = 0; 1305 prim[0].draw_id = i; 1306 prim[0].is_indirect = 0; 1307 if (basevertex != NULL) 1308 prim[0].basevertex = basevertex[i]; 1309 else 1310 prim[0].basevertex = 0; 1311 1312 ctx->Driver.Draw(ctx, prim, 1, &ib, false, 0, ~0, NULL, 0, NULL); 1313 } 1314 } 1315 1316 free(prim); 1317 1318 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 1319 _mesa_flush(ctx); 1320 } 1321} 1322 1323 1324static void GLAPIENTRY 1325_mesa_exec_MultiDrawElements(GLenum mode, 1326 const GLsizei *count, GLenum type, 1327 const GLvoid * const *indices, GLsizei primcount) 1328{ 1329 GET_CURRENT_CONTEXT(ctx); 1330 1331 FLUSH_FOR_DRAW(ctx); 1332 1333 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1334 1335 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, 1336 primcount)) 1337 return; 1338 1339 if (skip_validated_draw(ctx)) 1340 return; 1341 1342 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 1343 NULL); 1344} 1345 1346 1347static void GLAPIENTRY 1348_mesa_exec_MultiDrawElementsBaseVertex(GLenum mode, 1349 const GLsizei *count, GLenum type, 1350 const GLvoid * const *indices, 1351 GLsizei primcount, 1352 const GLsizei *basevertex) 1353{ 1354 GET_CURRENT_CONTEXT(ctx); 1355 1356 FLUSH_FOR_DRAW(ctx); 1357 1358 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1359 1360 if (_mesa_is_no_error_enabled(ctx)) { 1361 if (ctx->NewState) 1362 _mesa_update_state(ctx); 1363 } else { 1364 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices, 1365 primcount)) 1366 return; 1367 } 1368 1369 if (skip_validated_draw(ctx)) 1370 return; 1371 1372 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount, 1373 basevertex); 1374} 1375 1376 1377/** 1378 * Draw a GL primitive using a vertex count obtained from transform feedback. 1379 * \param mode the type of GL primitive to draw 1380 * \param obj the transform feedback object to use 1381 * \param stream index of the transform feedback stream from which to 1382 * get the primitive count. 1383 * \param numInstances number of instances to draw 1384 */ 1385static void 1386_mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode, 1387 struct gl_transform_feedback_object *obj, 1388 GLuint stream, GLuint numInstances) 1389{ 1390 struct _mesa_prim prim; 1391 1392 FLUSH_FOR_DRAW(ctx); 1393 1394 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1395 1396 if (_mesa_is_no_error_enabled(ctx)) { 1397 if (ctx->NewState) 1398 _mesa_update_state(ctx); 1399 } else { 1400 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream, 1401 numInstances)) { 1402 return; 1403 } 1404 } 1405 1406 if (ctx->Driver.GetTransformFeedbackVertexCount && 1407 (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount || 1408 !_mesa_all_varyings_in_vbos(ctx->Array.VAO))) { 1409 GLsizei n = 1410 ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream); 1411 _mesa_draw_arrays(ctx, mode, 0, n, numInstances, 0, 0); 1412 return; 1413 } 1414 1415 if (skip_validated_draw(ctx)) 1416 return; 1417 1418 /* init most fields to zero */ 1419 memset(&prim, 0, sizeof(prim)); 1420 prim.begin = 1; 1421 prim.end = 1; 1422 prim.mode = mode; 1423 prim.num_instances = numInstances; 1424 prim.base_instance = 0; 1425 prim.is_indirect = 0; 1426 1427 /* Maybe we should do some primitive splitting for primitive restart 1428 * (like in DrawArrays), but we have no way to know how many vertices 1429 * will be rendered. */ 1430 1431 ctx->Driver.Draw(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, obj, stream, NULL); 1432 1433 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 1434 _mesa_flush(ctx); 1435 } 1436} 1437 1438 1439/** 1440 * Like DrawArrays, but take the count from a transform feedback object. 1441 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc. 1442 * \param name the transform feedback object 1443 * User still has to setup of the vertex attribute info with 1444 * glVertexPointer, glColorPointer, etc. 1445 * Part of GL_ARB_transform_feedback2. 1446 */ 1447static void GLAPIENTRY 1448_mesa_exec_DrawTransformFeedback(GLenum mode, GLuint name) 1449{ 1450 GET_CURRENT_CONTEXT(ctx); 1451 struct gl_transform_feedback_object *obj = 1452 _mesa_lookup_transform_feedback_object(ctx, name); 1453 1454 if (MESA_VERBOSE & VERBOSE_DRAW) 1455 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n", 1456 _mesa_enum_to_string(mode), name); 1457 1458 _mesa_draw_transform_feedback(ctx, mode, obj, 0, 1); 1459} 1460 1461 1462static void GLAPIENTRY 1463_mesa_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream) 1464{ 1465 GET_CURRENT_CONTEXT(ctx); 1466 struct gl_transform_feedback_object *obj = 1467 _mesa_lookup_transform_feedback_object(ctx, name); 1468 1469 if (MESA_VERBOSE & VERBOSE_DRAW) 1470 _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n", 1471 _mesa_enum_to_string(mode), name, stream); 1472 1473 _mesa_draw_transform_feedback(ctx, mode, obj, stream, 1); 1474} 1475 1476 1477static void GLAPIENTRY 1478_mesa_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name, 1479 GLsizei primcount) 1480{ 1481 GET_CURRENT_CONTEXT(ctx); 1482 struct gl_transform_feedback_object *obj = 1483 _mesa_lookup_transform_feedback_object(ctx, name); 1484 1485 if (MESA_VERBOSE & VERBOSE_DRAW) 1486 _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n", 1487 _mesa_enum_to_string(mode), name); 1488 1489 _mesa_draw_transform_feedback(ctx, mode, obj, 0, primcount); 1490} 1491 1492 1493static void GLAPIENTRY 1494_mesa_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name, 1495 GLuint stream, 1496 GLsizei primcount) 1497{ 1498 GET_CURRENT_CONTEXT(ctx); 1499 struct gl_transform_feedback_object *obj = 1500 _mesa_lookup_transform_feedback_object(ctx, name); 1501 1502 if (MESA_VERBOSE & VERBOSE_DRAW) 1503 _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced" 1504 "(%s, %u, %u, %i)\n", 1505 _mesa_enum_to_string(mode), name, stream, primcount); 1506 1507 _mesa_draw_transform_feedback(ctx, mode, obj, stream, primcount); 1508} 1509 1510 1511static void 1512_mesa_validated_drawarraysindirect(struct gl_context *ctx, 1513 GLenum mode, const GLvoid *indirect) 1514{ 1515 ctx->Driver.DrawIndirect(ctx, mode, 1516 ctx->DrawIndirectBuffer, (GLsizeiptr) indirect, 1517 1 /* draw_count */ , 16 /* stride */ , 1518 NULL, 0, NULL); 1519 1520 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 1521 _mesa_flush(ctx); 1522} 1523 1524 1525static void 1526_mesa_validated_multidrawarraysindirect(struct gl_context *ctx, 1527 GLenum mode, 1528 const GLvoid *indirect, 1529 GLsizei primcount, GLsizei stride) 1530{ 1531 GLsizeiptr offset = (GLsizeiptr) indirect; 1532 1533 if (primcount == 0) 1534 return; 1535 1536 ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, offset, 1537 primcount, stride, NULL, 0, NULL); 1538 1539 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 1540 _mesa_flush(ctx); 1541} 1542 1543 1544static void 1545_mesa_validated_drawelementsindirect(struct gl_context *ctx, 1546 GLenum mode, GLenum type, 1547 const GLvoid *indirect) 1548{ 1549 struct _mesa_index_buffer ib; 1550 1551 ib.count = 0; /* unknown */ 1552 ib.index_size = sizeof_ib_type(type); 1553 ib.obj = ctx->Array.VAO->IndexBufferObj; 1554 ib.ptr = NULL; 1555 1556 ctx->Driver.DrawIndirect(ctx, mode, 1557 ctx->DrawIndirectBuffer, (GLsizeiptr) indirect, 1558 1 /* draw_count */ , 20 /* stride */ , 1559 NULL, 0, &ib); 1560 1561 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 1562 _mesa_flush(ctx); 1563} 1564 1565 1566static void 1567_mesa_validated_multidrawelementsindirect(struct gl_context *ctx, 1568 GLenum mode, GLenum type, 1569 const GLvoid *indirect, 1570 GLsizei primcount, GLsizei stride) 1571{ 1572 struct _mesa_index_buffer ib; 1573 GLsizeiptr offset = (GLsizeiptr) indirect; 1574 1575 if (primcount == 0) 1576 return; 1577 1578 /* NOTE: IndexBufferObj is guaranteed to be a VBO. */ 1579 1580 ib.count = 0; /* unknown */ 1581 ib.index_size = sizeof_ib_type(type); 1582 ib.obj = ctx->Array.VAO->IndexBufferObj; 1583 ib.ptr = NULL; 1584 1585 ctx->Driver.DrawIndirect(ctx, mode, 1586 ctx->DrawIndirectBuffer, offset, 1587 primcount, stride, NULL, 0, &ib); 1588 1589 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 1590 _mesa_flush(ctx); 1591} 1592 1593 1594/** 1595 * Like [Multi]DrawArrays/Elements, but they take most arguments from 1596 * a buffer object. 1597 */ 1598static void GLAPIENTRY 1599_mesa_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect) 1600{ 1601 GET_CURRENT_CONTEXT(ctx); 1602 1603 if (MESA_VERBOSE & VERBOSE_DRAW) 1604 _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n", 1605 _mesa_enum_to_string(mode), indirect); 1606 1607 /* From the ARB_draw_indirect spec: 1608 * 1609 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 1610 * compatibility profile, this indicates that DrawArraysIndirect and 1611 * DrawElementsIndirect are to source their arguments directly from the 1612 * pointer passed as their <indirect> parameters." 1613 */ 1614 if (ctx->API == API_OPENGL_COMPAT && 1615 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { 1616 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect; 1617 1618 _mesa_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count, 1619 cmd->primCount, 1620 cmd->baseInstance); 1621 return; 1622 } 1623 1624 FLUSH_FOR_DRAW(ctx); 1625 1626 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1627 1628 if (_mesa_is_no_error_enabled(ctx)) { 1629 if (ctx->NewState) 1630 _mesa_update_state(ctx); 1631 } else { 1632 if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect)) 1633 return; 1634 } 1635 1636 if (skip_validated_draw(ctx)) 1637 return; 1638 1639 _mesa_validated_drawarraysindirect(ctx, mode, indirect); 1640} 1641 1642 1643static void GLAPIENTRY 1644_mesa_exec_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect) 1645{ 1646 GET_CURRENT_CONTEXT(ctx); 1647 1648 if (MESA_VERBOSE & VERBOSE_DRAW) 1649 _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n", 1650 _mesa_enum_to_string(mode), 1651 _mesa_enum_to_string(type), indirect); 1652 1653 /* From the ARB_draw_indirect spec: 1654 * 1655 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 1656 * compatibility profile, this indicates that DrawArraysIndirect and 1657 * DrawElementsIndirect are to source their arguments directly from the 1658 * pointer passed as their <indirect> parameters." 1659 */ 1660 if (ctx->API == API_OPENGL_COMPAT && 1661 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { 1662 /* 1663 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices 1664 * may not come from a client array and must come from an index buffer. 1665 * If no element array buffer is bound, an INVALID_OPERATION error is 1666 * generated. 1667 */ 1668 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { 1669 _mesa_error(ctx, GL_INVALID_OPERATION, 1670 "glDrawElementsIndirect(no buffer bound " 1671 "to GL_ELEMENT_ARRAY_BUFFER)"); 1672 } else { 1673 DrawElementsIndirectCommand *cmd = 1674 (DrawElementsIndirectCommand *) indirect; 1675 1676 /* Convert offset to pointer */ 1677 void *offset = (void *) 1678 ((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL); 1679 1680 _mesa_exec_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count, 1681 type, offset, 1682 cmd->primCount, 1683 cmd->baseVertex, 1684 cmd->baseInstance); 1685 } 1686 1687 return; 1688 } 1689 1690 FLUSH_FOR_DRAW(ctx); 1691 1692 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1693 1694 if (_mesa_is_no_error_enabled(ctx)) { 1695 if (ctx->NewState) 1696 _mesa_update_state(ctx); 1697 } else { 1698 if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect)) 1699 return; 1700 } 1701 1702 if (skip_validated_draw(ctx)) 1703 return; 1704 1705 _mesa_validated_drawelementsindirect(ctx, mode, type, indirect); 1706} 1707 1708 1709static void GLAPIENTRY 1710_mesa_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect, 1711 GLsizei primcount, GLsizei stride) 1712{ 1713 GET_CURRENT_CONTEXT(ctx); 1714 1715 if (MESA_VERBOSE & VERBOSE_DRAW) 1716 _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n", 1717 _mesa_enum_to_string(mode), indirect, primcount, stride); 1718 1719 /* If <stride> is zero, the array elements are treated as tightly packed. */ 1720 if (stride == 0) 1721 stride = sizeof(DrawArraysIndirectCommand); 1722 1723 /* From the ARB_draw_indirect spec: 1724 * 1725 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 1726 * compatibility profile, this indicates that DrawArraysIndirect and 1727 * DrawElementsIndirect are to source their arguments directly from the 1728 * pointer passed as their <indirect> parameters." 1729 */ 1730 if (ctx->API == API_OPENGL_COMPAT && 1731 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { 1732 1733 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, 1734 "glMultiDrawArraysIndirect")) 1735 return; 1736 1737 const ubyte *ptr = (const ubyte *) indirect; 1738 for (unsigned i = 0; i < primcount; i++) { 1739 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr; 1740 _mesa_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, 1741 cmd->count, cmd->primCount, 1742 cmd->baseInstance); 1743 1744 if (stride == 0) { 1745 ptr += sizeof(DrawArraysIndirectCommand); 1746 } else { 1747 ptr += stride; 1748 } 1749 } 1750 1751 return; 1752 } 1753 1754 FLUSH_FOR_DRAW(ctx); 1755 1756 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1757 1758 if (_mesa_is_no_error_enabled(ctx)) { 1759 if (ctx->NewState) 1760 _mesa_update_state(ctx); 1761 } else { 1762 if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect, 1763 primcount, stride)) 1764 return; 1765 } 1766 1767 if (skip_validated_draw(ctx)) 1768 return; 1769 1770 _mesa_validated_multidrawarraysindirect(ctx, mode, indirect, 1771 primcount, stride); 1772} 1773 1774 1775static void GLAPIENTRY 1776_mesa_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type, 1777 const GLvoid *indirect, 1778 GLsizei primcount, GLsizei stride) 1779{ 1780 GET_CURRENT_CONTEXT(ctx); 1781 1782 if (MESA_VERBOSE & VERBOSE_DRAW) 1783 _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n", 1784 _mesa_enum_to_string(mode), 1785 _mesa_enum_to_string(type), indirect, primcount, stride); 1786 1787 /* If <stride> is zero, the array elements are treated as tightly packed. */ 1788 if (stride == 0) 1789 stride = sizeof(DrawElementsIndirectCommand); 1790 1791 1792 /* From the ARB_draw_indirect spec: 1793 * 1794 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the 1795 * compatibility profile, this indicates that DrawArraysIndirect and 1796 * DrawElementsIndirect are to source their arguments directly from the 1797 * pointer passed as their <indirect> parameters." 1798 */ 1799 if (ctx->API == API_OPENGL_COMPAT && 1800 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { 1801 /* 1802 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices 1803 * may not come from a client array and must come from an index buffer. 1804 * If no element array buffer is bound, an INVALID_OPERATION error is 1805 * generated. 1806 */ 1807 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { 1808 _mesa_error(ctx, GL_INVALID_OPERATION, 1809 "glMultiDrawElementsIndirect(no buffer bound " 1810 "to GL_ELEMENT_ARRAY_BUFFER)"); 1811 1812 return; 1813 } 1814 1815 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride, 1816 "glMultiDrawArraysIndirect")) 1817 return; 1818 1819 const ubyte *ptr = (const ubyte *) indirect; 1820 for (unsigned i = 0; i < primcount; i++) { 1821 _mesa_exec_DrawElementsIndirect(mode, type, ptr); 1822 1823 if (stride == 0) { 1824 ptr += sizeof(DrawElementsIndirectCommand); 1825 } else { 1826 ptr += stride; 1827 } 1828 } 1829 1830 return; 1831 } 1832 1833 FLUSH_FOR_DRAW(ctx); 1834 1835 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1836 1837 if (_mesa_is_no_error_enabled(ctx)) { 1838 if (ctx->NewState) 1839 _mesa_update_state(ctx); 1840 } else { 1841 if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect, 1842 primcount, stride)) 1843 return; 1844 } 1845 1846 if (skip_validated_draw(ctx)) 1847 return; 1848 1849 _mesa_validated_multidrawelementsindirect(ctx, mode, type, indirect, 1850 primcount, stride); 1851} 1852 1853 1854static void 1855_mesa_validated_multidrawarraysindirectcount(struct gl_context *ctx, 1856 GLenum mode, 1857 GLintptr indirect, 1858 GLintptr drawcount_offset, 1859 GLsizei maxdrawcount, 1860 GLsizei stride) 1861{ 1862 GLsizeiptr offset = indirect; 1863 1864 if (maxdrawcount == 0) 1865 return; 1866 1867 ctx->Driver.DrawIndirect(ctx, mode, 1868 ctx->DrawIndirectBuffer, offset, 1869 maxdrawcount, stride, 1870 ctx->ParameterBuffer, drawcount_offset, NULL); 1871 1872 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 1873 _mesa_flush(ctx); 1874} 1875 1876 1877static void 1878_mesa_validated_multidrawelementsindirectcount(struct gl_context *ctx, 1879 GLenum mode, GLenum type, 1880 GLintptr indirect, 1881 GLintptr drawcount_offset, 1882 GLsizei maxdrawcount, 1883 GLsizei stride) 1884{ 1885 struct _mesa_index_buffer ib; 1886 GLsizeiptr offset = (GLsizeiptr) indirect; 1887 1888 if (maxdrawcount == 0) 1889 return; 1890 1891 /* NOTE: IndexBufferObj is guaranteed to be a VBO. */ 1892 1893 ib.count = 0; /* unknown */ 1894 ib.index_size = sizeof_ib_type(type); 1895 ib.obj = ctx->Array.VAO->IndexBufferObj; 1896 ib.ptr = NULL; 1897 1898 ctx->Driver.DrawIndirect(ctx, mode, 1899 ctx->DrawIndirectBuffer, offset, 1900 maxdrawcount, stride, 1901 ctx->ParameterBuffer, drawcount_offset, &ib); 1902 1903 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) 1904 _mesa_flush(ctx); 1905} 1906 1907 1908static void GLAPIENTRY 1909_mesa_exec_MultiDrawArraysIndirectCount(GLenum mode, GLintptr indirect, 1910 GLintptr drawcount_offset, 1911 GLsizei maxdrawcount, GLsizei stride) 1912{ 1913 GET_CURRENT_CONTEXT(ctx); 1914 1915 if (MESA_VERBOSE & VERBOSE_DRAW) 1916 _mesa_debug(ctx, "glMultiDrawArraysIndirectCountARB" 1917 "(%s, %lx, %lx, %i, %i)\n", 1918 _mesa_enum_to_string(mode), 1919 (unsigned long) indirect, (unsigned long) drawcount_offset, 1920 maxdrawcount, stride); 1921 1922 /* If <stride> is zero, the array elements are treated as tightly packed. */ 1923 if (stride == 0) 1924 stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */ 1925 1926 FLUSH_FOR_DRAW(ctx); 1927 1928 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1929 1930 if (_mesa_is_no_error_enabled(ctx)) { 1931 if (ctx->NewState) 1932 _mesa_update_state(ctx); 1933 } else { 1934 if (!_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode, 1935 indirect, 1936 drawcount_offset, 1937 maxdrawcount, stride)) 1938 return; 1939 } 1940 1941 if (skip_validated_draw(ctx)) 1942 return; 1943 1944 _mesa_validated_multidrawarraysindirectcount(ctx, mode, indirect, 1945 drawcount_offset, 1946 maxdrawcount, stride); 1947} 1948 1949 1950static void GLAPIENTRY 1951_mesa_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type, 1952 GLintptr indirect, 1953 GLintptr drawcount_offset, 1954 GLsizei maxdrawcount, GLsizei stride) 1955{ 1956 GET_CURRENT_CONTEXT(ctx); 1957 1958 if (MESA_VERBOSE & VERBOSE_DRAW) 1959 _mesa_debug(ctx, "glMultiDrawElementsIndirectCountARB" 1960 "(%s, %s, %lx, %lx, %i, %i)\n", 1961 _mesa_enum_to_string(mode), _mesa_enum_to_string(type), 1962 (unsigned long) indirect, (unsigned long) drawcount_offset, 1963 maxdrawcount, stride); 1964 1965 /* If <stride> is zero, the array elements are treated as tightly packed. */ 1966 if (stride == 0) 1967 stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */ 1968 1969 FLUSH_FOR_DRAW(ctx); 1970 1971 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx)); 1972 1973 if (_mesa_is_no_error_enabled(ctx)) { 1974 if (ctx->NewState) 1975 _mesa_update_state(ctx); 1976 } else { 1977 if (!_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type, 1978 indirect, 1979 drawcount_offset, 1980 maxdrawcount, stride)) 1981 return; 1982 } 1983 1984 if (skip_validated_draw(ctx)) 1985 return; 1986 1987 _mesa_validated_multidrawelementsindirectcount(ctx, mode, type, indirect, 1988 drawcount_offset, maxdrawcount, 1989 stride); 1990} 1991 1992 1993/** 1994 * Initialize the dispatch table with the VBO functions for drawing. 1995 */ 1996void 1997_mesa_initialize_exec_dispatch(const struct gl_context *ctx, 1998 struct _glapi_table *exec) 1999{ 2000 SET_DrawArrays(exec, _mesa_exec_DrawArrays); 2001 SET_DrawElements(exec, _mesa_exec_DrawElements); 2002 2003 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { 2004 SET_DrawRangeElements(exec, _mesa_exec_DrawRangeElements); 2005 } 2006 2007 SET_MultiDrawArrays(exec, _mesa_exec_MultiDrawArrays); 2008 SET_MultiDrawElementsEXT(exec, _mesa_exec_MultiDrawElements); 2009 2010 if (ctx->API == API_OPENGL_COMPAT) { 2011 SET_Rectf(exec, _mesa_exec_Rectf); 2012 SET_EvalMesh1(exec, _mesa_exec_EvalMesh1); 2013 SET_EvalMesh2(exec, _mesa_exec_EvalMesh2); 2014 } 2015 2016 if (ctx->API != API_OPENGLES && 2017 ctx->Extensions.ARB_draw_elements_base_vertex) { 2018 SET_DrawElementsBaseVertex(exec, _mesa_exec_DrawElementsBaseVertex); 2019 SET_MultiDrawElementsBaseVertex(exec, 2020 _mesa_exec_MultiDrawElementsBaseVertex); 2021 2022 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { 2023 SET_DrawRangeElementsBaseVertex(exec, 2024 _mesa_exec_DrawRangeElementsBaseVertex); 2025 SET_DrawElementsInstancedBaseVertex(exec, 2026 _mesa_exec_DrawElementsInstancedBaseVertex); 2027 } 2028 } 2029 2030 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { 2031 SET_DrawArraysInstancedBaseInstance(exec, 2032 _mesa_exec_DrawArraysInstancedBaseInstance); 2033 SET_DrawElementsInstancedBaseInstance(exec, 2034 _mesa_exec_DrawElementsInstancedBaseInstance); 2035 SET_DrawElementsInstancedBaseVertexBaseInstance(exec, 2036 _mesa_exec_DrawElementsInstancedBaseVertexBaseInstance); 2037 } 2038 2039 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) { 2040 SET_DrawArraysIndirect(exec, _mesa_exec_DrawArraysIndirect); 2041 SET_DrawElementsIndirect(exec, _mesa_exec_DrawElementsIndirect); 2042 } 2043 2044 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { 2045 SET_DrawArraysInstancedARB(exec, _mesa_exec_DrawArraysInstanced); 2046 SET_DrawElementsInstancedARB(exec, _mesa_exec_DrawElementsInstanced); 2047 } 2048 2049 if (_mesa_is_desktop_gl(ctx)) { 2050 SET_DrawTransformFeedback(exec, _mesa_exec_DrawTransformFeedback); 2051 SET_DrawTransformFeedbackStream(exec, 2052 _mesa_exec_DrawTransformFeedbackStream); 2053 SET_DrawTransformFeedbackInstanced(exec, 2054 _mesa_exec_DrawTransformFeedbackInstanced); 2055 SET_DrawTransformFeedbackStreamInstanced(exec, 2056 _mesa_exec_DrawTransformFeedbackStreamInstanced); 2057 SET_MultiDrawArraysIndirect(exec, _mesa_exec_MultiDrawArraysIndirect); 2058 SET_MultiDrawElementsIndirect(exec, _mesa_exec_MultiDrawElementsIndirect); 2059 SET_MultiDrawArraysIndirectCountARB(exec, 2060 _mesa_exec_MultiDrawArraysIndirectCount); 2061 SET_MultiDrawElementsIndirectCountARB(exec, 2062 _mesa_exec_MultiDrawElementsIndirectCount); 2063 } 2064} 2065 2066 2067 2068/** 2069 * The following functions are only used for OpenGL ES 1/2 support. 2070 * And some aren't even supported (yet) in ES 1/2. 2071 */ 2072 2073 2074void GLAPIENTRY 2075_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count) 2076{ 2077 _mesa_exec_DrawArrays(mode, first, count); 2078} 2079 2080 2081void GLAPIENTRY 2082_mesa_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, 2083 GLsizei primcount) 2084{ 2085 _mesa_exec_DrawArraysInstanced(mode, first, count, primcount); 2086} 2087 2088 2089void GLAPIENTRY 2090_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, 2091 const GLvoid *indices) 2092{ 2093 _mesa_exec_DrawElements(mode, count, type, indices); 2094} 2095 2096 2097void GLAPIENTRY 2098_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 2099 const GLvoid *indices, GLint basevertex) 2100{ 2101 _mesa_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex); 2102} 2103 2104 2105void GLAPIENTRY 2106_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, 2107 GLenum type, const GLvoid * indices) 2108{ 2109 _mesa_exec_DrawRangeElements(mode, start, end, count, type, indices); 2110} 2111 2112 2113void GLAPIENTRY 2114_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, 2115 GLsizei count, GLenum type, 2116 const GLvoid *indices, GLint basevertex) 2117{ 2118 _mesa_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type, 2119 indices, basevertex); 2120} 2121 2122 2123void GLAPIENTRY 2124_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type, 2125 const GLvoid ** indices, GLsizei primcount) 2126{ 2127 _mesa_exec_MultiDrawElements(mode, count, type, indices, primcount); 2128} 2129 2130 2131void GLAPIENTRY 2132_mesa_MultiDrawElementsBaseVertex(GLenum mode, 2133 const GLsizei *count, GLenum type, 2134 const GLvoid **indices, GLsizei primcount, 2135 const GLint *basevertex) 2136{ 2137 _mesa_exec_MultiDrawElementsBaseVertex(mode, count, type, indices, 2138 primcount, basevertex); 2139} 2140 2141 2142void GLAPIENTRY 2143_mesa_DrawTransformFeedback(GLenum mode, GLuint name) 2144{ 2145 _mesa_exec_DrawTransformFeedback(mode, name); 2146} 2147 2148 2149/* GL_IBM_multimode_draw_arrays */ 2150void GLAPIENTRY 2151_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first, 2152 const GLsizei * count, 2153 GLsizei primcount, GLint modestride ) 2154{ 2155 GET_CURRENT_CONTEXT(ctx); 2156 GLint i; 2157 2158 FLUSH_VERTICES(ctx, 0); 2159 2160 for ( i = 0 ; i < primcount ; i++ ) { 2161 if ( count[i] > 0 ) { 2162 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); 2163 CALL_DrawArrays(ctx->CurrentServerDispatch, ( m, first[i], count[i] )); 2164 } 2165 } 2166} 2167 2168 2169/* GL_IBM_multimode_draw_arrays */ 2170void GLAPIENTRY 2171_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count, 2172 GLenum type, const GLvoid * const * indices, 2173 GLsizei primcount, GLint modestride ) 2174{ 2175 GET_CURRENT_CONTEXT(ctx); 2176 GLint i; 2177 2178 FLUSH_VERTICES(ctx, 0); 2179 2180 /* XXX not sure about ARB_vertex_buffer_object handling here */ 2181 2182 for ( i = 0 ; i < primcount ; i++ ) { 2183 if ( count[i] > 0 ) { 2184 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); 2185 CALL_DrawElements(ctx->CurrentServerDispatch, ( m, count[i], type, 2186 indices[i] )); 2187 } 2188 } 2189} 2190 2191 2192/* 2193 * Helper function for _mesa_draw_indirect below that additionally takes a zero 2194 * initialized array of _mesa_prim scratch space memory as the last argument. 2195 */ 2196static void 2197draw_indirect(struct gl_context *ctx, GLuint mode, 2198 struct gl_buffer_object *indirect_data, 2199 GLsizeiptr indirect_offset, unsigned draw_count, 2200 unsigned stride, 2201 struct gl_buffer_object *indirect_draw_count_buffer, 2202 GLsizeiptr indirect_draw_count_offset, 2203 const struct _mesa_index_buffer *ib, 2204 struct _mesa_prim *prim) 2205{ 2206 prim[0].begin = 1; 2207 prim[draw_count - 1].end = 1; 2208 for (unsigned i = 0; i < draw_count; ++i, indirect_offset += stride) { 2209 prim[i].mode = mode; 2210 prim[i].indexed = !!ib; 2211 prim[i].indirect_offset = indirect_offset; 2212 prim[i].is_indirect = 1; 2213 prim[i].draw_id = i; 2214 } 2215 2216 /* This should always be true at this time */ 2217 assert(indirect_data == ctx->DrawIndirectBuffer); 2218 2219 ctx->Driver.Draw(ctx, prim, draw_count, ib, false, 0u, ~0u, 2220 NULL, 0, indirect_data); 2221} 2222 2223 2224/* 2225 * Function to be put into dd_function_table::DrawIndirect as fallback. 2226 * Calls into dd_function_table::Draw past adapting call arguments. 2227 * See dd_function_table::DrawIndirect for call argument documentation. 2228 */ 2229void 2230_mesa_draw_indirect(struct gl_context *ctx, GLuint mode, 2231 struct gl_buffer_object *indirect_data, 2232 GLsizeiptr indirect_offset, unsigned draw_count, 2233 unsigned stride, 2234 struct gl_buffer_object *indirect_draw_count_buffer, 2235 GLsizeiptr indirect_draw_count_offset, 2236 const struct _mesa_index_buffer *ib) 2237{ 2238 /* Use alloca for the prim space if we are somehow in bounds. */ 2239 if (draw_count*sizeof(struct _mesa_prim) < 1024) { 2240 struct _mesa_prim *space = alloca(draw_count*sizeof(struct _mesa_prim)); 2241 memset(space, 0, draw_count*sizeof(struct _mesa_prim)); 2242 2243 draw_indirect(ctx, mode, indirect_data, indirect_offset, draw_count, 2244 stride, indirect_draw_count_buffer, 2245 indirect_draw_count_offset, ib, space); 2246 } else { 2247 struct _mesa_prim *space = calloc(draw_count, sizeof(struct _mesa_prim)); 2248 if (space == NULL) { 2249 _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s", 2250 (draw_count > 1) ? "Multi" : "", 2251 ib ? "Elements" : "Arrays", 2252 indirect_data ? "CountARB" : ""); 2253 return; 2254 } 2255 2256 draw_indirect(ctx, mode, indirect_data, indirect_offset, draw_count, 2257 stride, indirect_draw_count_buffer, 2258 indirect_draw_count_offset, ib, space); 2259 2260 free(space); 2261 } 2262} 2263