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