Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4358 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/dispatch.h"
34
#include "main/varray.h"
35
#include "main/bufferobj.h"
36
#include "main/enums.h"
37
#include "main/macros.h"
38
#include "main/transformfeedback.h"
39
 
40
#include "vbo_context.h"
41
 
42
 
43
/**
44
 * All vertex buffers should be in an unmapped state when we're about
45
 * to draw.  This debug function checks that.
46
 */
47
static void
48
check_buffers_are_unmapped(const struct gl_client_array **inputs)
49
{
50
#ifdef DEBUG
51
   GLuint i;
52
 
53
   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
54
      if (inputs[i]) {
55
         struct gl_buffer_object *obj = inputs[i]->BufferObj;
56
         assert(!_mesa_bufferobj_mapped(obj));
57
         (void) obj;
58
      }
59
   }
60
#endif
61
}
62
 
63
 
64
/**
65
 * A debug function that may be called from other parts of Mesa as
66
 * needed during debugging.
67
 */
68
void
69
vbo_check_buffers_are_unmapped(struct gl_context *ctx)
70
{
71
   struct vbo_context *vbo = vbo_context(ctx);
72
   struct vbo_exec_context *exec = &vbo->exec;
73
   /* check the current vertex arrays */
74
   check_buffers_are_unmapped(exec->array.inputs);
75
   /* check the current glBegin/glVertex/glEnd-style VBO */
76
   assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj));
77
}
78
 
79
 
80
 
81
/**
82
 * Compute min and max elements by scanning the index buffer for
83
 * glDraw[Range]Elements() calls.
84
 * If primitive restart is enabled, we need to ignore restart
85
 * indexes when computing min/max.
86
 */
87
static void
88
vbo_get_minmax_index(struct gl_context *ctx,
89
		     const struct _mesa_prim *prim,
90
		     const struct _mesa_index_buffer *ib,
91
		     GLuint *min_index, GLuint *max_index,
92
		     const GLuint count)
93
{
94
   const GLboolean restart = ctx->Array._PrimitiveRestart;
95
   const GLuint restartIndex = _mesa_primitive_restart_index(ctx, ib->type);
96
   const int index_size = vbo_sizeof_ib_type(ib->type);
97
   const char *indices;
98
   GLuint i;
99
 
100
   indices = (char *) ib->ptr + prim->start * index_size;
101
   if (_mesa_is_bufferobj(ib->obj)) {
102
      GLsizeiptr size = MIN2(count * index_size, ib->obj->Size);
103
      indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size,
104
                                           GL_MAP_READ_BIT, ib->obj);
105
   }
106
 
107
   switch (ib->type) {
108
   case GL_UNSIGNED_INT: {
109
      const GLuint *ui_indices = (const GLuint *)indices;
110
      GLuint max_ui = 0;
111
      GLuint min_ui = ~0U;
112
      if (restart) {
113
         for (i = 0; i < count; i++) {
114
            if (ui_indices[i] != restartIndex) {
115
               if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
116
               if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
117
            }
118
         }
119
      }
120
      else {
121
         for (i = 0; i < count; i++) {
122
            if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
123
            if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
124
         }
125
      }
126
      *min_index = min_ui;
127
      *max_index = max_ui;
128
      break;
129
   }
130
   case GL_UNSIGNED_SHORT: {
131
      const GLushort *us_indices = (const GLushort *)indices;
132
      GLuint max_us = 0;
133
      GLuint min_us = ~0U;
134
      if (restart) {
135
         for (i = 0; i < count; i++) {
136
            if (us_indices[i] != restartIndex) {
137
               if (us_indices[i] > max_us) max_us = us_indices[i];
138
               if (us_indices[i] < min_us) min_us = us_indices[i];
139
            }
140
         }
141
      }
142
      else {
143
         for (i = 0; i < count; i++) {
144
            if (us_indices[i] > max_us) max_us = us_indices[i];
145
            if (us_indices[i] < min_us) min_us = us_indices[i];
146
         }
147
      }
148
      *min_index = min_us;
149
      *max_index = max_us;
150
      break;
151
   }
152
   case GL_UNSIGNED_BYTE: {
153
      const GLubyte *ub_indices = (const GLubyte *)indices;
154
      GLuint max_ub = 0;
155
      GLuint min_ub = ~0U;
156
      if (restart) {
157
         for (i = 0; i < count; i++) {
158
            if (ub_indices[i] != restartIndex) {
159
               if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
160
               if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
161
            }
162
         }
163
      }
164
      else {
165
         for (i = 0; i < count; i++) {
166
            if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
167
            if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
168
         }
169
      }
170
      *min_index = min_ub;
171
      *max_index = max_ub;
172
      break;
173
   }
174
   default:
175
      assert(0);
176
      break;
177
   }
178
 
179
   if (_mesa_is_bufferobj(ib->obj)) {
180
      ctx->Driver.UnmapBuffer(ctx, ib->obj);
181
   }
182
}
183
 
184
/**
185
 * Compute min and max elements for nr_prims
186
 */
187
void
188
vbo_get_minmax_indices(struct gl_context *ctx,
189
                       const struct _mesa_prim *prims,
190
                       const struct _mesa_index_buffer *ib,
191
                       GLuint *min_index,
192
                       GLuint *max_index,
193
                       GLuint nr_prims)
194
{
195
   GLuint tmp_min, tmp_max;
196
   GLuint i;
197
   GLuint count;
198
 
199
   *min_index = ~0;
200
   *max_index = 0;
201
 
202
   for (i = 0; i < nr_prims; i++) {
203
      const struct _mesa_prim *start_prim;
204
 
205
      start_prim = &prims[i];
206
      count = start_prim->count;
207
      /* Do combination if possible to reduce map/unmap count */
208
      while ((i + 1 < nr_prims) &&
209
             (prims[i].start + prims[i].count == prims[i+1].start)) {
210
         count += prims[i+1].count;
211
         i++;
212
      }
213
      vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count);
214
      *min_index = MIN2(*min_index, tmp_min);
215
      *max_index = MAX2(*max_index, tmp_max);
216
   }
217
}
218
 
219
 
220
/**
221
 * Check that element 'j' of the array has reasonable data.
222
 * Map VBO if needed.
223
 * For debugging purposes; not normally used.
224
 */
225
static void
226
check_array_data(struct gl_context *ctx, struct gl_client_array *array,
227
                 GLuint attrib, GLuint j)
228
{
229
   if (array->Enabled) {
230
      const void *data = array->Ptr;
231
      if (_mesa_is_bufferobj(array->BufferObj)) {
232
         if (!array->BufferObj->Pointer) {
233
            /* need to map now */
234
            array->BufferObj->Pointer =
235
               ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size,
236
					  GL_MAP_READ_BIT, array->BufferObj);
237
         }
238
         data = ADD_POINTERS(data, array->BufferObj->Pointer);
239
      }
240
      switch (array->Type) {
241
      case GL_FLOAT:
242
         {
243
            GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
244
            GLint k;
245
            for (k = 0; k < array->Size; k++) {
246
               if (IS_INF_OR_NAN(f[k]) ||
247
                   f[k] >= 1.0e20 || f[k] <= -1.0e10) {
248
                  printf("Bad array data:\n");
249
                  printf("  Element[%u].%u = %f\n", j, k, f[k]);
250
                  printf("  Array %u at %p\n", attrib, (void* ) array);
251
                  printf("  Type 0x%x, Size %d, Stride %d\n",
252
			 array->Type, array->Size, array->Stride);
253
                  printf("  Address/offset %p in Buffer Object %u\n",
254
			 array->Ptr, array->BufferObj->Name);
255
                  f[k] = 1.0; /* XXX replace the bad value! */
256
               }
257
               /*assert(!IS_INF_OR_NAN(f[k]));*/
258
            }
259
         }
260
         break;
261
      default:
262
         ;
263
      }
264
   }
265
}
266
 
267
 
268
/**
269
 * Unmap the buffer object referenced by given array, if mapped.
270
 */
271
static void
272
unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
273
{
274
   if (array->Enabled &&
275
       _mesa_is_bufferobj(array->BufferObj) &&
276
       _mesa_bufferobj_mapped(array->BufferObj)) {
277
      ctx->Driver.UnmapBuffer(ctx, array->BufferObj);
278
   }
279
}
280
 
281
 
282
/**
283
 * Examine the array's data for NaNs, etc.
284
 * For debug purposes; not normally used.
285
 */
286
static void
287
check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
288
                         const void *elements, GLint basevertex)
289
{
290
   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
291
   const void *elemMap;
292
   GLint i, k;
293
 
294
   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
295
      elemMap = ctx->Driver.MapBufferRange(ctx, 0,
296
					   ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
297
					   GL_MAP_READ_BIT,
298
					   ctx->Array.ArrayObj->ElementArrayBufferObj);
299
      elements = ADD_POINTERS(elements, elemMap);
300
   }
301
 
302
   for (i = 0; i < count; i++) {
303
      GLuint j;
304
 
305
      /* j = element[i] */
306
      switch (elemType) {
307
      case GL_UNSIGNED_BYTE:
308
         j = ((const GLubyte *) elements)[i];
309
         break;
310
      case GL_UNSIGNED_SHORT:
311
         j = ((const GLushort *) elements)[i];
312
         break;
313
      case GL_UNSIGNED_INT:
314
         j = ((const GLuint *) elements)[i];
315
         break;
316
      default:
317
         assert(0);
318
      }
319
 
320
      /* check element j of each enabled array */
321
      for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
322
         check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j);
323
      }
324
   }
325
 
326
   if (_mesa_is_bufferobj(arrayObj->ElementArrayBufferObj)) {
327
      ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
328
   }
329
 
330
   for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
331
      unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
332
   }
333
}
334
 
335
 
336
/**
337
 * Check array data, looking for NaNs, etc.
338
 */
339
static void
340
check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
341
{
342
   /* TO DO */
343
}
344
 
345
 
346
/**
347
 * Print info/data for glDrawArrays(), for debugging.
348
 */
349
static void
350
print_draw_arrays(struct gl_context *ctx,
351
                  GLenum mode, GLint start, GLsizei count)
352
{
353
   struct vbo_context *vbo = vbo_context(ctx);
354
   struct vbo_exec_context *exec = &vbo->exec;
355
   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
356
   int i;
357
 
358
   printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
359
	  mode, start, count);
360
 
361
   for (i = 0; i < 32; i++) {
362
      struct gl_buffer_object *bufObj = exec->array.inputs[i]->BufferObj;
363
      GLuint bufName = bufObj->Name;
364
      GLint stride = exec->array.inputs[i]->Stride;
365
      printf("attr %2d: size %d stride %d  enabled %d  "
366
	     "ptr %p  Bufobj %u\n",
367
	     i,
368
	     exec->array.inputs[i]->Size,
369
	     stride,
370
	     /*exec->array.inputs[i]->Enabled,*/
371
	     arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)].Enabled,
372
	     exec->array.inputs[i]->Ptr,
373
	     bufName);
374
 
375
      if (bufName) {
376
         GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size,
377
						 GL_MAP_READ_BIT, bufObj);
378
         int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
379
         float *f = (float *) (p + offset);
380
         int *k = (int *) f;
381
         int i;
382
         int n = (count * stride) / 4;
383
         if (n > 32)
384
            n = 32;
385
         printf("  Data at offset %d:\n", offset);
386
         for (i = 0; i < n; i++) {
387
            printf("    float[%d] = 0x%08x %f\n", i, k[i], f[i]);
388
         }
389
         ctx->Driver.UnmapBuffer(ctx, bufObj);
390
      }
391
   }
392
}
393
 
394
 
395
/**
396
 * Set the vbo->exec->inputs[] pointers to point to the enabled
397
 * vertex arrays.  This depends on the current vertex program/shader
398
 * being executed because of whether or not generic vertex arrays
399
 * alias the conventional vertex arrays.
400
 * For arrays that aren't enabled, we set the input[attrib] pointer
401
 * to point at a zero-stride current value "array".
402
 */
403
static void
404
recalculate_input_bindings(struct gl_context *ctx)
405
{
406
   struct vbo_context *vbo = vbo_context(ctx);
407
   struct vbo_exec_context *exec = &vbo->exec;
408
   struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib;
409
   const struct gl_client_array **inputs = &exec->array.inputs[0];
410
   GLbitfield64 const_inputs = 0x0;
411
   GLuint i;
412
 
413
   switch (get_program_mode(ctx)) {
414
   case VP_NONE:
415
      /* When no vertex program is active (or the vertex program is generated
416
       * from fixed-function state).  We put the material values into the
417
       * generic slots.  This is the only situation where material values
418
       * are available as per-vertex attributes.
419
       */
420
      for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
421
	 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
422
	    inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
423
	 else {
424
	    inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
425
            const_inputs |= VERT_BIT(i);
426
         }
427
      }
428
 
429
      for (i = 0; i < MAT_ATTRIB_MAX; i++) {
430
	 inputs[VERT_ATTRIB_GENERIC(i)] =
431
	    &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i];
432
         const_inputs |= VERT_BIT_GENERIC(i);
433
      }
434
 
435
      /* Could use just about anything, just to fill in the empty
436
       * slots:
437
       */
438
      for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
439
	 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
440
         const_inputs |= VERT_BIT_GENERIC(i);
441
      }
442
      break;
443
 
444
   case VP_ARB:
445
      /* There are no shaders in OpenGL ES 1.x, so this code path should be
446
       * impossible to reach.  The meta code is careful to not use shaders in
447
       * ES1.
448
       */
449
      assert(ctx->API != API_OPENGLES);
450
 
451
      /* In the compatibility profile of desktop OpenGL, the generic[0]
452
       * attribute array aliases and overrides the legacy position array.
453
       * Otherwise, legacy attributes available in the legacy slots,
454
       * generic attributes in the generic slots and materials are not
455
       * available as per-vertex attributes.
456
       *
457
       * In all other APIs, only the generic attributes exist, and none of the
458
       * slots are considered "magic."
459
       */
460
      if (ctx->API == API_OPENGL_COMPAT) {
461
         if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
462
            inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
463
         else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
464
            inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
465
         else {
466
            inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
467
            const_inputs |= VERT_BIT_POS;
468
         }
469
 
470
         for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
471
            if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
472
               inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
473
            else {
474
               inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
475
               const_inputs |= VERT_BIT_FF(i);
476
            }
477
         }
478
 
479
         for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
480
            if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
481
               inputs[VERT_ATTRIB_GENERIC(i)] =
482
                  &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
483
            else {
484
               inputs[VERT_ATTRIB_GENERIC(i)] =
485
                  &vbo->currval[VBO_ATTRIB_GENERIC0+i];
486
               const_inputs |= VERT_BIT_GENERIC(i);
487
            }
488
         }
489
 
490
         inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
491
      } else {
492
         /* Other parts of the code assume that inputs[0] through
493
          * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL.  However, in OpenGL
494
          * ES 2.0+ or OpenGL core profile, none of these arrays should ever
495
          * be enabled.
496
          */
497
         for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
498
            assert(!vertexAttrib[VERT_ATTRIB_FF(i)].Enabled);
499
 
500
            inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
501
            const_inputs |= VERT_BIT_FF(i);
502
         }
503
 
504
         for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
505
            if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
506
               inputs[VERT_ATTRIB_GENERIC(i)] =
507
                  &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
508
            else {
509
               inputs[VERT_ATTRIB_GENERIC(i)] =
510
                  &vbo->currval[VBO_ATTRIB_GENERIC0+i];
511
               const_inputs |= VERT_BIT_GENERIC(i);
512
            }
513
         }
514
      }
515
 
516
      break;
517
   }
518
 
519
   _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
520
   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
521
}
522
 
523
 
524
/**
525
 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
526
 * These will point to the arrays to actually use for drawing.  Some will
527
 * be user-provided arrays, other will be zero-stride const-valued arrays.
528
 * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
529
 * validation must be done after this call.
530
 */
531
void
532
vbo_bind_arrays(struct gl_context *ctx)
533
{
534
   struct vbo_context *vbo = vbo_context(ctx);
535
   struct vbo_exec_context *exec = &vbo->exec;
536
ENTER();
537
   vbo_draw_method(vbo, DRAW_ARRAYS);
538
 
539
   if (exec->array.recalculate_inputs) {
540
      recalculate_input_bindings(ctx);
541
      exec->array.recalculate_inputs = GL_FALSE;
542
 
543
      /* Again... because we may have changed the bitmask of per-vertex varying
544
       * attributes.  If we regenerate the fixed-function vertex program now
545
       * we may be able to prune down the number of vertex attributes which we
546
       * need in the shader.
547
       */
548
      if (ctx->NewState) {
549
         /* Setting "validating" to TRUE prevents _mesa_update_state from
550
          * invalidating what we just did.
551
          */
552
         exec->validating = GL_TRUE;
553
         _mesa_update_state(ctx);
554
         exec->validating = GL_FALSE;
555
      }
556
   }
557
LEAVE();
558
}
559
 
560
 
561
/**
562
 * Handle a draw case that potentially has primitive restart enabled.
563
 *
564
 * If primitive restart is enabled, and PrimitiveRestartInSoftware is
565
 * set, then vbo_sw_primitive_restart is used to handle the primitive
566
 * restart case in software.
567
 */
568
static void
569
vbo_handle_primitive_restart(struct gl_context *ctx,
570
                             const struct _mesa_prim *prim,
571
                             GLuint nr_prims,
572
                             const struct _mesa_index_buffer *ib,
573
                             GLboolean index_bounds_valid,
574
                             GLuint min_index,
575
                             GLuint max_index)
576
{
577
   struct vbo_context *vbo = vbo_context(ctx);
578
 
579
   if ((ib != NULL) &&
580
       ctx->Const.PrimitiveRestartInSoftware &&
581
       ctx->Array._PrimitiveRestart) {
582
      /* Handle primitive restart in software */
583
      vbo_sw_primitive_restart(ctx, prim, nr_prims, ib);
584
   } else {
585
      /* Call driver directly for draw_prims */
586
      vbo->draw_prims(ctx, prim, nr_prims, ib,
587
                      index_bounds_valid, min_index, max_index, NULL);
588
   }
589
}
590
 
591
 
592
/**
593
 * Helper function called by the other DrawArrays() functions below.
594
 * This is where we handle primitive restart for drawing non-indexed
595
 * arrays.  If primitive restart is enabled, it typically means
596
 * splitting one DrawArrays() into two.
597
 */
598
static void
599
vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
600
                GLsizei count, GLuint numInstances, GLuint baseInstance)
601
{
602
   struct vbo_context *vbo = vbo_context(ctx);
603
   struct vbo_exec_context *exec = &vbo->exec;
604
   struct _mesa_prim prim[2];
605
ENTER();
606
   vbo_bind_arrays(ctx);
607
 
608
   /* init most fields to zero */
609
   memset(prim, 0, sizeof(prim));
610
   prim[0].begin = 1;
611
   prim[0].end = 1;
612
   prim[0].mode = mode;
613
   prim[0].num_instances = numInstances;
614
   prim[0].base_instance = baseInstance;
615
 
616
   /* Implement the primitive restart index */
617
   if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
618
      GLuint primCount = 0;
619
 
620
      if (ctx->Array.RestartIndex == start) {
621
         /* special case: RestartIndex at beginning */
622
         if (count > 1) {
623
            prim[0].start = start + 1;
624
            prim[0].count = count - 1;
625
            primCount = 1;
626
         }
627
      }
628
      else if (ctx->Array.RestartIndex == start + count - 1) {
629
         /* special case: RestartIndex at end */
630
         if (count > 1) {
631
            prim[0].start = start;
632
            prim[0].count = count - 1;
633
            primCount = 1;
634
         }
635
      }
636
      else {
637
         /* general case: RestartIndex in middle, split into two prims */
638
         prim[0].start = start;
639
         prim[0].count = ctx->Array.RestartIndex - start;
640
 
641
         prim[1] = prim[0];
642
         prim[1].start = ctx->Array.RestartIndex + 1;
643
         prim[1].count = count - prim[1].start;
644
 
645
         primCount = 2;
646
      }
647
 
648
      if (primCount > 0) {
649
         /* draw one or two prims */
650
         check_buffers_are_unmapped(exec->array.inputs);
651
         vbo->draw_prims(ctx, prim, primCount, NULL,
652
                         GL_TRUE, start, start + count - 1, NULL);
653
      }
654
   }
655
   else {
656
      /* no prim restart */
657
      prim[0].start = start;
658
      prim[0].count = count;
659
 
660
      check_buffers_are_unmapped(exec->array.inputs);
661
      vbo->draw_prims(ctx, prim, 1, NULL,
662
                      GL_TRUE, start, start + count - 1,
663
                      NULL);
664
   }
665
 
666
   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
667
      _mesa_flush(ctx);
668
   }
669
LEAVE();
670
}
671
 
672
 
673
/**
674
 * Execute a glRectf() function.
675
 */
676
static void GLAPIENTRY
677
vbo_exec_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
678
{
679
   GET_CURRENT_CONTEXT(ctx);
680
   ASSERT_OUTSIDE_BEGIN_END(ctx);
681
 
682
   CALL_Begin(GET_DISPATCH(), (GL_QUADS));
683
   CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
684
   CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
685
   CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
686
   CALL_Vertex2f(GET_DISPATCH(), (x1, y2));
687
   CALL_End(GET_DISPATCH(), ());
688
}
689
 
690
 
691
static void GLAPIENTRY
692
vbo_exec_EvalMesh1(GLenum mode, GLint i1, GLint i2)
693
{
694
   GET_CURRENT_CONTEXT(ctx);
695
   GLint i;
696
   GLfloat u, du;
697
   GLenum prim;
698
 
699
   switch (mode) {
700
   case GL_POINT:
701
      prim = GL_POINTS;
702
      break;
703
   case GL_LINE:
704
      prim = GL_LINE_STRIP;
705
      break;
706
   default:
707
      _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
708
      return;
709
   }
710
 
711
   /* No effect if vertex maps disabled.
712
    */
713
   if (!ctx->Eval.Map1Vertex4 &&
714
       !ctx->Eval.Map1Vertex3)
715
      return;
716
 
717
   du = ctx->Eval.MapGrid1du;
718
   u = ctx->Eval.MapGrid1u1 + i1 * du;
719
 
720
   CALL_Begin(GET_DISPATCH(), (prim));
721
   for (i=i1;i<=i2;i++,u+=du) {
722
      CALL_EvalCoord1f(GET_DISPATCH(), (u));
723
   }
724
   CALL_End(GET_DISPATCH(), ());
725
}
726
 
727
 
728
static void GLAPIENTRY
729
vbo_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
730
{
731
   GET_CURRENT_CONTEXT(ctx);
732
   GLfloat u, du, v, dv, v1, u1;
733
   GLint i, j;
734
 
735
   switch (mode) {
736
   case GL_POINT:
737
   case GL_LINE:
738
   case GL_FILL:
739
      break;
740
   default:
741
      _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
742
      return;
743
   }
744
 
745
   /* No effect if vertex maps disabled.
746
    */
747
   if (!ctx->Eval.Map2Vertex4 &&
748
       !ctx->Eval.Map2Vertex3)
749
      return;
750
 
751
   du = ctx->Eval.MapGrid2du;
752
   dv = ctx->Eval.MapGrid2dv;
753
   v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
754
   u1 = ctx->Eval.MapGrid2u1 + i1 * du;
755
 
756
   switch (mode) {
757
   case GL_POINT:
758
      CALL_Begin(GET_DISPATCH(), (GL_POINTS));
759
      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
760
	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
761
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
762
	 }
763
      }
764
      CALL_End(GET_DISPATCH(), ());
765
      break;
766
   case GL_LINE:
767
      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
768
	 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
769
	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
770
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
771
	 }
772
	 CALL_End(GET_DISPATCH(), ());
773
      }
774
      for (u=u1,i=i1;i<=i2;i++,u+=du) {
775
	 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
776
	 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
777
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
778
	 }
779
	 CALL_End(GET_DISPATCH(), ());
780
      }
781
      break;
782
   case GL_FILL:
783
      for (v=v1,j=j1;j
784
	 CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
785
	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
786
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
787
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v+dv));
788
	 }
789
	 CALL_End(GET_DISPATCH(), ());
790
      }
791
      break;
792
   }
793
}
794
 
795
 
796
/**
797
 * Called from glDrawArrays when in immediate mode (not display list mode).
798
 */
799
static void GLAPIENTRY
800
vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
801
{
802
   GET_CURRENT_CONTEXT(ctx);
803
 
804
   if (MESA_VERBOSE & VERBOSE_DRAW)
805
      _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
806
                  _mesa_lookup_enum_by_nr(mode), start, count);
807
 
808
   if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
809
      return;
810
 
811
   if (0)
812
      check_draw_arrays_data(ctx, start, count);
813
 
814
   vbo_draw_arrays(ctx, mode, start, count, 1, 0);
815
 
816
   if (0)
817
      print_draw_arrays(ctx, mode, start, count);
818
}
819
 
820
 
821
/**
822
 * Called from glDrawArraysInstanced when in immediate mode (not
823
 * display list mode).
824
 */
825
static void GLAPIENTRY
826
vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
827
                             GLsizei numInstances)
828
{
829
   GET_CURRENT_CONTEXT(ctx);
830
 
831
   if (MESA_VERBOSE & VERBOSE_DRAW)
832
      _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
833
                  _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
834
 
835
   if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
836
      return;
837
 
838
   if (0)
839
      check_draw_arrays_data(ctx, start, count);
840
 
841
   vbo_draw_arrays(ctx, mode, start, count, numInstances, 0);
842
 
843
   if (0)
844
      print_draw_arrays(ctx, mode, start, count);
845
}
846
 
847
 
848
/**
849
 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
850
 */
851
static void GLAPIENTRY
852
vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count,
853
                                         GLsizei numInstances, GLuint baseInstance)
854
{
855
   GET_CURRENT_CONTEXT(ctx);
856
 
857
   if (MESA_VERBOSE & VERBOSE_DRAW)
858
      _mesa_debug(ctx, "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
859
                  _mesa_lookup_enum_by_nr(mode), first, count,
860
                  numInstances, baseInstance);
861
 
862
   if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
863
                                           numInstances))
864
      return;
865
 
866
   if (0)
867
      check_draw_arrays_data(ctx, first, count);
868
 
869
   vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
870
 
871
   if (0)
872
      print_draw_arrays(ctx, mode, first, count);
873
}
874
 
875
 
876
 
877
/**
878
 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
879
 * For debugging.
880
 */
881
#if 0
882
static void
883
dump_element_buffer(struct gl_context *ctx, GLenum type)
884
{
885
   const GLvoid *map =
886
      ctx->Driver.MapBufferRange(ctx, 0,
887
				 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
888
				 GL_MAP_READ_BIT,
889
				 ctx->Array.ArrayObj->ElementArrayBufferObj);
890
   switch (type) {
891
   case GL_UNSIGNED_BYTE:
892
      {
893
         const GLubyte *us = (const GLubyte *) map;
894
         GLint i;
895
         for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) {
896
            printf("%02x ", us[i]);
897
            if (i % 32 == 31)
898
               printf("\n");
899
         }
900
         printf("\n");
901
      }
902
      break;
903
   case GL_UNSIGNED_SHORT:
904
      {
905
         const GLushort *us = (const GLushort *) map;
906
         GLint i;
907
         for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) {
908
            printf("%04x ", us[i]);
909
            if (i % 16 == 15)
910
               printf("\n");
911
         }
912
         printf("\n");
913
      }
914
      break;
915
   case GL_UNSIGNED_INT:
916
      {
917
         const GLuint *us = (const GLuint *) map;
918
         GLint i;
919
         for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) {
920
            printf("%08x ", us[i]);
921
            if (i % 8 == 7)
922
               printf("\n");
923
         }
924
         printf("\n");
925
      }
926
      break;
927
   default:
928
      ;
929
   }
930
 
931
   ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
932
}
933
#endif
934
 
935
 
936
/**
937
 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
938
 * Do the rendering for a glDrawElements or glDrawRangeElements call after
939
 * we've validated buffer bounds, etc.
940
 */
941
static void
942
vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
943
				GLboolean index_bounds_valid,
944
				GLuint start, GLuint end,
945
				GLsizei count, GLenum type,
946
				const GLvoid *indices,
947
				GLint basevertex, GLuint numInstances,
948
				GLuint baseInstance)
949
{
950
   struct vbo_context *vbo = vbo_context(ctx);
951
   struct vbo_exec_context *exec = &vbo->exec;
952
   struct _mesa_index_buffer ib;
953
   struct _mesa_prim prim[1];
954
 
955
   vbo_bind_arrays(ctx);
956
 
957
   ib.count = count;
958
   ib.type = type;
959
   ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
960
   ib.ptr = indices;
961
 
962
   prim[0].begin = 1;
963
   prim[0].end = 1;
964
   prim[0].weak = 0;
965
   prim[0].pad = 0;
966
   prim[0].mode = mode;
967
   prim[0].start = 0;
968
   prim[0].count = count;
969
   prim[0].indexed = 1;
970
   prim[0].basevertex = basevertex;
971
   prim[0].num_instances = numInstances;
972
   prim[0].base_instance = baseInstance;
973
 
974
   /* Need to give special consideration to rendering a range of
975
    * indices starting somewhere above zero.  Typically the
976
    * application is issuing multiple DrawRangeElements() to draw
977
    * successive primitives layed out linearly in the vertex arrays.
978
    * Unless the vertex arrays are all in a VBO (or locked as with
979
    * CVA), the OpenGL semantics imply that we need to re-read or
980
    * re-upload the vertex data on each draw call.
981
    *
982
    * In the case of hardware tnl, we want to avoid starting the
983
    * upload at zero, as it will mean every draw call uploads an
984
    * increasing amount of not-used vertex data.  Worse - in the
985
    * software tnl module, all those vertices might be transformed and
986
    * lit but never rendered.
987
    *
988
    * If we just upload or transform the vertices in start..end,
989
    * however, the indices will be incorrect.
990
    *
991
    * At this level, we don't know exactly what the requirements of
992
    * the backend are going to be, though it will likely boil down to
993
    * either:
994
    *
995
    * 1) Do nothing, everything is in a VBO and is processed once
996
    *       only.
997
    *
998
    * 2) Adjust the indices and vertex arrays so that start becomes
999
    *    zero.
1000
    *
1001
    * Rather than doing anything here, I'll provide a helper function
1002
    * for the latter case elsewhere.
1003
    */
1004
 
1005
   check_buffers_are_unmapped(exec->array.inputs);
1006
   vbo_handle_primitive_restart(ctx, prim, 1, &ib,
1007
                                index_bounds_valid, start, end);
1008
 
1009
   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1010
      _mesa_flush(ctx);
1011
   }
1012
}
1013
 
1014
 
1015
/**
1016
 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
1017
 */
1018
static void GLAPIENTRY
1019
vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
1020
				     GLuint start, GLuint end,
1021
				     GLsizei count, GLenum type,
1022
				     const GLvoid *indices,
1023
				     GLint basevertex)
1024
{
1025
   static GLuint warnCount = 0;
1026
   GLboolean index_bounds_valid = GL_TRUE;
1027
   GLuint max_element;
1028
   GET_CURRENT_CONTEXT(ctx);
1029
 
1030
   if (MESA_VERBOSE & VERBOSE_DRAW)
1031
      _mesa_debug(ctx,
1032
                "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
1033
                _mesa_lookup_enum_by_nr(mode), start, end, count,
1034
                _mesa_lookup_enum_by_nr(type), indices, basevertex);
1035
 
1036
   if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
1037
                                          type, indices, basevertex ))
1038
      return;
1039
 
1040
   if (ctx->Const.CheckArrayBounds) {
1041
      /* _MaxElement was computed, so we can use it.
1042
       * This path is used for drivers which need strict bounds checking.
1043
       */
1044
      max_element = ctx->Array.ArrayObj->_MaxElement;
1045
   }
1046
   else {
1047
      /* Generally, hardware drivers don't need to know the buffer bounds
1048
       * if all vertex attributes are in VBOs.
1049
       * However, if none of vertex attributes are in VBOs, _MaxElement
1050
       * is always set to some random big number anyway, so bounds checking
1051
       * is mostly useless.
1052
       *
1053
       * This is only useful to catch invalid values in the "end" parameter
1054
       * like ~0.
1055
       */
1056
      max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
1057
   }
1058
 
1059
   if ((int) end + basevertex < 0 ||
1060
       start + basevertex >= max_element) {
1061
      /* The application requested we draw using a range of indices that's
1062
       * outside the bounds of the current VBO.  This is invalid and appears
1063
       * to give undefined results.  The safest thing to do is to simply
1064
       * ignore the range, in case the application botched their range tracking
1065
       * but did provide valid indices.  Also issue a warning indicating that
1066
       * the application is broken.
1067
       */
1068
      if (warnCount++ < 10) {
1069
         _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
1070
                       "basevertex %d, count %d, type 0x%x, indices=%p):\n"
1071
                       "\trange is outside VBO bounds (max=%u); ignoring.\n"
1072
                       "\tThis should be fixed in the application.",
1073
                       start, end, basevertex, count, type, indices,
1074
                       max_element - 1);
1075
      }
1076
      index_bounds_valid = GL_FALSE;
1077
   }
1078
 
1079
   /* NOTE: It's important that 'end' is a reasonable value.
1080
    * in _tnl_draw_prims(), we use end to determine how many vertices
1081
    * to transform.  If it's too large, we can unnecessarily split prims
1082
    * or we can read/write out of memory in several different places!
1083
    */
1084
 
1085
   /* Catch/fix some potential user errors */
1086
   if (type == GL_UNSIGNED_BYTE) {
1087
      start = MIN2(start, 0xff);
1088
      end = MIN2(end, 0xff);
1089
   }
1090
   else if (type == GL_UNSIGNED_SHORT) {
1091
      start = MIN2(start, 0xffff);
1092
      end = MIN2(end, 0xffff);
1093
   }
1094
 
1095
   if (0) {
1096
      printf("glDraw[Range]Elements{,BaseVertex}"
1097
	     "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
1098
	     "base %d\n",
1099
	     start, end, type, count,
1100
	     ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
1101
	     basevertex);
1102
   }
1103
 
1104
   if ((int) start + basevertex < 0 ||
1105
       end + basevertex >= max_element)
1106
      index_bounds_valid = GL_FALSE;
1107
 
1108
#if 0
1109
   check_draw_elements_data(ctx, count, type, indices);
1110
#else
1111
   (void) check_draw_elements_data;
1112
#endif
1113
 
1114
   vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
1115
				   count, type, indices, basevertex, 1, 0);
1116
}
1117
 
1118
 
1119
/**
1120
 * Called by glDrawRangeElements() in immediate mode.
1121
 */
1122
static void GLAPIENTRY
1123
vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1124
                           GLsizei count, GLenum type, const GLvoid *indices)
1125
{
1126
   if (MESA_VERBOSE & VERBOSE_DRAW) {
1127
      GET_CURRENT_CONTEXT(ctx);
1128
      _mesa_debug(ctx,
1129
                  "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
1130
                  _mesa_lookup_enum_by_nr(mode), start, end, count,
1131
                  _mesa_lookup_enum_by_nr(type), indices);
1132
   }
1133
 
1134
   vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1135
					indices, 0);
1136
}
1137
 
1138
 
1139
/**
1140
 * Called by glDrawElements() in immediate mode.
1141
 */
1142
static void GLAPIENTRY
1143
vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
1144
                      const GLvoid *indices)
1145
{
1146
   GET_CURRENT_CONTEXT(ctx);
1147
 
1148
   if (MESA_VERBOSE & VERBOSE_DRAW)
1149
      _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1150
                  _mesa_lookup_enum_by_nr(mode), count,
1151
                  _mesa_lookup_enum_by_nr(type), indices);
1152
 
1153
   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
1154
      return;
1155
 
1156
   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1157
				   count, type, indices, 0, 1, 0);
1158
}
1159
 
1160
 
1161
/**
1162
 * Called by glDrawElementsBaseVertex() in immediate mode.
1163
 */
1164
static void GLAPIENTRY
1165
vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1166
				const GLvoid *indices, GLint basevertex)
1167
{
1168
   GET_CURRENT_CONTEXT(ctx);
1169
 
1170
   if (MESA_VERBOSE & VERBOSE_DRAW)
1171
      _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
1172
                  _mesa_lookup_enum_by_nr(mode), count,
1173
                  _mesa_lookup_enum_by_nr(type), indices, basevertex);
1174
 
1175
   if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
1176
				     basevertex ))
1177
      return;
1178
 
1179
   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1180
				   count, type, indices, basevertex, 1, 0);
1181
}
1182
 
1183
 
1184
/**
1185
 * Called by glDrawElementsInstanced() in immediate mode.
1186
 */
1187
static void GLAPIENTRY
1188
vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1189
                               const GLvoid *indices, GLsizei numInstances)
1190
{
1191
   GET_CURRENT_CONTEXT(ctx);
1192
 
1193
   if (MESA_VERBOSE & VERBOSE_DRAW)
1194
      _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
1195
                  _mesa_lookup_enum_by_nr(mode), count,
1196
                  _mesa_lookup_enum_by_nr(type), indices, numInstances);
1197
 
1198
   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1199
                                             numInstances, 0))
1200
      return;
1201
 
1202
   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1203
				   count, type, indices, 0, numInstances, 0);
1204
}
1205
 
1206
 
1207
/**
1208
 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1209
 */
1210
static void GLAPIENTRY
1211
vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1212
                               const GLvoid *indices, GLsizei numInstances,
1213
                               GLint basevertex)
1214
{
1215
   GET_CURRENT_CONTEXT(ctx);
1216
 
1217
   if (MESA_VERBOSE & VERBOSE_DRAW)
1218
      _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1219
                  _mesa_lookup_enum_by_nr(mode), count,
1220
                  _mesa_lookup_enum_by_nr(type), indices,
1221
                  numInstances, basevertex);
1222
 
1223
   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1224
                                             numInstances, basevertex))
1225
      return;
1226
 
1227
   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1228
				   count, type, indices, basevertex, numInstances, 0);
1229
}
1230
 
1231
 
1232
/**
1233
 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1234
 */
1235
static void GLAPIENTRY
1236
vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type,
1237
                                           const GLvoid *indices, GLsizei numInstances,
1238
                                           GLuint baseInstance)
1239
{
1240
   GET_CURRENT_CONTEXT(ctx);
1241
 
1242
   if (MESA_VERBOSE & VERBOSE_DRAW)
1243
      _mesa_debug(ctx, "glDrawElementsInstancedBaseInstance(%s, %d, %s, %p, %d, %d)\n",
1244
                  _mesa_lookup_enum_by_nr(mode), count,
1245
                  _mesa_lookup_enum_by_nr(type), indices,
1246
                  numInstances, baseInstance);
1247
 
1248
   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1249
                                             numInstances, 0))
1250
      return;
1251
 
1252
   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1253
                                   count, type, indices, 0, numInstances,
1254
                                   baseInstance);
1255
}
1256
 
1257
 
1258
/**
1259
 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1260
 */
1261
static void GLAPIENTRY
1262
vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
1263
                                                     const GLvoid *indices, GLsizei numInstances,
1264
                                                     GLint basevertex, GLuint baseInstance)
1265
{
1266
   GET_CURRENT_CONTEXT(ctx);
1267
 
1268
   if (MESA_VERBOSE & VERBOSE_DRAW)
1269
      _mesa_debug(ctx, "glDrawElementsInstancedBaseVertexBaseInstance(%s, %d, %s, %p, %d, %d, %d)\n",
1270
                  _mesa_lookup_enum_by_nr(mode), count,
1271
                  _mesa_lookup_enum_by_nr(type), indices,
1272
                  numInstances, basevertex, baseInstance);
1273
 
1274
   if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1275
                                             numInstances, basevertex))
1276
      return;
1277
 
1278
   vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1279
                                   count, type, indices, basevertex, numInstances,
1280
                                   baseInstance);
1281
}
1282
 
1283
 
1284
/**
1285
 * Inner support for both _mesa_MultiDrawElements() and
1286
 * _mesa_MultiDrawRangeElements().
1287
 * This does the actual rendering after we've checked array indexes, etc.
1288
 */
1289
static void
1290
vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1291
				const GLsizei *count, GLenum type,
1292
				const GLvoid * const *indices,
1293
				GLsizei primcount,
1294
				const GLint *basevertex)
1295
{
1296
   struct vbo_context *vbo = vbo_context(ctx);
1297
   struct vbo_exec_context *exec = &vbo->exec;
1298
   struct _mesa_index_buffer ib;
1299
   struct _mesa_prim *prim;
1300
   unsigned int index_type_size = vbo_sizeof_ib_type(type);
1301
   uintptr_t min_index_ptr, max_index_ptr;
1302
   GLboolean fallback = GL_FALSE;
1303
   int i;
1304
 
1305
   if (primcount == 0)
1306
      return;
1307
 
1308
   prim = calloc(1, primcount * sizeof(*prim));
1309
   if (prim == NULL) {
1310
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1311
      return;
1312
   }
1313
 
1314
   vbo_bind_arrays(ctx);
1315
 
1316
   min_index_ptr = (uintptr_t)indices[0];
1317
   max_index_ptr = 0;
1318
   for (i = 0; i < primcount; i++) {
1319
      min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1320
      max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1321
			   index_type_size * count[i]);
1322
   }
1323
 
1324
   /* Check if we can handle this thing as a bunch of index offsets from the
1325
    * same index pointer.  If we can't, then we have to fall back to doing
1326
    * a draw_prims per primitive.
1327
    * Check that the difference between each prim's indexes is a multiple of
1328
    * the index/element size.
1329
    */
1330
   if (index_type_size != 1) {
1331
      for (i = 0; i < primcount; i++) {
1332
	 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1333
	    fallback = GL_TRUE;
1334
	    break;
1335
	 }
1336
      }
1337
   }
1338
 
1339
   /* If the index buffer isn't in a VBO, then treating the application's
1340
    * subranges of the index buffer as one large index buffer may lead to
1341
    * us reading unmapped memory.
1342
    */
1343
   if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
1344
      fallback = GL_TRUE;
1345
 
1346
   if (!fallback) {
1347
      ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1348
      ib.type = type;
1349
      ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1350
      ib.ptr = (void *)min_index_ptr;
1351
 
1352
      for (i = 0; i < primcount; i++) {
1353
	 prim[i].begin = (i == 0);
1354
	 prim[i].end = (i == primcount - 1);
1355
	 prim[i].weak = 0;
1356
	 prim[i].pad = 0;
1357
	 prim[i].mode = mode;
1358
	 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1359
	 prim[i].count = count[i];
1360
	 prim[i].indexed = 1;
1361
         prim[i].num_instances = 1;
1362
         prim[i].base_instance = 0;
1363
	 if (basevertex != NULL)
1364
	    prim[i].basevertex = basevertex[i];
1365
	 else
1366
	    prim[i].basevertex = 0;
1367
      }
1368
 
1369
      check_buffers_are_unmapped(exec->array.inputs);
1370
      vbo_handle_primitive_restart(ctx, prim, primcount, &ib,
1371
                                   GL_FALSE, ~0, ~0);
1372
   } else {
1373
      /* render one prim at a time */
1374
      for (i = 0; i < primcount; i++) {
1375
	 ib.count = count[i];
1376
	 ib.type = type;
1377
	 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1378
	 ib.ptr = indices[i];
1379
 
1380
	 prim[0].begin = 1;
1381
	 prim[0].end = 1;
1382
	 prim[0].weak = 0;
1383
	 prim[0].pad = 0;
1384
	 prim[0].mode = mode;
1385
	 prim[0].start = 0;
1386
	 prim[0].count = count[i];
1387
	 prim[0].indexed = 1;
1388
         prim[0].num_instances = 1;
1389
         prim[0].base_instance = 0;
1390
	 if (basevertex != NULL)
1391
	    prim[0].basevertex = basevertex[i];
1392
	 else
1393
	    prim[0].basevertex = 0;
1394
 
1395
         check_buffers_are_unmapped(exec->array.inputs);
1396
         vbo_handle_primitive_restart(ctx, prim, 1, &ib,
1397
                                      GL_FALSE, ~0, ~0);
1398
      }
1399
   }
1400
 
1401
   free(prim);
1402
 
1403
   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1404
      _mesa_flush(ctx);
1405
   }
1406
}
1407
 
1408
 
1409
static void GLAPIENTRY
1410
vbo_exec_MultiDrawElements(GLenum mode,
1411
			   const GLsizei *count, GLenum type,
1412
			   const GLvoid * const *indices,
1413
			   GLsizei primcount)
1414
{
1415
   GET_CURRENT_CONTEXT(ctx);
1416
 
1417
   if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1418
                                         primcount, NULL))
1419
      return;
1420
 
1421
   vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1422
				   NULL);
1423
}
1424
 
1425
 
1426
static void GLAPIENTRY
1427
vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1428
				     const GLsizei *count, GLenum type,
1429
				     const GLvoid * const *indices,
1430
				     GLsizei primcount,
1431
				     const GLsizei *basevertex)
1432
{
1433
   GET_CURRENT_CONTEXT(ctx);
1434
 
1435
   if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1436
                                         primcount, basevertex))
1437
      return;
1438
 
1439
   vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1440
				   basevertex);
1441
}
1442
 
1443
static void
1444
vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1445
                            struct gl_transform_feedback_object *obj,
1446
                            GLuint stream, GLuint numInstances)
1447
{
1448
   struct vbo_context *vbo = vbo_context(ctx);
1449
   struct vbo_exec_context *exec = &vbo->exec;
1450
   struct _mesa_prim prim[2];
1451
 
1452
   if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
1453
                                             numInstances)) {
1454
      return;
1455
   }
1456
 
1457
   vbo_bind_arrays(ctx);
1458
 
1459
   /* init most fields to zero */
1460
   memset(prim, 0, sizeof(prim));
1461
   prim[0].begin = 1;
1462
   prim[0].end = 1;
1463
   prim[0].mode = mode;
1464
   prim[0].num_instances = numInstances;
1465
   prim[0].base_instance = 0;
1466
 
1467
   /* Maybe we should do some primitive splitting for primitive restart
1468
    * (like in DrawArrays), but we have no way to know how many vertices
1469
    * will be rendered. */
1470
 
1471
   check_buffers_are_unmapped(exec->array.inputs);
1472
   vbo->draw_prims(ctx, prim, 1, NULL,
1473
                   GL_TRUE, 0, 0, obj);
1474
 
1475
   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1476
      _mesa_flush(ctx);
1477
   }
1478
}
1479
 
1480
/**
1481
 * Like DrawArrays, but take the count from a transform feedback object.
1482
 * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1483
 * \param name  the transform feedback object
1484
 * User still has to setup of the vertex attribute info with
1485
 * glVertexPointer, glColorPointer, etc.
1486
 * Part of GL_ARB_transform_feedback2.
1487
 */
1488
static void GLAPIENTRY
1489
vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
1490
{
1491
   GET_CURRENT_CONTEXT(ctx);
1492
   struct gl_transform_feedback_object *obj =
1493
      _mesa_lookup_transform_feedback_object(ctx, name);
1494
 
1495
   if (MESA_VERBOSE & VERBOSE_DRAW)
1496
      _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1497
                  _mesa_lookup_enum_by_nr(mode), name);
1498
 
1499
   vbo_draw_transform_feedback(ctx, mode, obj, 0, 1);
1500
}
1501
 
1502
static void GLAPIENTRY
1503
vbo_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
1504
{
1505
   GET_CURRENT_CONTEXT(ctx);
1506
   struct gl_transform_feedback_object *obj =
1507
      _mesa_lookup_transform_feedback_object(ctx, name);
1508
 
1509
   if (MESA_VERBOSE & VERBOSE_DRAW)
1510
      _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
1511
                  _mesa_lookup_enum_by_nr(mode), name, stream);
1512
 
1513
   vbo_draw_transform_feedback(ctx, mode, obj, stream, 1);
1514
}
1515
 
1516
static void GLAPIENTRY
1517
vbo_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
1518
                                        GLsizei primcount)
1519
{
1520
   GET_CURRENT_CONTEXT(ctx);
1521
   struct gl_transform_feedback_object *obj =
1522
      _mesa_lookup_transform_feedback_object(ctx, name);
1523
 
1524
   if (MESA_VERBOSE & VERBOSE_DRAW)
1525
      _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
1526
                  _mesa_lookup_enum_by_nr(mode), name);
1527
 
1528
   vbo_draw_transform_feedback(ctx, mode, obj, 0, primcount);
1529
}
1530
 
1531
static void GLAPIENTRY
1532
vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
1533
                                              GLuint stream, GLsizei primcount)
1534
{
1535
   GET_CURRENT_CONTEXT(ctx);
1536
   struct gl_transform_feedback_object *obj =
1537
      _mesa_lookup_transform_feedback_object(ctx, name);
1538
 
1539
   if (MESA_VERBOSE & VERBOSE_DRAW)
1540
      _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
1541
                  "(%s, %u, %u, %i)\n",
1542
                  _mesa_lookup_enum_by_nr(mode), name, stream, primcount);
1543
 
1544
   vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
1545
}
1546
 
1547
 
1548
/**
1549
 * Initialize the dispatch table with the VBO functions for drawing.
1550
 */
1551
void
1552
vbo_initialize_exec_dispatch(const struct gl_context *ctx,
1553
                             struct _glapi_table *exec)
1554
{
1555
   SET_DrawArrays(exec, vbo_exec_DrawArrays);
1556
   SET_DrawElements(exec, vbo_exec_DrawElements);
1557
 
1558
   if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1559
      SET_DrawRangeElements(exec, vbo_exec_DrawRangeElements);
1560
   }
1561
 
1562
   SET_MultiDrawElementsEXT(exec, vbo_exec_MultiDrawElements);
1563
 
1564
   if (ctx->API == API_OPENGL_COMPAT) {
1565
      SET_Rectf(exec, vbo_exec_Rectf);
1566
      SET_EvalMesh1(exec, vbo_exec_EvalMesh1);
1567
      SET_EvalMesh2(exec, vbo_exec_EvalMesh2);
1568
   }
1569
 
1570
   if (_mesa_is_desktop_gl(ctx)) {
1571
      SET_DrawElementsBaseVertex(exec, vbo_exec_DrawElementsBaseVertex);
1572
      SET_DrawRangeElementsBaseVertex(exec, vbo_exec_DrawRangeElementsBaseVertex);
1573
      SET_MultiDrawElementsBaseVertex(exec, vbo_exec_MultiDrawElementsBaseVertex);
1574
      SET_DrawArraysInstancedBaseInstance(exec, vbo_exec_DrawArraysInstancedBaseInstance);
1575
      SET_DrawElementsInstancedBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseInstance);
1576
      SET_DrawElementsInstancedBaseVertex(exec, vbo_exec_DrawElementsInstancedBaseVertex);
1577
      SET_DrawElementsInstancedBaseVertexBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseVertexBaseInstance);
1578
   }
1579
 
1580
   if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1581
      SET_DrawArraysInstancedARB(exec, vbo_exec_DrawArraysInstanced);
1582
      SET_DrawElementsInstancedARB(exec, vbo_exec_DrawElementsInstanced);
1583
   }
1584
 
1585
   if (_mesa_is_desktop_gl(ctx)) {
1586
      SET_DrawTransformFeedback(exec, vbo_exec_DrawTransformFeedback);
1587
      SET_DrawTransformFeedbackStream(exec, vbo_exec_DrawTransformFeedbackStream);
1588
      SET_DrawTransformFeedbackInstanced(exec, vbo_exec_DrawTransformFeedbackInstanced);
1589
      SET_DrawTransformFeedbackStreamInstanced(exec, vbo_exec_DrawTransformFeedbackStreamInstanced);
1590
   }
1591
}
1592
 
1593
 
1594
 
1595
/**
1596
 * The following functions are only used for OpenGL ES 1/2 support.
1597
 * And some aren't even supported (yet) in ES 1/2.
1598
 */
1599
 
1600
 
1601
void GLAPIENTRY
1602
_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1603
{
1604
   vbo_exec_DrawArrays(mode, first, count);
1605
}
1606
 
1607
 
1608
void GLAPIENTRY
1609
_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1610
                   const GLvoid *indices)
1611
{
1612
   vbo_exec_DrawElements(mode, count, type, indices);
1613
}
1614
 
1615
 
1616
void GLAPIENTRY
1617
_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1618
			     const GLvoid *indices, GLint basevertex)
1619
{
1620
   vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1621
}
1622
 
1623
 
1624
void GLAPIENTRY
1625
_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1626
                        GLenum type, const GLvoid *indices)
1627
{
1628
   vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1629
}
1630
 
1631
 
1632
void GLAPIENTRY
1633
_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1634
				  GLsizei count, GLenum type,
1635
				  const GLvoid *indices, GLint basevertex)
1636
{
1637
   vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1638
					indices, basevertex);
1639
}
1640
 
1641
 
1642
void GLAPIENTRY
1643
_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1644
			   const GLvoid **indices, GLsizei primcount)
1645
{
1646
   vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1647
}
1648
 
1649
 
1650
void GLAPIENTRY
1651
_mesa_MultiDrawElementsBaseVertex(GLenum mode,
1652
				  const GLsizei *count, GLenum type,
1653
				  const GLvoid **indices, GLsizei primcount,
1654
				  const GLint *basevertex)
1655
{
1656
   vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1657
					primcount, basevertex);
1658
}
1659
 
1660
void GLAPIENTRY
1661
_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1662
{
1663
   vbo_exec_DrawTransformFeedback(mode, name);
1664
}