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