vbo: signal _NEW_ARRAY when transitioning between glBegin/End, glDrawArrays
[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 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 {
92 const GLboolean restart = ctx->Array.PrimitiveRestart;
93 const GLuint restartIndex = ctx->Array.RestartIndex;
94 const GLuint count = prim->count;
95 const void *indices;
96 GLuint i;
97
98 if (_mesa_is_bufferobj(ib->obj)) {
99 unsigned map_size;
100
101 switch (ib->type) {
102 case GL_UNSIGNED_INT:
103 map_size = count * sizeof(GLuint);
104 break;
105 case GL_UNSIGNED_SHORT:
106 map_size = count * sizeof(GLushort);
107 break;
108 case GL_UNSIGNED_BYTE:
109 map_size = count * sizeof(GLubyte);
110 break;
111 default:
112 assert(0);
113 map_size = 0;
114 }
115
116 indices = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr, map_size,
117 GL_MAP_READ_BIT, ib->obj);
118 } else {
119 indices = ib->ptr;
120 }
121
122 switch (ib->type) {
123 case GL_UNSIGNED_INT: {
124 const GLuint *ui_indices = (const GLuint *)indices;
125 GLuint max_ui = 0;
126 GLuint min_ui = ~0U;
127 if (restart) {
128 for (i = 0; i < count; i++) {
129 if (ui_indices[i] != restartIndex) {
130 if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
131 if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
132 }
133 }
134 }
135 else {
136 for (i = 0; i < count; i++) {
137 if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
138 if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
139 }
140 }
141 *min_index = min_ui;
142 *max_index = max_ui;
143 break;
144 }
145 case GL_UNSIGNED_SHORT: {
146 const GLushort *us_indices = (const GLushort *)indices;
147 GLuint max_us = 0;
148 GLuint min_us = ~0U;
149 if (restart) {
150 for (i = 0; i < count; i++) {
151 if (us_indices[i] != restartIndex) {
152 if (us_indices[i] > max_us) max_us = us_indices[i];
153 if (us_indices[i] < min_us) min_us = us_indices[i];
154 }
155 }
156 }
157 else {
158 for (i = 0; i < count; i++) {
159 if (us_indices[i] > max_us) max_us = us_indices[i];
160 if (us_indices[i] < min_us) min_us = us_indices[i];
161 }
162 }
163 *min_index = min_us;
164 *max_index = max_us;
165 break;
166 }
167 case GL_UNSIGNED_BYTE: {
168 const GLubyte *ub_indices = (const GLubyte *)indices;
169 GLuint max_ub = 0;
170 GLuint min_ub = ~0U;
171 if (restart) {
172 for (i = 0; i < count; i++) {
173 if (ub_indices[i] != restartIndex) {
174 if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
175 if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
176 }
177 }
178 }
179 else {
180 for (i = 0; i < count; i++) {
181 if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
182 if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
183 }
184 }
185 *min_index = min_ub;
186 *max_index = max_ub;
187 break;
188 }
189 default:
190 assert(0);
191 break;
192 }
193
194 if (_mesa_is_bufferobj(ib->obj)) {
195 ctx->Driver.UnmapBuffer(ctx, ib->obj);
196 }
197 }
198
199
200 /**
201 * Check that element 'j' of the array has reasonable data.
202 * Map VBO if needed.
203 * For debugging purposes; not normally used.
204 */
205 static void
206 check_array_data(struct gl_context *ctx, struct gl_client_array *array,
207 GLuint attrib, GLuint j)
208 {
209 if (array->Enabled) {
210 const void *data = array->Ptr;
211 if (_mesa_is_bufferobj(array->BufferObj)) {
212 if (!array->BufferObj->Pointer) {
213 /* need to map now */
214 array->BufferObj->Pointer =
215 ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size,
216 GL_MAP_READ_BIT, array->BufferObj);
217 }
218 data = ADD_POINTERS(data, array->BufferObj->Pointer);
219 }
220 switch (array->Type) {
221 case GL_FLOAT:
222 {
223 GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
224 GLint k;
225 for (k = 0; k < array->Size; k++) {
226 if (IS_INF_OR_NAN(f[k]) ||
227 f[k] >= 1.0e20 || f[k] <= -1.0e10) {
228 printf("Bad array data:\n");
229 printf(" Element[%u].%u = %f\n", j, k, f[k]);
230 printf(" Array %u at %p\n", attrib, (void* ) array);
231 printf(" Type 0x%x, Size %d, Stride %d\n",
232 array->Type, array->Size, array->Stride);
233 printf(" Address/offset %p in Buffer Object %u\n",
234 array->Ptr, array->BufferObj->Name);
235 f[k] = 1.0; /* XXX replace the bad value! */
236 }
237 /*assert(!IS_INF_OR_NAN(f[k]));*/
238 }
239 }
240 break;
241 default:
242 ;
243 }
244 }
245 }
246
247
248 /**
249 * Unmap the buffer object referenced by given array, if mapped.
250 */
251 static void
252 unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
253 {
254 if (array->Enabled &&
255 _mesa_is_bufferobj(array->BufferObj) &&
256 _mesa_bufferobj_mapped(array->BufferObj)) {
257 ctx->Driver.UnmapBuffer(ctx, array->BufferObj);
258 }
259 }
260
261
262 /**
263 * Examine the array's data for NaNs, etc.
264 * For debug purposes; not normally used.
265 */
266 static void
267 check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
268 const void *elements, GLint basevertex)
269 {
270 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
271 const void *elemMap;
272 GLint i, k;
273
274 if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
275 elemMap = ctx->Driver.MapBufferRange(ctx, 0,
276 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
277 GL_MAP_READ_BIT,
278 ctx->Array.ArrayObj->ElementArrayBufferObj);
279 elements = ADD_POINTERS(elements, elemMap);
280 }
281
282 for (i = 0; i < count; i++) {
283 GLuint j;
284
285 /* j = element[i] */
286 switch (elemType) {
287 case GL_UNSIGNED_BYTE:
288 j = ((const GLubyte *) elements)[i];
289 break;
290 case GL_UNSIGNED_SHORT:
291 j = ((const GLushort *) elements)[i];
292 break;
293 case GL_UNSIGNED_INT:
294 j = ((const GLuint *) elements)[i];
295 break;
296 default:
297 assert(0);
298 }
299
300 /* check element j of each enabled array */
301 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
302 check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j);
303 }
304 }
305
306 if (_mesa_is_bufferobj(arrayObj->ElementArrayBufferObj)) {
307 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
308 }
309
310 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
311 unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
312 }
313 }
314
315
316 /**
317 * Check array data, looking for NaNs, etc.
318 */
319 static void
320 check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
321 {
322 /* TO DO */
323 }
324
325
326 /**
327 * Print info/data for glDrawArrays(), for debugging.
328 */
329 static void
330 print_draw_arrays(struct gl_context *ctx,
331 GLenum mode, GLint start, GLsizei count)
332 {
333 struct vbo_context *vbo = vbo_context(ctx);
334 struct vbo_exec_context *exec = &vbo->exec;
335 int i;
336
337 printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
338 mode, start, count);
339
340 for (i = 0; i < 32; i++) {
341 struct gl_buffer_object *bufObj = exec->array.inputs[i]->BufferObj;
342 GLuint bufName = bufObj->Name;
343 GLint stride = exec->array.inputs[i]->Stride;
344 printf("attr %2d: size %d stride %d enabled %d "
345 "ptr %p Bufobj %u\n",
346 i,
347 exec->array.inputs[i]->Size,
348 stride,
349 /*exec->array.inputs[i]->Enabled,*/
350 exec->array.legacy_array[i]->Enabled,
351 exec->array.inputs[i]->Ptr,
352 bufName);
353
354 if (bufName) {
355 GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size,
356 GL_MAP_READ_BIT, bufObj);
357 int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
358 float *f = (float *) (p + offset);
359 int *k = (int *) f;
360 int i;
361 int n = (count * stride) / 4;
362 if (n > 32)
363 n = 32;
364 printf(" Data at offset %d:\n", offset);
365 for (i = 0; i < n; i++) {
366 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
367 }
368 ctx->Driver.UnmapBuffer(ctx, bufObj);
369 }
370 }
371 }
372
373
374 /**
375 * Bind the VBO executor to the current vertex array object prior
376 * to drawing.
377 *
378 * Just translate the arrayobj into a sane layout.
379 */
380 static void
381 bind_array_obj(struct gl_context *ctx)
382 {
383 struct vbo_context *vbo = vbo_context(ctx);
384 struct vbo_exec_context *exec = &vbo->exec;
385 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
386 GLuint i;
387
388 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++)
389 exec->array.legacy_array[i] = &arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)];
390
391 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
392 assert(i < Elements(exec->array.generic_array));
393 exec->array.generic_array[i] = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)];
394 }
395 }
396
397
398 /**
399 * Set the vbo->exec->inputs[] pointers to point to the enabled
400 * vertex arrays. This depends on the current vertex program/shader
401 * being executed because of whether or not generic vertex arrays
402 * alias the conventional vertex arrays.
403 * For arrays that aren't enabled, we set the input[attrib] pointer
404 * to point at a zero-stride current value "array".
405 */
406 static void
407 recalculate_input_bindings(struct gl_context *ctx)
408 {
409 struct vbo_context *vbo = vbo_context(ctx);
410 struct vbo_exec_context *exec = &vbo->exec;
411 const struct gl_client_array **inputs = &exec->array.inputs[0];
412 GLbitfield64 const_inputs = 0x0;
413 GLuint i;
414
415 switch (get_program_mode(ctx)) {
416 case VP_NONE:
417 /* When no vertex program is active (or the vertex program is generated
418 * from fixed-function state). We put the material values into the
419 * generic slots. This is the only situation where material values
420 * are available as per-vertex attributes.
421 */
422 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
423 if (exec->array.legacy_array[i]->Enabled)
424 inputs[i] = exec->array.legacy_array[i];
425 else {
426 inputs[i] = &vbo->legacy_currval[i];
427 const_inputs |= VERT_BIT(i);
428 }
429 }
430
431 for (i = 0; i < MAT_ATTRIB_MAX; i++) {
432 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->mat_currval[i];
433 const_inputs |= VERT_BIT_GENERIC(i);
434 }
435
436 /* Could use just about anything, just to fill in the empty
437 * slots:
438 */
439 for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
440 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
441 const_inputs |= VERT_BIT_GENERIC(i);
442 }
443
444 /* There is no need to make _NEW_ARRAY dirty here for the TnL program,
445 * because it already takes care of invalidating the state necessary
446 * to revalidate vertex arrays. Not marking the state as dirty also
447 * improves performance (quite significantly in some apps).
448 */
449 if (!ctx->VertexProgram._MaintainTnlProgram)
450 ctx->NewState |= _NEW_ARRAY;
451 break;
452
453 case VP_NV:
454 /* NV_vertex_program - attribute arrays alias and override
455 * conventional, legacy arrays. No materials, and the generic
456 * slots are vacant.
457 */
458 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
459 if (i < VERT_ATTRIB_GENERIC_MAX
460 && exec->array.generic_array[i]->Enabled)
461 inputs[i] = exec->array.generic_array[i];
462 else if (exec->array.legacy_array[i]->Enabled)
463 inputs[i] = exec->array.legacy_array[i];
464 else {
465 inputs[i] = &vbo->legacy_currval[i];
466 const_inputs |= VERT_BIT_FF(i);
467 }
468 }
469
470 /* Could use just about anything, just to fill in the empty
471 * slots:
472 */
473 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
474 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
475 const_inputs |= VERT_BIT_GENERIC(i);
476 }
477
478 ctx->NewState |= _NEW_ARRAY;
479 break;
480
481 case VP_ARB:
482 /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
483 * attribute array aliases and overrides the legacy position array.
484 *
485 * Otherwise, legacy attributes available in the legacy slots,
486 * generic attributes in the generic slots and materials are not
487 * available as per-vertex attributes.
488 */
489 if (exec->array.generic_array[0]->Enabled)
490 inputs[0] = exec->array.generic_array[0];
491 else if (exec->array.legacy_array[0]->Enabled)
492 inputs[0] = exec->array.legacy_array[0];
493 else {
494 inputs[0] = &vbo->legacy_currval[0];
495 const_inputs |= VERT_BIT_POS;
496 }
497
498 for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
499 if (exec->array.legacy_array[i]->Enabled)
500 inputs[i] = exec->array.legacy_array[i];
501 else {
502 inputs[i] = &vbo->legacy_currval[i];
503 const_inputs |= VERT_BIT_FF(i);
504 }
505 }
506
507 for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
508 if (exec->array.generic_array[i]->Enabled)
509 inputs[VERT_ATTRIB_GENERIC(i)] = exec->array.generic_array[i];
510 else {
511 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->generic_currval[i];
512 const_inputs |= VERT_BIT_GENERIC(i);
513 }
514 }
515
516 inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
517 ctx->NewState |= _NEW_ARRAY;
518 break;
519 }
520
521 _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
522 }
523
524
525 /**
526 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
527 * These will point to the arrays to actually use for drawing. Some will
528 * be user-provided arrays, other will be zero-stride const-valued arrays.
529 * Note that this might set the _NEW_ARRAY dirty flag so state validation
530 * must be done after this call.
531 */
532 void
533 vbo_bind_arrays(struct gl_context *ctx)
534 {
535 if (!ctx->Array.RebindArrays) {
536 return;
537 }
538
539 bind_array_obj(ctx);
540 recalculate_input_bindings(ctx);
541 ctx->Array.RebindArrays = GL_FALSE;
542 }
543
544
545 /**
546 * Helper function called by the other DrawArrays() functions below.
547 * This is where we handle primitive restart for drawing non-indexed
548 * arrays. If primitive restart is enabled, it typically means
549 * splitting one DrawArrays() into two.
550 */
551 static void
552 vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
553 GLsizei count, GLuint numInstances)
554 {
555 struct vbo_context *vbo = vbo_context(ctx);
556 struct vbo_exec_context *exec = &vbo->exec;
557 struct _mesa_prim prim[2];
558
559 vbo_bind_arrays(ctx);
560
561 vbo_draw_method(exec, DRAW_ARRAYS);
562
563 /* Again... because we may have changed the bitmask of per-vertex varying
564 * attributes. If we regenerate the fixed-function vertex program now
565 * we may be able to prune down the number of vertex attributes which we
566 * need in the shader.
567 */
568 if (ctx->NewState)
569 _mesa_update_state(ctx);
570
571 /* init most fields to zero */
572 memset(prim, 0, sizeof(prim));
573 prim[0].begin = 1;
574 prim[0].end = 1;
575 prim[0].mode = mode;
576 prim[0].num_instances = numInstances;
577
578 /* Implement the primitive restart index */
579 if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
580 GLuint primCount = 0;
581
582 if (ctx->Array.RestartIndex == start) {
583 /* special case: RestartIndex at beginning */
584 if (count > 1) {
585 prim[0].start = start + 1;
586 prim[0].count = count - 1;
587 primCount = 1;
588 }
589 }
590 else if (ctx->Array.RestartIndex == start + count - 1) {
591 /* special case: RestartIndex at end */
592 if (count > 1) {
593 prim[0].start = start;
594 prim[0].count = count - 1;
595 primCount = 1;
596 }
597 }
598 else {
599 /* general case: RestartIndex in middle, split into two prims */
600 prim[0].start = start;
601 prim[0].count = ctx->Array.RestartIndex - start;
602
603 prim[1] = prim[0];
604 prim[1].start = ctx->Array.RestartIndex + 1;
605 prim[1].count = count - prim[1].start;
606
607 primCount = 2;
608 }
609
610 if (primCount > 0) {
611 /* draw one or two prims */
612 check_buffers_are_unmapped(exec->array.inputs);
613 vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
614 GL_TRUE, start, start + count - 1, NULL);
615 }
616 }
617 else {
618 /* no prim restart */
619 prim[0].start = start;
620 prim[0].count = count;
621
622 check_buffers_are_unmapped(exec->array.inputs);
623 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
624 GL_TRUE, start, start + count - 1,
625 NULL);
626 }
627 }
628
629
630
631 /**
632 * Called from glDrawArrays when in immediate mode (not display list mode).
633 */
634 static void GLAPIENTRY
635 vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
636 {
637 GET_CURRENT_CONTEXT(ctx);
638
639 if (MESA_VERBOSE & VERBOSE_DRAW)
640 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
641 _mesa_lookup_enum_by_nr(mode), start, count);
642
643 if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
644 return;
645
646 FLUSH_CURRENT( ctx, 0 );
647
648 if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
649 return;
650 }
651
652 if (0)
653 check_draw_arrays_data(ctx, start, count);
654
655 vbo_draw_arrays(ctx, mode, start, count, 1);
656
657 if (0)
658 print_draw_arrays(ctx, mode, start, count);
659 }
660
661
662 /**
663 * Called from glDrawArraysInstanced when in immediate mode (not
664 * display list mode).
665 */
666 static void GLAPIENTRY
667 vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
668 GLsizei numInstances)
669 {
670 GET_CURRENT_CONTEXT(ctx);
671
672 if (MESA_VERBOSE & VERBOSE_DRAW)
673 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
674 _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
675
676 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
677 return;
678
679 FLUSH_CURRENT( ctx, 0 );
680
681 if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
682 return;
683 }
684
685 if (0)
686 check_draw_arrays_data(ctx, start, count);
687
688 vbo_draw_arrays(ctx, mode, start, count, numInstances);
689
690 if (0)
691 print_draw_arrays(ctx, mode, start, count);
692 }
693
694
695 /**
696 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
697 * For debugging.
698 */
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
751
752 /**
753 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
754 * Do the rendering for a glDrawElements or glDrawRangeElements call after
755 * we've validated buffer bounds, etc.
756 */
757 static void
758 vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
759 GLboolean index_bounds_valid,
760 GLuint start, GLuint end,
761 GLsizei count, GLenum type,
762 const GLvoid *indices,
763 GLint basevertex, GLint numInstances)
764 {
765 struct vbo_context *vbo = vbo_context(ctx);
766 struct vbo_exec_context *exec = &vbo->exec;
767 struct _mesa_index_buffer ib;
768 struct _mesa_prim prim[1];
769
770 FLUSH_CURRENT( ctx, 0 );
771
772 if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
773 return;
774 }
775
776 vbo_bind_arrays( ctx );
777
778 vbo_draw_method(exec, DRAW_ARRAYS);
779
780 /* check for dirty state again */
781 if (ctx->NewState)
782 _mesa_update_state( ctx );
783
784 ib.count = count;
785 ib.type = type;
786 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
787 ib.ptr = indices;
788
789 prim[0].begin = 1;
790 prim[0].end = 1;
791 prim[0].weak = 0;
792 prim[0].pad = 0;
793 prim[0].mode = mode;
794 prim[0].start = 0;
795 prim[0].count = count;
796 prim[0].indexed = 1;
797 prim[0].basevertex = basevertex;
798 prim[0].num_instances = numInstances;
799
800 /* Need to give special consideration to rendering a range of
801 * indices starting somewhere above zero. Typically the
802 * application is issuing multiple DrawRangeElements() to draw
803 * successive primitives layed out linearly in the vertex arrays.
804 * Unless the vertex arrays are all in a VBO (or locked as with
805 * CVA), the OpenGL semantics imply that we need to re-read or
806 * re-upload the vertex data on each draw call.
807 *
808 * In the case of hardware tnl, we want to avoid starting the
809 * upload at zero, as it will mean every draw call uploads an
810 * increasing amount of not-used vertex data. Worse - in the
811 * software tnl module, all those vertices might be transformed and
812 * lit but never rendered.
813 *
814 * If we just upload or transform the vertices in start..end,
815 * however, the indices will be incorrect.
816 *
817 * At this level, we don't know exactly what the requirements of
818 * the backend are going to be, though it will likely boil down to
819 * either:
820 *
821 * 1) Do nothing, everything is in a VBO and is processed once
822 * only.
823 *
824 * 2) Adjust the indices and vertex arrays so that start becomes
825 * zero.
826 *
827 * Rather than doing anything here, I'll provide a helper function
828 * for the latter case elsewhere.
829 */
830
831 check_buffers_are_unmapped(exec->array.inputs);
832 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
833 index_bounds_valid, start, end, NULL );
834 }
835
836
837 /**
838 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
839 */
840 static void GLAPIENTRY
841 vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
842 GLuint start, GLuint end,
843 GLsizei count, GLenum type,
844 const GLvoid *indices,
845 GLint basevertex)
846 {
847 static GLuint warnCount = 0;
848 GET_CURRENT_CONTEXT(ctx);
849
850 if (MESA_VERBOSE & VERBOSE_DRAW)
851 _mesa_debug(ctx,
852 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
853 _mesa_lookup_enum_by_nr(mode), start, end, count,
854 _mesa_lookup_enum_by_nr(type), indices, basevertex);
855
856 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
857 type, indices, basevertex ))
858 return;
859
860 /* NOTE: It's important that 'end' is a reasonable value.
861 * in _tnl_draw_prims(), we use end to determine how many vertices
862 * to transform. If it's too large, we can unnecessarily split prims
863 * or we can read/write out of memory in several different places!
864 */
865
866 /* Catch/fix some potential user errors */
867 if (type == GL_UNSIGNED_BYTE) {
868 start = MIN2(start, 0xff);
869 end = MIN2(end, 0xff);
870 }
871 else if (type == GL_UNSIGNED_SHORT) {
872 start = MIN2(start, 0xffff);
873 end = MIN2(end, 0xffff);
874 }
875
876 if (end >= ctx->Array.ArrayObj->_MaxElement) {
877 /* the max element is out of bounds of one or more enabled arrays */
878 warnCount++;
879
880 if (warnCount < 10) {
881 _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
882 "type 0x%x, indices=%p)\n"
883 "\tend is out of bounds (max=%u) "
884 "Element Buffer %u (size %d)\n"
885 "\tThis should probably be fixed in the application.",
886 start, end, count, type, indices,
887 ctx->Array.ArrayObj->_MaxElement - 1,
888 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
889 (int) ctx->Array.ArrayObj->ElementArrayBufferObj->Size);
890 }
891
892 if (0)
893 dump_element_buffer(ctx, type);
894
895 if (0)
896 _mesa_print_arrays(ctx);
897
898 /* 'end' was out of bounds, but now let's check the actual array
899 * indexes to see if any of them are out of bounds.
900 */
901 if (0) {
902 GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
903 ctx->Array.ArrayObj->ElementArrayBufferObj);
904 if (max >= ctx->Array.ArrayObj->_MaxElement) {
905 if (warnCount < 10) {
906 _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
907 "count %d, type 0x%x, indices=%p)\n"
908 "\tindex=%u is out of bounds (max=%u) "
909 "Element Buffer %u (size %d)\n"
910 "\tSkipping the glDrawRangeElements() call",
911 start, end, count, type, indices, max,
912 ctx->Array.ArrayObj->_MaxElement - 1,
913 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
914 (int) ctx->Array.ArrayObj->ElementArrayBufferObj->Size);
915 }
916 }
917 /* XXX we could also find the min index and compare to 'start'
918 * to see if start is correct. But it's more likely to get the
919 * upper bound wrong.
920 */
921 }
922
923 /* Set 'end' to the max possible legal value */
924 assert(ctx->Array.ArrayObj->_MaxElement >= 1);
925 end = ctx->Array.ArrayObj->_MaxElement - 1;
926
927 if (end < start) {
928 return;
929 }
930 }
931
932 if (0) {
933 printf("glDraw[Range]Elements{,BaseVertex}"
934 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
935 "base %d\n",
936 start, end, type, count,
937 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
938 basevertex);
939 }
940
941 #if 0
942 check_draw_elements_data(ctx, count, type, indices);
943 #else
944 (void) check_draw_elements_data;
945 #endif
946
947 vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
948 count, type, indices, basevertex, 1);
949 }
950
951
952 /**
953 * Called by glDrawRangeElements() in immediate mode.
954 */
955 static void GLAPIENTRY
956 vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
957 GLsizei count, GLenum type, const GLvoid *indices)
958 {
959 if (MESA_VERBOSE & VERBOSE_DRAW) {
960 GET_CURRENT_CONTEXT(ctx);
961 _mesa_debug(ctx,
962 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
963 _mesa_lookup_enum_by_nr(mode), start, end, count,
964 _mesa_lookup_enum_by_nr(type), indices);
965 }
966
967 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
968 indices, 0);
969 }
970
971
972 /**
973 * Called by glDrawElements() in immediate mode.
974 */
975 static void GLAPIENTRY
976 vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
977 const GLvoid *indices)
978 {
979 GET_CURRENT_CONTEXT(ctx);
980
981 if (MESA_VERBOSE & VERBOSE_DRAW)
982 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
983 _mesa_lookup_enum_by_nr(mode), count,
984 _mesa_lookup_enum_by_nr(type), indices);
985
986 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
987 return;
988
989 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
990 count, type, indices, 0, 1);
991 }
992
993
994 /**
995 * Called by glDrawElementsBaseVertex() in immediate mode.
996 */
997 static void GLAPIENTRY
998 vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
999 const GLvoid *indices, GLint basevertex)
1000 {
1001 GET_CURRENT_CONTEXT(ctx);
1002
1003 if (MESA_VERBOSE & VERBOSE_DRAW)
1004 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
1005 _mesa_lookup_enum_by_nr(mode), count,
1006 _mesa_lookup_enum_by_nr(type), indices, basevertex);
1007
1008 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
1009 basevertex ))
1010 return;
1011
1012 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1013 count, type, indices, basevertex, 1);
1014 }
1015
1016
1017 /**
1018 * Called by glDrawElementsInstanced() in immediate mode.
1019 */
1020 static void GLAPIENTRY
1021 vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1022 const GLvoid *indices, GLsizei numInstances)
1023 {
1024 GET_CURRENT_CONTEXT(ctx);
1025
1026 if (MESA_VERBOSE & VERBOSE_DRAW)
1027 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
1028 _mesa_lookup_enum_by_nr(mode), count,
1029 _mesa_lookup_enum_by_nr(type), indices, numInstances);
1030
1031 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1032 numInstances, 0))
1033 return;
1034
1035 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1036 count, type, indices, 0, numInstances);
1037 }
1038
1039 /**
1040 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1041 */
1042 static void GLAPIENTRY
1043 vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1044 const GLvoid *indices, GLsizei numInstances,
1045 GLint basevertex)
1046 {
1047 GET_CURRENT_CONTEXT(ctx);
1048
1049 if (MESA_VERBOSE & VERBOSE_DRAW)
1050 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1051 _mesa_lookup_enum_by_nr(mode), count,
1052 _mesa_lookup_enum_by_nr(type), indices,
1053 numInstances, basevertex);
1054
1055 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1056 numInstances, basevertex))
1057 return;
1058
1059 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1060 count, type, indices, basevertex, numInstances);
1061 }
1062
1063
1064 /**
1065 * Inner support for both _mesa_MultiDrawElements() and
1066 * _mesa_MultiDrawRangeElements().
1067 * This does the actual rendering after we've checked array indexes, etc.
1068 */
1069 static void
1070 vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1071 const GLsizei *count, GLenum type,
1072 const GLvoid **indices, GLsizei primcount,
1073 const GLint *basevertex)
1074 {
1075 struct vbo_context *vbo = vbo_context(ctx);
1076 struct vbo_exec_context *exec = &vbo->exec;
1077 struct _mesa_index_buffer ib;
1078 struct _mesa_prim *prim;
1079 unsigned int index_type_size = 0;
1080 uintptr_t min_index_ptr, max_index_ptr;
1081 GLboolean fallback = GL_FALSE;
1082 int i;
1083
1084 if (primcount == 0)
1085 return;
1086
1087 FLUSH_CURRENT( ctx, 0 );
1088
1089 if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
1090 return;
1091 }
1092
1093 prim = calloc(1, primcount * sizeof(*prim));
1094 if (prim == NULL) {
1095 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1096 return;
1097 }
1098
1099 /* Decide if we can do this all as one set of primitives sharing the
1100 * same index buffer, or if we have to reset the index pointer per
1101 * primitive.
1102 */
1103 vbo_bind_arrays( ctx );
1104
1105 /* check for dirty state again */
1106 if (ctx->NewState)
1107 _mesa_update_state( ctx );
1108
1109 switch (type) {
1110 case GL_UNSIGNED_INT:
1111 index_type_size = 4;
1112 break;
1113 case GL_UNSIGNED_SHORT:
1114 index_type_size = 2;
1115 break;
1116 case GL_UNSIGNED_BYTE:
1117 index_type_size = 1;
1118 break;
1119 default:
1120 assert(0);
1121 }
1122
1123 min_index_ptr = (uintptr_t)indices[0];
1124 max_index_ptr = 0;
1125 for (i = 0; i < primcount; i++) {
1126 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1127 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1128 index_type_size * count[i]);
1129 }
1130
1131 /* Check if we can handle this thing as a bunch of index offsets from the
1132 * same index pointer. If we can't, then we have to fall back to doing
1133 * a draw_prims per primitive.
1134 * Check that the difference between each prim's indexes is a multiple of
1135 * the index/element size.
1136 */
1137 if (index_type_size != 1) {
1138 for (i = 0; i < primcount; i++) {
1139 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1140 fallback = GL_TRUE;
1141 break;
1142 }
1143 }
1144 }
1145
1146 /* If the index buffer isn't in a VBO, then treating the application's
1147 * subranges of the index buffer as one large index buffer may lead to
1148 * us reading unmapped memory.
1149 */
1150 if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
1151 fallback = GL_TRUE;
1152
1153 if (!fallback) {
1154 ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1155 ib.type = type;
1156 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1157 ib.ptr = (void *)min_index_ptr;
1158
1159 for (i = 0; i < primcount; i++) {
1160 prim[i].begin = (i == 0);
1161 prim[i].end = (i == primcount - 1);
1162 prim[i].weak = 0;
1163 prim[i].pad = 0;
1164 prim[i].mode = mode;
1165 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1166 prim[i].count = count[i];
1167 prim[i].indexed = 1;
1168 prim[i].num_instances = 1;
1169 if (basevertex != NULL)
1170 prim[i].basevertex = basevertex[i];
1171 else
1172 prim[i].basevertex = 0;
1173 }
1174
1175 check_buffers_are_unmapped(exec->array.inputs);
1176 vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
1177 GL_FALSE, ~0, ~0, NULL);
1178 } else {
1179 /* render one prim at a time */
1180 for (i = 0; i < primcount; i++) {
1181 ib.count = count[i];
1182 ib.type = type;
1183 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1184 ib.ptr = indices[i];
1185
1186 prim[0].begin = 1;
1187 prim[0].end = 1;
1188 prim[0].weak = 0;
1189 prim[0].pad = 0;
1190 prim[0].mode = mode;
1191 prim[0].start = 0;
1192 prim[0].count = count[i];
1193 prim[0].indexed = 1;
1194 prim[0].num_instances = 1;
1195 if (basevertex != NULL)
1196 prim[0].basevertex = basevertex[i];
1197 else
1198 prim[0].basevertex = 0;
1199
1200 check_buffers_are_unmapped(exec->array.inputs);
1201 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
1202 GL_FALSE, ~0, ~0, NULL);
1203 }
1204 }
1205
1206 free(prim);
1207 }
1208
1209
1210 static void GLAPIENTRY
1211 vbo_exec_MultiDrawElements(GLenum mode,
1212 const GLsizei *count, GLenum type,
1213 const GLvoid **indices,
1214 GLsizei primcount)
1215 {
1216 GET_CURRENT_CONTEXT(ctx);
1217 GLint i;
1218
1219 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1220
1221 for (i = 0; i < primcount; i++) {
1222 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1223 0))
1224 return;
1225 }
1226
1227 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1228 NULL);
1229 }
1230
1231
1232 static void GLAPIENTRY
1233 vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1234 const GLsizei *count, GLenum type,
1235 const GLvoid **indices,
1236 GLsizei primcount,
1237 const GLsizei *basevertex)
1238 {
1239 GET_CURRENT_CONTEXT(ctx);
1240 GLint i;
1241
1242 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1243
1244 for (i = 0; i < primcount; i++) {
1245 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1246 basevertex[i]))
1247 return;
1248 }
1249
1250 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1251 basevertex);
1252 }
1253
1254 #if FEATURE_EXT_transform_feedback
1255
1256 static void
1257 vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1258 struct gl_transform_feedback_object *obj,
1259 GLuint numInstances)
1260 {
1261 struct vbo_context *vbo = vbo_context(ctx);
1262 struct vbo_exec_context *exec = &vbo->exec;
1263 struct _mesa_prim prim[2];
1264
1265 vbo_bind_arrays(ctx);
1266
1267 /* Again... because we may have changed the bitmask of per-vertex varying
1268 * attributes. If we regenerate the fixed-function vertex program now
1269 * we may be able to prune down the number of vertex attributes which we
1270 * need in the shader.
1271 */
1272 if (ctx->NewState)
1273 _mesa_update_state(ctx);
1274
1275 /* init most fields to zero */
1276 memset(prim, 0, sizeof(prim));
1277 prim[0].begin = 1;
1278 prim[0].end = 1;
1279 prim[0].mode = mode;
1280 prim[0].num_instances = numInstances;
1281
1282 /* Maybe we should do some primitive splitting for primitive restart
1283 * (like in DrawArrays), but we have no way to know how many vertices
1284 * will be rendered. */
1285
1286 check_buffers_are_unmapped(exec->array.inputs);
1287 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
1288 GL_TRUE, 0, 0, obj);
1289 }
1290
1291 /**
1292 * Like DrawArrays, but take the count from a transform feedback object.
1293 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1294 * \param name the transform feedback object
1295 * User still has to setup of the vertex attribute info with
1296 * glVertexPointer, glColorPointer, etc.
1297 * Part of GL_ARB_transform_feedback2.
1298 */
1299 static void GLAPIENTRY
1300 vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
1301 {
1302 GET_CURRENT_CONTEXT(ctx);
1303 struct gl_transform_feedback_object *obj =
1304 _mesa_lookup_transform_feedback_object(ctx, name);
1305
1306 if (MESA_VERBOSE & VERBOSE_DRAW)
1307 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1308 _mesa_lookup_enum_by_nr(mode), name);
1309
1310 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) {
1311 return;
1312 }
1313
1314 FLUSH_CURRENT(ctx, 0);
1315
1316 if (!_mesa_valid_to_render(ctx, "glDrawTransformFeedback")) {
1317 return;
1318 }
1319
1320 vbo_draw_transform_feedback(ctx, mode, obj, 1);
1321 }
1322
1323 #endif
1324
1325 /**
1326 * Plug in the immediate-mode vertex array drawing commands into the
1327 * givven vbo_exec_context object.
1328 */
1329 void
1330 vbo_exec_array_init( struct vbo_exec_context *exec )
1331 {
1332 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
1333 exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
1334 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
1335 exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
1336 exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
1337 exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
1338 exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
1339 exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
1340 exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
1341 exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex;
1342 exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback;
1343 }
1344
1345
1346 void
1347 vbo_exec_array_destroy( struct vbo_exec_context *exec )
1348 {
1349 /* nothing to do */
1350 }
1351
1352
1353
1354 /**
1355 * The following functions are only used for OpenGL ES 1/2 support.
1356 * And some aren't even supported (yet) in ES 1/2.
1357 */
1358
1359
1360 void GLAPIENTRY
1361 _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1362 {
1363 vbo_exec_DrawArrays(mode, first, count);
1364 }
1365
1366
1367 void GLAPIENTRY
1368 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1369 const GLvoid *indices)
1370 {
1371 vbo_exec_DrawElements(mode, count, type, indices);
1372 }
1373
1374
1375 void GLAPIENTRY
1376 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1377 const GLvoid *indices, GLint basevertex)
1378 {
1379 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1380 }
1381
1382
1383 void GLAPIENTRY
1384 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1385 GLenum type, const GLvoid *indices)
1386 {
1387 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1388 }
1389
1390
1391 void GLAPIENTRY
1392 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1393 GLsizei count, GLenum type,
1394 const GLvoid *indices, GLint basevertex)
1395 {
1396 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1397 indices, basevertex);
1398 }
1399
1400
1401 void GLAPIENTRY
1402 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1403 const GLvoid **indices, GLsizei primcount)
1404 {
1405 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1406 }
1407
1408
1409 void GLAPIENTRY
1410 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
1411 const GLsizei *count, GLenum type,
1412 const GLvoid **indices, GLsizei primcount,
1413 const GLint *basevertex)
1414 {
1415 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1416 primcount, basevertex);
1417 }
1418
1419 #if FEATURE_EXT_transform_feedback
1420
1421 void GLAPIENTRY
1422 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1423 {
1424 vbo_exec_DrawTransformFeedback(mode, name);
1425 }
1426
1427 #endif