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