mesa: don't unroll glMultiDrawElements with user indices for gallium
[mesa.git] / src / mesa / main / draw.c
1 /**************************************************************************
2 *
3 * Copyright 2003 VMware, Inc.
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 VMWARE 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 <stdio.h>
30 #include "arrayobj.h"
31 #include "glheader.h"
32 #include "c99_alloca.h"
33 #include "context.h"
34 #include "state.h"
35 #include "draw.h"
36 #include "draw_validate.h"
37 #include "dispatch.h"
38 #include "varray.h"
39 #include "bufferobj.h"
40 #include "enums.h"
41 #include "macros.h"
42 #include "transformfeedback.h"
43
44 typedef struct {
45 GLuint count;
46 GLuint primCount;
47 GLuint first;
48 GLuint baseInstance;
49 } DrawArraysIndirectCommand;
50
51 typedef struct {
52 GLuint count;
53 GLuint primCount;
54 GLuint firstIndex;
55 GLint baseVertex;
56 GLuint baseInstance;
57 } DrawElementsIndirectCommand;
58
59
60 /**
61 * Check that element 'j' of the array has reasonable data.
62 * Map VBO if needed.
63 * For debugging purposes; not normally used.
64 */
65 static void
66 check_array_data(struct gl_context *ctx, struct gl_vertex_array_object *vao,
67 GLuint attrib, GLuint j)
68 {
69 const struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
70 if (vao->Enabled & VERT_BIT(attrib)) {
71 const struct gl_vertex_buffer_binding *binding =
72 &vao->BufferBinding[array->BufferBindingIndex];
73 struct gl_buffer_object *bo = binding->BufferObj;
74 const void *data = array->Ptr;
75 if (_mesa_is_bufferobj(bo)) {
76 data = ADD_POINTERS(_mesa_vertex_attrib_address(array, binding),
77 bo->Mappings[MAP_INTERNAL].Pointer);
78 }
79 switch (array->Format.Type) {
80 case GL_FLOAT:
81 {
82 GLfloat *f = (GLfloat *) ((GLubyte *) data + binding->Stride * j);
83 GLint k;
84 for (k = 0; k < array->Format.Size; k++) {
85 if (IS_INF_OR_NAN(f[k]) || f[k] >= 1.0e20F || f[k] <= -1.0e10F) {
86 printf("Bad array data:\n");
87 printf(" Element[%u].%u = %f\n", j, k, f[k]);
88 printf(" Array %u at %p\n", attrib, (void *) array);
89 printf(" Type 0x%x, Size %d, Stride %d\n",
90 array->Format.Type, array->Format.Size,
91 binding->Stride);
92 printf(" Address/offset %p in Buffer Object %u\n",
93 array->Ptr, bo->Name);
94 f[k] = 1.0F; /* XXX replace the bad value! */
95 }
96 /*assert(!IS_INF_OR_NAN(f[k])); */
97 }
98 }
99 break;
100 default:
101 ;
102 }
103 }
104 }
105
106
107 static inline void
108 get_index_size(GLenum type, struct _mesa_index_buffer *ib)
109 {
110 /* The type is already validated, so use a fast conversion.
111 *
112 * GL_UNSIGNED_BYTE - GL_UNSIGNED_BYTE = 0
113 * GL_UNSIGNED_SHORT - GL_UNSIGNED_BYTE = 2
114 * GL_UNSIGNED_INT - GL_UNSIGNED_BYTE = 4
115 *
116 * Divide by 2 to get 0,1,2.
117 */
118 ib->index_size_shift = (type - GL_UNSIGNED_BYTE) >> 1;
119 }
120
121 /**
122 * Examine the array's data for NaNs, etc.
123 * For debug purposes; not normally used.
124 */
125 static void
126 check_draw_elements_data(struct gl_context *ctx, GLsizei count,
127 GLenum elemType, const void *elements,
128 GLint basevertex)
129 {
130 struct gl_vertex_array_object *vao = ctx->Array.VAO;
131 GLint i;
132 GLuint k;
133
134 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
135
136 if (_mesa_is_bufferobj(vao->IndexBufferObj))
137 elements =
138 ADD_POINTERS(vao->IndexBufferObj->Mappings[MAP_INTERNAL].Pointer, elements);
139
140 for (i = 0; i < count; i++) {
141 GLuint j;
142
143 /* j = element[i] */
144 switch (elemType) {
145 case GL_UNSIGNED_BYTE:
146 j = ((const GLubyte *) elements)[i];
147 break;
148 case GL_UNSIGNED_SHORT:
149 j = ((const GLushort *) elements)[i];
150 break;
151 case GL_UNSIGNED_INT:
152 j = ((const GLuint *) elements)[i];
153 break;
154 default:
155 unreachable("Unexpected index buffer type");
156 }
157
158 /* check element j of each enabled array */
159 for (k = 0; k < VERT_ATTRIB_MAX; k++) {
160 check_array_data(ctx, vao, k, j);
161 }
162 }
163
164 _mesa_vao_unmap(ctx, vao);
165 }
166
167
168 /**
169 * Check array data, looking for NaNs, etc.
170 */
171 static void
172 check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
173 {
174 /* TO DO */
175 }
176
177
178 /**
179 * Check if we should skip the draw call even after validation was successful.
180 */
181 static bool
182 skip_validated_draw(struct gl_context *ctx)
183 {
184 switch (ctx->API) {
185 case API_OPENGLES2:
186 /* For ES2, we can draw if we have a vertex program/shader). */
187 return ctx->VertexProgram._Current == NULL;
188
189 case API_OPENGLES:
190 /* For OpenGL ES, only draw if we have vertex positions
191 */
192 if (!(ctx->Array.VAO->Enabled & VERT_BIT_POS))
193 return true;
194 break;
195
196 case API_OPENGL_CORE:
197 /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec
198 * says:
199 *
200 * "If there is no active program for the vertex or fragment shader
201 * stages, the results of vertex and/or fragment processing will be
202 * undefined. However, this is not an error."
203 *
204 * The fragment shader is not tested here because other state (e.g.,
205 * GL_RASTERIZER_DISCARD) affects whether or not we actually care.
206 */
207 return ctx->VertexProgram._Current == NULL;
208
209 case API_OPENGL_COMPAT:
210 if (ctx->VertexProgram._Current != NULL) {
211 /* Draw regardless of whether or not we have any vertex arrays.
212 * (Ex: could draw a point using a constant vertex pos)
213 */
214 return false;
215 } else {
216 /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic
217 * array [0]).
218 */
219 return !(ctx->Array.VAO->Enabled & (VERT_BIT_POS|VERT_BIT_GENERIC0));
220 }
221 break;
222
223 default:
224 unreachable("Invalid API value in check_valid_to_render()");
225 }
226
227 return false;
228 }
229
230
231 /**
232 * Print info/data for glDrawArrays(), for debugging.
233 */
234 static void
235 print_draw_arrays(struct gl_context *ctx,
236 GLenum mode, GLint start, GLsizei count)
237 {
238 struct gl_vertex_array_object *vao = ctx->Array.VAO;
239
240 printf("_mesa_DrawArrays(mode 0x%x, start %d, count %d):\n",
241 mode, start, count);
242
243 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
244
245 GLbitfield mask = vao->Enabled;
246 while (mask) {
247 const gl_vert_attrib i = u_bit_scan(&mask);
248 const struct gl_array_attributes *array = &vao->VertexAttrib[i];
249
250 const struct gl_vertex_buffer_binding *binding =
251 &vao->BufferBinding[array->BufferBindingIndex];
252 struct gl_buffer_object *bufObj = binding->BufferObj;
253
254 printf("attr %s: size %d stride %d "
255 "ptr %p Bufobj %u\n",
256 gl_vert_attrib_name((gl_vert_attrib) i),
257 array->Format.Size, binding->Stride,
258 array->Ptr, bufObj->Name);
259
260 if (_mesa_is_bufferobj(bufObj)) {
261 GLubyte *p = bufObj->Mappings[MAP_INTERNAL].Pointer;
262 int offset = (int) (GLintptr)
263 _mesa_vertex_attrib_address(array, binding);
264
265 unsigned multiplier;
266 switch (array->Format.Type) {
267 case GL_DOUBLE:
268 case GL_INT64_ARB:
269 case GL_UNSIGNED_INT64_ARB:
270 multiplier = 2;
271 break;
272 default:
273 multiplier = 1;
274 }
275
276 float *f = (float *) (p + offset);
277 int *k = (int *) f;
278 int i = 0;
279 int n = (count - 1) * (binding->Stride / (4 * multiplier))
280 + array->Format.Size;
281 if (n > 32)
282 n = 32;
283 printf(" Data at offset %d:\n", offset);
284 do {
285 if (multiplier == 2)
286 printf(" double[%d] = 0x%016llx %lf\n", i,
287 ((unsigned long long *) k)[i], ((double *) f)[i]);
288 else
289 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
290 i++;
291 } while (i < n);
292 }
293 }
294
295 _mesa_vao_unmap_arrays(ctx, vao);
296 }
297
298
299 /**
300 * Return a filter mask for the net enabled vao arrays.
301 * This is to mask out arrays that would otherwise supersed required current
302 * values for the fixed function shaders for example.
303 */
304 static GLbitfield
305 enabled_filter(const struct gl_context *ctx)
306 {
307 switch (ctx->VertexProgram._VPMode) {
308 case VP_MODE_FF:
309 /* When no vertex program is active (or the vertex program is generated
310 * from fixed-function state). We put the material values into the
311 * generic slots. Since the vao has no material arrays, mute these
312 * slots from the enabled arrays so that the current material values
313 * are pulled instead of the vao arrays.
314 */
315 return VERT_BIT_FF_ALL;
316
317 case VP_MODE_SHADER:
318 /* There are no shaders in OpenGL ES 1.x, so this code path should be
319 * impossible to reach. The meta code is careful to not use shaders in
320 * ES1.
321 */
322 assert(ctx->API != API_OPENGLES);
323
324 /* Other parts of the code assume that inputs[VERT_ATTRIB_POS] through
325 * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL. However, in OpenGL
326 * ES 2.0+ or OpenGL core profile, none of these arrays should ever
327 * be enabled.
328 */
329 if (ctx->API != API_OPENGL_COMPAT)
330 return VERT_BIT_GENERIC_ALL;
331
332 return VERT_BIT_ALL;
333
334 default:
335 assert(0);
336 return 0;
337 }
338 }
339
340
341 /**
342 * Helper function called by the other DrawArrays() functions below.
343 * This is where we handle primitive restart for drawing non-indexed
344 * arrays. If primitive restart is enabled, it typically means
345 * splitting one DrawArrays() into two.
346 */
347 static void
348 _mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
349 GLsizei count, GLuint numInstances, GLuint baseInstance,
350 GLuint drawID)
351 {
352 if (skip_validated_draw(ctx))
353 return;
354
355 /* OpenGL 4.5 says that primitive restart is ignored with non-indexed
356 * draws.
357 */
358 struct _mesa_prim prim = {
359 .begin = 1,
360 .end = 1,
361 .mode = mode,
362 .draw_id = drawID,
363 .start = start,
364 .count = count,
365 };
366
367 ctx->Driver.Draw(ctx, &prim, 1, NULL,
368 GL_TRUE, start, start + count - 1,
369 numInstances, baseInstance, NULL, 0);
370
371 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
372 _mesa_flush(ctx);
373 }
374 }
375
376
377 /**
378 * Execute a glRectf() function.
379 */
380 static void GLAPIENTRY
381 _mesa_exec_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
382 {
383 GET_CURRENT_CONTEXT(ctx);
384 ASSERT_OUTSIDE_BEGIN_END(ctx);
385
386 CALL_Begin(GET_DISPATCH(), (GL_QUADS));
387 CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
388 CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
389 CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
390 CALL_Vertex2f(GET_DISPATCH(), (x1, y2));
391 CALL_End(GET_DISPATCH(), ());
392 }
393
394
395 static void GLAPIENTRY
396 _mesa_exec_EvalMesh1(GLenum mode, GLint i1, GLint i2)
397 {
398 GET_CURRENT_CONTEXT(ctx);
399 GLint i;
400 GLfloat u, du;
401 GLenum prim;
402
403 switch (mode) {
404 case GL_POINT:
405 prim = GL_POINTS;
406 break;
407 case GL_LINE:
408 prim = GL_LINE_STRIP;
409 break;
410 default:
411 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)");
412 return;
413 }
414
415 /* No effect if vertex maps disabled.
416 */
417 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
418 return;
419
420 du = ctx->Eval.MapGrid1du;
421 u = ctx->Eval.MapGrid1u1 + i1 * du;
422
423 CALL_Begin(GET_DISPATCH(), (prim));
424 for (i = i1; i <= i2; i++, u += du) {
425 CALL_EvalCoord1f(GET_DISPATCH(), (u));
426 }
427 CALL_End(GET_DISPATCH(), ());
428 }
429
430
431 static void GLAPIENTRY
432 _mesa_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
433 {
434 GET_CURRENT_CONTEXT(ctx);
435 GLfloat u, du, v, dv, v1, u1;
436 GLint i, j;
437
438 switch (mode) {
439 case GL_POINT:
440 case GL_LINE:
441 case GL_FILL:
442 break;
443 default:
444 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)");
445 return;
446 }
447
448 /* No effect if vertex maps disabled.
449 */
450 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
451 return;
452
453 du = ctx->Eval.MapGrid2du;
454 dv = ctx->Eval.MapGrid2dv;
455 v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
456 u1 = ctx->Eval.MapGrid2u1 + i1 * du;
457
458 switch (mode) {
459 case GL_POINT:
460 CALL_Begin(GET_DISPATCH(), (GL_POINTS));
461 for (v = v1, j = j1; j <= j2; j++, v += dv) {
462 for (u = u1, i = i1; i <= i2; i++, u += du) {
463 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
464 }
465 }
466 CALL_End(GET_DISPATCH(), ());
467 break;
468 case GL_LINE:
469 for (v = v1, j = j1; j <= j2; j++, v += dv) {
470 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
471 for (u = u1, i = i1; i <= i2; i++, u += du) {
472 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
473 }
474 CALL_End(GET_DISPATCH(), ());
475 }
476 for (u = u1, i = i1; i <= i2; i++, u += du) {
477 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
478 for (v = v1, j = j1; j <= j2; j++, v += dv) {
479 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
480 }
481 CALL_End(GET_DISPATCH(), ());
482 }
483 break;
484 case GL_FILL:
485 for (v = v1, j = j1; j < j2; j++, v += dv) {
486 CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
487 for (u = u1, i = i1; i <= i2; i++, u += du) {
488 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
489 CALL_EvalCoord2f(GET_DISPATCH(), (u, v + dv));
490 }
491 CALL_End(GET_DISPATCH(), ());
492 }
493 break;
494 }
495 }
496
497
498 /**
499 * Called from glDrawArrays when in immediate mode (not display list mode).
500 */
501 void GLAPIENTRY
502 _mesa_DrawArrays(GLenum mode, GLint start, GLsizei count)
503 {
504 GET_CURRENT_CONTEXT(ctx);
505
506 if (MESA_VERBOSE & VERBOSE_DRAW)
507 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
508 _mesa_enum_to_string(mode), start, count);
509
510 FLUSH_FOR_DRAW(ctx);
511
512 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
513
514 if (_mesa_is_no_error_enabled(ctx)) {
515 if (ctx->NewState)
516 _mesa_update_state(ctx);
517 } else {
518 if (!_mesa_validate_DrawArrays(ctx, mode, count))
519 return;
520 }
521
522 if (0)
523 check_draw_arrays_data(ctx, start, count);
524
525 _mesa_draw_arrays(ctx, mode, start, count, 1, 0, 0);
526
527 if (0)
528 print_draw_arrays(ctx, mode, start, count);
529 }
530
531
532 /**
533 * Called from glDrawArraysInstanced when in immediate mode (not
534 * display list mode).
535 */
536 void GLAPIENTRY
537 _mesa_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
538 GLsizei numInstances)
539 {
540 GET_CURRENT_CONTEXT(ctx);
541
542 if (MESA_VERBOSE & VERBOSE_DRAW)
543 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
544 _mesa_enum_to_string(mode), start, count, numInstances);
545
546 FLUSH_FOR_DRAW(ctx);
547
548 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
549
550 if (_mesa_is_no_error_enabled(ctx)) {
551 if (ctx->NewState)
552 _mesa_update_state(ctx);
553 } else {
554 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count,
555 numInstances))
556 return;
557 }
558
559 if (0)
560 check_draw_arrays_data(ctx, start, count);
561
562 _mesa_draw_arrays(ctx, mode, start, count, numInstances, 0, 0);
563
564 if (0)
565 print_draw_arrays(ctx, mode, start, count);
566 }
567
568
569 /**
570 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
571 */
572 static void GLAPIENTRY
573 _mesa_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
574 GLsizei count, GLsizei numInstances,
575 GLuint baseInstance)
576 {
577 GET_CURRENT_CONTEXT(ctx);
578
579 if (MESA_VERBOSE & VERBOSE_DRAW)
580 _mesa_debug(ctx,
581 "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
582 _mesa_enum_to_string(mode), first, count,
583 numInstances, baseInstance);
584
585 FLUSH_FOR_DRAW(ctx);
586
587 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
588
589 if (_mesa_is_no_error_enabled(ctx)) {
590 if (ctx->NewState)
591 _mesa_update_state(ctx);
592 } else {
593 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
594 numInstances))
595 return;
596 }
597
598 if (0)
599 check_draw_arrays_data(ctx, first, count);
600
601 _mesa_draw_arrays(ctx, mode, first, count, numInstances, baseInstance, 0);
602
603 if (0)
604 print_draw_arrays(ctx, mode, first, count);
605 }
606
607
608 #define MAX_ALLOCA_PRIMS (50000 / sizeof(*prim))
609
610 /* Use calloc for large allocations and alloca for small allocations. */
611 /* We have to use a macro because alloca is local within the function. */
612 #define ALLOC_PRIMS(prim, primcount, func) do { \
613 if (unlikely(primcount > MAX_ALLOCA_PRIMS)) { \
614 prim = calloc(primcount, sizeof(*prim)); \
615 if (!prim) { \
616 _mesa_error(ctx, GL_OUT_OF_MEMORY, func); \
617 return; \
618 } \
619 } else { \
620 prim = alloca(primcount * sizeof(*prim)); \
621 } \
622 } while (0)
623
624 #define FREE_PRIMS(prim, primcount) do { \
625 if (primcount > MAX_ALLOCA_PRIMS) \
626 free(prim); \
627 } while (0)
628
629
630 /**
631 * Called from glMultiDrawArrays when in immediate mode.
632 */
633 static void GLAPIENTRY
634 _mesa_exec_MultiDrawArrays(GLenum mode, const GLint *first,
635 const GLsizei *count, GLsizei primcount)
636 {
637 GET_CURRENT_CONTEXT(ctx);
638 GLint i;
639
640 if (MESA_VERBOSE & VERBOSE_DRAW)
641 _mesa_debug(ctx,
642 "glMultiDrawArrays(%s, %p, %p, %d)\n",
643 _mesa_enum_to_string(mode), first, count, primcount);
644
645 FLUSH_FOR_DRAW(ctx);
646
647 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
648
649 if (_mesa_is_no_error_enabled(ctx)) {
650 if (ctx->NewState)
651 _mesa_update_state(ctx);
652 } else {
653 if (!_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount))
654 return;
655 }
656
657 if (skip_validated_draw(ctx))
658 return;
659
660 struct _mesa_prim *prim;
661
662 ALLOC_PRIMS(prim, primcount, "glMultiDrawElements");
663
664 for (i = 0; i < primcount; i++) {
665 prim[i].begin = 1;
666 prim[i].end = 1;
667 prim[i].mode = mode;
668 prim[i].draw_id = i;
669 prim[i].start = first[i];
670 prim[i].count = count[i];
671 prim[i].basevertex = 0;
672 }
673
674 ctx->Driver.Draw(ctx, prim, primcount, NULL, GL_FALSE, 0, 0, 1, 0,
675 NULL, 0);
676
677 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
678 _mesa_flush(ctx);
679
680 FREE_PRIMS(prim, primcount);
681 }
682
683
684
685 /**
686 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
687 * For debugging.
688 */
689 #if 0
690 static void
691 dump_element_buffer(struct gl_context *ctx, GLenum type)
692 {
693 const GLvoid *map =
694 ctx->Driver.MapBufferRange(ctx, 0,
695 ctx->Array.VAO->IndexBufferObj->Size,
696 GL_MAP_READ_BIT,
697 ctx->Array.VAO->IndexBufferObj,
698 MAP_INTERNAL);
699 switch (type) {
700 case GL_UNSIGNED_BYTE:
701 {
702 const GLubyte *us = (const GLubyte *) map;
703 GLint i;
704 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) {
705 printf("%02x ", us[i]);
706 if (i % 32 == 31)
707 printf("\n");
708 }
709 printf("\n");
710 }
711 break;
712 case GL_UNSIGNED_SHORT:
713 {
714 const GLushort *us = (const GLushort *) map;
715 GLint i;
716 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) {
717 printf("%04x ", us[i]);
718 if (i % 16 == 15)
719 printf("\n");
720 }
721 printf("\n");
722 }
723 break;
724 case GL_UNSIGNED_INT:
725 {
726 const GLuint *us = (const GLuint *) map;
727 GLint i;
728 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) {
729 printf("%08x ", us[i]);
730 if (i % 8 == 7)
731 printf("\n");
732 }
733 printf("\n");
734 }
735 break;
736 default:
737 ;
738 }
739
740 ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL);
741 }
742 #endif
743
744
745 static bool
746 skip_draw_elements(struct gl_context *ctx, GLsizei count,
747 const GLvoid *indices)
748 {
749 if (count == 0)
750 return true;
751
752 /* Not using a VBO for indices, so avoid NULL pointer derefs later.
753 */
754 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL)
755 return true;
756
757 if (skip_validated_draw(ctx))
758 return true;
759
760 return false;
761 }
762
763
764 /**
765 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
766 * Do the rendering for a glDrawElements or glDrawRangeElements call after
767 * we've validated buffer bounds, etc.
768 */
769 static void
770 _mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
771 GLboolean index_bounds_valid,
772 GLuint start, GLuint end,
773 GLsizei count, GLenum type,
774 const GLvoid * indices,
775 GLint basevertex, GLuint numInstances,
776 GLuint baseInstance)
777 {
778 struct _mesa_index_buffer ib;
779 struct _mesa_prim prim;
780
781 if (!index_bounds_valid) {
782 assert(start == 0u);
783 assert(end == ~0u);
784 }
785
786 if (skip_draw_elements(ctx, count, indices))
787 return;
788
789 ib.count = count;
790 ib.obj = ctx->Array.VAO->IndexBufferObj;
791 ib.ptr = indices;
792 get_index_size(type, &ib);
793
794 prim.begin = 1;
795 prim.end = 1;
796 prim.mode = mode;
797 prim.start = 0;
798 prim.count = count;
799 prim.basevertex = basevertex;
800 prim.draw_id = 0;
801
802 /* Need to give special consideration to rendering a range of
803 * indices starting somewhere above zero. Typically the
804 * application is issuing multiple DrawRangeElements() to draw
805 * successive primitives layed out linearly in the vertex arrays.
806 * Unless the vertex arrays are all in a VBO (or locked as with
807 * CVA), the OpenGL semantics imply that we need to re-read or
808 * re-upload the vertex data on each draw call.
809 *
810 * In the case of hardware tnl, we want to avoid starting the
811 * upload at zero, as it will mean every draw call uploads an
812 * increasing amount of not-used vertex data. Worse - in the
813 * software tnl module, all those vertices might be transformed and
814 * lit but never rendered.
815 *
816 * If we just upload or transform the vertices in start..end,
817 * however, the indices will be incorrect.
818 *
819 * At this level, we don't know exactly what the requirements of
820 * the backend are going to be, though it will likely boil down to
821 * either:
822 *
823 * 1) Do nothing, everything is in a VBO and is processed once
824 * only.
825 *
826 * 2) Adjust the indices and vertex arrays so that start becomes
827 * zero.
828 *
829 * Rather than doing anything here, I'll provide a helper function
830 * for the latter case elsewhere.
831 */
832
833 ctx->Driver.Draw(ctx, &prim, 1, &ib,
834 index_bounds_valid, start, end,
835 numInstances, baseInstance, NULL, 0);
836
837 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
838 _mesa_flush(ctx);
839 }
840 }
841
842
843 /**
844 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
845 */
846 void GLAPIENTRY
847 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
848 GLsizei count, GLenum type,
849 const GLvoid * indices, GLint basevertex)
850 {
851 static GLuint warnCount = 0;
852 GLboolean index_bounds_valid = GL_TRUE;
853
854 /* This is only useful to catch invalid values in the "end" parameter
855 * like ~0.
856 */
857 GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
858
859 GET_CURRENT_CONTEXT(ctx);
860
861 if (MESA_VERBOSE & VERBOSE_DRAW)
862 _mesa_debug(ctx,
863 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
864 _mesa_enum_to_string(mode), start, end, count,
865 _mesa_enum_to_string(type), indices, basevertex);
866
867 FLUSH_FOR_DRAW(ctx);
868
869 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
870
871 if (_mesa_is_no_error_enabled(ctx)) {
872 if (ctx->NewState)
873 _mesa_update_state(ctx);
874 } else {
875 if (!_mesa_validate_DrawRangeElements(ctx, mode, start, end, count,
876 type, indices))
877 return;
878 }
879
880 if ((int) end + basevertex < 0 || start + basevertex >= max_element) {
881 /* The application requested we draw using a range of indices that's
882 * outside the bounds of the current VBO. This is invalid and appears
883 * to give undefined results. The safest thing to do is to simply
884 * ignore the range, in case the application botched their range tracking
885 * but did provide valid indices. Also issue a warning indicating that
886 * the application is broken.
887 */
888 if (warnCount++ < 10) {
889 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
890 "basevertex %d, count %d, type 0x%x, indices=%p):\n"
891 "\trange is outside VBO bounds (max=%u); ignoring.\n"
892 "\tThis should be fixed in the application.",
893 start, end, basevertex, count, type, indices,
894 max_element - 1);
895 }
896 index_bounds_valid = GL_FALSE;
897 }
898
899 /* NOTE: It's important that 'end' is a reasonable value.
900 * in _tnl_draw_prims(), we use end to determine how many vertices
901 * to transform. If it's too large, we can unnecessarily split prims
902 * or we can read/write out of memory in several different places!
903 */
904
905 /* Catch/fix some potential user errors */
906 if (type == GL_UNSIGNED_BYTE) {
907 start = MIN2(start, 0xff);
908 end = MIN2(end, 0xff);
909 }
910 else if (type == GL_UNSIGNED_SHORT) {
911 start = MIN2(start, 0xffff);
912 end = MIN2(end, 0xffff);
913 }
914
915 if (0) {
916 printf("glDraw[Range]Elements{,BaseVertex}"
917 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
918 "base %d\n",
919 start, end, type, count,
920 ctx->Array.VAO->IndexBufferObj->Name, basevertex);
921 }
922
923 if ((int) start + basevertex < 0 || end + basevertex >= max_element)
924 index_bounds_valid = GL_FALSE;
925
926 #if 0
927 check_draw_elements_data(ctx, count, type, indices, basevertex);
928 #else
929 (void) check_draw_elements_data;
930 #endif
931
932 if (!index_bounds_valid) {
933 start = 0;
934 end = ~0;
935 }
936
937 _mesa_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
938 count, type, indices, basevertex, 1, 0);
939 }
940
941
942 /**
943 * Called by glDrawRangeElements() in immediate mode.
944 */
945 void GLAPIENTRY
946 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
947 GLsizei count, GLenum type, const GLvoid * indices)
948 {
949 if (MESA_VERBOSE & VERBOSE_DRAW) {
950 GET_CURRENT_CONTEXT(ctx);
951 _mesa_debug(ctx,
952 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
953 _mesa_enum_to_string(mode), start, end, count,
954 _mesa_enum_to_string(type), indices);
955 }
956
957 _mesa_DrawRangeElementsBaseVertex(mode, start, end, count, type,
958 indices, 0);
959 }
960
961
962 /**
963 * Called by glDrawElements() in immediate mode.
964 */
965 void GLAPIENTRY
966 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
967 const GLvoid * indices)
968 {
969 GET_CURRENT_CONTEXT(ctx);
970
971 if (MESA_VERBOSE & VERBOSE_DRAW)
972 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
973 _mesa_enum_to_string(mode), count,
974 _mesa_enum_to_string(type), indices);
975
976 FLUSH_FOR_DRAW(ctx);
977
978 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
979
980 if (_mesa_is_no_error_enabled(ctx)) {
981 if (ctx->NewState)
982 _mesa_update_state(ctx);
983 } else {
984 if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices))
985 return;
986 }
987
988 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
989 count, type, indices, 0, 1, 0);
990 }
991
992
993 /**
994 * Called by glDrawElementsBaseVertex() in immediate mode.
995 */
996 void GLAPIENTRY
997 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
998 const GLvoid * indices, GLint basevertex)
999 {
1000 GET_CURRENT_CONTEXT(ctx);
1001
1002 if (MESA_VERBOSE & VERBOSE_DRAW)
1003 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1004 _mesa_enum_to_string(mode), count,
1005 _mesa_enum_to_string(type), indices);
1006
1007 FLUSH_FOR_DRAW(ctx);
1008
1009 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1010
1011 if (_mesa_is_no_error_enabled(ctx)) {
1012 if (ctx->NewState)
1013 _mesa_update_state(ctx);
1014 } else {
1015 if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices))
1016 return;
1017 }
1018
1019 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1020 count, type, indices, basevertex, 1, 0);
1021 }
1022
1023
1024 /**
1025 * Called by glDrawElementsInstanced() in immediate mode.
1026 */
1027 static void GLAPIENTRY
1028 _mesa_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1029 const GLvoid * indices, GLsizei numInstances)
1030 {
1031 GET_CURRENT_CONTEXT(ctx);
1032
1033 if (MESA_VERBOSE & VERBOSE_DRAW)
1034 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1035 _mesa_enum_to_string(mode), count,
1036 _mesa_enum_to_string(type), indices);
1037
1038 FLUSH_FOR_DRAW(ctx);
1039
1040 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1041
1042 if (_mesa_is_no_error_enabled(ctx)) {
1043 if (ctx->NewState)
1044 _mesa_update_state(ctx);
1045 } else {
1046 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1047 indices, numInstances))
1048 return;
1049 }
1050
1051 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1052 count, type, indices, 0, numInstances, 0);
1053 }
1054
1055
1056 /**
1057 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1058 */
1059 static void GLAPIENTRY
1060 _mesa_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count,
1061 GLenum type, const GLvoid * indices,
1062 GLsizei numInstances,
1063 GLint basevertex)
1064 {
1065 GET_CURRENT_CONTEXT(ctx);
1066
1067 if (MESA_VERBOSE & VERBOSE_DRAW)
1068 _mesa_debug(ctx,
1069 "glDrawElementsInstancedBaseVertex"
1070 "(%s, %d, %s, %p, %d; %d)\n",
1071 _mesa_enum_to_string(mode), count,
1072 _mesa_enum_to_string(type), indices,
1073 numInstances, basevertex);
1074
1075 FLUSH_FOR_DRAW(ctx);
1076
1077 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1078
1079 if (_mesa_is_no_error_enabled(ctx)) {
1080 if (ctx->NewState)
1081 _mesa_update_state(ctx);
1082 } else {
1083 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1084 indices, numInstances))
1085 return;
1086 }
1087
1088 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1089 count, type, indices,
1090 basevertex, numInstances, 0);
1091 }
1092
1093
1094 /**
1095 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1096 */
1097 static void GLAPIENTRY
1098 _mesa_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,
1099 GLenum type,
1100 const GLvoid *indices,
1101 GLsizei numInstances,
1102 GLuint baseInstance)
1103 {
1104 GET_CURRENT_CONTEXT(ctx);
1105
1106 if (MESA_VERBOSE & VERBOSE_DRAW)
1107 _mesa_debug(ctx,
1108 "glDrawElementsInstancedBaseInstance"
1109 "(%s, %d, %s, %p, %d, %d)\n",
1110 _mesa_enum_to_string(mode), count,
1111 _mesa_enum_to_string(type), indices,
1112 numInstances, baseInstance);
1113
1114 FLUSH_FOR_DRAW(ctx);
1115
1116 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1117
1118 if (_mesa_is_no_error_enabled(ctx)) {
1119 if (ctx->NewState)
1120 _mesa_update_state(ctx);
1121 } else {
1122 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1123 indices, numInstances))
1124 return;
1125 }
1126
1127 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1128 count, type, indices, 0, numInstances,
1129 baseInstance);
1130 }
1131
1132
1133 /**
1134 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1135 */
1136 static void GLAPIENTRY
1137 _mesa_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
1138 GLsizei count,
1139 GLenum type,
1140 const GLvoid *indices,
1141 GLsizei numInstances,
1142 GLint basevertex,
1143 GLuint baseInstance)
1144 {
1145 GET_CURRENT_CONTEXT(ctx);
1146
1147 if (MESA_VERBOSE & VERBOSE_DRAW)
1148 _mesa_debug(ctx,
1149 "glDrawElementsInstancedBaseVertexBaseInstance"
1150 "(%s, %d, %s, %p, %d, %d, %d)\n",
1151 _mesa_enum_to_string(mode), count,
1152 _mesa_enum_to_string(type), indices,
1153 numInstances, basevertex, baseInstance);
1154
1155 FLUSH_FOR_DRAW(ctx);
1156
1157 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1158
1159 if (_mesa_is_no_error_enabled(ctx)) {
1160 if (ctx->NewState)
1161 _mesa_update_state(ctx);
1162 } else {
1163 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1164 indices, numInstances))
1165 return;
1166 }
1167
1168 _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1169 count, type, indices, basevertex,
1170 numInstances, baseInstance);
1171 }
1172
1173
1174 /**
1175 * Inner support for both _mesa_MultiDrawElements() and
1176 * _mesa_MultiDrawRangeElements().
1177 * This does the actual rendering after we've checked array indexes, etc.
1178 */
1179 static void
1180 _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1181 const GLsizei *count, GLenum type,
1182 const GLvoid * const *indices,
1183 GLsizei primcount, const GLint *basevertex)
1184 {
1185 struct _mesa_index_buffer ib;
1186 uintptr_t min_index_ptr, max_index_ptr;
1187 GLboolean fallback = GL_FALSE;
1188 int i;
1189
1190 if (primcount == 0)
1191 return;
1192
1193 get_index_size(type, &ib);
1194
1195 min_index_ptr = (uintptr_t) indices[0];
1196 max_index_ptr = 0;
1197 for (i = 0; i < primcount; i++) {
1198 min_index_ptr = MIN2(min_index_ptr, (uintptr_t) indices[i]);
1199 max_index_ptr = MAX2(max_index_ptr, (uintptr_t) indices[i] +
1200 (count[i] << ib.index_size_shift));
1201 }
1202
1203 /* Check if we can handle this thing as a bunch of index offsets from the
1204 * same index pointer. If we can't, then we have to fall back to doing
1205 * a draw_prims per primitive.
1206 * Check that the difference between each prim's indexes is a multiple of
1207 * the index/element size.
1208 */
1209 if (ib.index_size_shift) {
1210 for (i = 0; i < primcount; i++) {
1211 if ((((uintptr_t) indices[i] - min_index_ptr) &
1212 ((1 << ib.index_size_shift) - 1)) != 0) {
1213 fallback = GL_TRUE;
1214 break;
1215 }
1216 }
1217 }
1218
1219 if (ctx->Const.MultiDrawWithUserIndices) {
1220 /* Check whether prim[i].start would overflow. */
1221 if (((max_index_ptr - min_index_ptr) >> ib.index_size_shift) > UINT_MAX)
1222 fallback = GL_TRUE;
1223 } else {
1224 /* If the index buffer isn't in a VBO, then treating the application's
1225 * subranges of the index buffer as one large index buffer may lead to
1226 * us reading unmapped memory.
1227 */
1228 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj))
1229 fallback = GL_TRUE;
1230 }
1231
1232 if (!fallback) {
1233 struct _mesa_prim *prim;
1234
1235 ALLOC_PRIMS(prim, primcount, "glMultiDrawElements");
1236
1237 ib.count = (max_index_ptr - min_index_ptr) >> ib.index_size_shift;
1238 ib.obj = ctx->Array.VAO->IndexBufferObj;
1239 ib.ptr = (void *) min_index_ptr;
1240
1241 for (i = 0; i < primcount; i++) {
1242 prim[i].begin = 1;
1243 prim[i].end = 1;
1244 prim[i].mode = mode;
1245 prim[i].start =
1246 ((uintptr_t) indices[i] - min_index_ptr) >> ib.index_size_shift;
1247 prim[i].count = count[i];
1248 prim[i].draw_id = i;
1249 if (basevertex != NULL)
1250 prim[i].basevertex = basevertex[i];
1251 else
1252 prim[i].basevertex = 0;
1253 }
1254
1255 ctx->Driver.Draw(ctx, prim, primcount, &ib,
1256 false, 0, ~0, 1, 0, NULL, 0);
1257 FREE_PRIMS(prim, primcount);
1258 }
1259 else {
1260 /* render one prim at a time */
1261 for (i = 0; i < primcount; i++) {
1262 if (count[i] == 0)
1263 continue;
1264
1265 ib.count = count[i];
1266 ib.obj = ctx->Array.VAO->IndexBufferObj;
1267 ib.ptr = indices[i];
1268
1269 struct _mesa_prim prim;
1270 prim.begin = 1;
1271 prim.end = 1;
1272 prim.mode = mode;
1273 prim.start = 0;
1274 prim.count = count[i];
1275 prim.draw_id = i;
1276 if (basevertex != NULL)
1277 prim.basevertex = basevertex[i];
1278 else
1279 prim.basevertex = 0;
1280
1281 ctx->Driver.Draw(ctx, &prim, 1, &ib, false, 0, ~0, 1, 0, NULL, 0);
1282 }
1283 }
1284
1285 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1286 _mesa_flush(ctx);
1287 }
1288 }
1289
1290
1291 void GLAPIENTRY
1292 _mesa_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1293 const GLvoid * const *indices, GLsizei primcount)
1294 {
1295 GET_CURRENT_CONTEXT(ctx);
1296
1297 FLUSH_FOR_DRAW(ctx);
1298
1299 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1300
1301 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1302 primcount))
1303 return;
1304
1305 if (skip_validated_draw(ctx))
1306 return;
1307
1308 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1309 NULL);
1310 }
1311
1312
1313 void GLAPIENTRY
1314 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
1315 const GLsizei *count, GLenum type,
1316 const GLvoid * const *indices,
1317 GLsizei primcount,
1318 const GLsizei *basevertex)
1319 {
1320 GET_CURRENT_CONTEXT(ctx);
1321
1322 FLUSH_FOR_DRAW(ctx);
1323
1324 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1325
1326 if (_mesa_is_no_error_enabled(ctx)) {
1327 if (ctx->NewState)
1328 _mesa_update_state(ctx);
1329 } else {
1330 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1331 primcount))
1332 return;
1333 }
1334
1335 if (skip_validated_draw(ctx))
1336 return;
1337
1338 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1339 basevertex);
1340 }
1341
1342
1343 /**
1344 * Draw a GL primitive using a vertex count obtained from transform feedback.
1345 * \param mode the type of GL primitive to draw
1346 * \param obj the transform feedback object to use
1347 * \param stream index of the transform feedback stream from which to
1348 * get the primitive count.
1349 * \param numInstances number of instances to draw
1350 */
1351 static void
1352 _mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1353 struct gl_transform_feedback_object *obj,
1354 GLuint stream, GLuint numInstances)
1355 {
1356 struct _mesa_prim prim;
1357
1358 FLUSH_FOR_DRAW(ctx);
1359
1360 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1361
1362 if (_mesa_is_no_error_enabled(ctx)) {
1363 if (ctx->NewState)
1364 _mesa_update_state(ctx);
1365 } else {
1366 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
1367 numInstances)) {
1368 return;
1369 }
1370 }
1371
1372 if (ctx->Driver.GetTransformFeedbackVertexCount &&
1373 (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
1374 !_mesa_all_varyings_in_vbos(ctx->Array.VAO))) {
1375 GLsizei n =
1376 ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
1377 _mesa_draw_arrays(ctx, mode, 0, n, numInstances, 0, 0);
1378 return;
1379 }
1380
1381 if (skip_validated_draw(ctx))
1382 return;
1383
1384 /* init most fields to zero */
1385 memset(&prim, 0, sizeof(prim));
1386 prim.begin = 1;
1387 prim.end = 1;
1388 prim.mode = mode;
1389
1390 /* Maybe we should do some primitive splitting for primitive restart
1391 * (like in DrawArrays), but we have no way to know how many vertices
1392 * will be rendered. */
1393
1394 ctx->Driver.Draw(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, numInstances, 0,
1395 obj, stream);
1396
1397 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1398 _mesa_flush(ctx);
1399 }
1400 }
1401
1402
1403 /**
1404 * Like DrawArrays, but take the count from a transform feedback object.
1405 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1406 * \param name the transform feedback object
1407 * User still has to setup of the vertex attribute info with
1408 * glVertexPointer, glColorPointer, etc.
1409 * Part of GL_ARB_transform_feedback2.
1410 */
1411 void GLAPIENTRY
1412 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1413 {
1414 GET_CURRENT_CONTEXT(ctx);
1415 struct gl_transform_feedback_object *obj =
1416 _mesa_lookup_transform_feedback_object(ctx, name);
1417
1418 if (MESA_VERBOSE & VERBOSE_DRAW)
1419 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1420 _mesa_enum_to_string(mode), name);
1421
1422 _mesa_draw_transform_feedback(ctx, mode, obj, 0, 1);
1423 }
1424
1425
1426 static void GLAPIENTRY
1427 _mesa_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
1428 {
1429 GET_CURRENT_CONTEXT(ctx);
1430 struct gl_transform_feedback_object *obj =
1431 _mesa_lookup_transform_feedback_object(ctx, name);
1432
1433 if (MESA_VERBOSE & VERBOSE_DRAW)
1434 _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
1435 _mesa_enum_to_string(mode), name, stream);
1436
1437 _mesa_draw_transform_feedback(ctx, mode, obj, stream, 1);
1438 }
1439
1440
1441 static void GLAPIENTRY
1442 _mesa_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
1443 GLsizei primcount)
1444 {
1445 GET_CURRENT_CONTEXT(ctx);
1446 struct gl_transform_feedback_object *obj =
1447 _mesa_lookup_transform_feedback_object(ctx, name);
1448
1449 if (MESA_VERBOSE & VERBOSE_DRAW)
1450 _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
1451 _mesa_enum_to_string(mode), name);
1452
1453 _mesa_draw_transform_feedback(ctx, mode, obj, 0, primcount);
1454 }
1455
1456
1457 static void GLAPIENTRY
1458 _mesa_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
1459 GLuint stream,
1460 GLsizei primcount)
1461 {
1462 GET_CURRENT_CONTEXT(ctx);
1463 struct gl_transform_feedback_object *obj =
1464 _mesa_lookup_transform_feedback_object(ctx, name);
1465
1466 if (MESA_VERBOSE & VERBOSE_DRAW)
1467 _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
1468 "(%s, %u, %u, %i)\n",
1469 _mesa_enum_to_string(mode), name, stream, primcount);
1470
1471 _mesa_draw_transform_feedback(ctx, mode, obj, stream, primcount);
1472 }
1473
1474
1475 static void
1476 _mesa_validated_multidrawarraysindirect(struct gl_context *ctx, GLenum mode,
1477 GLintptr indirect,
1478 GLintptr drawcount_offset,
1479 GLsizei drawcount, GLsizei stride,
1480 struct gl_buffer_object *drawcount_buffer)
1481 {
1482 /* If drawcount_buffer is set, drawcount is the maximum draw count.*/
1483 if (drawcount == 0)
1484 return;
1485
1486 ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, indirect,
1487 drawcount, stride, drawcount_buffer,
1488 drawcount_offset, NULL);
1489
1490 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1491 _mesa_flush(ctx);
1492 }
1493
1494
1495 static void
1496 _mesa_validated_multidrawelementsindirect(struct gl_context *ctx,
1497 GLenum mode, GLenum type,
1498 GLintptr indirect,
1499 GLintptr drawcount_offset,
1500 GLsizei drawcount, GLsizei stride,
1501 struct gl_buffer_object *drawcount_buffer)
1502 {
1503 /* If drawcount_buffer is set, drawcount is the maximum draw count.*/
1504 if (drawcount == 0)
1505 return;
1506
1507 /* NOTE: IndexBufferObj is guaranteed to be a VBO. */
1508 struct _mesa_index_buffer ib;
1509 ib.count = 0; /* unknown */
1510 ib.obj = ctx->Array.VAO->IndexBufferObj;
1511 ib.ptr = NULL;
1512 get_index_size(type, &ib);
1513
1514 ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, indirect,
1515 drawcount, stride, drawcount_buffer,
1516 drawcount_offset, &ib);
1517
1518 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1519 _mesa_flush(ctx);
1520 }
1521
1522
1523 /**
1524 * Like [Multi]DrawArrays/Elements, but they take most arguments from
1525 * a buffer object.
1526 */
1527 static void GLAPIENTRY
1528 _mesa_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
1529 {
1530 GET_CURRENT_CONTEXT(ctx);
1531
1532 if (MESA_VERBOSE & VERBOSE_DRAW)
1533 _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n",
1534 _mesa_enum_to_string(mode), indirect);
1535
1536 /* From the ARB_draw_indirect spec:
1537 *
1538 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1539 * compatibility profile, this indicates that DrawArraysIndirect and
1540 * DrawElementsIndirect are to source their arguments directly from the
1541 * pointer passed as their <indirect> parameters."
1542 */
1543 if (ctx->API == API_OPENGL_COMPAT &&
1544 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1545 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect;
1546
1547 _mesa_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count,
1548 cmd->primCount,
1549 cmd->baseInstance);
1550 return;
1551 }
1552
1553 FLUSH_FOR_DRAW(ctx);
1554
1555 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1556
1557 if (_mesa_is_no_error_enabled(ctx)) {
1558 if (ctx->NewState)
1559 _mesa_update_state(ctx);
1560 } else {
1561 if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
1562 return;
1563 }
1564
1565 if (skip_validated_draw(ctx))
1566 return;
1567
1568 _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect,
1569 0, 1, 16, NULL);
1570 }
1571
1572
1573 static void GLAPIENTRY
1574 _mesa_exec_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
1575 {
1576 GET_CURRENT_CONTEXT(ctx);
1577
1578 if (MESA_VERBOSE & VERBOSE_DRAW)
1579 _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n",
1580 _mesa_enum_to_string(mode),
1581 _mesa_enum_to_string(type), indirect);
1582
1583 /* From the ARB_draw_indirect spec:
1584 *
1585 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1586 * compatibility profile, this indicates that DrawArraysIndirect and
1587 * DrawElementsIndirect are to source their arguments directly from the
1588 * pointer passed as their <indirect> parameters."
1589 */
1590 if (ctx->API == API_OPENGL_COMPAT &&
1591 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1592 /*
1593 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
1594 * may not come from a client array and must come from an index buffer.
1595 * If no element array buffer is bound, an INVALID_OPERATION error is
1596 * generated.
1597 */
1598 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
1599 _mesa_error(ctx, GL_INVALID_OPERATION,
1600 "glDrawElementsIndirect(no buffer bound "
1601 "to GL_ELEMENT_ARRAY_BUFFER)");
1602 } else {
1603 DrawElementsIndirectCommand *cmd =
1604 (DrawElementsIndirectCommand *) indirect;
1605
1606 /* Convert offset to pointer */
1607 void *offset = (void *)
1608 (uintptr_t)((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL);
1609
1610 _mesa_exec_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count,
1611 type, offset,
1612 cmd->primCount,
1613 cmd->baseVertex,
1614 cmd->baseInstance);
1615 }
1616
1617 return;
1618 }
1619
1620 FLUSH_FOR_DRAW(ctx);
1621
1622 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1623
1624 if (_mesa_is_no_error_enabled(ctx)) {
1625 if (ctx->NewState)
1626 _mesa_update_state(ctx);
1627 } else {
1628 if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
1629 return;
1630 }
1631
1632 if (skip_validated_draw(ctx))
1633 return;
1634
1635 _mesa_validated_multidrawelementsindirect(ctx, mode, type,
1636 (GLintptr)indirect, 0,
1637 1, 20, NULL);
1638 }
1639
1640
1641 static void GLAPIENTRY
1642 _mesa_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
1643 GLsizei primcount, GLsizei stride)
1644 {
1645 GET_CURRENT_CONTEXT(ctx);
1646
1647 if (MESA_VERBOSE & VERBOSE_DRAW)
1648 _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n",
1649 _mesa_enum_to_string(mode), indirect, primcount, stride);
1650
1651 /* If <stride> is zero, the array elements are treated as tightly packed. */
1652 if (stride == 0)
1653 stride = sizeof(DrawArraysIndirectCommand);
1654
1655 /* From the ARB_draw_indirect spec:
1656 *
1657 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1658 * compatibility profile, this indicates that DrawArraysIndirect and
1659 * DrawElementsIndirect are to source their arguments directly from the
1660 * pointer passed as their <indirect> parameters."
1661 */
1662 if (ctx->API == API_OPENGL_COMPAT &&
1663 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1664
1665 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
1666 "glMultiDrawArraysIndirect"))
1667 return;
1668
1669 const uint8_t *ptr = (const uint8_t *) indirect;
1670 for (unsigned i = 0; i < primcount; i++) {
1671 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr;
1672 _mesa_exec_DrawArraysInstancedBaseInstance(mode, cmd->first,
1673 cmd->count, cmd->primCount,
1674 cmd->baseInstance);
1675
1676 if (stride == 0) {
1677 ptr += sizeof(DrawArraysIndirectCommand);
1678 } else {
1679 ptr += stride;
1680 }
1681 }
1682
1683 return;
1684 }
1685
1686 FLUSH_FOR_DRAW(ctx);
1687
1688 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1689
1690 if (_mesa_is_no_error_enabled(ctx)) {
1691 if (ctx->NewState)
1692 _mesa_update_state(ctx);
1693 } else {
1694 if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect,
1695 primcount, stride))
1696 return;
1697 }
1698
1699 if (skip_validated_draw(ctx))
1700 return;
1701
1702 _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect, 0,
1703 primcount, stride, NULL);
1704 }
1705
1706
1707 static void GLAPIENTRY
1708 _mesa_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
1709 const GLvoid *indirect,
1710 GLsizei primcount, GLsizei stride)
1711 {
1712 GET_CURRENT_CONTEXT(ctx);
1713
1714 if (MESA_VERBOSE & VERBOSE_DRAW)
1715 _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n",
1716 _mesa_enum_to_string(mode),
1717 _mesa_enum_to_string(type), indirect, primcount, stride);
1718
1719 /* If <stride> is zero, the array elements are treated as tightly packed. */
1720 if (stride == 0)
1721 stride = sizeof(DrawElementsIndirectCommand);
1722
1723
1724 /* From the ARB_draw_indirect spec:
1725 *
1726 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1727 * compatibility profile, this indicates that DrawArraysIndirect and
1728 * DrawElementsIndirect are to source their arguments directly from the
1729 * pointer passed as their <indirect> parameters."
1730 */
1731 if (ctx->API == API_OPENGL_COMPAT &&
1732 !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1733 /*
1734 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
1735 * may not come from a client array and must come from an index buffer.
1736 * If no element array buffer is bound, an INVALID_OPERATION error is
1737 * generated.
1738 */
1739 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
1740 _mesa_error(ctx, GL_INVALID_OPERATION,
1741 "glMultiDrawElementsIndirect(no buffer bound "
1742 "to GL_ELEMENT_ARRAY_BUFFER)");
1743
1744 return;
1745 }
1746
1747 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
1748 "glMultiDrawArraysIndirect"))
1749 return;
1750
1751 const uint8_t *ptr = (const uint8_t *) indirect;
1752 for (unsigned i = 0; i < primcount; i++) {
1753 _mesa_exec_DrawElementsIndirect(mode, type, ptr);
1754
1755 if (stride == 0) {
1756 ptr += sizeof(DrawElementsIndirectCommand);
1757 } else {
1758 ptr += stride;
1759 }
1760 }
1761
1762 return;
1763 }
1764
1765 FLUSH_FOR_DRAW(ctx);
1766
1767 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1768
1769 if (_mesa_is_no_error_enabled(ctx)) {
1770 if (ctx->NewState)
1771 _mesa_update_state(ctx);
1772 } else {
1773 if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect,
1774 primcount, stride))
1775 return;
1776 }
1777
1778 if (skip_validated_draw(ctx))
1779 return;
1780
1781 _mesa_validated_multidrawelementsindirect(ctx, mode, type,
1782 (GLintptr)indirect, 0, primcount,
1783 stride, NULL);
1784 }
1785
1786
1787 static void GLAPIENTRY
1788 _mesa_exec_MultiDrawArraysIndirectCount(GLenum mode, GLintptr indirect,
1789 GLintptr drawcount_offset,
1790 GLsizei maxdrawcount, GLsizei stride)
1791 {
1792 GET_CURRENT_CONTEXT(ctx);
1793
1794 if (MESA_VERBOSE & VERBOSE_DRAW)
1795 _mesa_debug(ctx, "glMultiDrawArraysIndirectCountARB"
1796 "(%s, %lx, %lx, %i, %i)\n",
1797 _mesa_enum_to_string(mode),
1798 (unsigned long) indirect, (unsigned long) drawcount_offset,
1799 maxdrawcount, stride);
1800
1801 /* If <stride> is zero, the array elements are treated as tightly packed. */
1802 if (stride == 0)
1803 stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
1804
1805 FLUSH_FOR_DRAW(ctx);
1806
1807 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1808
1809 if (_mesa_is_no_error_enabled(ctx)) {
1810 if (ctx->NewState)
1811 _mesa_update_state(ctx);
1812 } else {
1813 if (!_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode,
1814 indirect,
1815 drawcount_offset,
1816 maxdrawcount, stride))
1817 return;
1818 }
1819
1820 if (skip_validated_draw(ctx))
1821 return;
1822
1823 _mesa_validated_multidrawarraysindirect(ctx, mode, indirect,
1824 drawcount_offset, maxdrawcount,
1825 stride, ctx->ParameterBuffer);
1826 }
1827
1828
1829 static void GLAPIENTRY
1830 _mesa_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type,
1831 GLintptr indirect,
1832 GLintptr drawcount_offset,
1833 GLsizei maxdrawcount, GLsizei stride)
1834 {
1835 GET_CURRENT_CONTEXT(ctx);
1836
1837 if (MESA_VERBOSE & VERBOSE_DRAW)
1838 _mesa_debug(ctx, "glMultiDrawElementsIndirectCountARB"
1839 "(%s, %s, %lx, %lx, %i, %i)\n",
1840 _mesa_enum_to_string(mode), _mesa_enum_to_string(type),
1841 (unsigned long) indirect, (unsigned long) drawcount_offset,
1842 maxdrawcount, stride);
1843
1844 /* If <stride> is zero, the array elements are treated as tightly packed. */
1845 if (stride == 0)
1846 stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
1847
1848 FLUSH_FOR_DRAW(ctx);
1849
1850 _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1851
1852 if (_mesa_is_no_error_enabled(ctx)) {
1853 if (ctx->NewState)
1854 _mesa_update_state(ctx);
1855 } else {
1856 if (!_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type,
1857 indirect,
1858 drawcount_offset,
1859 maxdrawcount, stride))
1860 return;
1861 }
1862
1863 if (skip_validated_draw(ctx))
1864 return;
1865
1866 _mesa_validated_multidrawelementsindirect(ctx, mode, type, indirect,
1867 drawcount_offset, maxdrawcount,
1868 stride, ctx->ParameterBuffer);
1869 }
1870
1871
1872 /**
1873 * Initialize the dispatch table with the VBO functions for drawing.
1874 */
1875 void
1876 _mesa_initialize_exec_dispatch(const struct gl_context *ctx,
1877 struct _glapi_table *exec)
1878 {
1879 SET_DrawArrays(exec, _mesa_DrawArrays);
1880 SET_DrawElements(exec, _mesa_DrawElements);
1881
1882 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1883 SET_DrawRangeElements(exec, _mesa_DrawRangeElements);
1884 }
1885
1886 SET_MultiDrawArrays(exec, _mesa_exec_MultiDrawArrays);
1887 SET_MultiDrawElementsEXT(exec, _mesa_MultiDrawElements);
1888
1889 if (ctx->API == API_OPENGL_COMPAT) {
1890 SET_Rectf(exec, _mesa_exec_Rectf);
1891 SET_EvalMesh1(exec, _mesa_exec_EvalMesh1);
1892 SET_EvalMesh2(exec, _mesa_exec_EvalMesh2);
1893 }
1894
1895 if (ctx->API != API_OPENGLES &&
1896 ctx->Extensions.ARB_draw_elements_base_vertex) {
1897 SET_DrawElementsBaseVertex(exec, _mesa_DrawElementsBaseVertex);
1898 SET_MultiDrawElementsBaseVertex(exec,
1899 _mesa_MultiDrawElementsBaseVertex);
1900
1901 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1902 SET_DrawRangeElementsBaseVertex(exec,
1903 _mesa_DrawRangeElementsBaseVertex);
1904 SET_DrawElementsInstancedBaseVertex(exec,
1905 _mesa_exec_DrawElementsInstancedBaseVertex);
1906 }
1907 }
1908
1909 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1910 SET_DrawArraysInstancedBaseInstance(exec,
1911 _mesa_exec_DrawArraysInstancedBaseInstance);
1912 SET_DrawElementsInstancedBaseInstance(exec,
1913 _mesa_exec_DrawElementsInstancedBaseInstance);
1914 SET_DrawElementsInstancedBaseVertexBaseInstance(exec,
1915 _mesa_exec_DrawElementsInstancedBaseVertexBaseInstance);
1916 }
1917
1918 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) {
1919 SET_DrawArraysIndirect(exec, _mesa_exec_DrawArraysIndirect);
1920 SET_DrawElementsIndirect(exec, _mesa_exec_DrawElementsIndirect);
1921 }
1922
1923 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1924 SET_DrawArraysInstancedARB(exec, _mesa_DrawArraysInstanced);
1925 SET_DrawElementsInstancedARB(exec, _mesa_exec_DrawElementsInstanced);
1926 }
1927
1928 if (_mesa_is_desktop_gl(ctx)) {
1929 SET_DrawTransformFeedback(exec, _mesa_DrawTransformFeedback);
1930 SET_DrawTransformFeedbackStream(exec,
1931 _mesa_exec_DrawTransformFeedbackStream);
1932 SET_DrawTransformFeedbackInstanced(exec,
1933 _mesa_exec_DrawTransformFeedbackInstanced);
1934 SET_DrawTransformFeedbackStreamInstanced(exec,
1935 _mesa_exec_DrawTransformFeedbackStreamInstanced);
1936 SET_MultiDrawArraysIndirect(exec, _mesa_exec_MultiDrawArraysIndirect);
1937 SET_MultiDrawElementsIndirect(exec, _mesa_exec_MultiDrawElementsIndirect);
1938 SET_MultiDrawArraysIndirectCountARB(exec,
1939 _mesa_exec_MultiDrawArraysIndirectCount);
1940 SET_MultiDrawElementsIndirectCountARB(exec,
1941 _mesa_exec_MultiDrawElementsIndirectCount);
1942 }
1943 }
1944
1945
1946
1947 /* GL_IBM_multimode_draw_arrays */
1948 void GLAPIENTRY
1949 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1950 const GLsizei * count,
1951 GLsizei primcount, GLint modestride )
1952 {
1953 GET_CURRENT_CONTEXT(ctx);
1954 GLint i;
1955
1956 FLUSH_VERTICES(ctx, 0);
1957
1958 for ( i = 0 ; i < primcount ; i++ ) {
1959 if ( count[i] > 0 ) {
1960 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1961 CALL_DrawArrays(ctx->CurrentServerDispatch, ( m, first[i], count[i] ));
1962 }
1963 }
1964 }
1965
1966
1967 /* GL_IBM_multimode_draw_arrays */
1968 void GLAPIENTRY
1969 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1970 GLenum type, const GLvoid * const * indices,
1971 GLsizei primcount, GLint modestride )
1972 {
1973 GET_CURRENT_CONTEXT(ctx);
1974 GLint i;
1975
1976 FLUSH_VERTICES(ctx, 0);
1977
1978 /* XXX not sure about ARB_vertex_buffer_object handling here */
1979
1980 for ( i = 0 ; i < primcount ; i++ ) {
1981 if ( count[i] > 0 ) {
1982 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1983 CALL_DrawElements(ctx->CurrentServerDispatch, ( m, count[i], type,
1984 indices[i] ));
1985 }
1986 }
1987 }