vbo_exec_array.c revision f9995b30756140724f41daf963fa06167912be7f
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
38#include "vbo_context.h"
39
40
41/**
42 * Compute min and max elements by scanning the index buffer for
43 * glDraw[Range]Elements() calls.
44 */
45void
46vbo_get_minmax_index(struct gl_context *ctx,
47		     const struct _mesa_prim *prim,
48		     const struct _mesa_index_buffer *ib,
49		     GLuint *min_index, GLuint *max_index)
50{
51   GLuint i;
52   GLuint count = prim->count;
53   const void *indices;
54
55   if (_mesa_is_bufferobj(ib->obj)) {
56      const GLvoid *map =
57         ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
58                               GL_READ_ONLY, ib->obj);
59      indices = ADD_POINTERS(map, ib->ptr);
60   } else {
61      indices = ib->ptr;
62   }
63
64   switch (ib->type) {
65   case GL_UNSIGNED_INT: {
66      const GLuint *ui_indices = (const GLuint *)indices;
67      GLuint max_ui = ui_indices[count-1];
68      GLuint min_ui = ui_indices[0];
69      for (i = 0; i < count; i++) {
70	 if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
71	 if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
72      }
73      *min_index = min_ui;
74      *max_index = max_ui;
75      break;
76   }
77   case GL_UNSIGNED_SHORT: {
78      const GLushort *us_indices = (const GLushort *)indices;
79      GLuint max_us = us_indices[count-1];
80      GLuint min_us = us_indices[0];
81      for (i = 0; i < count; i++) {
82	 if (us_indices[i] > max_us) max_us = us_indices[i];
83	 if (us_indices[i] < min_us) min_us = us_indices[i];
84      }
85      *min_index = min_us;
86      *max_index = max_us;
87      break;
88   }
89   case GL_UNSIGNED_BYTE: {
90      const GLubyte *ub_indices = (const GLubyte *)indices;
91      GLuint max_ub = ub_indices[count-1];
92      GLuint min_ub = ub_indices[0];
93      for (i = 0; i < count; i++) {
94	 if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
95	 if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
96      }
97      *min_index = min_ub;
98      *max_index = max_ub;
99      break;
100   }
101   default:
102      assert(0);
103      break;
104   }
105
106   if (_mesa_is_bufferobj(ib->obj)) {
107      ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ib->obj);
108   }
109}
110
111
112/**
113 * Check that element 'j' of the array has reasonable data.
114 * Map VBO if needed.
115 * For debugging purposes; not normally used.
116 */
117static void
118check_array_data(struct gl_context *ctx, struct gl_client_array *array,
119                 GLuint attrib, GLuint j)
120{
121   if (array->Enabled) {
122      const void *data = array->Ptr;
123      if (_mesa_is_bufferobj(array->BufferObj)) {
124         if (!array->BufferObj->Pointer) {
125            /* need to map now */
126            array->BufferObj->Pointer =
127               ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
128                                     GL_READ_ONLY, array->BufferObj);
129         }
130         data = ADD_POINTERS(data, array->BufferObj->Pointer);
131      }
132      switch (array->Type) {
133      case GL_FLOAT:
134         {
135            GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
136            GLint k;
137            for (k = 0; k < array->Size; k++) {
138               if (IS_INF_OR_NAN(f[k]) ||
139                   f[k] >= 1.0e20 || f[k] <= -1.0e10) {
140                  printf("Bad array data:\n");
141                  printf("  Element[%u].%u = %f\n", j, k, f[k]);
142                  printf("  Array %u at %p\n", attrib, (void* ) array);
143                  printf("  Type 0x%x, Size %d, Stride %d\n",
144			 array->Type, array->Size, array->Stride);
145                  printf("  Address/offset %p in Buffer Object %u\n",
146			 array->Ptr, array->BufferObj->Name);
147                  f[k] = 1.0; /* XXX replace the bad value! */
148               }
149               /*assert(!IS_INF_OR_NAN(f[k]));*/
150            }
151         }
152         break;
153      default:
154         ;
155      }
156   }
157}
158
159
160/**
161 * Unmap the buffer object referenced by given array, if mapped.
162 */
163static void
164unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
165{
166   if (array->Enabled &&
167       _mesa_is_bufferobj(array->BufferObj) &&
168       _mesa_bufferobj_mapped(array->BufferObj)) {
169      ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, array->BufferObj);
170   }
171}
172
173
174/**
175 * Examine the array's data for NaNs, etc.
176 * For debug purposes; not normally used.
177 */
178static void
179check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
180                         const void *elements, GLint basevertex)
181{
182   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
183   const void *elemMap;
184   GLint i, k;
185
186   if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
187      elemMap = ctx->Driver.MapBuffer(ctx,
188                                      GL_ELEMENT_ARRAY_BUFFER_ARB,
189                                      GL_READ_ONLY,
190                                      ctx->Array.ElementArrayBufferObj);
191      elements = ADD_POINTERS(elements, elemMap);
192   }
193
194   for (i = 0; i < count; i++) {
195      GLuint j;
196
197      /* j = element[i] */
198      switch (elemType) {
199      case GL_UNSIGNED_BYTE:
200         j = ((const GLubyte *) elements)[i];
201         break;
202      case GL_UNSIGNED_SHORT:
203         j = ((const GLushort *) elements)[i];
204         break;
205      case GL_UNSIGNED_INT:
206         j = ((const GLuint *) elements)[i];
207         break;
208      default:
209         assert(0);
210      }
211
212      /* check element j of each enabled array */
213      check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
214      check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
215      check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
216      check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
217      for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
218         check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
219      }
220      for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
221         check_array_data(ctx, &arrayObj->VertexAttrib[k],
222                          VERT_ATTRIB_GENERIC0 + k, j);
223      }
224   }
225
226   if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
227      ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
228			      ctx->Array.ElementArrayBufferObj);
229   }
230
231   unmap_array_buffer(ctx, &arrayObj->Vertex);
232   unmap_array_buffer(ctx, &arrayObj->Normal);
233   unmap_array_buffer(ctx, &arrayObj->Color);
234   for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
235      unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
236   }
237   for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
238      unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
239   }
240}
241
242
243/**
244 * Check array data, looking for NaNs, etc.
245 */
246static void
247check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
248{
249   /* TO DO */
250}
251
252
253/**
254 * Print info/data for glDrawArrays(), for debugging.
255 */
256static void
257print_draw_arrays(struct gl_context *ctx, struct vbo_exec_context *exec,
258                  GLenum mode, GLint start, GLsizei count)
259{
260   int i;
261
262   printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
263	  mode, start, count);
264
265   for (i = 0; i < 32; i++) {
266      GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
267      GLint stride = exec->array.inputs[i]->Stride;
268      printf("attr %2d: size %d stride %d  enabled %d  "
269	     "ptr %p  Bufobj %u\n",
270	     i,
271	     exec->array.inputs[i]->Size,
272	     stride,
273	     /*exec->array.inputs[i]->Enabled,*/
274	     exec->array.legacy_array[i]->Enabled,
275	     exec->array.inputs[i]->Ptr,
276	     bufName);
277
278      if (bufName) {
279         struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
280         GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
281                                            GL_READ_ONLY_ARB, buf);
282         int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
283         float *f = (float *) (p + offset);
284         int *k = (int *) f;
285         int i;
286         int n = (count * stride) / 4;
287         if (n > 32)
288            n = 32;
289         printf("  Data at offset %d:\n", offset);
290         for (i = 0; i < n; i++) {
291            printf("    float[%d] = 0x%08x %f\n", i, k[i], f[i]);
292         }
293         ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
294      }
295   }
296}
297
298
299/**
300 * Bind the VBO executor to the current vertex array object prior
301 * to drawing.
302 *
303 * Just translate the arrayobj into a sane layout.
304 */
305static void
306bind_array_obj(struct gl_context *ctx)
307{
308   struct vbo_context *vbo = vbo_context(ctx);
309   struct vbo_exec_context *exec = &vbo->exec;
310   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
311   GLuint i;
312
313   /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array
314    * rather than as individual named arrays.  Then this function can
315    * go away.
316    */
317   exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
318   exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
319   exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
320   exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
321   exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
322   exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord;
323   exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index;
324   if (arrayObj->PointSize.Enabled) {
325      /* this aliases COLOR_INDEX */
326      exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize;
327   }
328   exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
329
330   for (i = 0; i < Elements(arrayObj->TexCoord); i++)
331      exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
332
333   for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
334      assert(i < Elements(exec->array.generic_array));
335      exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
336   }
337
338   exec->array.array_obj = arrayObj->Name;
339}
340
341
342/**
343 * Set the vbo->exec->inputs[] pointers to point to the enabled
344 * vertex arrays.  This depends on the current vertex program/shader
345 * being executed because of whether or not generic vertex arrays
346 * alias the conventional vertex arrays.
347 * For arrays that aren't enabled, we set the input[attrib] pointer
348 * to point at a zero-stride current value "array".
349 */
350static void
351recalculate_input_bindings(struct gl_context *ctx)
352{
353   struct vbo_context *vbo = vbo_context(ctx);
354   struct vbo_exec_context *exec = &vbo->exec;
355   const struct gl_client_array **inputs = &exec->array.inputs[0];
356   GLbitfield const_inputs = 0x0;
357   GLuint i;
358
359   exec->array.program_mode = get_program_mode(ctx);
360   exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled;
361
362   switch (exec->array.program_mode) {
363   case VP_NONE:
364      /* When no vertex program is active (or the vertex program is generated
365       * from fixed-function state).  We put the material values into the
366       * generic slots.  This is the only situation where material values
367       * are available as per-vertex attributes.
368       */
369      for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
370	 if (exec->array.legacy_array[i]->Enabled)
371	    inputs[i] = exec->array.legacy_array[i];
372	 else {
373	    inputs[i] = &vbo->legacy_currval[i];
374            const_inputs |= 1 << i;
375         }
376      }
377
378      for (i = 0; i < MAT_ATTRIB_MAX; i++) {
379	 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
380         const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
381      }
382
383      /* Could use just about anything, just to fill in the empty
384       * slots:
385       */
386      for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
387	 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
388         const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
389      }
390      break;
391
392   case VP_NV:
393      /* NV_vertex_program - attribute arrays alias and override
394       * conventional, legacy arrays.  No materials, and the generic
395       * slots are vacant.
396       */
397      for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
398	 if (exec->array.generic_array[i]->Enabled)
399	    inputs[i] = exec->array.generic_array[i];
400	 else if (exec->array.legacy_array[i]->Enabled)
401	    inputs[i] = exec->array.legacy_array[i];
402	 else {
403	    inputs[i] = &vbo->legacy_currval[i];
404            const_inputs |= 1 << i;
405         }
406      }
407
408      /* Could use just about anything, just to fill in the empty
409       * slots:
410       */
411      for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
412	 inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
413         const_inputs |= 1 << i;
414      }
415      break;
416
417   case VP_ARB:
418      /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
419       * attribute array aliases and overrides the legacy position array.
420       *
421       * Otherwise, legacy attributes available in the legacy slots,
422       * generic attributes in the generic slots and materials are not
423       * available as per-vertex attributes.
424       */
425      if (exec->array.generic_array[0]->Enabled)
426	 inputs[0] = exec->array.generic_array[0];
427      else if (exec->array.legacy_array[0]->Enabled)
428	 inputs[0] = exec->array.legacy_array[0];
429      else {
430	 inputs[0] = &vbo->legacy_currval[0];
431         const_inputs |= 1 << 0;
432      }
433
434      for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
435	 if (exec->array.legacy_array[i]->Enabled)
436	    inputs[i] = exec->array.legacy_array[i];
437	 else {
438	    inputs[i] = &vbo->legacy_currval[i];
439            const_inputs |= 1 << i;
440         }
441      }
442
443      for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
444	 if (exec->array.generic_array[i]->Enabled)
445	    inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
446	 else {
447	    inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
448            const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
449         }
450
451      }
452      break;
453   }
454
455   _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
456}
457
458
459/**
460 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
461 * These will point to the arrays to actually use for drawing.  Some will
462 * be user-provided arrays, other will be zero-stride const-valued arrays.
463 * Note that this might set the _NEW_ARRAY dirty flag so state validation
464 * must be done after this call.
465 */
466static void
467bind_arrays(struct gl_context *ctx)
468{
469   bind_array_obj(ctx);
470   recalculate_input_bindings(ctx);
471}
472
473
474
475/**
476 * Called from glDrawArrays when in immediate mode (not display list mode).
477 */
478static void GLAPIENTRY
479vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
480{
481   GET_CURRENT_CONTEXT(ctx);
482   struct vbo_context *vbo = vbo_context(ctx);
483   struct vbo_exec_context *exec = &vbo->exec;
484   struct _mesa_prim prim[1];
485
486   if (MESA_VERBOSE & VERBOSE_DRAW)
487      _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
488                  _mesa_lookup_enum_by_nr(mode), start, count);
489
490   if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
491      return;
492
493   FLUSH_CURRENT( ctx, 0 );
494
495   if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
496      return;
497   }
498
499#if 0
500   check_draw_arrays_data(ctx, start, count);
501#else
502   (void) check_draw_arrays_data;
503#endif
504
505   bind_arrays( ctx );
506
507   /* Again... because we may have changed the bitmask of per-vertex varying
508    * attributes.  If we regenerate the fixed-function vertex program now
509    * we may be able to prune down the number of vertex attributes which we
510    * need in the shader.
511    */
512   if (ctx->NewState)
513      _mesa_update_state( ctx );
514
515   prim[0].begin = 1;
516   prim[0].end = 1;
517   prim[0].weak = 0;
518   prim[0].pad = 0;
519   prim[0].mode = mode;
520   prim[0].start = start;
521   prim[0].count = count;
522   prim[0].indexed = 0;
523   prim[0].basevertex = 0;
524   prim[0].num_instances = 1;
525
526   vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
527                    GL_TRUE, start, start + count - 1 );
528
529#if 0
530   print_draw_arrays(ctx, exec, mode, start, count);
531#else
532   (void) print_draw_arrays;
533#endif
534}
535
536
537/**
538 * Called from glDrawArraysInstanced when in immediate mode (not
539 * display list mode).
540 */
541static void GLAPIENTRY
542vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
543                             GLsizei primcount)
544{
545   GET_CURRENT_CONTEXT(ctx);
546   struct vbo_context *vbo = vbo_context(ctx);
547   struct vbo_exec_context *exec = &vbo->exec;
548   struct _mesa_prim prim[1];
549
550   if (MESA_VERBOSE & VERBOSE_DRAW)
551      _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
552                  _mesa_lookup_enum_by_nr(mode), start, count, primcount);
553
554   if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, primcount))
555      return;
556
557   FLUSH_CURRENT( ctx, 0 );
558
559   if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
560      return;
561   }
562
563#if 0 /* debug */
564   check_draw_arrays_data(ctx, start, count);
565#endif
566
567   bind_arrays( ctx );
568
569   /* Again... because we may have changed the bitmask of per-vertex varying
570    * attributes.  If we regenerate the fixed-function vertex program now
571    * we may be able to prune down the number of vertex attributes which we
572    * need in the shader.
573    */
574   if (ctx->NewState)
575      _mesa_update_state( ctx );
576
577   prim[0].begin = 1;
578   prim[0].end = 1;
579   prim[0].weak = 0;
580   prim[0].pad = 0;
581   prim[0].mode = mode;
582   prim[0].start = start;
583   prim[0].count = count;
584   prim[0].indexed = 0;
585   prim[0].basevertex = 0;
586   prim[0].num_instances = primcount;
587
588   vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
589                    GL_TRUE, start, start + count - 1 );
590
591#if 0 /* debug */
592   print_draw_arrays(ctx, exec, mode, start, count);
593#endif
594}
595
596
597/**
598 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
599 * For debugging.
600 */
601static void
602dump_element_buffer(struct gl_context *ctx, GLenum type)
603{
604   const GLvoid *map = ctx->Driver.MapBuffer(ctx,
605                                             GL_ELEMENT_ARRAY_BUFFER_ARB,
606                                             GL_READ_ONLY,
607                                             ctx->Array.ElementArrayBufferObj);
608   switch (type) {
609   case GL_UNSIGNED_BYTE:
610      {
611         const GLubyte *us = (const GLubyte *) map;
612         GLint i;
613         for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
614            printf("%02x ", us[i]);
615            if (i % 32 == 31)
616               printf("\n");
617         }
618         printf("\n");
619      }
620      break;
621   case GL_UNSIGNED_SHORT:
622      {
623         const GLushort *us = (const GLushort *) map;
624         GLint i;
625         for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
626            printf("%04x ", us[i]);
627            if (i % 16 == 15)
628               printf("\n");
629         }
630         printf("\n");
631      }
632      break;
633   case GL_UNSIGNED_INT:
634      {
635         const GLuint *us = (const GLuint *) map;
636         GLint i;
637         for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
638            printf("%08x ", us[i]);
639            if (i % 8 == 7)
640               printf("\n");
641         }
642         printf("\n");
643      }
644      break;
645   default:
646      ;
647   }
648
649   ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
650                           ctx->Array.ElementArrayBufferObj);
651}
652
653
654/**
655 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
656 * Do the rendering for a glDrawElements or glDrawRangeElements call after
657 * we've validated buffer bounds, etc.
658 */
659static void
660vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
661				GLboolean index_bounds_valid,
662				GLuint start, GLuint end,
663				GLsizei count, GLenum type,
664				const GLvoid *indices,
665				GLint basevertex, GLint primcount)
666{
667   struct vbo_context *vbo = vbo_context(ctx);
668   struct vbo_exec_context *exec = &vbo->exec;
669   struct _mesa_index_buffer ib;
670   struct _mesa_prim prim[1];
671
672   FLUSH_CURRENT( ctx, 0 );
673
674   if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
675      return;
676   }
677
678   bind_arrays( ctx );
679
680   /* check for dirty state again */
681   if (ctx->NewState)
682      _mesa_update_state( ctx );
683
684   ib.count = count;
685   ib.type = type;
686   ib.obj = ctx->Array.ElementArrayBufferObj;
687   ib.ptr = indices;
688
689   prim[0].begin = 1;
690   prim[0].end = 1;
691   prim[0].weak = 0;
692   prim[0].pad = 0;
693   prim[0].mode = mode;
694   prim[0].start = 0;
695   prim[0].count = count;
696   prim[0].indexed = 1;
697   prim[0].basevertex = basevertex;
698   prim[0].num_instances = primcount;
699
700   /* Need to give special consideration to rendering a range of
701    * indices starting somewhere above zero.  Typically the
702    * application is issuing multiple DrawRangeElements() to draw
703    * successive primitives layed out linearly in the vertex arrays.
704    * Unless the vertex arrays are all in a VBO (or locked as with
705    * CVA), the OpenGL semantics imply that we need to re-read or
706    * re-upload the vertex data on each draw call.
707    *
708    * In the case of hardware tnl, we want to avoid starting the
709    * upload at zero, as it will mean every draw call uploads an
710    * increasing amount of not-used vertex data.  Worse - in the
711    * software tnl module, all those vertices might be transformed and
712    * lit but never rendered.
713    *
714    * If we just upload or transform the vertices in start..end,
715    * however, the indices will be incorrect.
716    *
717    * At this level, we don't know exactly what the requirements of
718    * the backend are going to be, though it will likely boil down to
719    * either:
720    *
721    * 1) Do nothing, everything is in a VBO and is processed once
722    *       only.
723    *
724    * 2) Adjust the indices and vertex arrays so that start becomes
725    *    zero.
726    *
727    * Rather than doing anything here, I'll provide a helper function
728    * for the latter case elsewhere.
729    */
730
731   vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
732		    index_bounds_valid, start, end );
733}
734
735
736/**
737 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
738 */
739static void GLAPIENTRY
740vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
741				     GLuint start, GLuint end,
742				     GLsizei count, GLenum type,
743				     const GLvoid *indices,
744				     GLint basevertex)
745{
746   static GLuint warnCount = 0;
747   GET_CURRENT_CONTEXT(ctx);
748
749   if (MESA_VERBOSE & VERBOSE_DRAW)
750      _mesa_debug(ctx,
751                "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
752                _mesa_lookup_enum_by_nr(mode), start, end, count,
753                _mesa_lookup_enum_by_nr(type), indices, basevertex);
754
755   if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
756                                          type, indices, basevertex ))
757      return;
758
759   /* NOTE: It's important that 'end' is a reasonable value.
760    * in _tnl_draw_prims(), we use end to determine how many vertices
761    * to transform.  If it's too large, we can unnecessarily split prims
762    * or we can read/write out of memory in several different places!
763    */
764
765   /* Catch/fix some potential user errors */
766   if (type == GL_UNSIGNED_BYTE) {
767      start = MIN2(start, 0xff);
768      end = MIN2(end, 0xff);
769   }
770   else if (type == GL_UNSIGNED_SHORT) {
771      start = MIN2(start, 0xffff);
772      end = MIN2(end, 0xffff);
773   }
774
775   if (end >= ctx->Array.ArrayObj->_MaxElement) {
776      /* the max element is out of bounds of one or more enabled arrays */
777      warnCount++;
778
779      if (warnCount < 10) {
780         _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
781                       "type 0x%x, indices=%p)\n"
782                       "\tend is out of bounds (max=%u)  "
783                       "Element Buffer %u (size %d)\n"
784                       "\tThis should probably be fixed in the application.",
785                       start, end, count, type, indices,
786                       ctx->Array.ArrayObj->_MaxElement - 1,
787                       ctx->Array.ElementArrayBufferObj->Name,
788                       (int) ctx->Array.ElementArrayBufferObj->Size);
789      }
790
791      if (0)
792         dump_element_buffer(ctx, type);
793
794      if (0)
795         _mesa_print_arrays(ctx);
796
797#ifdef DEBUG
798      /* 'end' was out of bounds, but now let's check the actual array
799       * indexes to see if any of them are out of bounds.
800       */
801      {
802         GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
803                                             ctx->Array.ElementArrayBufferObj);
804         if (max >= ctx->Array.ArrayObj->_MaxElement) {
805            if (warnCount < 10) {
806               _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
807                             "count %d, type 0x%x, indices=%p)\n"
808                             "\tindex=%u is out of bounds (max=%u)  "
809                             "Element Buffer %u (size %d)\n"
810                             "\tSkipping the glDrawRangeElements() call",
811                             start, end, count, type, indices, max,
812                             ctx->Array.ArrayObj->_MaxElement - 1,
813                             ctx->Array.ElementArrayBufferObj->Name,
814                             (int) ctx->Array.ElementArrayBufferObj->Size);
815            }
816         }
817         /* XXX we could also find the min index and compare to 'start'
818          * to see if start is correct.  But it's more likely to get the
819          * upper bound wrong.
820          */
821      }
822#endif
823
824      /* Set 'end' to the max possible legal value */
825      assert(ctx->Array.ArrayObj->_MaxElement >= 1);
826      end = ctx->Array.ArrayObj->_MaxElement - 1;
827   }
828   else if (0) {
829      printf("glDraw[Range]Elements{,BaseVertex}"
830	     "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
831	     "base %d\n",
832	     start, end, type, count,
833	     ctx->Array.ElementArrayBufferObj->Name,
834	     basevertex);
835   }
836
837#if 0
838   check_draw_elements_data(ctx, count, type, indices);
839#else
840   (void) check_draw_elements_data;
841#endif
842
843   vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
844				   count, type, indices, basevertex, 1);
845}
846
847
848/**
849 * Called by glDrawRangeElements() in immediate mode.
850 */
851static void GLAPIENTRY
852vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
853                           GLsizei count, GLenum type, const GLvoid *indices)
854{
855   GET_CURRENT_CONTEXT(ctx);
856
857   if (MESA_VERBOSE & VERBOSE_DRAW)
858      _mesa_debug(ctx,
859                  "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
860                  _mesa_lookup_enum_by_nr(mode), start, end, count,
861                  _mesa_lookup_enum_by_nr(type), indices);
862
863   vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
864					indices, 0);
865}
866
867
868/**
869 * Called by glDrawElements() in immediate mode.
870 */
871static void GLAPIENTRY
872vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
873                      const GLvoid *indices)
874{
875   GET_CURRENT_CONTEXT(ctx);
876
877   if (MESA_VERBOSE & VERBOSE_DRAW)
878      _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
879                  _mesa_lookup_enum_by_nr(mode), count,
880                  _mesa_lookup_enum_by_nr(type), indices);
881
882   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
883      return;
884
885   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
886				   count, type, indices, 0, 1);
887}
888
889
890/**
891 * Called by glDrawElementsBaseVertex() in immediate mode.
892 */
893static void GLAPIENTRY
894vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
895				const GLvoid *indices, GLint basevertex)
896{
897   GET_CURRENT_CONTEXT(ctx);
898
899   if (MESA_VERBOSE & VERBOSE_DRAW)
900      _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
901                  _mesa_lookup_enum_by_nr(mode), count,
902                  _mesa_lookup_enum_by_nr(type), indices, basevertex);
903
904   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
905				     basevertex ))
906      return;
907
908   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
909				   count, type, indices, basevertex, 1);
910}
911
912
913/**
914 * Called by glDrawElementsInstanced() in immediate mode.
915 */
916static void GLAPIENTRY
917vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
918                               const GLvoid *indices, GLsizei primcount)
919{
920   GET_CURRENT_CONTEXT(ctx);
921
922   if (MESA_VERBOSE & VERBOSE_DRAW)
923      _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
924                  _mesa_lookup_enum_by_nr(mode), count,
925                  _mesa_lookup_enum_by_nr(type), indices, primcount);
926
927   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
928                                             primcount))
929      return;
930
931   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
932				   count, type, indices, 0, primcount);
933}
934
935
936/**
937 * Inner support for both _mesa_MultiDrawElements() and
938 * _mesa_MultiDrawRangeElements().
939 * This does the actual rendering after we've checked array indexes, etc.
940 */
941static void
942vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
943				const GLsizei *count, GLenum type,
944				const GLvoid **indices, GLsizei primcount,
945				const GLint *basevertex)
946{
947   struct vbo_context *vbo = vbo_context(ctx);
948   struct vbo_exec_context *exec = &vbo->exec;
949   struct _mesa_index_buffer ib;
950   struct _mesa_prim *prim;
951   unsigned int index_type_size = 0;
952   uintptr_t min_index_ptr, max_index_ptr;
953   GLboolean fallback = GL_FALSE;
954   int i;
955
956   if (primcount == 0)
957      return;
958
959   FLUSH_CURRENT( ctx, 0 );
960
961   if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
962      return;
963   }
964
965   prim = calloc(1, primcount * sizeof(*prim));
966   if (prim == NULL) {
967      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
968      return;
969   }
970
971   /* Decide if we can do this all as one set of primitives sharing the
972    * same index buffer, or if we have to reset the index pointer per
973    * primitive.
974    */
975   bind_arrays( ctx );
976
977   /* check for dirty state again */
978   if (ctx->NewState)
979      _mesa_update_state( ctx );
980
981   switch (type) {
982   case GL_UNSIGNED_INT:
983      index_type_size = 4;
984      break;
985   case GL_UNSIGNED_SHORT:
986      index_type_size = 2;
987      break;
988   case GL_UNSIGNED_BYTE:
989      index_type_size = 1;
990      break;
991   default:
992      assert(0);
993   }
994
995   min_index_ptr = (uintptr_t)indices[0];
996   max_index_ptr = 0;
997   for (i = 0; i < primcount; i++) {
998      min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
999      max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1000			   index_type_size * count[i]);
1001   }
1002
1003   /* Check if we can handle this thing as a bunch of index offsets from the
1004    * same index pointer.  If we can't, then we have to fall back to doing
1005    * a draw_prims per primitive.
1006    */
1007   if (index_type_size != 1) {
1008      for (i = 0; i < primcount; i++) {
1009	 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1010	    fallback = GL_TRUE;
1011	    break;
1012	 }
1013      }
1014   }
1015
1016   /* If the index buffer isn't in a VBO, then treating the application's
1017    * subranges of the index buffer as one large index buffer may lead to
1018    * us reading unmapped memory.
1019    */
1020   if (!_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
1021      fallback = GL_TRUE;
1022
1023   if (!fallback) {
1024      ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1025      ib.type = type;
1026      ib.obj = ctx->Array.ElementArrayBufferObj;
1027      ib.ptr = (void *)min_index_ptr;
1028
1029      for (i = 0; i < primcount; i++) {
1030	 prim[i].begin = (i == 0);
1031	 prim[i].end = (i == primcount - 1);
1032	 prim[i].weak = 0;
1033	 prim[i].pad = 0;
1034	 prim[i].mode = mode;
1035	 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1036	 prim[i].count = count[i];
1037	 prim[i].indexed = 1;
1038         prim[i].num_instances = 1;
1039	 if (basevertex != NULL)
1040	    prim[i].basevertex = basevertex[i];
1041	 else
1042	    prim[i].basevertex = 0;
1043      }
1044
1045      vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
1046		      GL_FALSE, ~0, ~0);
1047   } else {
1048      /* render one prim at a time */
1049      for (i = 0; i < primcount; i++) {
1050	 ib.count = count[i];
1051	 ib.type = type;
1052	 ib.obj = ctx->Array.ElementArrayBufferObj;
1053	 ib.ptr = indices[i];
1054
1055	 prim[0].begin = 1;
1056	 prim[0].end = 1;
1057	 prim[0].weak = 0;
1058	 prim[0].pad = 0;
1059	 prim[0].mode = mode;
1060	 prim[0].start = 0;
1061	 prim[0].count = count[i];
1062	 prim[0].indexed = 1;
1063         prim[0].num_instances = 1;
1064	 if (basevertex != NULL)
1065	    prim[0].basevertex = basevertex[i];
1066	 else
1067	    prim[0].basevertex = 0;
1068
1069         vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
1070                         GL_FALSE, ~0, ~0);
1071      }
1072   }
1073
1074   free(prim);
1075}
1076
1077
1078static void GLAPIENTRY
1079vbo_exec_MultiDrawElements(GLenum mode,
1080			   const GLsizei *count, GLenum type,
1081			   const GLvoid **indices,
1082			   GLsizei primcount)
1083{
1084   GET_CURRENT_CONTEXT(ctx);
1085   GLint i;
1086
1087   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1088
1089   for (i = 0; i < primcount; i++) {
1090      if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1091				       0))
1092	 return;
1093   }
1094
1095   vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1096				   NULL);
1097}
1098
1099
1100static void GLAPIENTRY
1101vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1102				     const GLsizei *count, GLenum type,
1103				     const GLvoid **indices,
1104				     GLsizei primcount,
1105				     const GLsizei *basevertex)
1106{
1107   GET_CURRENT_CONTEXT(ctx);
1108   GLint i;
1109
1110   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1111
1112   for (i = 0; i < primcount; i++) {
1113      if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1114				       basevertex[i]))
1115	 return;
1116   }
1117
1118   vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1119				   basevertex);
1120}
1121
1122
1123/**
1124 * Plug in the immediate-mode vertex array drawing commands into the
1125 * givven vbo_exec_context object.
1126 */
1127void
1128vbo_exec_array_init( struct vbo_exec_context *exec )
1129{
1130   exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
1131   exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
1132   exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
1133   exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
1134   exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
1135   exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
1136   exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
1137   exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
1138   exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
1139}
1140
1141
1142void
1143vbo_exec_array_destroy( struct vbo_exec_context *exec )
1144{
1145   /* nothing to do */
1146}
1147
1148
1149
1150/**
1151 * The following functions are only used for OpenGL ES 1/2 support.
1152 * And some aren't even supported (yet) in ES 1/2.
1153 */
1154
1155
1156void GLAPIENTRY
1157_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1158{
1159   vbo_exec_DrawArrays(mode, first, count);
1160}
1161
1162
1163void GLAPIENTRY
1164_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1165                   const GLvoid *indices)
1166{
1167   vbo_exec_DrawElements(mode, count, type, indices);
1168}
1169
1170
1171void GLAPIENTRY
1172_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1173			     const GLvoid *indices, GLint basevertex)
1174{
1175   vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1176}
1177
1178
1179void GLAPIENTRY
1180_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1181                        GLenum type, const GLvoid *indices)
1182{
1183   vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1184}
1185
1186
1187void GLAPIENTRY
1188_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1189				  GLsizei count, GLenum type,
1190				  const GLvoid *indices, GLint basevertex)
1191{
1192   vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1193					indices, basevertex);
1194}
1195
1196
1197void GLAPIENTRY
1198_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1199			   const GLvoid **indices, GLsizei primcount)
1200{
1201   vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1202}
1203
1204
1205void GLAPIENTRY
1206_mesa_MultiDrawElementsBaseVertex(GLenum mode,
1207				  const GLsizei *count, GLenum type,
1208				  const GLvoid **indices, GLsizei primcount,
1209				  const GLint *basevertex)
1210{
1211   vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1212					primcount, basevertex);
1213}
1214