vbo_exec_array.c revision 0a7602b938893e1b04a01ca8680376cbeec053ab
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 */
46static void
47check_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 */
67void
68vbo_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 */
86void
87vbo_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 */
205static void
206check_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 */
251static void
252unmap_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 */
266static void
267check_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 */
319static void
320check_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 */
329static void
330print_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 */
380static void
381bind_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 */
406static void
407recalculate_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 */
532void
533vbo_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 */
551static void
552vbo_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 */
634static void GLAPIENTRY
635vbo_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 */
666static void GLAPIENTRY
667vbo_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 */
699static void
700dump_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 */
757static void
758vbo_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 */
840static void GLAPIENTRY
841vbo_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 */
955static void GLAPIENTRY
956vbo_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 */
975static void GLAPIENTRY
976vbo_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 */
997static void GLAPIENTRY
998vbo_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 */
1020static void GLAPIENTRY
1021vbo_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 */
1042static void GLAPIENTRY
1043vbo_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 */
1069static void
1070vbo_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
1210static void GLAPIENTRY
1211vbo_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
1232static void GLAPIENTRY
1233vbo_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
1256static void
1257vbo_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 */
1299static void GLAPIENTRY
1300vbo_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 */
1329void
1330vbo_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
1346void
1347vbo_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
1360void GLAPIENTRY
1361_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1362{
1363   vbo_exec_DrawArrays(mode, first, count);
1364}
1365
1366
1367void 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
1375void 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
1383void 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
1391void 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
1401void 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
1409void 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
1421void GLAPIENTRY
1422_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1423{
1424   vbo_exec_DrawTransformFeedback(mode, name);
1425}
1426
1427#endif
1428