mesa: move ElementArrayBufferObj to gl_array_object
[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_TEX7; 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 |= 1 << i;
458 }
459 }
460
461 for (i = 0; i < MAT_ATTRIB_MAX; i++) {
462 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
463 const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + 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_MAX - VERT_ATTRIB_GENERIC0; i++) {
470 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
471 const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + 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_TEX7; i++) {
489 if (exec->array.generic_array[i]->Enabled)
490 inputs[i] = exec->array.generic_array[i];
491 else if (exec->array.legacy_array[i]->Enabled)
492 inputs[i] = exec->array.legacy_array[i];
493 else {
494 inputs[i] = &vbo->legacy_currval[i];
495 const_inputs |= 1 << i;
496 }
497 }
498
499 /* Could use just about anything, just to fill in the empty
500 * slots:
501 */
502 for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
503 inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
504 const_inputs |= 1 << i;
505 }
506
507 ctx->NewState |= _NEW_ARRAY;
508 break;
509
510 case VP_ARB:
511 /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
512 * attribute array aliases and overrides the legacy position array.
513 *
514 * Otherwise, legacy attributes available in the legacy slots,
515 * generic attributes in the generic slots and materials are not
516 * available as per-vertex attributes.
517 */
518 if (exec->array.generic_array[0]->Enabled)
519 inputs[0] = exec->array.generic_array[0];
520 else if (exec->array.legacy_array[0]->Enabled)
521 inputs[0] = exec->array.legacy_array[0];
522 else {
523 inputs[0] = &vbo->legacy_currval[0];
524 const_inputs |= 1 << 0;
525 }
526
527 for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
528 if (exec->array.legacy_array[i]->Enabled)
529 inputs[i] = exec->array.legacy_array[i];
530 else {
531 inputs[i] = &vbo->legacy_currval[i];
532 const_inputs |= 1 << i;
533 }
534 }
535
536 for (i = 1; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
537 if (exec->array.generic_array[i]->Enabled)
538 inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
539 else {
540 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
541 const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
542 }
543 }
544
545 inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
546 ctx->NewState |= _NEW_ARRAY;
547 break;
548 }
549
550 _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
551 }
552
553
554 /**
555 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
556 * These will point to the arrays to actually use for drawing. Some will
557 * be user-provided arrays, other will be zero-stride const-valued arrays.
558 * Note that this might set the _NEW_ARRAY dirty flag so state validation
559 * must be done after this call.
560 */
561 void
562 vbo_bind_arrays(struct gl_context *ctx)
563 {
564 if (!ctx->Array.RebindArrays) {
565 return;
566 }
567
568 bind_array_obj(ctx);
569 recalculate_input_bindings(ctx);
570 ctx->Array.RebindArrays = GL_FALSE;
571 }
572
573
574 /**
575 * Helper function called by the other DrawArrays() functions below.
576 * This is where we handle primitive restart for drawing non-indexed
577 * arrays. If primitive restart is enabled, it typically means
578 * splitting one DrawArrays() into two.
579 */
580 static void
581 vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
582 GLsizei count, GLuint numInstances)
583 {
584 struct vbo_context *vbo = vbo_context(ctx);
585 struct vbo_exec_context *exec = &vbo->exec;
586 struct _mesa_prim prim[2];
587
588 vbo_bind_arrays(ctx);
589
590 /* Again... because we may have changed the bitmask of per-vertex varying
591 * attributes. If we regenerate the fixed-function vertex program now
592 * we may be able to prune down the number of vertex attributes which we
593 * need in the shader.
594 */
595 if (ctx->NewState)
596 _mesa_update_state(ctx);
597
598 /* init most fields to zero */
599 memset(prim, 0, sizeof(prim));
600 prim[0].begin = 1;
601 prim[0].end = 1;
602 prim[0].mode = mode;
603 prim[0].num_instances = numInstances;
604
605 /* Implement the primitive restart index */
606 if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
607 GLuint primCount = 0;
608
609 if (ctx->Array.RestartIndex == start) {
610 /* special case: RestartIndex at beginning */
611 if (count > 1) {
612 prim[0].start = start + 1;
613 prim[0].count = count - 1;
614 primCount = 1;
615 }
616 }
617 else if (ctx->Array.RestartIndex == start + count - 1) {
618 /* special case: RestartIndex at end */
619 if (count > 1) {
620 prim[0].start = start;
621 prim[0].count = count - 1;
622 primCount = 1;
623 }
624 }
625 else {
626 /* general case: RestartIndex in middle, split into two prims */
627 prim[0].start = start;
628 prim[0].count = ctx->Array.RestartIndex - start;
629
630 prim[1] = prim[0];
631 prim[1].start = ctx->Array.RestartIndex + 1;
632 prim[1].count = count - prim[1].start;
633
634 primCount = 2;
635 }
636
637 if (primCount > 0) {
638 /* draw one or two prims */
639 check_buffers_are_unmapped(exec->array.inputs);
640 vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
641 GL_TRUE, start, start + count - 1);
642 }
643 }
644 else {
645 /* no prim restart */
646 prim[0].start = start;
647 prim[0].count = count;
648
649 check_buffers_are_unmapped(exec->array.inputs);
650 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
651 GL_TRUE, start, start + count - 1);
652 }
653 }
654
655
656
657 /**
658 * Called from glDrawArrays when in immediate mode (not display list mode).
659 */
660 static void GLAPIENTRY
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 FLUSH_CURRENT( ctx, 0 );
673
674 if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
675 return;
676 }
677
678 if (0)
679 check_draw_arrays_data(ctx, start, count);
680
681 vbo_draw_arrays(ctx, mode, start, count, 1);
682
683 if (0)
684 print_draw_arrays(ctx, mode, start, count);
685 }
686
687
688 /**
689 * Called from glDrawArraysInstanced when in immediate mode (not
690 * display list mode).
691 */
692 static void GLAPIENTRY
693 vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
694 GLsizei numInstances)
695 {
696 GET_CURRENT_CONTEXT(ctx);
697
698 if (MESA_VERBOSE & VERBOSE_DRAW)
699 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
700 _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
701
702 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
703 return;
704
705 FLUSH_CURRENT( ctx, 0 );
706
707 if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
708 return;
709 }
710
711 if (0)
712 check_draw_arrays_data(ctx, start, count);
713
714 vbo_draw_arrays(ctx, mode, start, count, numInstances);
715
716 if (0)
717 print_draw_arrays(ctx, mode, start, count);
718 }
719
720
721 /**
722 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
723 * For debugging.
724 */
725 static void
726 dump_element_buffer(struct gl_context *ctx, GLenum type)
727 {
728 const GLvoid *map =
729 ctx->Driver.MapBufferRange(ctx, 0,
730 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
731 GL_MAP_READ_BIT,
732 ctx->Array.ArrayObj->ElementArrayBufferObj);
733 switch (type) {
734 case GL_UNSIGNED_BYTE:
735 {
736 const GLubyte *us = (const GLubyte *) map;
737 GLint i;
738 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) {
739 printf("%02x ", us[i]);
740 if (i % 32 == 31)
741 printf("\n");
742 }
743 printf("\n");
744 }
745 break;
746 case GL_UNSIGNED_SHORT:
747 {
748 const GLushort *us = (const GLushort *) map;
749 GLint i;
750 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) {
751 printf("%04x ", us[i]);
752 if (i % 16 == 15)
753 printf("\n");
754 }
755 printf("\n");
756 }
757 break;
758 case GL_UNSIGNED_INT:
759 {
760 const GLuint *us = (const GLuint *) map;
761 GLint i;
762 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) {
763 printf("%08x ", us[i]);
764 if (i % 8 == 7)
765 printf("\n");
766 }
767 printf("\n");
768 }
769 break;
770 default:
771 ;
772 }
773
774 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
775 }
776
777
778 /**
779 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
780 * Do the rendering for a glDrawElements or glDrawRangeElements call after
781 * we've validated buffer bounds, etc.
782 */
783 static void
784 vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
785 GLboolean index_bounds_valid,
786 GLuint start, GLuint end,
787 GLsizei count, GLenum type,
788 const GLvoid *indices,
789 GLint basevertex, GLint numInstances)
790 {
791 struct vbo_context *vbo = vbo_context(ctx);
792 struct vbo_exec_context *exec = &vbo->exec;
793 struct _mesa_index_buffer ib;
794 struct _mesa_prim prim[1];
795
796 FLUSH_CURRENT( ctx, 0 );
797
798 if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
799 return;
800 }
801
802 vbo_bind_arrays( ctx );
803
804 /* check for dirty state again */
805 if (ctx->NewState)
806 _mesa_update_state( ctx );
807
808 ib.count = count;
809 ib.type = type;
810 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
811 ib.ptr = indices;
812
813 prim[0].begin = 1;
814 prim[0].end = 1;
815 prim[0].weak = 0;
816 prim[0].pad = 0;
817 prim[0].mode = mode;
818 prim[0].start = 0;
819 prim[0].count = count;
820 prim[0].indexed = 1;
821 prim[0].basevertex = basevertex;
822 prim[0].num_instances = numInstances;
823
824 /* Need to give special consideration to rendering a range of
825 * indices starting somewhere above zero. Typically the
826 * application is issuing multiple DrawRangeElements() to draw
827 * successive primitives layed out linearly in the vertex arrays.
828 * Unless the vertex arrays are all in a VBO (or locked as with
829 * CVA), the OpenGL semantics imply that we need to re-read or
830 * re-upload the vertex data on each draw call.
831 *
832 * In the case of hardware tnl, we want to avoid starting the
833 * upload at zero, as it will mean every draw call uploads an
834 * increasing amount of not-used vertex data. Worse - in the
835 * software tnl module, all those vertices might be transformed and
836 * lit but never rendered.
837 *
838 * If we just upload or transform the vertices in start..end,
839 * however, the indices will be incorrect.
840 *
841 * At this level, we don't know exactly what the requirements of
842 * the backend are going to be, though it will likely boil down to
843 * either:
844 *
845 * 1) Do nothing, everything is in a VBO and is processed once
846 * only.
847 *
848 * 2) Adjust the indices and vertex arrays so that start becomes
849 * zero.
850 *
851 * Rather than doing anything here, I'll provide a helper function
852 * for the latter case elsewhere.
853 */
854
855 check_buffers_are_unmapped(exec->array.inputs);
856 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
857 index_bounds_valid, start, end );
858 }
859
860
861 /**
862 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
863 */
864 static void GLAPIENTRY
865 vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
866 GLuint start, GLuint end,
867 GLsizei count, GLenum type,
868 const GLvoid *indices,
869 GLint basevertex)
870 {
871 static GLuint warnCount = 0;
872 GET_CURRENT_CONTEXT(ctx);
873
874 if (MESA_VERBOSE & VERBOSE_DRAW)
875 _mesa_debug(ctx,
876 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
877 _mesa_lookup_enum_by_nr(mode), start, end, count,
878 _mesa_lookup_enum_by_nr(type), indices, basevertex);
879
880 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
881 type, indices, basevertex ))
882 return;
883
884 /* NOTE: It's important that 'end' is a reasonable value.
885 * in _tnl_draw_prims(), we use end to determine how many vertices
886 * to transform. If it's too large, we can unnecessarily split prims
887 * or we can read/write out of memory in several different places!
888 */
889
890 /* Catch/fix some potential user errors */
891 if (type == GL_UNSIGNED_BYTE) {
892 start = MIN2(start, 0xff);
893 end = MIN2(end, 0xff);
894 }
895 else if (type == GL_UNSIGNED_SHORT) {
896 start = MIN2(start, 0xffff);
897 end = MIN2(end, 0xffff);
898 }
899
900 if (end >= ctx->Array.ArrayObj->_MaxElement) {
901 /* the max element is out of bounds of one or more enabled arrays */
902 warnCount++;
903
904 if (warnCount < 10) {
905 _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
906 "type 0x%x, indices=%p)\n"
907 "\tend is out of bounds (max=%u) "
908 "Element Buffer %u (size %d)\n"
909 "\tThis should probably be fixed in the application.",
910 start, end, count, type, indices,
911 ctx->Array.ArrayObj->_MaxElement - 1,
912 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
913 (int) ctx->Array.ArrayObj->ElementArrayBufferObj->Size);
914 }
915
916 if (0)
917 dump_element_buffer(ctx, type);
918
919 if (0)
920 _mesa_print_arrays(ctx);
921
922 /* 'end' was out of bounds, but now let's check the actual array
923 * indexes to see if any of them are out of bounds.
924 */
925 if (0) {
926 GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
927 ctx->Array.ArrayObj->ElementArrayBufferObj);
928 if (max >= ctx->Array.ArrayObj->_MaxElement) {
929 if (warnCount < 10) {
930 _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
931 "count %d, type 0x%x, indices=%p)\n"
932 "\tindex=%u is out of bounds (max=%u) "
933 "Element Buffer %u (size %d)\n"
934 "\tSkipping the glDrawRangeElements() call",
935 start, end, count, type, indices, max,
936 ctx->Array.ArrayObj->_MaxElement - 1,
937 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
938 (int) ctx->Array.ArrayObj->ElementArrayBufferObj->Size);
939 }
940 }
941 /* XXX we could also find the min index and compare to 'start'
942 * to see if start is correct. But it's more likely to get the
943 * upper bound wrong.
944 */
945 }
946
947 /* Set 'end' to the max possible legal value */
948 assert(ctx->Array.ArrayObj->_MaxElement >= 1);
949 end = ctx->Array.ArrayObj->_MaxElement - 1;
950
951 if (end < start) {
952 return;
953 }
954 }
955
956 if (0) {
957 printf("glDraw[Range]Elements{,BaseVertex}"
958 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
959 "base %d\n",
960 start, end, type, count,
961 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
962 basevertex);
963 }
964
965 #if 0
966 check_draw_elements_data(ctx, count, type, indices);
967 #else
968 (void) check_draw_elements_data;
969 #endif
970
971 vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
972 count, type, indices, basevertex, 1);
973 }
974
975
976 /**
977 * Called by glDrawRangeElements() in immediate mode.
978 */
979 static void GLAPIENTRY
980 vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
981 GLsizei count, GLenum type, const GLvoid *indices)
982 {
983 if (MESA_VERBOSE & VERBOSE_DRAW) {
984 GET_CURRENT_CONTEXT(ctx);
985 _mesa_debug(ctx,
986 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
987 _mesa_lookup_enum_by_nr(mode), start, end, count,
988 _mesa_lookup_enum_by_nr(type), indices);
989 }
990
991 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
992 indices, 0);
993 }
994
995
996 /**
997 * Called by glDrawElements() in immediate mode.
998 */
999 static void GLAPIENTRY
1000 vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
1001 const GLvoid *indices)
1002 {
1003 GET_CURRENT_CONTEXT(ctx);
1004
1005 if (MESA_VERBOSE & VERBOSE_DRAW)
1006 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1007 _mesa_lookup_enum_by_nr(mode), count,
1008 _mesa_lookup_enum_by_nr(type), indices);
1009
1010 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
1011 return;
1012
1013 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1014 count, type, indices, 0, 1);
1015 }
1016
1017
1018 /**
1019 * Called by glDrawElementsBaseVertex() in immediate mode.
1020 */
1021 static void GLAPIENTRY
1022 vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1023 const GLvoid *indices, GLint basevertex)
1024 {
1025 GET_CURRENT_CONTEXT(ctx);
1026
1027 if (MESA_VERBOSE & VERBOSE_DRAW)
1028 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
1029 _mesa_lookup_enum_by_nr(mode), count,
1030 _mesa_lookup_enum_by_nr(type), indices, basevertex);
1031
1032 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
1033 basevertex ))
1034 return;
1035
1036 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1037 count, type, indices, basevertex, 1);
1038 }
1039
1040
1041 /**
1042 * Called by glDrawElementsInstanced() in immediate mode.
1043 */
1044 static void GLAPIENTRY
1045 vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1046 const GLvoid *indices, GLsizei numInstances)
1047 {
1048 GET_CURRENT_CONTEXT(ctx);
1049
1050 if (MESA_VERBOSE & VERBOSE_DRAW)
1051 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
1052 _mesa_lookup_enum_by_nr(mode), count,
1053 _mesa_lookup_enum_by_nr(type), indices, numInstances);
1054
1055 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1056 numInstances, 0))
1057 return;
1058
1059 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1060 count, type, indices, 0, numInstances);
1061 }
1062
1063 /**
1064 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1065 */
1066 static void GLAPIENTRY
1067 vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1068 const GLvoid *indices, GLsizei numInstances,
1069 GLint basevertex)
1070 {
1071 GET_CURRENT_CONTEXT(ctx);
1072
1073 if (MESA_VERBOSE & VERBOSE_DRAW)
1074 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1075 _mesa_lookup_enum_by_nr(mode), count,
1076 _mesa_lookup_enum_by_nr(type), indices,
1077 numInstances, basevertex);
1078
1079 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1080 numInstances, basevertex))
1081 return;
1082
1083 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1084 count, type, indices, basevertex, numInstances);
1085 }
1086
1087
1088 /**
1089 * Inner support for both _mesa_MultiDrawElements() and
1090 * _mesa_MultiDrawRangeElements().
1091 * This does the actual rendering after we've checked array indexes, etc.
1092 */
1093 static void
1094 vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1095 const GLsizei *count, GLenum type,
1096 const GLvoid **indices, GLsizei primcount,
1097 const GLint *basevertex)
1098 {
1099 struct vbo_context *vbo = vbo_context(ctx);
1100 struct vbo_exec_context *exec = &vbo->exec;
1101 struct _mesa_index_buffer ib;
1102 struct _mesa_prim *prim;
1103 unsigned int index_type_size = 0;
1104 uintptr_t min_index_ptr, max_index_ptr;
1105 GLboolean fallback = GL_FALSE;
1106 int i;
1107
1108 if (primcount == 0)
1109 return;
1110
1111 FLUSH_CURRENT( ctx, 0 );
1112
1113 if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
1114 return;
1115 }
1116
1117 prim = calloc(1, primcount * sizeof(*prim));
1118 if (prim == NULL) {
1119 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1120 return;
1121 }
1122
1123 /* Decide if we can do this all as one set of primitives sharing the
1124 * same index buffer, or if we have to reset the index pointer per
1125 * primitive.
1126 */
1127 vbo_bind_arrays( ctx );
1128
1129 /* check for dirty state again */
1130 if (ctx->NewState)
1131 _mesa_update_state( ctx );
1132
1133 switch (type) {
1134 case GL_UNSIGNED_INT:
1135 index_type_size = 4;
1136 break;
1137 case GL_UNSIGNED_SHORT:
1138 index_type_size = 2;
1139 break;
1140 case GL_UNSIGNED_BYTE:
1141 index_type_size = 1;
1142 break;
1143 default:
1144 assert(0);
1145 }
1146
1147 min_index_ptr = (uintptr_t)indices[0];
1148 max_index_ptr = 0;
1149 for (i = 0; i < primcount; i++) {
1150 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1151 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1152 index_type_size * count[i]);
1153 }
1154
1155 /* Check if we can handle this thing as a bunch of index offsets from the
1156 * same index pointer. If we can't, then we have to fall back to doing
1157 * a draw_prims per primitive.
1158 * Check that the difference between each prim's indexes is a multiple of
1159 * the index/element size.
1160 */
1161 if (index_type_size != 1) {
1162 for (i = 0; i < primcount; i++) {
1163 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1164 fallback = GL_TRUE;
1165 break;
1166 }
1167 }
1168 }
1169
1170 /* If the index buffer isn't in a VBO, then treating the application's
1171 * subranges of the index buffer as one large index buffer may lead to
1172 * us reading unmapped memory.
1173 */
1174 if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
1175 fallback = GL_TRUE;
1176
1177 if (!fallback) {
1178 ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1179 ib.type = type;
1180 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1181 ib.ptr = (void *)min_index_ptr;
1182
1183 for (i = 0; i < primcount; i++) {
1184 prim[i].begin = (i == 0);
1185 prim[i].end = (i == primcount - 1);
1186 prim[i].weak = 0;
1187 prim[i].pad = 0;
1188 prim[i].mode = mode;
1189 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1190 prim[i].count = count[i];
1191 prim[i].indexed = 1;
1192 prim[i].num_instances = 1;
1193 if (basevertex != NULL)
1194 prim[i].basevertex = basevertex[i];
1195 else
1196 prim[i].basevertex = 0;
1197 }
1198
1199 check_buffers_are_unmapped(exec->array.inputs);
1200 vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
1201 GL_FALSE, ~0, ~0);
1202 } else {
1203 /* render one prim at a time */
1204 for (i = 0; i < primcount; i++) {
1205 ib.count = count[i];
1206 ib.type = type;
1207 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1208 ib.ptr = indices[i];
1209
1210 prim[0].begin = 1;
1211 prim[0].end = 1;
1212 prim[0].weak = 0;
1213 prim[0].pad = 0;
1214 prim[0].mode = mode;
1215 prim[0].start = 0;
1216 prim[0].count = count[i];
1217 prim[0].indexed = 1;
1218 prim[0].num_instances = 1;
1219 if (basevertex != NULL)
1220 prim[0].basevertex = basevertex[i];
1221 else
1222 prim[0].basevertex = 0;
1223
1224 check_buffers_are_unmapped(exec->array.inputs);
1225 vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
1226 GL_FALSE, ~0, ~0);
1227 }
1228 }
1229
1230 free(prim);
1231 }
1232
1233
1234 static void GLAPIENTRY
1235 vbo_exec_MultiDrawElements(GLenum mode,
1236 const GLsizei *count, GLenum type,
1237 const GLvoid **indices,
1238 GLsizei primcount)
1239 {
1240 GET_CURRENT_CONTEXT(ctx);
1241 GLint i;
1242
1243 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1244
1245 for (i = 0; i < primcount; i++) {
1246 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1247 0))
1248 return;
1249 }
1250
1251 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1252 NULL);
1253 }
1254
1255
1256 static void GLAPIENTRY
1257 vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1258 const GLsizei *count, GLenum type,
1259 const GLvoid **indices,
1260 GLsizei primcount,
1261 const GLsizei *basevertex)
1262 {
1263 GET_CURRENT_CONTEXT(ctx);
1264 GLint i;
1265
1266 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1267
1268 for (i = 0; i < primcount; i++) {
1269 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1270 basevertex[i]))
1271 return;
1272 }
1273
1274 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1275 basevertex);
1276 }
1277
1278
1279 /**
1280 * Plug in the immediate-mode vertex array drawing commands into the
1281 * givven vbo_exec_context object.
1282 */
1283 void
1284 vbo_exec_array_init( struct vbo_exec_context *exec )
1285 {
1286 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
1287 exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
1288 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
1289 exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
1290 exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
1291 exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
1292 exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
1293 exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
1294 exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
1295 exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex;
1296 }
1297
1298
1299 void
1300 vbo_exec_array_destroy( struct vbo_exec_context *exec )
1301 {
1302 /* nothing to do */
1303 }
1304
1305
1306
1307 /**
1308 * The following functions are only used for OpenGL ES 1/2 support.
1309 * And some aren't even supported (yet) in ES 1/2.
1310 */
1311
1312
1313 void GLAPIENTRY
1314 _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1315 {
1316 vbo_exec_DrawArrays(mode, first, count);
1317 }
1318
1319
1320 void GLAPIENTRY
1321 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1322 const GLvoid *indices)
1323 {
1324 vbo_exec_DrawElements(mode, count, type, indices);
1325 }
1326
1327
1328 void GLAPIENTRY
1329 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1330 const GLvoid *indices, GLint basevertex)
1331 {
1332 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1333 }
1334
1335
1336 void GLAPIENTRY
1337 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1338 GLenum type, const GLvoid *indices)
1339 {
1340 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1341 }
1342
1343
1344 void GLAPIENTRY
1345 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1346 GLsizei count, GLenum type,
1347 const GLvoid *indices, GLint basevertex)
1348 {
1349 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1350 indices, basevertex);
1351 }
1352
1353
1354 void GLAPIENTRY
1355 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1356 const GLvoid **indices, GLsizei primcount)
1357 {
1358 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1359 }
1360
1361
1362 void GLAPIENTRY
1363 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
1364 const GLsizei *count, GLenum type,
1365 const GLvoid **indices, GLsizei primcount,
1366 const GLint *basevertex)
1367 {
1368 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1369 primcount, basevertex);
1370 }