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