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