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