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