mesa: add _NEW_VARYING_VP_INPUTS for gl_context::varying_vp_inputs
[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->legacy_currval[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)] = &vbo->mat_currval[i];
430 const_inputs |= VERT_BIT_GENERIC(i);
431 }
432
433 /* Could use just about anything, just to fill in the empty
434 * slots:
435 */
436 for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
437 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
438 const_inputs |= VERT_BIT_GENERIC(i);
439 }
440
441 /* There is no need to make _NEW_ARRAY dirty here for the TnL program,
442 * because it already takes care of invalidating the state necessary
443 * to revalidate vertex arrays. Not marking the state as dirty also
444 * improves performance (quite significantly in some apps).
445 */
446 if (!ctx->VertexProgram._MaintainTnlProgram)
447 ctx->NewState |= _NEW_ARRAY;
448 break;
449
450 case VP_NV:
451 /* NV_vertex_program - attribute arrays alias and override
452 * conventional, legacy arrays. No materials, and the generic
453 * slots are vacant.
454 */
455 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
456 if (i < VERT_ATTRIB_GENERIC_MAX
457 && vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
458 inputs[i] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
459 else if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
460 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
461 else {
462 inputs[i] = &vbo->legacy_currval[i];
463 const_inputs |= VERT_BIT_FF(i);
464 }
465 }
466
467 /* Could use just about anything, just to fill in the empty
468 * slots:
469 */
470 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
471 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
472 const_inputs |= VERT_BIT_GENERIC(i);
473 }
474
475 ctx->NewState |= _NEW_ARRAY;
476 break;
477
478 case VP_ARB:
479 /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
480 * attribute array aliases and overrides the legacy position array.
481 *
482 * Otherwise, legacy attributes available in the legacy slots,
483 * generic attributes in the generic slots and materials are not
484 * available as per-vertex attributes.
485 */
486 if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
487 inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
488 else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
489 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
490 else {
491 inputs[0] = &vbo->legacy_currval[0];
492 const_inputs |= VERT_BIT_POS;
493 }
494
495 for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
496 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
497 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
498 else {
499 inputs[i] = &vbo->legacy_currval[i];
500 const_inputs |= VERT_BIT_FF(i);
501 }
502 }
503
504 for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
505 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
506 inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
507 else {
508 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
509 const_inputs |= VERT_BIT_GENERIC(i);
510 }
511 }
512
513 inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
514 ctx->NewState |= _NEW_ARRAY;
515 break;
516 }
517
518 _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
519 }
520
521
522 /**
523 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
524 * These will point to the arrays to actually use for drawing. Some will
525 * be user-provided arrays, other will be zero-stride const-valued arrays.
526 * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
527 * validation must be done after this call.
528 */
529 void
530 vbo_bind_arrays(struct gl_context *ctx)
531 {
532 struct vbo_context *vbo = vbo_context(ctx);
533 struct vbo_exec_context *exec = &vbo->exec;
534
535 vbo_draw_method(exec, DRAW_ARRAYS);
536
537 if (exec->array.recalculate_inputs) {
538 recalculate_input_bindings(ctx);
539
540 /* Again... because we may have changed the bitmask of per-vertex varying
541 * attributes. If we regenerate the fixed-function vertex program now
542 * we may be able to prune down the number of vertex attributes which we
543 * need in the shader.
544 */
545 if (ctx->NewState) {
546 _mesa_update_state(ctx);
547 }
548
549 exec->array.recalculate_inputs = GL_FALSE;
550 }
551 }
552
553
554 /**
555 * Helper function called by the other DrawArrays() functions below.
556 * This is where we handle primitive restart for drawing non-indexed
557 * arrays. If primitive restart is enabled, it typically means
558 * splitting one DrawArrays() into two.
559 */
560 static void
561 vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
562 GLsizei count, GLuint numInstances)
563 {
564 struct vbo_context *vbo = vbo_context(ctx);
565 struct vbo_exec_context *exec = &vbo->exec;
566 struct _mesa_prim prim[2];
567
568 vbo_bind_arrays(ctx);
569
570 /* init most fields to zero */
571 memset(prim, 0, sizeof(prim));
572 prim[0].begin = 1;
573 prim[0].end = 1;
574 prim[0].mode = mode;
575 prim[0].num_instances = numInstances;
576
577 /* Implement the primitive restart index */
578 if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
579 GLuint primCount = 0;
580
581 if (ctx->Array.RestartIndex == start) {
582 /* special case: RestartIndex at beginning */
583 if (count > 1) {
584 prim[0].start = start + 1;
585 prim[0].count = count - 1;
586 primCount = 1;
587 }
588 }
589 else if (ctx->Array.RestartIndex == start + count - 1) {
590 /* special case: RestartIndex at end */
591 if (count > 1) {
592 prim[0].start = start;
593 prim[0].count = count - 1;
594 primCount = 1;
595 }
596 }
597 else {
598 /* general case: RestartIndex in middle, split into two prims */
599 prim[0].start = start;
600 prim[0].count = ctx->Array.RestartIndex - start;
601
602 prim[1] = prim[0];
603 prim[1].start = ctx->Array.RestartIndex + 1;
604 prim[1].count = count - prim[1].start;
605
606 primCount = 2;
607 }
608
609 if (primCount > 0) {
610 /* draw one or two prims */
611 check_buffers_are_unmapped(exec->array.inputs);
612 vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
613 GL_TRUE, start, start + count - 1, NULL);
614 }
615 }
616 else {
617 /* no prim restart */
618 prim[0].start = start;
619 prim[0].count = count;
620
621 check_buffers_are_unmapped(exec->array.inputs);
622 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
623 GL_TRUE, start, start + count - 1,
624 NULL);
625 }
626 }
627
628
629
630 /**
631 * Called from glDrawArrays when in immediate mode (not display list mode).
632 */
633 static void GLAPIENTRY
634 vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
635 {
636 GET_CURRENT_CONTEXT(ctx);
637
638 if (MESA_VERBOSE & VERBOSE_DRAW)
639 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
640 _mesa_lookup_enum_by_nr(mode), start, count);
641
642 if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
643 return;
644
645 FLUSH_CURRENT( ctx, 0 );
646
647 if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
648 return;
649 }
650
651 if (0)
652 check_draw_arrays_data(ctx, start, count);
653
654 vbo_draw_arrays(ctx, mode, start, count, 1);
655
656 if (0)
657 print_draw_arrays(ctx, mode, start, count);
658 }
659
660
661 /**
662 * Called from glDrawArraysInstanced when in immediate mode (not
663 * display list mode).
664 */
665 static void GLAPIENTRY
666 vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
667 GLsizei numInstances)
668 {
669 GET_CURRENT_CONTEXT(ctx);
670
671 if (MESA_VERBOSE & VERBOSE_DRAW)
672 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
673 _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
674
675 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
676 return;
677
678 FLUSH_CURRENT( ctx, 0 );
679
680 if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
681 return;
682 }
683
684 if (0)
685 check_draw_arrays_data(ctx, start, count);
686
687 vbo_draw_arrays(ctx, mode, start, count, numInstances);
688
689 if (0)
690 print_draw_arrays(ctx, mode, start, count);
691 }
692
693
694 /**
695 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
696 * For debugging.
697 */
698 #if 0
699 static void
700 dump_element_buffer(struct gl_context *ctx, GLenum type)
701 {
702 const GLvoid *map =
703 ctx->Driver.MapBufferRange(ctx, 0,
704 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
705 GL_MAP_READ_BIT,
706 ctx->Array.ArrayObj->ElementArrayBufferObj);
707 switch (type) {
708 case GL_UNSIGNED_BYTE:
709 {
710 const GLubyte *us = (const GLubyte *) map;
711 GLint i;
712 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) {
713 printf("%02x ", us[i]);
714 if (i % 32 == 31)
715 printf("\n");
716 }
717 printf("\n");
718 }
719 break;
720 case GL_UNSIGNED_SHORT:
721 {
722 const GLushort *us = (const GLushort *) map;
723 GLint i;
724 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) {
725 printf("%04x ", us[i]);
726 if (i % 16 == 15)
727 printf("\n");
728 }
729 printf("\n");
730 }
731 break;
732 case GL_UNSIGNED_INT:
733 {
734 const GLuint *us = (const GLuint *) map;
735 GLint i;
736 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) {
737 printf("%08x ", us[i]);
738 if (i % 8 == 7)
739 printf("\n");
740 }
741 printf("\n");
742 }
743 break;
744 default:
745 ;
746 }
747
748 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
749 }
750 #endif
751
752
753 /**
754 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
755 * Do the rendering for a glDrawElements or glDrawRangeElements call after
756 * we've validated buffer bounds, etc.
757 */
758 static void
759 vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
760 GLboolean index_bounds_valid,
761 GLuint start, GLuint end,
762 GLsizei count, GLenum type,
763 const GLvoid *indices,
764 GLint basevertex, GLint numInstances)
765 {
766 struct vbo_context *vbo = vbo_context(ctx);
767 struct vbo_exec_context *exec = &vbo->exec;
768 struct _mesa_index_buffer ib;
769 struct _mesa_prim prim[1];
770
771 FLUSH_CURRENT( ctx, 0 );
772
773 if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
774 return;
775 }
776
777 vbo_bind_arrays(ctx);
778
779 ib.count = count;
780 ib.type = type;
781 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
782 ib.ptr = indices;
783
784 prim[0].begin = 1;
785 prim[0].end = 1;
786 prim[0].weak = 0;
787 prim[0].pad = 0;
788 prim[0].mode = mode;
789 prim[0].start = 0;
790 prim[0].count = count;
791 prim[0].indexed = 1;
792 prim[0].basevertex = basevertex;
793 prim[0].num_instances = numInstances;
794
795 /* Need to give special consideration to rendering a range of
796 * indices starting somewhere above zero. Typically the
797 * application is issuing multiple DrawRangeElements() to draw
798 * successive primitives layed out linearly in the vertex arrays.
799 * Unless the vertex arrays are all in a VBO (or locked as with
800 * CVA), the OpenGL semantics imply that we need to re-read or
801 * re-upload the vertex data on each draw call.
802 *
803 * In the case of hardware tnl, we want to avoid starting the
804 * upload at zero, as it will mean every draw call uploads an
805 * increasing amount of not-used vertex data. Worse - in the
806 * software tnl module, all those vertices might be transformed and
807 * lit but never rendered.
808 *
809 * If we just upload or transform the vertices in start..end,
810 * however, the indices will be incorrect.
811 *
812 * At this level, we don't know exactly what the requirements of
813 * the backend are going to be, though it will likely boil down to
814 * either:
815 *
816 * 1) Do nothing, everything is in a VBO and is processed once
817 * only.
818 *
819 * 2) Adjust the indices and vertex arrays so that start becomes
820 * zero.
821 *
822 * Rather than doing anything here, I'll provide a helper function
823 * for the latter case elsewhere.
824 */
825
826 check_buffers_are_unmapped(exec->array.inputs);
827 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
828 index_bounds_valid, start, end, NULL );
829 }
830
831
832 /**
833 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
834 */
835 static void GLAPIENTRY
836 vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
837 GLuint start, GLuint end,
838 GLsizei count, GLenum type,
839 const GLvoid *indices,
840 GLint basevertex)
841 {
842 static GLuint warnCount = 0;
843 GLboolean index_bounds_valid = GL_TRUE;
844 GET_CURRENT_CONTEXT(ctx);
845
846 if (MESA_VERBOSE & VERBOSE_DRAW)
847 _mesa_debug(ctx,
848 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
849 _mesa_lookup_enum_by_nr(mode), start, end, count,
850 _mesa_lookup_enum_by_nr(type), indices, basevertex);
851
852 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
853 type, indices, basevertex ))
854 return;
855
856 if ((int) end + basevertex < 0 ||
857 start + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
858 /* The application requested we draw using a range of indices that's
859 * outside the bounds of the current VBO. This is invalid and appears
860 * to give undefined results. The safest thing to do is to simply
861 * ignore the range, in case the application botched their range tracking
862 * but did provide valid indices. Also issue a warning indicating that
863 * the application is broken.
864 */
865 if (warnCount++ < 10) {
866 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
867 "basevertex %d, count %d, type 0x%x, indices=%p):\n"
868 "\trange is outside VBO bounds (max=%u); ignoring.\n"
869 "\tThis should be fixed in the application.",
870 start, end, basevertex, count, type, indices,
871 ctx->Array.ArrayObj->_MaxElement - 1);
872 }
873 index_bounds_valid = GL_FALSE;
874 }
875
876 /* NOTE: It's important that 'end' is a reasonable value.
877 * in _tnl_draw_prims(), we use end to determine how many vertices
878 * to transform. If it's too large, we can unnecessarily split prims
879 * or we can read/write out of memory in several different places!
880 */
881
882 /* Catch/fix some potential user errors */
883 if (type == GL_UNSIGNED_BYTE) {
884 start = MIN2(start, 0xff);
885 end = MIN2(end, 0xff);
886 }
887 else if (type == GL_UNSIGNED_SHORT) {
888 start = MIN2(start, 0xffff);
889 end = MIN2(end, 0xffff);
890 }
891
892 if (0) {
893 printf("glDraw[Range]Elements{,BaseVertex}"
894 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
895 "base %d\n",
896 start, end, type, count,
897 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
898 basevertex);
899 }
900
901 if ((int) start + basevertex < 0 ||
902 end + basevertex >= ctx->Array.ArrayObj->_MaxElement)
903 index_bounds_valid = GL_FALSE;
904
905 #if 0
906 check_draw_elements_data(ctx, count, type, indices);
907 #else
908 (void) check_draw_elements_data;
909 #endif
910
911 vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
912 count, type, indices, basevertex, 1);
913 }
914
915
916 /**
917 * Called by glDrawRangeElements() in immediate mode.
918 */
919 static void GLAPIENTRY
920 vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
921 GLsizei count, GLenum type, const GLvoid *indices)
922 {
923 if (MESA_VERBOSE & VERBOSE_DRAW) {
924 GET_CURRENT_CONTEXT(ctx);
925 _mesa_debug(ctx,
926 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
927 _mesa_lookup_enum_by_nr(mode), start, end, count,
928 _mesa_lookup_enum_by_nr(type), indices);
929 }
930
931 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
932 indices, 0);
933 }
934
935
936 /**
937 * Called by glDrawElements() in immediate mode.
938 */
939 static void GLAPIENTRY
940 vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
941 const GLvoid *indices)
942 {
943 GET_CURRENT_CONTEXT(ctx);
944
945 if (MESA_VERBOSE & VERBOSE_DRAW)
946 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
947 _mesa_lookup_enum_by_nr(mode), count,
948 _mesa_lookup_enum_by_nr(type), indices);
949
950 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
951 return;
952
953 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
954 count, type, indices, 0, 1);
955 }
956
957
958 /**
959 * Called by glDrawElementsBaseVertex() in immediate mode.
960 */
961 static void GLAPIENTRY
962 vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
963 const GLvoid *indices, GLint basevertex)
964 {
965 GET_CURRENT_CONTEXT(ctx);
966
967 if (MESA_VERBOSE & VERBOSE_DRAW)
968 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
969 _mesa_lookup_enum_by_nr(mode), count,
970 _mesa_lookup_enum_by_nr(type), indices, basevertex);
971
972 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
973 basevertex ))
974 return;
975
976 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
977 count, type, indices, basevertex, 1);
978 }
979
980
981 /**
982 * Called by glDrawElementsInstanced() in immediate mode.
983 */
984 static void GLAPIENTRY
985 vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
986 const GLvoid *indices, GLsizei numInstances)
987 {
988 GET_CURRENT_CONTEXT(ctx);
989
990 if (MESA_VERBOSE & VERBOSE_DRAW)
991 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
992 _mesa_lookup_enum_by_nr(mode), count,
993 _mesa_lookup_enum_by_nr(type), indices, numInstances);
994
995 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
996 numInstances, 0))
997 return;
998
999 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1000 count, type, indices, 0, numInstances);
1001 }
1002
1003 /**
1004 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1005 */
1006 static void GLAPIENTRY
1007 vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1008 const GLvoid *indices, GLsizei numInstances,
1009 GLint basevertex)
1010 {
1011 GET_CURRENT_CONTEXT(ctx);
1012
1013 if (MESA_VERBOSE & VERBOSE_DRAW)
1014 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1015 _mesa_lookup_enum_by_nr(mode), count,
1016 _mesa_lookup_enum_by_nr(type), indices,
1017 numInstances, basevertex);
1018
1019 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1020 numInstances, basevertex))
1021 return;
1022
1023 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1024 count, type, indices, basevertex, numInstances);
1025 }
1026
1027
1028 /**
1029 * Inner support for both _mesa_MultiDrawElements() and
1030 * _mesa_MultiDrawRangeElements().
1031 * This does the actual rendering after we've checked array indexes, etc.
1032 */
1033 static void
1034 vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1035 const GLsizei *count, GLenum type,
1036 const GLvoid **indices, GLsizei primcount,
1037 const GLint *basevertex)
1038 {
1039 struct vbo_context *vbo = vbo_context(ctx);
1040 struct vbo_exec_context *exec = &vbo->exec;
1041 struct _mesa_index_buffer ib;
1042 struct _mesa_prim *prim;
1043 unsigned int index_type_size = vbo_sizeof_ib_type(type);
1044 uintptr_t min_index_ptr, max_index_ptr;
1045 GLboolean fallback = GL_FALSE;
1046 int i;
1047
1048 if (primcount == 0)
1049 return;
1050
1051 FLUSH_CURRENT( ctx, 0 );
1052
1053 if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
1054 return;
1055 }
1056
1057 prim = calloc(1, primcount * sizeof(*prim));
1058 if (prim == NULL) {
1059 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1060 return;
1061 }
1062
1063 vbo_bind_arrays(ctx);
1064
1065 min_index_ptr = (uintptr_t)indices[0];
1066 max_index_ptr = 0;
1067 for (i = 0; i < primcount; i++) {
1068 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1069 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1070 index_type_size * count[i]);
1071 }
1072
1073 /* Check if we can handle this thing as a bunch of index offsets from the
1074 * same index pointer. If we can't, then we have to fall back to doing
1075 * a draw_prims per primitive.
1076 * Check that the difference between each prim's indexes is a multiple of
1077 * the index/element size.
1078 */
1079 if (index_type_size != 1) {
1080 for (i = 0; i < primcount; i++) {
1081 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1082 fallback = GL_TRUE;
1083 break;
1084 }
1085 }
1086 }
1087
1088 /* If the index buffer isn't in a VBO, then treating the application's
1089 * subranges of the index buffer as one large index buffer may lead to
1090 * us reading unmapped memory.
1091 */
1092 if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
1093 fallback = GL_TRUE;
1094
1095 if (!fallback) {
1096 ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1097 ib.type = type;
1098 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1099 ib.ptr = (void *)min_index_ptr;
1100
1101 for (i = 0; i < primcount; i++) {
1102 prim[i].begin = (i == 0);
1103 prim[i].end = (i == primcount - 1);
1104 prim[i].weak = 0;
1105 prim[i].pad = 0;
1106 prim[i].mode = mode;
1107 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1108 prim[i].count = count[i];
1109 prim[i].indexed = 1;
1110 prim[i].num_instances = 1;
1111 if (basevertex != NULL)
1112 prim[i].basevertex = basevertex[i];
1113 else
1114 prim[i].basevertex = 0;
1115 }
1116
1117 check_buffers_are_unmapped(exec->array.inputs);
1118 vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
1119 GL_FALSE, ~0, ~0, NULL);
1120 } else {
1121 /* render one prim at a time */
1122 for (i = 0; i < primcount; i++) {
1123 ib.count = count[i];
1124 ib.type = type;
1125 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1126 ib.ptr = indices[i];
1127
1128 prim[0].begin = 1;
1129 prim[0].end = 1;
1130 prim[0].weak = 0;
1131 prim[0].pad = 0;
1132 prim[0].mode = mode;
1133 prim[0].start = 0;
1134 prim[0].count = count[i];
1135 prim[0].indexed = 1;
1136 prim[0].num_instances = 1;
1137 if (basevertex != NULL)
1138 prim[0].basevertex = basevertex[i];
1139 else
1140 prim[0].basevertex = 0;
1141
1142 check_buffers_are_unmapped(exec->array.inputs);
1143 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
1144 GL_FALSE, ~0, ~0, NULL);
1145 }
1146 }
1147
1148 free(prim);
1149 }
1150
1151
1152 static void GLAPIENTRY
1153 vbo_exec_MultiDrawElements(GLenum mode,
1154 const GLsizei *count, GLenum type,
1155 const GLvoid **indices,
1156 GLsizei primcount)
1157 {
1158 GET_CURRENT_CONTEXT(ctx);
1159 GLint i;
1160
1161 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1162
1163 for (i = 0; i < primcount; i++) {
1164 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1165 0))
1166 return;
1167 }
1168
1169 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1170 NULL);
1171 }
1172
1173
1174 static void GLAPIENTRY
1175 vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1176 const GLsizei *count, GLenum type,
1177 const GLvoid **indices,
1178 GLsizei primcount,
1179 const GLsizei *basevertex)
1180 {
1181 GET_CURRENT_CONTEXT(ctx);
1182 GLint i;
1183
1184 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1185
1186 for (i = 0; i < primcount; i++) {
1187 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1188 basevertex[i]))
1189 return;
1190 }
1191
1192 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1193 basevertex);
1194 }
1195
1196 #if FEATURE_EXT_transform_feedback
1197
1198 static void
1199 vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1200 struct gl_transform_feedback_object *obj,
1201 GLuint numInstances)
1202 {
1203 struct vbo_context *vbo = vbo_context(ctx);
1204 struct vbo_exec_context *exec = &vbo->exec;
1205 struct _mesa_prim prim[2];
1206
1207 vbo_bind_arrays(ctx);
1208
1209 /* init most fields to zero */
1210 memset(prim, 0, sizeof(prim));
1211 prim[0].begin = 1;
1212 prim[0].end = 1;
1213 prim[0].mode = mode;
1214 prim[0].num_instances = numInstances;
1215
1216 /* Maybe we should do some primitive splitting for primitive restart
1217 * (like in DrawArrays), but we have no way to know how many vertices
1218 * will be rendered. */
1219
1220 check_buffers_are_unmapped(exec->array.inputs);
1221 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
1222 GL_TRUE, 0, 0, obj);
1223 }
1224
1225 /**
1226 * Like DrawArrays, but take the count from a transform feedback object.
1227 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1228 * \param name the transform feedback object
1229 * User still has to setup of the vertex attribute info with
1230 * glVertexPointer, glColorPointer, etc.
1231 * Part of GL_ARB_transform_feedback2.
1232 */
1233 static void GLAPIENTRY
1234 vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
1235 {
1236 GET_CURRENT_CONTEXT(ctx);
1237 struct gl_transform_feedback_object *obj =
1238 _mesa_lookup_transform_feedback_object(ctx, name);
1239
1240 if (MESA_VERBOSE & VERBOSE_DRAW)
1241 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1242 _mesa_lookup_enum_by_nr(mode), name);
1243
1244 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) {
1245 return;
1246 }
1247
1248 FLUSH_CURRENT(ctx, 0);
1249
1250 if (!_mesa_valid_to_render(ctx, "glDrawTransformFeedback")) {
1251 return;
1252 }
1253
1254 vbo_draw_transform_feedback(ctx, mode, obj, 1);
1255 }
1256
1257 #endif
1258
1259 /**
1260 * Plug in the immediate-mode vertex array drawing commands into the
1261 * givven vbo_exec_context object.
1262 */
1263 void
1264 vbo_exec_array_init( struct vbo_exec_context *exec )
1265 {
1266 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
1267 exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
1268 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
1269 exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
1270 exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
1271 exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
1272 exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
1273 exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
1274 exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
1275 exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex;
1276 #if FEATURE_EXT_transform_feedback
1277 exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback;
1278 #endif
1279 }
1280
1281
1282 void
1283 vbo_exec_array_destroy( struct vbo_exec_context *exec )
1284 {
1285 /* nothing to do */
1286 }
1287
1288
1289
1290 /**
1291 * The following functions are only used for OpenGL ES 1/2 support.
1292 * And some aren't even supported (yet) in ES 1/2.
1293 */
1294
1295
1296 void GLAPIENTRY
1297 _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1298 {
1299 vbo_exec_DrawArrays(mode, first, count);
1300 }
1301
1302
1303 void GLAPIENTRY
1304 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1305 const GLvoid *indices)
1306 {
1307 vbo_exec_DrawElements(mode, count, type, indices);
1308 }
1309
1310
1311 void GLAPIENTRY
1312 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1313 const GLvoid *indices, GLint basevertex)
1314 {
1315 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1316 }
1317
1318
1319 void GLAPIENTRY
1320 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1321 GLenum type, const GLvoid *indices)
1322 {
1323 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1324 }
1325
1326
1327 void GLAPIENTRY
1328 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1329 GLsizei count, GLenum type,
1330 const GLvoid *indices, GLint basevertex)
1331 {
1332 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1333 indices, basevertex);
1334 }
1335
1336
1337 void GLAPIENTRY
1338 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1339 const GLvoid **indices, GLsizei primcount)
1340 {
1341 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1342 }
1343
1344
1345 void GLAPIENTRY
1346 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
1347 const GLsizei *count, GLenum type,
1348 const GLvoid **indices, GLsizei primcount,
1349 const GLint *basevertex)
1350 {
1351 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1352 primcount, basevertex);
1353 }
1354
1355 #if FEATURE_EXT_transform_feedback
1356
1357 void GLAPIENTRY
1358 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1359 {
1360 vbo_exec_DrawTransformFeedback(mode, name);
1361 }
1362
1363 #endif