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