Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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