mesa/vbo: Use unreachable to silence uninitialized var warning.
[mesa.git] / src / mesa / vbo / vbo_exec_array.c
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 "main/glheader.h"
30 #include "main/context.h"
31 #include "main/state.h"
32 #include "main/api_validate.h"
33 #include "main/dispatch.h"
34 #include "main/varray.h"
35 #include "main/bufferobj.h"
36 #include "main/enums.h"
37 #include "main/macros.h"
38 #include "main/transformfeedback.h"
39 #include "main/sse_minmax.h"
40 #include "x86/common_x86_asm.h"
41
42 #include "vbo_context.h"
43
44
45 /**
46 * All vertex buffers should be in an unmapped state when we're about
47 * to draw. This debug function checks that.
48 */
49 static void
50 check_buffers_are_unmapped(const struct gl_client_array **inputs)
51 {
52 #ifdef DEBUG
53 GLuint i;
54
55 for (i = 0; i < VERT_ATTRIB_MAX; i++) {
56 if (inputs[i]) {
57 struct gl_buffer_object *obj = inputs[i]->BufferObj;
58 assert(!_mesa_check_disallowed_mapping(obj));
59 (void) obj;
60 }
61 }
62 #endif
63 }
64
65
66 /**
67 * A debug function that may be called from other parts of Mesa as
68 * needed during debugging.
69 */
70 void
71 vbo_check_buffers_are_unmapped(struct gl_context *ctx)
72 {
73 struct vbo_context *vbo = vbo_context(ctx);
74 struct vbo_exec_context *exec = &vbo->exec;
75 /* check the current vertex arrays */
76 check_buffers_are_unmapped(exec->array.inputs);
77 /* check the current glBegin/glVertex/glEnd-style VBO */
78 assert(!_mesa_check_disallowed_mapping(exec->vtx.bufferobj));
79 }
80
81
82
83 /**
84 * Compute min and max elements by scanning the index buffer for
85 * glDraw[Range]Elements() calls.
86 * If primitive restart is enabled, we need to ignore restart
87 * indexes when computing min/max.
88 */
89 static void
90 vbo_get_minmax_index(struct gl_context *ctx,
91 const struct _mesa_prim *prim,
92 const struct _mesa_index_buffer *ib,
93 GLuint *min_index, GLuint *max_index,
94 const GLuint count)
95 {
96 const GLboolean restart = ctx->Array._PrimitiveRestart;
97 const GLuint restartIndex = _mesa_primitive_restart_index(ctx, ib->type);
98 const int index_size = vbo_sizeof_ib_type(ib->type);
99 const char *indices;
100 GLuint i;
101
102 indices = (char *) ib->ptr + prim->start * index_size;
103 if (_mesa_is_bufferobj(ib->obj)) {
104 GLsizeiptr size = MIN2(count * index_size, ib->obj->Size);
105 indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size,
106 GL_MAP_READ_BIT, ib->obj,
107 MAP_INTERNAL);
108 }
109
110 switch (ib->type) {
111 case GL_UNSIGNED_INT: {
112 const GLuint *ui_indices = (const GLuint *)indices;
113 GLuint max_ui = 0;
114 GLuint min_ui = ~0U;
115 if (restart) {
116 for (i = 0; i < count; i++) {
117 if (ui_indices[i] != restartIndex) {
118 if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
119 if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
120 }
121 }
122 }
123 else {
124 #if defined(USE_SSE41)
125 if (cpu_has_sse4_1) {
126 _mesa_uint_array_min_max(ui_indices, &min_ui, &max_ui, count);
127 }
128 else
129 #endif
130 for (i = 0; i < count; i++) {
131 if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
132 if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
133 }
134 }
135 *min_index = min_ui;
136 *max_index = max_ui;
137 break;
138 }
139 case GL_UNSIGNED_SHORT: {
140 const GLushort *us_indices = (const GLushort *)indices;
141 GLuint max_us = 0;
142 GLuint min_us = ~0U;
143 if (restart) {
144 for (i = 0; i < count; i++) {
145 if (us_indices[i] != restartIndex) {
146 if (us_indices[i] > max_us) max_us = us_indices[i];
147 if (us_indices[i] < min_us) min_us = us_indices[i];
148 }
149 }
150 }
151 else {
152 for (i = 0; i < count; i++) {
153 if (us_indices[i] > max_us) max_us = us_indices[i];
154 if (us_indices[i] < min_us) min_us = us_indices[i];
155 }
156 }
157 *min_index = min_us;
158 *max_index = max_us;
159 break;
160 }
161 case GL_UNSIGNED_BYTE: {
162 const GLubyte *ub_indices = (const GLubyte *)indices;
163 GLuint max_ub = 0;
164 GLuint min_ub = ~0U;
165 if (restart) {
166 for (i = 0; i < count; i++) {
167 if (ub_indices[i] != restartIndex) {
168 if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
169 if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
170 }
171 }
172 }
173 else {
174 for (i = 0; i < count; i++) {
175 if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
176 if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
177 }
178 }
179 *min_index = min_ub;
180 *max_index = max_ub;
181 break;
182 }
183 default:
184 unreachable("not reached");
185 }
186
187 if (_mesa_is_bufferobj(ib->obj)) {
188 ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL);
189 }
190 }
191
192 /**
193 * Compute min and max elements for nr_prims
194 */
195 void
196 vbo_get_minmax_indices(struct gl_context *ctx,
197 const struct _mesa_prim *prims,
198 const struct _mesa_index_buffer *ib,
199 GLuint *min_index,
200 GLuint *max_index,
201 GLuint nr_prims)
202 {
203 GLuint tmp_min, tmp_max;
204 GLuint i;
205 GLuint count;
206
207 *min_index = ~0;
208 *max_index = 0;
209
210 for (i = 0; i < nr_prims; i++) {
211 const struct _mesa_prim *start_prim;
212
213 start_prim = &prims[i];
214 count = start_prim->count;
215 /* Do combination if possible to reduce map/unmap count */
216 while ((i + 1 < nr_prims) &&
217 (prims[i].start + prims[i].count == prims[i+1].start)) {
218 count += prims[i+1].count;
219 i++;
220 }
221 vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count);
222 *min_index = MIN2(*min_index, tmp_min);
223 *max_index = MAX2(*max_index, tmp_max);
224 }
225 }
226
227
228 /**
229 * Check that element 'j' of the array has reasonable data.
230 * Map VBO if needed.
231 * For debugging purposes; not normally used.
232 */
233 static void
234 check_array_data(struct gl_context *ctx, struct gl_client_array *array,
235 GLuint attrib, GLuint j)
236 {
237 if (array->Enabled) {
238 const void *data = array->Ptr;
239 if (_mesa_is_bufferobj(array->BufferObj)) {
240 if (!array->BufferObj->Mappings[MAP_INTERNAL].Pointer) {
241 /* need to map now */
242 array->BufferObj->Mappings[MAP_INTERNAL].Pointer =
243 ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size,
244 GL_MAP_READ_BIT, array->BufferObj,
245 MAP_INTERNAL);
246 }
247 data = ADD_POINTERS(data,
248 array->BufferObj->Mappings[MAP_INTERNAL].Pointer);
249 }
250 switch (array->Type) {
251 case GL_FLOAT:
252 {
253 GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
254 GLint k;
255 for (k = 0; k < array->Size; k++) {
256 if (IS_INF_OR_NAN(f[k]) ||
257 f[k] >= 1.0e20 || f[k] <= -1.0e10) {
258 printf("Bad array data:\n");
259 printf(" Element[%u].%u = %f\n", j, k, f[k]);
260 printf(" Array %u at %p\n", attrib, (void* ) array);
261 printf(" Type 0x%x, Size %d, Stride %d\n",
262 array->Type, array->Size, array->Stride);
263 printf(" Address/offset %p in Buffer Object %u\n",
264 array->Ptr, array->BufferObj->Name);
265 f[k] = 1.0; /* XXX replace the bad value! */
266 }
267 /*assert(!IS_INF_OR_NAN(f[k]));*/
268 }
269 }
270 break;
271 default:
272 ;
273 }
274 }
275 }
276
277
278 /**
279 * Unmap the buffer object referenced by given array, if mapped.
280 */
281 static void
282 unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
283 {
284 if (array->Enabled &&
285 _mesa_is_bufferobj(array->BufferObj) &&
286 _mesa_bufferobj_mapped(array->BufferObj, MAP_INTERNAL)) {
287 ctx->Driver.UnmapBuffer(ctx, array->BufferObj, MAP_INTERNAL);
288 }
289 }
290
291
292 /**
293 * Examine the array's data for NaNs, etc.
294 * For debug purposes; not normally used.
295 */
296 static void
297 check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
298 const void *elements, GLint basevertex)
299 {
300 struct gl_vertex_array_object *vao = ctx->Array.VAO;
301 const void *elemMap;
302 GLint i;
303 GLuint k;
304
305 if (_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
306 elemMap = ctx->Driver.MapBufferRange(ctx, 0,
307 ctx->Array.VAO->IndexBufferObj->Size,
308 GL_MAP_READ_BIT,
309 ctx->Array.VAO->IndexBufferObj,
310 MAP_INTERNAL);
311 elements = ADD_POINTERS(elements, elemMap);
312 }
313
314 for (i = 0; i < count; i++) {
315 GLuint j;
316
317 /* j = element[i] */
318 switch (elemType) {
319 case GL_UNSIGNED_BYTE:
320 j = ((const GLubyte *) elements)[i];
321 break;
322 case GL_UNSIGNED_SHORT:
323 j = ((const GLushort *) elements)[i];
324 break;
325 case GL_UNSIGNED_INT:
326 j = ((const GLuint *) elements)[i];
327 break;
328 default:
329 assert(0);
330 }
331
332 /* check element j of each enabled array */
333 for (k = 0; k < Elements(vao->_VertexAttrib); k++) {
334 check_array_data(ctx, &vao->_VertexAttrib[k], k, j);
335 }
336 }
337
338 if (_mesa_is_bufferobj(vao->IndexBufferObj)) {
339 ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj,
340 MAP_INTERNAL);
341 }
342
343 for (k = 0; k < Elements(vao->_VertexAttrib); k++) {
344 unmap_array_buffer(ctx, &vao->_VertexAttrib[k]);
345 }
346 }
347
348
349 /**
350 * Check array data, looking for NaNs, etc.
351 */
352 static void
353 check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
354 {
355 /* TO DO */
356 }
357
358
359 /**
360 * Print info/data for glDrawArrays(), for debugging.
361 */
362 static void
363 print_draw_arrays(struct gl_context *ctx,
364 GLenum mode, GLint start, GLsizei count)
365 {
366 struct vbo_context *vbo = vbo_context(ctx);
367 struct vbo_exec_context *exec = &vbo->exec;
368 struct gl_vertex_array_object *vao = ctx->Array.VAO;
369 int i;
370
371 printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
372 mode, start, count);
373
374 for (i = 0; i < 32; i++) {
375 struct gl_buffer_object *bufObj = exec->array.inputs[i]->BufferObj;
376 GLuint bufName = bufObj->Name;
377 GLint stride = exec->array.inputs[i]->Stride;
378 printf("attr %2d: size %d stride %d enabled %d "
379 "ptr %p Bufobj %u\n",
380 i,
381 exec->array.inputs[i]->Size,
382 stride,
383 /*exec->array.inputs[i]->Enabled,*/
384 vao->_VertexAttrib[VERT_ATTRIB_FF(i)].Enabled,
385 exec->array.inputs[i]->Ptr,
386 bufName);
387
388 if (bufName) {
389 GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size,
390 GL_MAP_READ_BIT, bufObj,
391 MAP_INTERNAL);
392 int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
393 float *f = (float *) (p + offset);
394 int *k = (int *) f;
395 int i;
396 int n = (count * stride) / 4;
397 if (n > 32)
398 n = 32;
399 printf(" Data at offset %d:\n", offset);
400 for (i = 0; i < n; i++) {
401 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
402 }
403 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL);
404 }
405 }
406 }
407
408
409 /**
410 * Set the vbo->exec->inputs[] pointers to point to the enabled
411 * vertex arrays. This depends on the current vertex program/shader
412 * being executed because of whether or not generic vertex arrays
413 * alias the conventional vertex arrays.
414 * For arrays that aren't enabled, we set the input[attrib] pointer
415 * to point at a zero-stride current value "array".
416 */
417 static void
418 recalculate_input_bindings(struct gl_context *ctx)
419 {
420 struct vbo_context *vbo = vbo_context(ctx);
421 struct vbo_exec_context *exec = &vbo->exec;
422 struct gl_client_array *vertexAttrib = ctx->Array.VAO->_VertexAttrib;
423 const struct gl_client_array **inputs = &exec->array.inputs[0];
424 GLbitfield64 const_inputs = 0x0;
425 GLuint i;
426
427 switch (get_program_mode(ctx)) {
428 case VP_NONE:
429 /* When no vertex program is active (or the vertex program is generated
430 * from fixed-function state). We put the material values into the
431 * generic slots. This is the only situation where material values
432 * are available as per-vertex attributes.
433 */
434 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
435 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
436 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
437 else {
438 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
439 const_inputs |= VERT_BIT(i);
440 }
441 }
442
443 for (i = 0; i < MAT_ATTRIB_MAX; i++) {
444 inputs[VERT_ATTRIB_GENERIC(i)] =
445 &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i];
446 const_inputs |= VERT_BIT_GENERIC(i);
447 }
448
449 /* Could use just about anything, just to fill in the empty
450 * slots:
451 */
452 for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
453 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
454 const_inputs |= VERT_BIT_GENERIC(i);
455 }
456 break;
457
458 case VP_ARB:
459 /* There are no shaders in OpenGL ES 1.x, so this code path should be
460 * impossible to reach. The meta code is careful to not use shaders in
461 * ES1.
462 */
463 assert(ctx->API != API_OPENGLES);
464
465 /* In the compatibility profile of desktop OpenGL, the generic[0]
466 * attribute array aliases and overrides the legacy position array.
467 * Otherwise, legacy attributes available in the legacy slots,
468 * generic attributes in the generic slots and materials are not
469 * available as per-vertex attributes.
470 *
471 * In all other APIs, only the generic attributes exist, and none of the
472 * slots are considered "magic."
473 */
474 if (ctx->API == API_OPENGL_COMPAT) {
475 if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
476 inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
477 else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
478 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
479 else {
480 inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
481 const_inputs |= VERT_BIT_POS;
482 }
483
484 for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
485 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
486 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
487 else {
488 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
489 const_inputs |= VERT_BIT_FF(i);
490 }
491 }
492
493 for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
494 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
495 inputs[VERT_ATTRIB_GENERIC(i)] =
496 &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
497 else {
498 inputs[VERT_ATTRIB_GENERIC(i)] =
499 &vbo->currval[VBO_ATTRIB_GENERIC0+i];
500 const_inputs |= VERT_BIT_GENERIC(i);
501 }
502 }
503
504 inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
505 } else {
506 /* Other parts of the code assume that inputs[0] through
507 * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL. However, in OpenGL
508 * ES 2.0+ or OpenGL core profile, none of these arrays should ever
509 * be enabled.
510 */
511 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
512 assert(!vertexAttrib[VERT_ATTRIB_FF(i)].Enabled);
513
514 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
515 const_inputs |= VERT_BIT_FF(i);
516 }
517
518 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
519 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
520 inputs[VERT_ATTRIB_GENERIC(i)] =
521 &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
522 else {
523 inputs[VERT_ATTRIB_GENERIC(i)] =
524 &vbo->currval[VBO_ATTRIB_GENERIC0+i];
525 const_inputs |= VERT_BIT_GENERIC(i);
526 }
527 }
528 }
529
530 break;
531 }
532
533 _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
534 ctx->NewDriverState |= ctx->DriverFlags.NewArray;
535 }
536
537
538 /**
539 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
540 * These will point to the arrays to actually use for drawing. Some will
541 * be user-provided arrays, other will be zero-stride const-valued arrays.
542 * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
543 * validation must be done after this call.
544 */
545 void
546 vbo_bind_arrays(struct gl_context *ctx)
547 {
548 struct vbo_context *vbo = vbo_context(ctx);
549 struct vbo_exec_context *exec = &vbo->exec;
550
551 vbo_draw_method(vbo, DRAW_ARRAYS);
552
553 if (exec->array.recalculate_inputs) {
554 recalculate_input_bindings(ctx);
555 exec->array.recalculate_inputs = GL_FALSE;
556
557 /* Again... because we may have changed the bitmask of per-vertex varying
558 * attributes. If we regenerate the fixed-function vertex program now
559 * we may be able to prune down the number of vertex attributes which we
560 * need in the shader.
561 */
562 if (ctx->NewState) {
563 /* Setting "validating" to TRUE prevents _mesa_update_state from
564 * invalidating what we just did.
565 */
566 exec->validating = GL_TRUE;
567 _mesa_update_state(ctx);
568 exec->validating = GL_FALSE;
569 }
570 }
571 }
572
573 /**
574 * Helper function called by the other DrawArrays() functions below.
575 * This is where we handle primitive restart for drawing non-indexed
576 * arrays. If primitive restart is enabled, it typically means
577 * splitting one DrawArrays() into two.
578 */
579 static void
580 vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
581 GLsizei count, GLuint numInstances, GLuint baseInstance)
582 {
583 struct vbo_context *vbo = vbo_context(ctx);
584 struct vbo_exec_context *exec = &vbo->exec;
585 struct _mesa_prim prim[2];
586
587 vbo_bind_arrays(ctx);
588
589 /* init most fields to zero */
590 memset(prim, 0, sizeof(prim));
591 prim[0].begin = 1;
592 prim[0].end = 1;
593 prim[0].mode = mode;
594 prim[0].num_instances = numInstances;
595 prim[0].base_instance = baseInstance;
596 prim[0].is_indirect = 0;
597
598 /* Implement the primitive restart index */
599 if (ctx->Array.PrimitiveRestart && !ctx->Array.PrimitiveRestartFixedIndex &&
600 ctx->Array.RestartIndex < count) {
601 GLuint primCount = 0;
602
603 if (ctx->Array.RestartIndex == start) {
604 /* special case: RestartIndex at beginning */
605 if (count > 1) {
606 prim[0].start = start + 1;
607 prim[0].count = count - 1;
608 primCount = 1;
609 }
610 }
611 else if (ctx->Array.RestartIndex == start + count - 1) {
612 /* special case: RestartIndex at end */
613 if (count > 1) {
614 prim[0].start = start;
615 prim[0].count = count - 1;
616 primCount = 1;
617 }
618 }
619 else {
620 /* general case: RestartIndex in middle, split into two prims */
621 prim[0].start = start;
622 prim[0].count = ctx->Array.RestartIndex - start;
623
624 prim[1] = prim[0];
625 prim[1].start = ctx->Array.RestartIndex + 1;
626 prim[1].count = count - prim[1].start;
627
628 primCount = 2;
629 }
630
631 if (primCount > 0) {
632 /* draw one or two prims */
633 check_buffers_are_unmapped(exec->array.inputs);
634 vbo->draw_prims(ctx, prim, primCount, NULL,
635 GL_TRUE, start, start + count - 1, NULL, NULL);
636 }
637 }
638 else {
639 /* no prim restart */
640 prim[0].start = start;
641 prim[0].count = count;
642
643 check_buffers_are_unmapped(exec->array.inputs);
644 vbo->draw_prims(ctx, prim, 1, NULL,
645 GL_TRUE, start, start + count - 1,
646 NULL, NULL);
647 }
648
649 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
650 _mesa_flush(ctx);
651 }
652 }
653
654
655 /**
656 * Execute a glRectf() function.
657 */
658 static void GLAPIENTRY
659 vbo_exec_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
660 {
661 GET_CURRENT_CONTEXT(ctx);
662 ASSERT_OUTSIDE_BEGIN_END(ctx);
663
664 CALL_Begin(GET_DISPATCH(), (GL_QUADS));
665 CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
666 CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
667 CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
668 CALL_Vertex2f(GET_DISPATCH(), (x1, y2));
669 CALL_End(GET_DISPATCH(), ());
670 }
671
672
673 static void GLAPIENTRY
674 vbo_exec_EvalMesh1(GLenum mode, GLint i1, GLint i2)
675 {
676 GET_CURRENT_CONTEXT(ctx);
677 GLint i;
678 GLfloat u, du;
679 GLenum prim;
680
681 switch (mode) {
682 case GL_POINT:
683 prim = GL_POINTS;
684 break;
685 case GL_LINE:
686 prim = GL_LINE_STRIP;
687 break;
688 default:
689 _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
690 return;
691 }
692
693 /* No effect if vertex maps disabled.
694 */
695 if (!ctx->Eval.Map1Vertex4 &&
696 !ctx->Eval.Map1Vertex3)
697 return;
698
699 du = ctx->Eval.MapGrid1du;
700 u = ctx->Eval.MapGrid1u1 + i1 * du;
701
702 CALL_Begin(GET_DISPATCH(), (prim));
703 for (i=i1;i<=i2;i++,u+=du) {
704 CALL_EvalCoord1f(GET_DISPATCH(), (u));
705 }
706 CALL_End(GET_DISPATCH(), ());
707 }
708
709
710 static void GLAPIENTRY
711 vbo_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
712 {
713 GET_CURRENT_CONTEXT(ctx);
714 GLfloat u, du, v, dv, v1, u1;
715 GLint i, j;
716
717 switch (mode) {
718 case GL_POINT:
719 case GL_LINE:
720 case GL_FILL:
721 break;
722 default:
723 _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
724 return;
725 }
726
727 /* No effect if vertex maps disabled.
728 */
729 if (!ctx->Eval.Map2Vertex4 &&
730 !ctx->Eval.Map2Vertex3)
731 return;
732
733 du = ctx->Eval.MapGrid2du;
734 dv = ctx->Eval.MapGrid2dv;
735 v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
736 u1 = ctx->Eval.MapGrid2u1 + i1 * du;
737
738 switch (mode) {
739 case GL_POINT:
740 CALL_Begin(GET_DISPATCH(), (GL_POINTS));
741 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
742 for (u=u1,i=i1;i<=i2;i++,u+=du) {
743 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
744 }
745 }
746 CALL_End(GET_DISPATCH(), ());
747 break;
748 case GL_LINE:
749 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
750 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
751 for (u=u1,i=i1;i<=i2;i++,u+=du) {
752 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
753 }
754 CALL_End(GET_DISPATCH(), ());
755 }
756 for (u=u1,i=i1;i<=i2;i++,u+=du) {
757 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
758 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
759 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
760 }
761 CALL_End(GET_DISPATCH(), ());
762 }
763 break;
764 case GL_FILL:
765 for (v=v1,j=j1;j<j2;j++,v+=dv) {
766 CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
767 for (u=u1,i=i1;i<=i2;i++,u+=du) {
768 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
769 CALL_EvalCoord2f(GET_DISPATCH(), (u, v+dv));
770 }
771 CALL_End(GET_DISPATCH(), ());
772 }
773 break;
774 }
775 }
776
777
778 /**
779 * Called from glDrawArrays when in immediate mode (not display list mode).
780 */
781 static void GLAPIENTRY
782 vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
783 {
784 GET_CURRENT_CONTEXT(ctx);
785
786 if (MESA_VERBOSE & VERBOSE_DRAW)
787 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
788 _mesa_lookup_enum_by_nr(mode), start, count);
789
790 if (!_mesa_validate_DrawArrays(ctx, mode, count))
791 return;
792
793 if (0)
794 check_draw_arrays_data(ctx, start, count);
795
796 vbo_draw_arrays(ctx, mode, start, count, 1, 0);
797
798 if (0)
799 print_draw_arrays(ctx, mode, start, count);
800 }
801
802
803 /**
804 * Called from glDrawArraysInstanced when in immediate mode (not
805 * display list mode).
806 */
807 static void GLAPIENTRY
808 vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
809 GLsizei numInstances)
810 {
811 GET_CURRENT_CONTEXT(ctx);
812
813 if (MESA_VERBOSE & VERBOSE_DRAW)
814 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
815 _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
816
817 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
818 return;
819
820 if (0)
821 check_draw_arrays_data(ctx, start, count);
822
823 vbo_draw_arrays(ctx, mode, start, count, numInstances, 0);
824
825 if (0)
826 print_draw_arrays(ctx, mode, start, count);
827 }
828
829
830 /**
831 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
832 */
833 static void GLAPIENTRY
834 vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count,
835 GLsizei numInstances, GLuint baseInstance)
836 {
837 GET_CURRENT_CONTEXT(ctx);
838
839 if (MESA_VERBOSE & VERBOSE_DRAW)
840 _mesa_debug(ctx, "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
841 _mesa_lookup_enum_by_nr(mode), first, count,
842 numInstances, baseInstance);
843
844 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
845 numInstances))
846 return;
847
848 if (0)
849 check_draw_arrays_data(ctx, first, count);
850
851 vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
852
853 if (0)
854 print_draw_arrays(ctx, mode, first, count);
855 }
856
857
858
859 /**
860 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
861 * For debugging.
862 */
863 #if 0
864 static void
865 dump_element_buffer(struct gl_context *ctx, GLenum type)
866 {
867 const GLvoid *map =
868 ctx->Driver.MapBufferRange(ctx, 0,
869 ctx->Array.VAO->IndexBufferObj->Size,
870 GL_MAP_READ_BIT,
871 ctx->Array.VAO->IndexBufferObj,
872 MAP_INTERNAL);
873 switch (type) {
874 case GL_UNSIGNED_BYTE:
875 {
876 const GLubyte *us = (const GLubyte *) map;
877 GLint i;
878 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) {
879 printf("%02x ", us[i]);
880 if (i % 32 == 31)
881 printf("\n");
882 }
883 printf("\n");
884 }
885 break;
886 case GL_UNSIGNED_SHORT:
887 {
888 const GLushort *us = (const GLushort *) map;
889 GLint i;
890 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) {
891 printf("%04x ", us[i]);
892 if (i % 16 == 15)
893 printf("\n");
894 }
895 printf("\n");
896 }
897 break;
898 case GL_UNSIGNED_INT:
899 {
900 const GLuint *us = (const GLuint *) map;
901 GLint i;
902 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) {
903 printf("%08x ", us[i]);
904 if (i % 8 == 7)
905 printf("\n");
906 }
907 printf("\n");
908 }
909 break;
910 default:
911 ;
912 }
913
914 ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj,
915 MAP_INTERNAL);
916 }
917 #endif
918
919
920 /**
921 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
922 * Do the rendering for a glDrawElements or glDrawRangeElements call after
923 * we've validated buffer bounds, etc.
924 */
925 static void
926 vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
927 GLboolean index_bounds_valid,
928 GLuint start, GLuint end,
929 GLsizei count, GLenum type,
930 const GLvoid *indices,
931 GLint basevertex, GLuint numInstances,
932 GLuint baseInstance)
933 {
934 struct vbo_context *vbo = vbo_context(ctx);
935 struct vbo_exec_context *exec = &vbo->exec;
936 struct _mesa_index_buffer ib;
937 struct _mesa_prim prim[1];
938
939 vbo_bind_arrays(ctx);
940
941 ib.count = count;
942 ib.type = type;
943 ib.obj = ctx->Array.VAO->IndexBufferObj;
944 ib.ptr = indices;
945
946 prim[0].begin = 1;
947 prim[0].end = 1;
948 prim[0].weak = 0;
949 prim[0].pad = 0;
950 prim[0].mode = mode;
951 prim[0].start = 0;
952 prim[0].count = count;
953 prim[0].indexed = 1;
954 prim[0].is_indirect = 0;
955 prim[0].basevertex = basevertex;
956 prim[0].num_instances = numInstances;
957 prim[0].base_instance = baseInstance;
958
959 /* Need to give special consideration to rendering a range of
960 * indices starting somewhere above zero. Typically the
961 * application is issuing multiple DrawRangeElements() to draw
962 * successive primitives layed out linearly in the vertex arrays.
963 * Unless the vertex arrays are all in a VBO (or locked as with
964 * CVA), the OpenGL semantics imply that we need to re-read or
965 * re-upload the vertex data on each draw call.
966 *
967 * In the case of hardware tnl, we want to avoid starting the
968 * upload at zero, as it will mean every draw call uploads an
969 * increasing amount of not-used vertex data. Worse - in the
970 * software tnl module, all those vertices might be transformed and
971 * lit but never rendered.
972 *
973 * If we just upload or transform the vertices in start..end,
974 * however, the indices will be incorrect.
975 *
976 * At this level, we don't know exactly what the requirements of
977 * the backend are going to be, though it will likely boil down to
978 * either:
979 *
980 * 1) Do nothing, everything is in a VBO and is processed once
981 * only.
982 *
983 * 2) Adjust the indices and vertex arrays so that start becomes
984 * zero.
985 *
986 * Rather than doing anything here, I'll provide a helper function
987 * for the latter case elsewhere.
988 */
989
990 check_buffers_are_unmapped(exec->array.inputs);
991 vbo->draw_prims(ctx, prim, 1, &ib,
992 index_bounds_valid, start, end, NULL, NULL);
993
994 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
995 _mesa_flush(ctx);
996 }
997 }
998
999
1000 /**
1001 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
1002 */
1003 static void GLAPIENTRY
1004 vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
1005 GLuint start, GLuint end,
1006 GLsizei count, GLenum type,
1007 const GLvoid *indices,
1008 GLint basevertex)
1009 {
1010 static GLuint warnCount = 0;
1011 GLboolean index_bounds_valid = GL_TRUE;
1012
1013 /* This is only useful to catch invalid values in the "end" parameter
1014 * like ~0.
1015 */
1016 GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
1017
1018 GET_CURRENT_CONTEXT(ctx);
1019
1020 if (MESA_VERBOSE & VERBOSE_DRAW)
1021 _mesa_debug(ctx,
1022 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
1023 _mesa_lookup_enum_by_nr(mode), start, end, count,
1024 _mesa_lookup_enum_by_nr(type), indices, basevertex);
1025
1026 if (!_mesa_validate_DrawRangeElements(ctx, mode, start, end, count,
1027 type, indices))
1028 return;
1029
1030 if ((int) end + basevertex < 0 ||
1031 start + basevertex >= max_element) {
1032 /* The application requested we draw using a range of indices that's
1033 * outside the bounds of the current VBO. This is invalid and appears
1034 * to give undefined results. The safest thing to do is to simply
1035 * ignore the range, in case the application botched their range tracking
1036 * but did provide valid indices. Also issue a warning indicating that
1037 * the application is broken.
1038 */
1039 if (warnCount++ < 10) {
1040 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
1041 "basevertex %d, count %d, type 0x%x, indices=%p):\n"
1042 "\trange is outside VBO bounds (max=%u); ignoring.\n"
1043 "\tThis should be fixed in the application.",
1044 start, end, basevertex, count, type, indices,
1045 max_element - 1);
1046 }
1047 index_bounds_valid = GL_FALSE;
1048 }
1049
1050 /* NOTE: It's important that 'end' is a reasonable value.
1051 * in _tnl_draw_prims(), we use end to determine how many vertices
1052 * to transform. If it's too large, we can unnecessarily split prims
1053 * or we can read/write out of memory in several different places!
1054 */
1055
1056 /* Catch/fix some potential user errors */
1057 if (type == GL_UNSIGNED_BYTE) {
1058 start = MIN2(start, 0xff);
1059 end = MIN2(end, 0xff);
1060 }
1061 else if (type == GL_UNSIGNED_SHORT) {
1062 start = MIN2(start, 0xffff);
1063 end = MIN2(end, 0xffff);
1064 }
1065
1066 if (0) {
1067 printf("glDraw[Range]Elements{,BaseVertex}"
1068 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
1069 "base %d\n",
1070 start, end, type, count,
1071 ctx->Array.VAO->IndexBufferObj->Name,
1072 basevertex);
1073 }
1074
1075 if ((int) start + basevertex < 0 ||
1076 end + basevertex >= max_element)
1077 index_bounds_valid = GL_FALSE;
1078
1079 #if 0
1080 check_draw_elements_data(ctx, count, type, indices);
1081 #else
1082 (void) check_draw_elements_data;
1083 #endif
1084
1085 vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
1086 count, type, indices, basevertex, 1, 0);
1087 }
1088
1089
1090 /**
1091 * Called by glDrawRangeElements() in immediate mode.
1092 */
1093 static void GLAPIENTRY
1094 vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1095 GLsizei count, GLenum type, const GLvoid *indices)
1096 {
1097 if (MESA_VERBOSE & VERBOSE_DRAW) {
1098 GET_CURRENT_CONTEXT(ctx);
1099 _mesa_debug(ctx,
1100 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
1101 _mesa_lookup_enum_by_nr(mode), start, end, count,
1102 _mesa_lookup_enum_by_nr(type), indices);
1103 }
1104
1105 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1106 indices, 0);
1107 }
1108
1109
1110 /**
1111 * Called by glDrawElements() in immediate mode.
1112 */
1113 static void GLAPIENTRY
1114 vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
1115 const GLvoid *indices)
1116 {
1117 GET_CURRENT_CONTEXT(ctx);
1118
1119 if (MESA_VERBOSE & VERBOSE_DRAW)
1120 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1121 _mesa_lookup_enum_by_nr(mode), count,
1122 _mesa_lookup_enum_by_nr(type), indices);
1123
1124 if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices))
1125 return;
1126
1127 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1128 count, type, indices, 0, 1, 0);
1129 }
1130
1131
1132 /**
1133 * Called by glDrawElementsBaseVertex() in immediate mode.
1134 */
1135 static void GLAPIENTRY
1136 vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1137 const GLvoid *indices, GLint basevertex)
1138 {
1139 GET_CURRENT_CONTEXT(ctx);
1140
1141 if (MESA_VERBOSE & VERBOSE_DRAW)
1142 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
1143 _mesa_lookup_enum_by_nr(mode), count,
1144 _mesa_lookup_enum_by_nr(type), indices, basevertex);
1145
1146 if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices))
1147 return;
1148
1149 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1150 count, type, indices, basevertex, 1, 0);
1151 }
1152
1153
1154 /**
1155 * Called by glDrawElementsInstanced() in immediate mode.
1156 */
1157 static void GLAPIENTRY
1158 vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1159 const GLvoid *indices, GLsizei numInstances)
1160 {
1161 GET_CURRENT_CONTEXT(ctx);
1162
1163 if (MESA_VERBOSE & VERBOSE_DRAW)
1164 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
1165 _mesa_lookup_enum_by_nr(mode), count,
1166 _mesa_lookup_enum_by_nr(type), indices, numInstances);
1167
1168 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1169 numInstances))
1170 return;
1171
1172 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1173 count, type, indices, 0, numInstances, 0);
1174 }
1175
1176
1177 /**
1178 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1179 */
1180 static void GLAPIENTRY
1181 vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1182 const GLvoid *indices, GLsizei numInstances,
1183 GLint basevertex)
1184 {
1185 GET_CURRENT_CONTEXT(ctx);
1186
1187 if (MESA_VERBOSE & VERBOSE_DRAW)
1188 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1189 _mesa_lookup_enum_by_nr(mode), count,
1190 _mesa_lookup_enum_by_nr(type), indices,
1191 numInstances, basevertex);
1192
1193 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1194 numInstances))
1195 return;
1196
1197 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1198 count, type, indices, basevertex, numInstances, 0);
1199 }
1200
1201
1202 /**
1203 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1204 */
1205 static void GLAPIENTRY
1206 vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type,
1207 const GLvoid *indices, GLsizei numInstances,
1208 GLuint baseInstance)
1209 {
1210 GET_CURRENT_CONTEXT(ctx);
1211
1212 if (MESA_VERBOSE & VERBOSE_DRAW)
1213 _mesa_debug(ctx, "glDrawElementsInstancedBaseInstance(%s, %d, %s, %p, %d, %d)\n",
1214 _mesa_lookup_enum_by_nr(mode), count,
1215 _mesa_lookup_enum_by_nr(type), indices,
1216 numInstances, baseInstance);
1217
1218 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1219 numInstances))
1220 return;
1221
1222 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1223 count, type, indices, 0, numInstances,
1224 baseInstance);
1225 }
1226
1227
1228 /**
1229 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1230 */
1231 static void GLAPIENTRY
1232 vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
1233 const GLvoid *indices, GLsizei numInstances,
1234 GLint basevertex, GLuint baseInstance)
1235 {
1236 GET_CURRENT_CONTEXT(ctx);
1237
1238 if (MESA_VERBOSE & VERBOSE_DRAW)
1239 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertexBaseInstance(%s, %d, %s, %p, %d, %d, %d)\n",
1240 _mesa_lookup_enum_by_nr(mode), count,
1241 _mesa_lookup_enum_by_nr(type), indices,
1242 numInstances, basevertex, baseInstance);
1243
1244 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1245 numInstances))
1246 return;
1247
1248 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1249 count, type, indices, basevertex, numInstances,
1250 baseInstance);
1251 }
1252
1253
1254 /**
1255 * Inner support for both _mesa_MultiDrawElements() and
1256 * _mesa_MultiDrawRangeElements().
1257 * This does the actual rendering after we've checked array indexes, etc.
1258 */
1259 static void
1260 vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1261 const GLsizei *count, GLenum type,
1262 const GLvoid * const *indices,
1263 GLsizei primcount,
1264 const GLint *basevertex)
1265 {
1266 struct vbo_context *vbo = vbo_context(ctx);
1267 struct vbo_exec_context *exec = &vbo->exec;
1268 struct _mesa_index_buffer ib;
1269 struct _mesa_prim *prim;
1270 unsigned int index_type_size = vbo_sizeof_ib_type(type);
1271 uintptr_t min_index_ptr, max_index_ptr;
1272 GLboolean fallback = GL_FALSE;
1273 int i;
1274
1275 if (primcount == 0)
1276 return;
1277
1278 prim = calloc(primcount, sizeof(*prim));
1279 if (prim == NULL) {
1280 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1281 return;
1282 }
1283
1284 vbo_bind_arrays(ctx);
1285
1286 min_index_ptr = (uintptr_t)indices[0];
1287 max_index_ptr = 0;
1288 for (i = 0; i < primcount; i++) {
1289 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1290 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1291 index_type_size * count[i]);
1292 }
1293
1294 /* Check if we can handle this thing as a bunch of index offsets from the
1295 * same index pointer. If we can't, then we have to fall back to doing
1296 * a draw_prims per primitive.
1297 * Check that the difference between each prim's indexes is a multiple of
1298 * the index/element size.
1299 */
1300 if (index_type_size != 1) {
1301 for (i = 0; i < primcount; i++) {
1302 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1303 fallback = GL_TRUE;
1304 break;
1305 }
1306 }
1307 }
1308
1309 /* Draw primitives individually if one count is zero, so we can easily skip
1310 * that primitive.
1311 */
1312 for (i = 0; i < primcount; i++) {
1313 if (count[i] == 0) {
1314 fallback = GL_TRUE;
1315 break;
1316 }
1317 }
1318
1319 /* If the index buffer isn't in a VBO, then treating the application's
1320 * subranges of the index buffer as one large index buffer may lead to
1321 * us reading unmapped memory.
1322 */
1323 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj))
1324 fallback = GL_TRUE;
1325
1326 if (!fallback) {
1327 ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1328 ib.type = type;
1329 ib.obj = ctx->Array.VAO->IndexBufferObj;
1330 ib.ptr = (void *)min_index_ptr;
1331
1332 for (i = 0; i < primcount; i++) {
1333 prim[i].begin = (i == 0);
1334 prim[i].end = (i == primcount - 1);
1335 prim[i].weak = 0;
1336 prim[i].pad = 0;
1337 prim[i].mode = mode;
1338 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1339 prim[i].count = count[i];
1340 prim[i].indexed = 1;
1341 prim[i].num_instances = 1;
1342 prim[i].base_instance = 0;
1343 prim[i].is_indirect = 0;
1344 if (basevertex != NULL)
1345 prim[i].basevertex = basevertex[i];
1346 else
1347 prim[i].basevertex = 0;
1348 }
1349
1350 check_buffers_are_unmapped(exec->array.inputs);
1351 vbo->draw_prims(ctx, prim, primcount, &ib,
1352 false, ~0, ~0, NULL, NULL);
1353 } else {
1354 /* render one prim at a time */
1355 for (i = 0; i < primcount; i++) {
1356 if (count[i] == 0)
1357 continue;
1358 ib.count = count[i];
1359 ib.type = type;
1360 ib.obj = ctx->Array.VAO->IndexBufferObj;
1361 ib.ptr = indices[i];
1362
1363 prim[0].begin = 1;
1364 prim[0].end = 1;
1365 prim[0].weak = 0;
1366 prim[0].pad = 0;
1367 prim[0].mode = mode;
1368 prim[0].start = 0;
1369 prim[0].count = count[i];
1370 prim[0].indexed = 1;
1371 prim[0].num_instances = 1;
1372 prim[0].base_instance = 0;
1373 prim[0].is_indirect = 0;
1374 if (basevertex != NULL)
1375 prim[0].basevertex = basevertex[i];
1376 else
1377 prim[0].basevertex = 0;
1378
1379 check_buffers_are_unmapped(exec->array.inputs);
1380 vbo->draw_prims(ctx, prim, 1, &ib,
1381 false, ~0, ~0, NULL, NULL);
1382 }
1383 }
1384
1385 free(prim);
1386
1387 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1388 _mesa_flush(ctx);
1389 }
1390 }
1391
1392
1393 static void GLAPIENTRY
1394 vbo_exec_MultiDrawElements(GLenum mode,
1395 const GLsizei *count, GLenum type,
1396 const GLvoid * const *indices,
1397 GLsizei primcount)
1398 {
1399 GET_CURRENT_CONTEXT(ctx);
1400
1401 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1402 primcount))
1403 return;
1404
1405 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1406 NULL);
1407 }
1408
1409
1410 static void GLAPIENTRY
1411 vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1412 const GLsizei *count, GLenum type,
1413 const GLvoid * const *indices,
1414 GLsizei primcount,
1415 const GLsizei *basevertex)
1416 {
1417 GET_CURRENT_CONTEXT(ctx);
1418
1419 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1420 primcount))
1421 return;
1422
1423 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1424 basevertex);
1425 }
1426
1427 static void
1428 vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1429 struct gl_transform_feedback_object *obj,
1430 GLuint stream, GLuint numInstances)
1431 {
1432 struct vbo_context *vbo = vbo_context(ctx);
1433 struct vbo_exec_context *exec = &vbo->exec;
1434 struct _mesa_prim prim[2];
1435
1436 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
1437 numInstances)) {
1438 return;
1439 }
1440
1441 if (ctx->Driver.GetTransformFeedbackVertexCount &&
1442 (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
1443 !vbo_all_varyings_in_vbos(exec->array.inputs))) {
1444 GLsizei n = ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
1445 vbo_draw_arrays(ctx, mode, 0, n, numInstances, 0);
1446 return;
1447 }
1448
1449 vbo_bind_arrays(ctx);
1450
1451 /* init most fields to zero */
1452 memset(prim, 0, sizeof(prim));
1453 prim[0].begin = 1;
1454 prim[0].end = 1;
1455 prim[0].mode = mode;
1456 prim[0].num_instances = numInstances;
1457 prim[0].base_instance = 0;
1458 prim[0].is_indirect = 0;
1459
1460 /* Maybe we should do some primitive splitting for primitive restart
1461 * (like in DrawArrays), but we have no way to know how many vertices
1462 * will be rendered. */
1463
1464 check_buffers_are_unmapped(exec->array.inputs);
1465 vbo->draw_prims(ctx, prim, 1, NULL,
1466 GL_TRUE, 0, 0, obj, NULL);
1467
1468 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1469 _mesa_flush(ctx);
1470 }
1471 }
1472
1473 /**
1474 * Like DrawArrays, but take the count from a transform feedback object.
1475 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1476 * \param name the transform feedback object
1477 * User still has to setup of the vertex attribute info with
1478 * glVertexPointer, glColorPointer, etc.
1479 * Part of GL_ARB_transform_feedback2.
1480 */
1481 static void GLAPIENTRY
1482 vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
1483 {
1484 GET_CURRENT_CONTEXT(ctx);
1485 struct gl_transform_feedback_object *obj =
1486 _mesa_lookup_transform_feedback_object(ctx, name);
1487
1488 if (MESA_VERBOSE & VERBOSE_DRAW)
1489 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1490 _mesa_lookup_enum_by_nr(mode), name);
1491
1492 vbo_draw_transform_feedback(ctx, mode, obj, 0, 1);
1493 }
1494
1495 static void GLAPIENTRY
1496 vbo_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
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, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
1504 _mesa_lookup_enum_by_nr(mode), name, stream);
1505
1506 vbo_draw_transform_feedback(ctx, mode, obj, stream, 1);
1507 }
1508
1509 static void GLAPIENTRY
1510 vbo_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
1511 GLsizei primcount)
1512 {
1513 GET_CURRENT_CONTEXT(ctx);
1514 struct gl_transform_feedback_object *obj =
1515 _mesa_lookup_transform_feedback_object(ctx, name);
1516
1517 if (MESA_VERBOSE & VERBOSE_DRAW)
1518 _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
1519 _mesa_lookup_enum_by_nr(mode), name);
1520
1521 vbo_draw_transform_feedback(ctx, mode, obj, 0, primcount);
1522 }
1523
1524 static void GLAPIENTRY
1525 vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
1526 GLuint stream, GLsizei primcount)
1527 {
1528 GET_CURRENT_CONTEXT(ctx);
1529 struct gl_transform_feedback_object *obj =
1530 _mesa_lookup_transform_feedback_object(ctx, name);
1531
1532 if (MESA_VERBOSE & VERBOSE_DRAW)
1533 _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
1534 "(%s, %u, %u, %i)\n",
1535 _mesa_lookup_enum_by_nr(mode), name, stream, primcount);
1536
1537 vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
1538 }
1539
1540 static void
1541 vbo_validated_drawarraysindirect(struct gl_context *ctx,
1542 GLenum mode, const GLvoid *indirect)
1543 {
1544 struct vbo_context *vbo = vbo_context(ctx);
1545 struct vbo_exec_context *exec = &vbo->exec;
1546 struct _mesa_prim prim[1];
1547
1548 vbo_bind_arrays(ctx);
1549
1550 memset(prim, 0, sizeof(prim));
1551 prim[0].begin = 1;
1552 prim[0].end = 1;
1553 prim[0].mode = mode;
1554 prim[0].is_indirect = 1;
1555 prim[0].indirect_offset = (GLsizeiptr)indirect;
1556
1557 /* NOTE: We do NOT want to handle primitive restart here, nor perform any
1558 * other checks that require knowledge of the values in the command buffer.
1559 * That would defeat the whole purpose of this function.
1560 */
1561
1562 check_buffers_are_unmapped(exec->array.inputs);
1563 vbo->draw_prims(ctx, prim, 1,
1564 NULL, GL_TRUE, 0, ~0,
1565 NULL,
1566 ctx->DrawIndirectBuffer);
1567
1568 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1569 _mesa_flush(ctx);
1570 }
1571
1572 static void
1573 vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
1574 GLenum mode,
1575 const GLvoid *indirect,
1576 GLsizei primcount, GLsizei stride)
1577 {
1578 struct vbo_context *vbo = vbo_context(ctx);
1579 struct vbo_exec_context *exec = &vbo->exec;
1580 struct _mesa_prim *prim;
1581 GLsizei i;
1582 GLsizeiptr offset = (GLsizeiptr)indirect;
1583
1584 if (primcount == 0)
1585 return;
1586 prim = calloc(primcount, sizeof(*prim));
1587 if (prim == NULL) {
1588 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect");
1589 return;
1590 }
1591
1592 vbo_bind_arrays(ctx);
1593
1594 prim[0].begin = 1;
1595 prim[primcount - 1].end = 1;
1596 for (i = 0; i < primcount; ++i, offset += stride) {
1597 prim[i].mode = mode;
1598 prim[i].indirect_offset = offset;
1599 prim[i].is_indirect = 1;
1600 }
1601
1602 check_buffers_are_unmapped(exec->array.inputs);
1603 vbo->draw_prims(ctx, prim, primcount,
1604 NULL, GL_TRUE, 0, ~0,
1605 NULL,
1606 ctx->DrawIndirectBuffer);
1607
1608 free(prim);
1609
1610 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1611 _mesa_flush(ctx);
1612 }
1613
1614 static void
1615 vbo_validated_drawelementsindirect(struct gl_context *ctx,
1616 GLenum mode, GLenum type,
1617 const GLvoid *indirect)
1618 {
1619 struct vbo_context *vbo = vbo_context(ctx);
1620 struct vbo_exec_context *exec = &vbo->exec;
1621 struct _mesa_index_buffer ib;
1622 struct _mesa_prim prim[1];
1623
1624 vbo_bind_arrays(ctx);
1625
1626 ib.count = 0; /* unknown */
1627 ib.type = type;
1628 ib.obj = ctx->Array.VAO->IndexBufferObj;
1629 ib.ptr = NULL;
1630
1631 memset(prim, 0, sizeof(prim));
1632 prim[0].begin = 1;
1633 prim[0].end = 1;
1634 prim[0].mode = mode;
1635 prim[0].indexed = 1;
1636 prim[0].indirect_offset = (GLsizeiptr)indirect;
1637 prim[0].is_indirect = 1;
1638
1639 check_buffers_are_unmapped(exec->array.inputs);
1640 vbo->draw_prims(ctx, prim, 1,
1641 &ib, GL_TRUE, 0, ~0,
1642 NULL,
1643 ctx->DrawIndirectBuffer);
1644
1645 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1646 _mesa_flush(ctx);
1647 }
1648
1649 static void
1650 vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
1651 GLenum mode, GLenum type,
1652 const GLvoid *indirect,
1653 GLsizei primcount, GLsizei stride)
1654 {
1655 struct vbo_context *vbo = vbo_context(ctx);
1656 struct vbo_exec_context *exec = &vbo->exec;
1657 struct _mesa_index_buffer ib;
1658 struct _mesa_prim *prim;
1659 GLsizei i;
1660 GLsizeiptr offset = (GLsizeiptr)indirect;
1661
1662 if (primcount == 0)
1663 return;
1664 prim = calloc(primcount, sizeof(*prim));
1665 if (prim == NULL) {
1666 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect");
1667 return;
1668 }
1669
1670 vbo_bind_arrays(ctx);
1671
1672 /* NOTE: IndexBufferObj is guaranteed to be a VBO. */
1673
1674 ib.count = 0; /* unknown */
1675 ib.type = type;
1676 ib.obj = ctx->Array.VAO->IndexBufferObj;
1677 ib.ptr = NULL;
1678
1679 prim[0].begin = 1;
1680 prim[primcount - 1].end = 1;
1681 for (i = 0; i < primcount; ++i, offset += stride) {
1682 prim[i].mode = mode;
1683 prim[i].indexed = 1;
1684 prim[i].indirect_offset = offset;
1685 prim[i].is_indirect = 1;
1686 }
1687
1688 check_buffers_are_unmapped(exec->array.inputs);
1689 vbo->draw_prims(ctx, prim, primcount,
1690 &ib, GL_TRUE, 0, ~0,
1691 NULL,
1692 ctx->DrawIndirectBuffer);
1693
1694 free(prim);
1695
1696 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1697 _mesa_flush(ctx);
1698 }
1699
1700 /**
1701 * Like [Multi]DrawArrays/Elements, but they take most arguments from
1702 * a buffer object.
1703 */
1704 static void GLAPIENTRY
1705 vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
1706 {
1707 GET_CURRENT_CONTEXT(ctx);
1708
1709 if (MESA_VERBOSE & VERBOSE_DRAW)
1710 _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n",
1711 _mesa_lookup_enum_by_nr(mode), indirect);
1712
1713 if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
1714 return;
1715
1716 vbo_validated_drawarraysindirect(ctx, mode, indirect);
1717 }
1718
1719 static void GLAPIENTRY
1720 vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type,
1721 const GLvoid *indirect)
1722 {
1723 GET_CURRENT_CONTEXT(ctx);
1724
1725 if (MESA_VERBOSE & VERBOSE_DRAW)
1726 _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n",
1727 _mesa_lookup_enum_by_nr(mode),
1728 _mesa_lookup_enum_by_nr(type), indirect);
1729
1730 if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
1731 return;
1732
1733 vbo_validated_drawelementsindirect(ctx, mode, type, indirect);
1734 }
1735
1736 static void GLAPIENTRY
1737 vbo_exec_MultiDrawArraysIndirect(GLenum mode,
1738 const GLvoid *indirect,
1739 GLsizei primcount, GLsizei stride)
1740 {
1741 GET_CURRENT_CONTEXT(ctx);
1742
1743 if (MESA_VERBOSE & VERBOSE_DRAW)
1744 _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n",
1745 _mesa_lookup_enum_by_nr(mode), indirect, primcount, stride);
1746
1747 /* If <stride> is zero, the array elements are treated as tightly packed. */
1748 if (stride == 0)
1749 stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
1750
1751 if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode,
1752 indirect,
1753 primcount, stride))
1754 return;
1755
1756 vbo_validated_multidrawarraysindirect(ctx, mode,
1757 indirect,
1758 primcount, stride);
1759 }
1760
1761 static void GLAPIENTRY
1762 vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
1763 const GLvoid *indirect,
1764 GLsizei primcount, GLsizei stride)
1765 {
1766 GET_CURRENT_CONTEXT(ctx);
1767
1768 if (MESA_VERBOSE & VERBOSE_DRAW)
1769 _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n",
1770 _mesa_lookup_enum_by_nr(mode),
1771 _mesa_lookup_enum_by_nr(type), indirect, primcount, stride);
1772
1773 /* If <stride> is zero, the array elements are treated as tightly packed. */
1774 if (stride == 0)
1775 stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
1776
1777 if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type,
1778 indirect,
1779 primcount, stride))
1780 return;
1781
1782 vbo_validated_multidrawelementsindirect(ctx, mode, type,
1783 indirect,
1784 primcount, stride);
1785 }
1786
1787 /**
1788 * Initialize the dispatch table with the VBO functions for drawing.
1789 */
1790 void
1791 vbo_initialize_exec_dispatch(const struct gl_context *ctx,
1792 struct _glapi_table *exec)
1793 {
1794 SET_DrawArrays(exec, vbo_exec_DrawArrays);
1795 SET_DrawElements(exec, vbo_exec_DrawElements);
1796
1797 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1798 SET_DrawRangeElements(exec, vbo_exec_DrawRangeElements);
1799 }
1800
1801 SET_MultiDrawElementsEXT(exec, vbo_exec_MultiDrawElements);
1802
1803 if (ctx->API == API_OPENGL_COMPAT) {
1804 SET_Rectf(exec, vbo_exec_Rectf);
1805 SET_EvalMesh1(exec, vbo_exec_EvalMesh1);
1806 SET_EvalMesh2(exec, vbo_exec_EvalMesh2);
1807 }
1808
1809 if (_mesa_is_desktop_gl(ctx)) {
1810 SET_DrawElementsBaseVertex(exec, vbo_exec_DrawElementsBaseVertex);
1811 SET_DrawRangeElementsBaseVertex(exec, vbo_exec_DrawRangeElementsBaseVertex);
1812 SET_MultiDrawElementsBaseVertex(exec, vbo_exec_MultiDrawElementsBaseVertex);
1813 SET_DrawArraysInstancedBaseInstance(exec, vbo_exec_DrawArraysInstancedBaseInstance);
1814 SET_DrawElementsInstancedBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseInstance);
1815 SET_DrawElementsInstancedBaseVertex(exec, vbo_exec_DrawElementsInstancedBaseVertex);
1816 SET_DrawElementsInstancedBaseVertexBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseVertexBaseInstance);
1817 }
1818
1819 if (ctx->API == API_OPENGL_CORE) {
1820 SET_DrawArraysIndirect(exec, vbo_exec_DrawArraysIndirect);
1821 SET_DrawElementsIndirect(exec, vbo_exec_DrawElementsIndirect);
1822 SET_MultiDrawArraysIndirect(exec, vbo_exec_MultiDrawArraysIndirect);
1823 SET_MultiDrawElementsIndirect(exec, vbo_exec_MultiDrawElementsIndirect);
1824 }
1825
1826 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1827 SET_DrawArraysInstancedARB(exec, vbo_exec_DrawArraysInstanced);
1828 SET_DrawElementsInstancedARB(exec, vbo_exec_DrawElementsInstanced);
1829 }
1830
1831 if (_mesa_is_desktop_gl(ctx)) {
1832 SET_DrawTransformFeedback(exec, vbo_exec_DrawTransformFeedback);
1833 SET_DrawTransformFeedbackStream(exec, vbo_exec_DrawTransformFeedbackStream);
1834 SET_DrawTransformFeedbackInstanced(exec, vbo_exec_DrawTransformFeedbackInstanced);
1835 SET_DrawTransformFeedbackStreamInstanced(exec, vbo_exec_DrawTransformFeedbackStreamInstanced);
1836 }
1837 }
1838
1839
1840
1841 /**
1842 * The following functions are only used for OpenGL ES 1/2 support.
1843 * And some aren't even supported (yet) in ES 1/2.
1844 */
1845
1846
1847 void GLAPIENTRY
1848 _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1849 {
1850 vbo_exec_DrawArrays(mode, first, count);
1851 }
1852
1853 void GLAPIENTRY
1854 _mesa_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
1855 GLsizei primcount)
1856 {
1857 vbo_exec_DrawArraysInstanced(mode, first, count, primcount);
1858 }
1859
1860 void GLAPIENTRY
1861 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1862 const GLvoid *indices)
1863 {
1864 vbo_exec_DrawElements(mode, count, type, indices);
1865 }
1866
1867
1868 void GLAPIENTRY
1869 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1870 const GLvoid *indices, GLint basevertex)
1871 {
1872 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1873 }
1874
1875
1876 void GLAPIENTRY
1877 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1878 GLenum type, const GLvoid *indices)
1879 {
1880 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1881 }
1882
1883
1884 void GLAPIENTRY
1885 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1886 GLsizei count, GLenum type,
1887 const GLvoid *indices, GLint basevertex)
1888 {
1889 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1890 indices, basevertex);
1891 }
1892
1893
1894 void GLAPIENTRY
1895 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1896 const GLvoid **indices, GLsizei primcount)
1897 {
1898 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1899 }
1900
1901
1902 void GLAPIENTRY
1903 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
1904 const GLsizei *count, GLenum type,
1905 const GLvoid **indices, GLsizei primcount,
1906 const GLint *basevertex)
1907 {
1908 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1909 primcount, basevertex);
1910 }
1911
1912 void GLAPIENTRY
1913 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1914 {
1915 vbo_exec_DrawTransformFeedback(mode, name);
1916 }