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