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