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