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