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 #include "pipe/p_state.h"
44
45 typedef struct {
46 GLuint count;
47 GLuint primCount;
48 GLuint first;
49 GLuint baseInstance;
50 } DrawArraysIndirectCommand;
51
52 typedef struct {
53 GLuint count;
54 GLuint primCount;
55 GLuint firstIndex;
56 GLint baseVertex;
57 GLuint baseInstance;
58 } DrawElementsIndirectCommand;
59
60
61 /**
62 * Want to figure out which fragment program inputs are actually
63 * constant/current values from ctx->Current. These should be
64 * referenced as a tracked state variable rather than a fragment
65 * program input, to save the overhead of putting a constant value in
66 * every submitted vertex, transferring it to hardware, interpolating
67 * it across the triangle, etc...
68 *
69 * When there is a VP bound, just use vp->outputs. But when we're
70 * generating vp from fixed function state, basically want to
71 * calculate:
72 *
73 * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) |
74 * potential_vp_outputs )
75 *
76 * Where potential_vp_outputs is calculated by looking at enabled
77 * texgen, etc.
78 *
79 * The generated fragment program should then only declare inputs that
80 * may vary or otherwise differ from the ctx->Current values.
81 * Otherwise, the fp should track them as state values instead.
82 */
83 void
_mesa_set_varying_vp_inputs(struct gl_context * ctx,GLbitfield varying_inputs)84 _mesa_set_varying_vp_inputs(struct gl_context *ctx, GLbitfield varying_inputs)
85 {
86 if (ctx->VertexProgram._VPModeOptimizesConstantAttribs &&
87 ctx->VertexProgram._VaryingInputs != varying_inputs) {
88 ctx->VertexProgram._VaryingInputs = varying_inputs;
89 ctx->NewState |= _NEW_FF_VERT_PROGRAM | _NEW_FF_FRAG_PROGRAM;
90 }
91 }
92
93
94 /**
95 * Set the _DrawVAO and the net enabled arrays.
96 * The vao->_Enabled bitmask is transformed due to position/generic0
97 * as stored in vao->_AttributeMapMode. Then the filter bitmask is applied
98 * to filter out arrays unwanted for the currently executed draw operation.
99 * For example, the generic attributes are masked out form the _DrawVAO's
100 * enabled arrays when a fixed function array draw is executed.
101 */
102 void
_mesa_set_draw_vao(struct gl_context * ctx,struct gl_vertex_array_object * vao,GLbitfield filter)103 _mesa_set_draw_vao(struct gl_context *ctx, struct gl_vertex_array_object *vao,
104 GLbitfield filter)
105 {
106 struct gl_vertex_array_object **ptr = &ctx->Array._DrawVAO;
107 bool new_array = false;
108 if (*ptr != vao) {
109 _mesa_reference_vao_(ctx, ptr, vao);
110
111 new_array = true;
112 }
113
114 if (vao->NewArrays) {
115 _mesa_update_vao_derived_arrays(ctx, vao);
116 vao->NewArrays = 0;
117
118 new_array = true;
119 }
120
121 assert(vao->_EnabledWithMapMode ==
122 _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled));
123
124 /* Filter out unwanted arrays. */
125 const GLbitfield enabled = filter & vao->_EnabledWithMapMode;
126 if (ctx->Array._DrawVAOEnabledAttribs != enabled) {
127 ctx->Array._DrawVAOEnabledAttribs = enabled;
128 new_array = true;
129 }
130
131 if (new_array)
132 ctx->NewDriverState |= ctx->DriverFlags.NewArray;
133
134 _mesa_set_varying_vp_inputs(ctx, enabled);
135 }
136
137
138 /**
139 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
140 * etc? Also, do additional checking related to transformation feedback.
141 * Note: this function cannot be called during glNewList(GL_COMPILE) because
142 * this code depends on current transform feedback state.
143 * Also, do additional checking related to tessellation shaders.
144 */
145 static GLenum
valid_prim_mode_custom(struct gl_context * ctx,GLenum mode,GLbitfield valid_prim_mask)146 valid_prim_mode_custom(struct gl_context *ctx, GLenum mode,
147 GLbitfield valid_prim_mask)
148 {
149 #if DEBUG
150 unsigned mask = ctx->ValidPrimMask;
151 unsigned mask_indexed = ctx->ValidPrimMaskIndexed;
152 bool drawpix_valid = ctx->DrawPixValid;
153 _mesa_update_valid_to_render_state(ctx);
154 assert(mask == ctx->ValidPrimMask &&
155 mask_indexed == ctx->ValidPrimMaskIndexed &&
156 drawpix_valid == ctx->DrawPixValid);
157 #endif
158
159 /* All primitive type enums are less than 32, so we can use the shift. */
160 if (mode >= 32 || !((1u << mode) & valid_prim_mask)) {
161 /* If the primitive type is not in SupportedPrimMask, set GL_INVALID_ENUM,
162 * else set DrawGLError (e.g. GL_INVALID_OPERATION).
163 */
164 return mode >= 32 || !((1u << mode) & ctx->SupportedPrimMask) ?
165 GL_INVALID_ENUM : ctx->DrawGLError;
166 }
167
168 return GL_NO_ERROR;
169 }
170
171 GLenum
_mesa_valid_prim_mode(struct gl_context * ctx,GLenum mode)172 _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode)
173 {
174 return valid_prim_mode_custom(ctx, mode, ctx->ValidPrimMask);
175 }
176
177 static GLenum
valid_prim_mode_indexed(struct gl_context * ctx,GLenum mode)178 valid_prim_mode_indexed(struct gl_context *ctx, GLenum mode)
179 {
180 return valid_prim_mode_custom(ctx, mode, ctx->ValidPrimMaskIndexed);
181 }
182
183 /**
184 * Verify that the element type is valid.
185 *
186 * Generates \c GL_INVALID_ENUM and returns \c false if it is not.
187 */
188 static GLenum
valid_elements_type(struct gl_context * ctx,GLenum type)189 valid_elements_type(struct gl_context *ctx, GLenum type)
190 {
191 /* GL_UNSIGNED_BYTE = 0x1401
192 * GL_UNSIGNED_SHORT = 0x1403
193 * GL_UNSIGNED_INT = 0x1405
194 *
195 * The trick is that bit 1 and bit 2 mean USHORT and UINT, respectively.
196 * After clearing those two bits (with ~6), we should get UBYTE.
197 * Both bits can't be set, because the enum would be greater than UINT.
198 */
199 if (!(type <= GL_UNSIGNED_INT && (type & ~6) == GL_UNSIGNED_BYTE))
200 return GL_INVALID_ENUM;
201
202 return GL_NO_ERROR;
203 }
204
205 static inline bool
indices_aligned(unsigned index_size_shift,const GLvoid * indices)206 indices_aligned(unsigned index_size_shift, const GLvoid *indices)
207 {
208 /* Require that indices are aligned to the element size. GL doesn't specify
209 * an error for this, but the ES 3.0 spec says:
210 *
211 * "Clients must align data elements consistently with the requirements
212 * of the client platform, with an additional base-level requirement
213 * that an offset within a buffer to a datum comprising N basic machine
214 * units be a multiple of N"
215 *
216 * This is only required by index buffers, not user indices.
217 */
218 return ((uintptr_t)indices & ((1 << index_size_shift) - 1)) == 0;
219 }
220
221 static GLenum
validate_DrawElements_common(struct gl_context * ctx,GLenum mode,GLsizei count,GLsizei numInstances,GLenum type)222 validate_DrawElements_common(struct gl_context *ctx, GLenum mode,
223 GLsizei count, GLsizei numInstances, GLenum type)
224 {
225 if (count < 0 || numInstances < 0)
226 return GL_INVALID_VALUE;
227
228 GLenum error = valid_prim_mode_indexed(ctx, mode);
229 if (error)
230 return error;
231
232 return valid_elements_type(ctx, type);
233 }
234
235 /**
236 * Error checking for glDrawElements(). Includes parameter checking
237 * and VBO bounds checking.
238 * \return GL_TRUE if OK to render, GL_FALSE if error found
239 */
240 static GLboolean
_mesa_validate_DrawElements(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type)241 _mesa_validate_DrawElements(struct gl_context *ctx,
242 GLenum mode, GLsizei count, GLenum type)
243 {
244 GLenum error = validate_DrawElements_common(ctx, mode, count, 1, type);
245 if (error)
246 _mesa_error(ctx, error, "glDrawElements");
247
248 return !error;
249 }
250
251
252 /**
253 * Error checking for glMultiDrawElements(). Includes parameter checking
254 * and VBO bounds checking.
255 * \return GL_TRUE if OK to render, GL_FALSE if error found
256 */
257 static GLboolean
_mesa_validate_MultiDrawElements(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount)258 _mesa_validate_MultiDrawElements(struct gl_context *ctx,
259 GLenum mode, const GLsizei *count,
260 GLenum type, const GLvoid * const *indices,
261 GLsizei primcount)
262 {
263 GLenum error;
264
265 /*
266 * Section 2.3.1 (Errors) of the OpenGL 4.5 (Core Profile) spec says:
267 *
268 * "If a negative number is provided where an argument of type sizei or
269 * sizeiptr is specified, an INVALID_VALUE error is generated."
270 *
271 * and in the same section:
272 *
273 * "In other cases, there are no side effects unless otherwise noted;
274 * the command which generates the error is ignored so that it has no
275 * effect on GL state or framebuffer contents."
276 *
277 * Hence, check both primcount and all the count[i].
278 */
279 if (primcount < 0) {
280 error = GL_INVALID_VALUE;
281 } else {
282 error = valid_prim_mode_indexed(ctx, mode);
283
284 if (!error) {
285 error = valid_elements_type(ctx, type);
286
287 if (!error) {
288 for (int i = 0; i < primcount; i++) {
289 if (count[i] < 0) {
290 error = GL_INVALID_VALUE;
291 break;
292 }
293 }
294 }
295 }
296 }
297
298 if (error)
299 _mesa_error(ctx, error, "glMultiDrawElements");
300
301 /* Not using a VBO for indices, so avoid NULL pointer derefs later.
302 */
303 if (!ctx->Array.VAO->IndexBufferObj) {
304 for (int i = 0; i < primcount; i++) {
305 if (!indices[i])
306 return GL_FALSE;
307 }
308 }
309
310 return !error;
311 }
312
313
314 /**
315 * Error checking for glDrawRangeElements(). Includes parameter checking
316 * and VBO bounds checking.
317 * \return GL_TRUE if OK to render, GL_FALSE if error found
318 */
319 static GLboolean
_mesa_validate_DrawRangeElements(struct gl_context * ctx,GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type)320 _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
321 GLuint start, GLuint end,
322 GLsizei count, GLenum type)
323 {
324 GLenum error;
325
326 if (end < start) {
327 error = GL_INVALID_VALUE;
328 } else {
329 error = validate_DrawElements_common(ctx, mode, count, 1, type);
330 }
331
332 if (error)
333 _mesa_error(ctx, error, "glDrawRangeElements");
334
335 return !error;
336 }
337
338
339 static bool
need_xfb_remaining_prims_check(const struct gl_context * ctx)340 need_xfb_remaining_prims_check(const struct gl_context *ctx)
341 {
342 /* From the GLES3 specification, section 2.14.2 (Transform Feedback
343 * Primitive Capture):
344 *
345 * The error INVALID_OPERATION is generated by DrawArrays and
346 * DrawArraysInstanced if recording the vertices of a primitive to the
347 * buffer objects being used for transform feedback purposes would result
348 * in either exceeding the limits of any buffer object’s size, or in
349 * exceeding the end position offset + size − 1, as set by
350 * BindBufferRange.
351 *
352 * This is in contrast to the behaviour of desktop GL, where the extra
353 * primitives are silently dropped from the transform feedback buffer.
354 *
355 * This text is removed in ES 3.2, presumably because it's not really
356 * implementable with geometry and tessellation shaders. In fact,
357 * the OES_geometry_shader spec says:
358 *
359 * "(13) Does this extension change how transform feedback operates
360 * compared to unextended OpenGL ES 3.0 or 3.1?
361 *
362 * RESOLVED: Yes. Because dynamic geometry amplification in a geometry
363 * shader can make it difficult if not impossible to predict the amount
364 * of geometry that may be generated in advance of executing the shader,
365 * the draw-time error for transform feedback buffer overflow conditions
366 * is removed and replaced with the GL behavior (primitives are not
367 * written and the corresponding counter is not updated)..."
368 */
369 return _mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx) &&
370 !_mesa_has_OES_geometry_shader(ctx) &&
371 !_mesa_has_OES_tessellation_shader(ctx);
372 }
373
374
375 /**
376 * Figure out the number of transform feedback primitives that will be output
377 * considering the drawing mode, number of vertices, and instance count,
378 * assuming that no geometry shading is done and primitive restart is not
379 * used.
380 *
381 * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED
382 * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries. It is also used to
383 * pre-validate draw calls in GLES3 (where draw calls only succeed if there is
384 * enough room in the transform feedback buffer for the result).
385 */
386 static size_t
count_tessellated_primitives(GLenum mode,GLuint count,GLuint num_instances)387 count_tessellated_primitives(GLenum mode, GLuint count, GLuint num_instances)
388 {
389 size_t num_primitives;
390 switch (mode) {
391 case GL_POINTS:
392 num_primitives = count;
393 break;
394 case GL_LINE_STRIP:
395 num_primitives = count >= 2 ? count - 1 : 0;
396 break;
397 case GL_LINE_LOOP:
398 num_primitives = count >= 2 ? count : 0;
399 break;
400 case GL_LINES:
401 num_primitives = count / 2;
402 break;
403 case GL_TRIANGLE_STRIP:
404 case GL_TRIANGLE_FAN:
405 case GL_POLYGON:
406 num_primitives = count >= 3 ? count - 2 : 0;
407 break;
408 case GL_TRIANGLES:
409 num_primitives = count / 3;
410 break;
411 case GL_QUAD_STRIP:
412 num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0;
413 break;
414 case GL_QUADS:
415 num_primitives = (count / 4) * 2;
416 break;
417 case GL_LINES_ADJACENCY:
418 num_primitives = count / 4;
419 break;
420 case GL_LINE_STRIP_ADJACENCY:
421 num_primitives = count >= 4 ? count - 3 : 0;
422 break;
423 case GL_TRIANGLES_ADJACENCY:
424 num_primitives = count / 6;
425 break;
426 case GL_TRIANGLE_STRIP_ADJACENCY:
427 num_primitives = count >= 6 ? (count - 4) / 2 : 0;
428 break;
429 default:
430 assert(!"Unexpected primitive type in count_tessellated_primitives");
431 num_primitives = 0;
432 break;
433 }
434 return num_primitives * num_instances;
435 }
436
437
438 static GLenum
validate_draw_arrays(struct gl_context * ctx,GLenum mode,GLsizei count,GLsizei numInstances)439 validate_draw_arrays(struct gl_context *ctx,
440 GLenum mode, GLsizei count, GLsizei numInstances)
441 {
442 if (count < 0 || numInstances < 0)
443 return GL_INVALID_VALUE;
444
445 GLenum error = _mesa_valid_prim_mode(ctx, mode);
446 if (error)
447 return error;
448
449 if (need_xfb_remaining_prims_check(ctx)) {
450 struct gl_transform_feedback_object *xfb_obj
451 = ctx->TransformFeedback.CurrentObject;
452 size_t prim_count = count_tessellated_primitives(mode, count, numInstances);
453 if (xfb_obj->GlesRemainingPrims < prim_count)
454 return GL_INVALID_OPERATION;
455
456 xfb_obj->GlesRemainingPrims -= prim_count;
457 }
458
459 return GL_NO_ERROR;
460 }
461
462 /**
463 * Called from the tnl module to error check the function parameters and
464 * verify that we really can draw something.
465 * \return GL_TRUE if OK to render, GL_FALSE if error found
466 */
467 static GLboolean
_mesa_validate_DrawArrays(struct gl_context * ctx,GLenum mode,GLsizei count)468 _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count)
469 {
470 GLenum error = validate_draw_arrays(ctx, mode, count, 1);
471
472 if (error)
473 _mesa_error(ctx, error, "glDrawArrays");
474
475 if (count == 0)
476 return false;
477
478 return !error;
479 }
480
481
482 static GLboolean
_mesa_validate_DrawArraysInstanced(struct gl_context * ctx,GLenum mode,GLint first,GLsizei count,GLsizei numInstances)483 _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
484 GLsizei count, GLsizei numInstances)
485 {
486 GLenum error;
487
488 if (first < 0) {
489 error = GL_INVALID_VALUE;
490 } else {
491 error = validate_draw_arrays(ctx, mode, count, numInstances);
492 }
493
494 if (error)
495 _mesa_error(ctx, error, "glDrawArraysInstanced");
496
497 return !error;
498 }
499
500
501 /**
502 * Called to error check the function parameters.
503 *
504 * Note that glMultiDrawArrays is not part of GLES, so there's limited scope
505 * for sharing code with the validation of glDrawArrays.
506 */
507 static bool
_mesa_validate_MultiDrawArrays(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLsizei primcount)508 _mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
509 const GLsizei *count, GLsizei primcount)
510 {
511 GLenum error;
512
513 if (primcount < 0) {
514 error = GL_INVALID_VALUE;
515 } else {
516 error = _mesa_valid_prim_mode(ctx, mode);
517
518 if (!error) {
519 for (int i = 0; i < primcount; ++i) {
520 if (count[i] < 0) {
521 error = GL_INVALID_VALUE;
522 break;
523 }
524 }
525
526 if (!error) {
527 if (need_xfb_remaining_prims_check(ctx)) {
528 struct gl_transform_feedback_object *xfb_obj
529 = ctx->TransformFeedback.CurrentObject;
530 size_t xfb_prim_count = 0;
531
532 for (int i = 0; i < primcount; ++i) {
533 xfb_prim_count +=
534 count_tessellated_primitives(mode, count[i], 1);
535 }
536
537 if (xfb_obj->GlesRemainingPrims < xfb_prim_count) {
538 error = GL_INVALID_OPERATION;
539 } else {
540 xfb_obj->GlesRemainingPrims -= xfb_prim_count;
541 }
542 }
543 }
544 }
545 }
546
547 if (error)
548 _mesa_error(ctx, error, "glMultiDrawArrays");
549
550 return !error;
551 }
552
553
554 static GLboolean
_mesa_validate_DrawElementsInstanced(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,GLsizei numInstances)555 _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
556 GLenum mode, GLsizei count, GLenum type,
557 GLsizei numInstances)
558 {
559 GLenum error =
560 validate_DrawElements_common(ctx, mode, count, numInstances, type);
561
562 if (error)
563 _mesa_error(ctx, error, "glDrawElementsInstanced");
564
565 return !error;
566 }
567
568
569 static GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context * ctx,GLenum mode,struct gl_transform_feedback_object * obj,GLuint stream,GLsizei numInstances)570 _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
571 GLenum mode,
572 struct gl_transform_feedback_object *obj,
573 GLuint stream,
574 GLsizei numInstances)
575 {
576 GLenum error;
577
578 /* From the GL 4.5 specification, page 429:
579 * "An INVALID_VALUE error is generated if id is not the name of a
580 * transform feedback object."
581 */
582 if (!obj || !obj->EverBound || stream >= ctx->Const.MaxVertexStreams ||
583 numInstances < 0) {
584 error = GL_INVALID_VALUE;
585 } else {
586 error = _mesa_valid_prim_mode(ctx, mode);
587
588 if (!error) {
589 if (!obj->EndedAnytime)
590 error = GL_INVALID_OPERATION;
591 }
592 }
593
594 if (error)
595 _mesa_error(ctx, error, "glDrawTransformFeedback*");
596
597 return !error;
598 }
599
600 static GLenum
valid_draw_indirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei size)601 valid_draw_indirect(struct gl_context *ctx,
602 GLenum mode, const GLvoid *indirect,
603 GLsizei size)
604 {
605 const uint64_t end = (uint64_t) (uintptr_t) indirect + size;
606
607 /* OpenGL ES 3.1 spec. section 10.5:
608 *
609 * "DrawArraysIndirect requires that all data sourced for the
610 * command, including the DrawArraysIndirectCommand
611 * structure, be in buffer objects, and may not be called when
612 * the default vertex array object is bound."
613 */
614 if (ctx->API != API_OPENGL_COMPAT &&
615 ctx->Array.VAO == ctx->Array.DefaultVAO)
616 return GL_INVALID_OPERATION;
617
618 /* From OpenGL ES 3.1 spec. section 10.5:
619 * "An INVALID_OPERATION error is generated if zero is bound to
620 * VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER or to any enabled
621 * vertex array."
622 *
623 * Here we check that for each enabled vertex array we have a vertex
624 * buffer bound.
625 */
626 if (_mesa_is_gles31(ctx) &&
627 ctx->Array.VAO->Enabled & ~ctx->Array.VAO->VertexAttribBufferMask)
628 return GL_INVALID_OPERATION;
629
630 GLenum error = _mesa_valid_prim_mode(ctx, mode);
631 if (error)
632 return error;
633
634 /* OpenGL ES 3.1 specification, section 10.5:
635 *
636 * "An INVALID_OPERATION error is generated if
637 * transform feedback is active and not paused."
638 *
639 * The OES_geometry_shader spec says:
640 *
641 * On p. 250 in the errors section for the DrawArraysIndirect command,
642 * and on p. 254 in the errors section for the DrawElementsIndirect
643 * command, delete the errors which state:
644 *
645 * "An INVALID_OPERATION error is generated if transform feedback is
646 * active and not paused."
647 *
648 * (thus allowing transform feedback to work with indirect draw commands).
649 */
650 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader &&
651 _mesa_is_xfb_active_and_unpaused(ctx))
652 return GL_INVALID_OPERATION;
653
654 /* From OpenGL version 4.4. section 10.5
655 * and OpenGL ES 3.1, section 10.6:
656 *
657 * "An INVALID_VALUE error is generated if indirect is not a
658 * multiple of the size, in basic machine units, of uint."
659 */
660 if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1))
661 return GL_INVALID_VALUE;
662
663 if (!ctx->DrawIndirectBuffer)
664 return GL_INVALID_OPERATION;
665
666 if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer))
667 return GL_INVALID_OPERATION;
668
669 /* From the ARB_draw_indirect specification:
670 * "An INVALID_OPERATION error is generated if the commands source data
671 * beyond the end of the buffer object [...]"
672 */
673 if (ctx->DrawIndirectBuffer->Size < end)
674 return GL_INVALID_OPERATION;
675
676 return GL_NO_ERROR;
677 }
678
679 static inline GLenum
valid_draw_indirect_elements(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizeiptr size)680 valid_draw_indirect_elements(struct gl_context *ctx,
681 GLenum mode, GLenum type, const GLvoid *indirect,
682 GLsizeiptr size)
683 {
684 GLenum error = valid_elements_type(ctx, type);
685 if (error)
686 return error;
687
688 /*
689 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
690 * may not come from a client array and must come from an index buffer.
691 * If no element array buffer is bound, an INVALID_OPERATION error is
692 * generated.
693 */
694 if (!ctx->Array.VAO->IndexBufferObj)
695 return GL_INVALID_OPERATION;
696
697 return valid_draw_indirect(ctx, mode, indirect, size);
698 }
699
700 static GLboolean
_mesa_valid_draw_indirect_multi(struct gl_context * ctx,GLsizei primcount,GLsizei stride,const char * name)701 _mesa_valid_draw_indirect_multi(struct gl_context *ctx,
702 GLsizei primcount, GLsizei stride,
703 const char *name)
704 {
705
706 /* From the ARB_multi_draw_indirect specification:
707 * "INVALID_VALUE is generated by MultiDrawArraysIndirect or
708 * MultiDrawElementsIndirect if <primcount> is negative."
709 *
710 * "<primcount> must be positive, otherwise an INVALID_VALUE error will
711 * be generated."
712 */
713 if (primcount < 0) {
714 _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name);
715 return GL_FALSE;
716 }
717
718
719 /* From the ARB_multi_draw_indirect specification:
720 * "<stride> must be a multiple of four, otherwise an INVALID_VALUE
721 * error is generated."
722 */
723 if (stride % 4) {
724 _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
725 return GL_FALSE;
726 }
727
728 return GL_TRUE;
729 }
730
731 static GLboolean
_mesa_validate_DrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect)732 _mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
733 GLenum mode,
734 const GLvoid *indirect)
735 {
736 const unsigned drawArraysNumParams = 4;
737 GLenum error =
738 valid_draw_indirect(ctx, mode, indirect,
739 drawArraysNumParams * sizeof(GLuint));
740
741 if (error)
742 _mesa_error(ctx, error, "glDrawArraysIndirect");
743
744 return !error;
745 }
746
747 static GLboolean
_mesa_validate_DrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect)748 _mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
749 GLenum mode, GLenum type,
750 const GLvoid *indirect)
751 {
752 const unsigned drawElementsNumParams = 5;
753 GLenum error = valid_draw_indirect_elements(ctx, mode, type, indirect,
754 drawElementsNumParams *
755 sizeof(GLuint));
756 if (error)
757 _mesa_error(ctx, error, "glDrawElementsIndirect");
758
759 return !error;
760 }
761
762 static GLboolean
_mesa_validate_MultiDrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)763 _mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
764 GLenum mode,
765 const GLvoid *indirect,
766 GLsizei primcount, GLsizei stride)
767 {
768 GLsizeiptr size = 0;
769 const unsigned drawArraysNumParams = 4;
770
771 /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
772 assert(stride != 0);
773
774 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
775 "glMultiDrawArraysIndirect"))
776 return GL_FALSE;
777
778 /* number of bytes of the indirect buffer which will be read */
779 size = primcount
780 ? (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
781 : 0;
782
783 GLenum error = valid_draw_indirect(ctx, mode, indirect, size);
784 if (error)
785 _mesa_error(ctx, error, "glMultiDrawArraysIndirect");
786
787 return !error;
788 }
789
790 static GLboolean
_mesa_validate_MultiDrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)791 _mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
792 GLenum mode, GLenum type,
793 const GLvoid *indirect,
794 GLsizei primcount, GLsizei stride)
795 {
796 GLsizeiptr size = 0;
797 const unsigned drawElementsNumParams = 5;
798
799 /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
800 assert(stride != 0);
801
802 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
803 "glMultiDrawElementsIndirect"))
804 return GL_FALSE;
805
806 /* number of bytes of the indirect buffer which will be read */
807 size = primcount
808 ? (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
809 : 0;
810
811 GLenum error = valid_draw_indirect_elements(ctx, mode, type, indirect,
812 size);
813 if (error)
814 _mesa_error(ctx, error, "glMultiDrawElementsIndirect");
815
816 return !error;
817 }
818
819 static GLenum
valid_draw_indirect_parameters(struct gl_context * ctx,GLintptr drawcount)820 valid_draw_indirect_parameters(struct gl_context *ctx,
821 GLintptr drawcount)
822 {
823 /* From the ARB_indirect_parameters specification:
824 * "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or
825 * MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of
826 * four."
827 */
828 if (drawcount & 3)
829 return GL_INVALID_VALUE;
830
831 /* From the ARB_indirect_parameters specification:
832 * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
833 * MultiDrawElementsIndirectCountARB if no buffer is bound to the
834 * PARAMETER_BUFFER_ARB binding point."
835 */
836 if (!ctx->ParameterBuffer)
837 return GL_INVALID_OPERATION;
838
839 if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer))
840 return GL_INVALID_OPERATION;
841
842 /* From the ARB_indirect_parameters specification:
843 * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
844 * MultiDrawElementsIndirectCountARB if reading a <sizei> typed value
845 * from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset
846 * specified by <drawcount> would result in an out-of-bounds access."
847 */
848 if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei))
849 return GL_INVALID_OPERATION;
850
851 return GL_NO_ERROR;
852 }
853
854 static GLboolean
_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context * ctx,GLenum mode,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)855 _mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx,
856 GLenum mode,
857 GLintptr indirect,
858 GLintptr drawcount,
859 GLsizei maxdrawcount,
860 GLsizei stride)
861 {
862 GLsizeiptr size = 0;
863 const unsigned drawArraysNumParams = 4;
864
865 /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
866 assert(stride != 0);
867
868 if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride,
869 "glMultiDrawArraysIndirectCountARB"))
870 return GL_FALSE;
871
872 /* number of bytes of the indirect buffer which will be read */
873 size = maxdrawcount
874 ? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
875 : 0;
876
877 GLenum error = valid_draw_indirect(ctx, mode, (void *)indirect, size);
878 if (!error)
879 error = valid_draw_indirect_parameters(ctx, drawcount);
880
881 if (error)
882 _mesa_error(ctx, error, "glMultiDrawArraysIndirectCountARB");
883
884 return !error;
885 }
886
887 static GLboolean
_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context * ctx,GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)888 _mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx,
889 GLenum mode, GLenum type,
890 GLintptr indirect,
891 GLintptr drawcount,
892 GLsizei maxdrawcount,
893 GLsizei stride)
894 {
895 GLsizeiptr size = 0;
896 const unsigned drawElementsNumParams = 5;
897
898 /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
899 assert(stride != 0);
900
901 if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride,
902 "glMultiDrawElementsIndirectCountARB"))
903 return GL_FALSE;
904
905 /* number of bytes of the indirect buffer which will be read */
906 size = maxdrawcount
907 ? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
908 : 0;
909
910 GLenum error = valid_draw_indirect_elements(ctx, mode, type,
911 (void *)indirect, size);
912 if (!error)
913 error = valid_draw_indirect_parameters(ctx, drawcount);
914
915 if (error)
916 _mesa_error(ctx, error, "glMultiDrawElementsIndirectCountARB");
917
918 return !error;
919 }
920
921
922 #define MAX_ALLOCA_PRIMS(prim) (50000 / sizeof(*prim))
923
924 /* Use calloc for large allocations and alloca for small allocations. */
925 /* We have to use a macro because alloca is local within the function. */
926 #define ALLOC_PRIMS(prim, primcount, func) do { \
927 if (unlikely(primcount > MAX_ALLOCA_PRIMS(prim))) { \
928 prim = calloc(primcount, sizeof(*prim)); \
929 if (!prim) { \
930 _mesa_error(ctx, GL_OUT_OF_MEMORY, func); \
931 return; \
932 } \
933 } else { \
934 prim = alloca(primcount * sizeof(*prim)); \
935 } \
936 } while (0)
937
938 #define FREE_PRIMS(prim, primcount) do { \
939 if (primcount > MAX_ALLOCA_PRIMS(prim)) \
940 free(prim); \
941 } while (0)
942
943
944 /**
945 * Called via Driver.DrawGallium. This is a fallback invoking Driver.Draw.
946 */
947 void
_mesa_draw_gallium_fallback(struct gl_context * ctx,struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)948 _mesa_draw_gallium_fallback(struct gl_context *ctx,
949 struct pipe_draw_info *info,
950 unsigned drawid_offset,
951 const struct pipe_draw_start_count_bias *draws,
952 unsigned num_draws)
953 {
954 struct _mesa_index_buffer ib;
955 unsigned index_size = info->index_size;
956 unsigned min_index = 0, max_index = ~0u;
957 bool index_bounds_valid = false;
958
959 if (!info->instance_count)
960 return;
961
962 if (index_size) {
963 if (info->index_bounds_valid) {
964 min_index = info->min_index;
965 max_index = info->max_index;
966 index_bounds_valid = true;
967 }
968 } else {
969 /* The index_bounds_valid field and min/max_index are not used for
970 * non-indexed draw calls (they are undefined), but classic drivers
971 * need the index bounds. They will be computed manually.
972 */
973 index_bounds_valid = true;
974 }
975
976 ib.index_size_shift = util_logbase2(index_size);
977
978 /* Single draw or a fallback for user indices. */
979 if (num_draws == 1 ||
980 (info->index_size && info->has_user_indices &&
981 !ctx->Const.MultiDrawWithUserIndices)) {
982 for (unsigned i = 0; i < num_draws; i++) {
983 if (!draws[i].count)
984 continue;
985
986 if (index_size) {
987 ib.count = draws[i].count;
988
989 if (info->has_user_indices) {
990 ib.obj = NULL;
991 /* User indices require start to be added here if
992 * Const.MultiDrawWithUserIndices is false.
993 */
994 ib.ptr = (const char*)info->index.user +
995 draws[i].start * index_size;
996 } else {
997 ib.obj = info->index.gl_bo;
998 ib.ptr = NULL;
999 }
1000 }
1001
1002 struct _mesa_prim prim;
1003 prim.mode = info->mode;
1004 prim.begin = 1;
1005 prim.end = 1;
1006 prim.start = index_size && info->has_user_indices ? 0 : draws[i].start;
1007 prim.count = draws[i].count;
1008 prim.basevertex = index_size ? draws[i].index_bias : 0;
1009 prim.draw_id = drawid_offset + (info->increment_draw_id ? i : 0);
1010
1011 if (!index_size) {
1012 min_index = draws[i].start;
1013 max_index = draws[i].start + draws[i].count - 1;
1014 }
1015
1016 ctx->Driver.Draw(ctx, &prim, 1, index_size ? &ib : NULL,
1017 index_bounds_valid, info->primitive_restart,
1018 info->restart_index, min_index, max_index,
1019 info->instance_count, info->start_instance);
1020 }
1021 return;
1022 }
1023
1024 struct _mesa_prim *prim;
1025 unsigned max_count = 0;
1026 unsigned num_prims = 0;
1027
1028 ALLOC_PRIMS(prim, num_draws, "DrawGallium");
1029
1030 min_index = ~0u;
1031 max_index = 0;
1032
1033 for (unsigned i = 0; i < num_draws; i++) {
1034 if (!draws[i].count)
1035 continue;
1036
1037 prim[num_prims].mode = info->mode;
1038 prim[num_prims].begin = 1;
1039 prim[num_prims].end = 1;
1040 prim[num_prims].start = draws[i].start;
1041 prim[num_prims].count = draws[i].count;
1042 prim[num_prims].basevertex = info->index_size ? draws[i].index_bias : 0;
1043 prim[num_prims].draw_id = drawid_offset + (info->increment_draw_id ? i : 0);
1044
1045 if (!index_size) {
1046 min_index = MIN2(min_index, draws[i].start);
1047 max_index = MAX2(max_index, draws[i].start + draws[i].count - 1);
1048 }
1049
1050 max_count = MAX2(max_count, prim[num_prims].count);
1051 num_prims++;
1052 }
1053
1054 if (info->index_size) {
1055 ib.count = max_count;
1056 ib.index_size_shift = util_logbase2(index_size);
1057
1058 if (info->has_user_indices) {
1059 ib.obj = NULL;
1060 ib.ptr = (const char*)info->index.user;
1061 } else {
1062 ib.obj = info->index.gl_bo;
1063 ib.ptr = NULL;
1064 }
1065 }
1066
1067 if (num_prims)
1068 ctx->Driver.Draw(ctx, prim, num_prims, index_size ? &ib : NULL,
1069 index_bounds_valid, info->primitive_restart,
1070 info->restart_index, min_index, max_index,
1071 info->instance_count, info->start_instance);
1072 FREE_PRIMS(prim, num_draws);
1073 }
1074
1075
1076 /**
1077 * Called via Driver.DrawGallium. This is a fallback invoking Driver.Draw.
1078 */
1079 void
_mesa_draw_gallium_multimode_fallback(struct gl_context * ctx,struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draws,const unsigned char * mode,unsigned num_draws)1080 _mesa_draw_gallium_multimode_fallback(struct gl_context *ctx,
1081 struct pipe_draw_info *info,
1082 const struct pipe_draw_start_count_bias *draws,
1083 const unsigned char *mode,
1084 unsigned num_draws)
1085 {
1086 unsigned i, first;
1087
1088 /* Find consecutive draws where mode doesn't vary. */
1089 for (i = 0, first = 0; i <= num_draws; i++) {
1090 if (i == num_draws || mode[i] != mode[first]) {
1091 info->mode = mode[first];
1092 ctx->Driver.DrawGallium(ctx, info, 0, &draws[first], i - first);
1093 first = i;
1094 }
1095 }
1096 }
1097
1098 /**
1099 * Check that element 'j' of the array has reasonable data.
1100 * Map VBO if needed.
1101 * For debugging purposes; not normally used.
1102 */
1103 static void
check_array_data(struct gl_context * ctx,struct gl_vertex_array_object * vao,GLuint attrib,GLuint j)1104 check_array_data(struct gl_context *ctx, struct gl_vertex_array_object *vao,
1105 GLuint attrib, GLuint j)
1106 {
1107 const struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
1108 if (vao->Enabled & VERT_BIT(attrib)) {
1109 const struct gl_vertex_buffer_binding *binding =
1110 &vao->BufferBinding[array->BufferBindingIndex];
1111 struct gl_buffer_object *bo = binding->BufferObj;
1112 const void *data = array->Ptr;
1113 if (bo) {
1114 data = ADD_POINTERS(_mesa_vertex_attrib_address(array, binding),
1115 bo->Mappings[MAP_INTERNAL].Pointer);
1116 }
1117 switch (array->Format.Type) {
1118 case GL_FLOAT:
1119 {
1120 GLfloat *f = (GLfloat *) ((GLubyte *) data + binding->Stride * j);
1121 GLint k;
1122 for (k = 0; k < array->Format.Size; k++) {
1123 if (util_is_inf_or_nan(f[k]) || f[k] >= 1.0e20F || f[k] <= -1.0e10F) {
1124 printf("Bad array data:\n");
1125 printf(" Element[%u].%u = %f\n", j, k, f[k]);
1126 printf(" Array %u at %p\n", attrib, (void *) array);
1127 printf(" Type 0x%x, Size %d, Stride %d\n",
1128 array->Format.Type, array->Format.Size,
1129 binding->Stride);
1130 printf(" Address/offset %p in Buffer Object %u\n",
1131 array->Ptr, bo ? bo->Name : 0);
1132 f[k] = 1.0F; /* XXX replace the bad value! */
1133 }
1134 /*assert(!util_is_inf_or_nan(f[k])); */
1135 }
1136 }
1137 break;
1138 default:
1139 ;
1140 }
1141 }
1142 }
1143
1144
1145 static inline unsigned
get_index_size_shift(GLenum type)1146 get_index_size_shift(GLenum type)
1147 {
1148 /* The type is already validated, so use a fast conversion.
1149 *
1150 * GL_UNSIGNED_BYTE - GL_UNSIGNED_BYTE = 0
1151 * GL_UNSIGNED_SHORT - GL_UNSIGNED_BYTE = 2
1152 * GL_UNSIGNED_INT - GL_UNSIGNED_BYTE = 4
1153 *
1154 * Divide by 2 to get 0,1,2.
1155 */
1156 return (type - GL_UNSIGNED_BYTE) >> 1;
1157 }
1158
1159 /**
1160 * Examine the array's data for NaNs, etc.
1161 * For debug purposes; not normally used.
1162 */
1163 static void
check_draw_elements_data(struct gl_context * ctx,GLsizei count,GLenum elemType,const void * elements,GLint basevertex)1164 check_draw_elements_data(struct gl_context *ctx, GLsizei count,
1165 GLenum elemType, const void *elements,
1166 GLint basevertex)
1167 {
1168 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1169 GLint i;
1170 GLuint k;
1171
1172 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1173
1174 if (vao->IndexBufferObj)
1175 elements =
1176 ADD_POINTERS(vao->IndexBufferObj->Mappings[MAP_INTERNAL].Pointer, elements);
1177
1178 for (i = 0; i < count; i++) {
1179 GLuint j;
1180
1181 /* j = element[i] */
1182 switch (elemType) {
1183 case GL_UNSIGNED_BYTE:
1184 j = ((const GLubyte *) elements)[i];
1185 break;
1186 case GL_UNSIGNED_SHORT:
1187 j = ((const GLushort *) elements)[i];
1188 break;
1189 case GL_UNSIGNED_INT:
1190 j = ((const GLuint *) elements)[i];
1191 break;
1192 default:
1193 unreachable("Unexpected index buffer type");
1194 }
1195
1196 /* check element j of each enabled array */
1197 for (k = 0; k < VERT_ATTRIB_MAX; k++) {
1198 check_array_data(ctx, vao, k, j);
1199 }
1200 }
1201
1202 _mesa_vao_unmap(ctx, vao);
1203 }
1204
1205
1206 /**
1207 * Check array data, looking for NaNs, etc.
1208 */
1209 static void
check_draw_arrays_data(struct gl_context * ctx,GLint start,GLsizei count)1210 check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
1211 {
1212 /* TO DO */
1213 }
1214
1215
1216 /**
1217 * Print info/data for glDrawArrays(), for debugging.
1218 */
1219 static void
print_draw_arrays(struct gl_context * ctx,GLenum mode,GLint start,GLsizei count)1220 print_draw_arrays(struct gl_context *ctx,
1221 GLenum mode, GLint start, GLsizei count)
1222 {
1223 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1224
1225 printf("_mesa_DrawArrays(mode 0x%x, start %d, count %d):\n",
1226 mode, start, count);
1227
1228 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1229
1230 GLbitfield mask = vao->Enabled;
1231 while (mask) {
1232 const gl_vert_attrib i = u_bit_scan(&mask);
1233 const struct gl_array_attributes *array = &vao->VertexAttrib[i];
1234
1235 const struct gl_vertex_buffer_binding *binding =
1236 &vao->BufferBinding[array->BufferBindingIndex];
1237 struct gl_buffer_object *bufObj = binding->BufferObj;
1238
1239 printf("attr %s: size %d stride %d "
1240 "ptr %p Bufobj %u\n",
1241 gl_vert_attrib_name((gl_vert_attrib) i),
1242 array->Format.Size, binding->Stride,
1243 array->Ptr, bufObj ? bufObj->Name : 0);
1244
1245 if (bufObj) {
1246 GLubyte *p = bufObj->Mappings[MAP_INTERNAL].Pointer;
1247 int offset = (int) (GLintptr)
1248 _mesa_vertex_attrib_address(array, binding);
1249
1250 unsigned multiplier;
1251 switch (array->Format.Type) {
1252 case GL_DOUBLE:
1253 case GL_INT64_ARB:
1254 case GL_UNSIGNED_INT64_ARB:
1255 multiplier = 2;
1256 break;
1257 default:
1258 multiplier = 1;
1259 }
1260
1261 float *f = (float *) (p + offset);
1262 int *k = (int *) f;
1263 int i = 0;
1264 int n = (count - 1) * (binding->Stride / (4 * multiplier))
1265 + array->Format.Size;
1266 if (n > 32)
1267 n = 32;
1268 printf(" Data at offset %d:\n", offset);
1269 do {
1270 if (multiplier == 2)
1271 printf(" double[%d] = 0x%016llx %lf\n", i,
1272 ((unsigned long long *) k)[i], ((double *) f)[i]);
1273 else
1274 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
1275 i++;
1276 } while (i < n);
1277 }
1278 }
1279
1280 _mesa_vao_unmap_arrays(ctx, vao);
1281 }
1282
1283
1284 /**
1285 * Helper function called by the other DrawArrays() functions below.
1286 * This is where we handle primitive restart for drawing non-indexed
1287 * arrays. If primitive restart is enabled, it typically means
1288 * splitting one DrawArrays() into two.
1289 */
1290 static void
_mesa_draw_arrays(struct gl_context * ctx,GLenum mode,GLint start,GLsizei count,GLuint numInstances,GLuint baseInstance)1291 _mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
1292 GLsizei count, GLuint numInstances, GLuint baseInstance)
1293 {
1294 /* OpenGL 4.5 says that primitive restart is ignored with non-indexed
1295 * draws.
1296 */
1297 struct pipe_draw_info info;
1298 struct pipe_draw_start_count_bias draw;
1299
1300 info.mode = mode;
1301 info.index_size = 0;
1302 /* Packed section begin. */
1303 info.primitive_restart = false;
1304 info.has_user_indices = false;
1305 info.index_bounds_valid = true;
1306 info.increment_draw_id = false;
1307 info.take_index_buffer_ownership = false;
1308 info.index_bias_varies = false;
1309 /* Packed section end. */
1310 info.start_instance = baseInstance;
1311 info.instance_count = numInstances;
1312 info.view_mask = 0;
1313 info.min_index = start;
1314 info.max_index = start + count - 1;
1315
1316 draw.start = start;
1317 draw.count = count;
1318
1319 ctx->Driver.DrawGallium(ctx, &info, 0, &draw, 1);
1320
1321 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1322 _mesa_flush(ctx);
1323 }
1324 }
1325
1326
1327 /**
1328 * Execute a glRectf() function.
1329 */
1330 void GLAPIENTRY
_mesa_Rectf(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)1331 _mesa_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1332 {
1333 GET_CURRENT_CONTEXT(ctx);
1334 ASSERT_OUTSIDE_BEGIN_END(ctx);
1335
1336 CALL_Begin(ctx->CurrentServerDispatch, (GL_QUADS));
1337 /* Begin can change CurrentServerDispatch. */
1338 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1339 CALL_Vertex2f(dispatch, (x1, y1));
1340 CALL_Vertex2f(dispatch, (x2, y1));
1341 CALL_Vertex2f(dispatch, (x2, y2));
1342 CALL_Vertex2f(dispatch, (x1, y2));
1343 CALL_End(dispatch, ());
1344 }
1345
1346
1347 void GLAPIENTRY
_mesa_Rectd(GLdouble x1,GLdouble y1,GLdouble x2,GLdouble y2)1348 _mesa_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1349 {
1350 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1351 }
1352
1353 void GLAPIENTRY
_mesa_Rectdv(const GLdouble * v1,const GLdouble * v2)1354 _mesa_Rectdv(const GLdouble *v1, const GLdouble *v2)
1355 {
1356 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1357 }
1358
1359 void GLAPIENTRY
_mesa_Rectfv(const GLfloat * v1,const GLfloat * v2)1360 _mesa_Rectfv(const GLfloat *v1, const GLfloat *v2)
1361 {
1362 _mesa_Rectf(v1[0], v1[1], v2[0], v2[1]);
1363 }
1364
1365 void GLAPIENTRY
_mesa_Recti(GLint x1,GLint y1,GLint x2,GLint y2)1366 _mesa_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1367 {
1368 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1369 }
1370
1371 void GLAPIENTRY
_mesa_Rectiv(const GLint * v1,const GLint * v2)1372 _mesa_Rectiv(const GLint *v1, const GLint *v2)
1373 {
1374 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1375 }
1376
1377 void GLAPIENTRY
_mesa_Rects(GLshort x1,GLshort y1,GLshort x2,GLshort y2)1378 _mesa_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1379 {
1380 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1381 }
1382
1383 void GLAPIENTRY
_mesa_Rectsv(const GLshort * v1,const GLshort * v2)1384 _mesa_Rectsv(const GLshort *v1, const GLshort *v2)
1385 {
1386 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1387 }
1388
1389
1390 void GLAPIENTRY
_mesa_EvalMesh1(GLenum mode,GLint i1,GLint i2)1391 _mesa_EvalMesh1(GLenum mode, GLint i1, GLint i2)
1392 {
1393 GET_CURRENT_CONTEXT(ctx);
1394 GLint i;
1395 GLfloat u, du;
1396 GLenum prim;
1397
1398 switch (mode) {
1399 case GL_POINT:
1400 prim = GL_POINTS;
1401 break;
1402 case GL_LINE:
1403 prim = GL_LINE_STRIP;
1404 break;
1405 default:
1406 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)");
1407 return;
1408 }
1409
1410 /* No effect if vertex maps disabled.
1411 */
1412 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
1413 return;
1414
1415 du = ctx->Eval.MapGrid1du;
1416 u = ctx->Eval.MapGrid1u1 + i1 * du;
1417
1418
1419 CALL_Begin(ctx->CurrentServerDispatch, (prim));
1420 /* Begin can change CurrentServerDispatch. */
1421 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1422 for (i = i1; i <= i2; i++, u += du) {
1423 CALL_EvalCoord1f(dispatch, (u));
1424 }
1425 CALL_End(dispatch, ());
1426 }
1427
1428
1429 void GLAPIENTRY
_mesa_EvalMesh2(GLenum mode,GLint i1,GLint i2,GLint j1,GLint j2)1430 _mesa_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
1431 {
1432 GET_CURRENT_CONTEXT(ctx);
1433 GLfloat u, du, v, dv, v1, u1;
1434 GLint i, j;
1435
1436 switch (mode) {
1437 case GL_POINT:
1438 case GL_LINE:
1439 case GL_FILL:
1440 break;
1441 default:
1442 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)");
1443 return;
1444 }
1445
1446 /* No effect if vertex maps disabled.
1447 */
1448 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
1449 return;
1450
1451 du = ctx->Eval.MapGrid2du;
1452 dv = ctx->Eval.MapGrid2dv;
1453 v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
1454 u1 = ctx->Eval.MapGrid2u1 + i1 * du;
1455
1456 struct _glapi_table *dispatch;
1457
1458 switch (mode) {
1459 case GL_POINT:
1460 CALL_Begin(ctx->CurrentServerDispatch, (GL_POINTS));
1461 /* Begin can change CurrentServerDispatch. */
1462 dispatch = ctx->CurrentServerDispatch;
1463 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1464 for (u = u1, i = i1; i <= i2; i++, u += du) {
1465 CALL_EvalCoord2f(dispatch, (u, v));
1466 }
1467 }
1468 CALL_End(dispatch, ());
1469 break;
1470 case GL_LINE:
1471 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1472 CALL_Begin(ctx->CurrentServerDispatch, (GL_LINE_STRIP));
1473 /* Begin can change CurrentServerDispatch. */
1474 dispatch = ctx->CurrentServerDispatch;
1475 for (u = u1, i = i1; i <= i2; i++, u += du) {
1476 CALL_EvalCoord2f(dispatch, (u, v));
1477 }
1478 CALL_End(dispatch, ());
1479 }
1480 for (u = u1, i = i1; i <= i2; i++, u += du) {
1481 CALL_Begin(ctx->CurrentServerDispatch, (GL_LINE_STRIP));
1482 /* Begin can change CurrentServerDispatch. */
1483 dispatch = ctx->CurrentServerDispatch;
1484 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1485 CALL_EvalCoord2f(dispatch, (u, v));
1486 }
1487 CALL_End(dispatch, ());
1488 }
1489 break;
1490 case GL_FILL:
1491 for (v = v1, j = j1; j < j2; j++, v += dv) {
1492 CALL_Begin(ctx->CurrentServerDispatch, (GL_TRIANGLE_STRIP));
1493 /* Begin can change CurrentServerDispatch. */
1494 dispatch = ctx->CurrentServerDispatch;
1495 for (u = u1, i = i1; i <= i2; i++, u += du) {
1496 CALL_EvalCoord2f(dispatch, (u, v));
1497 CALL_EvalCoord2f(dispatch, (u, v + dv));
1498 }
1499 CALL_End(dispatch, ());
1500 }
1501 break;
1502 }
1503 }
1504
1505
1506 /**
1507 * Called from glDrawArrays when in immediate mode (not display list mode).
1508 */
1509 void GLAPIENTRY
_mesa_DrawArrays(GLenum mode,GLint start,GLsizei count)1510 _mesa_DrawArrays(GLenum mode, GLint start, GLsizei count)
1511 {
1512 GET_CURRENT_CONTEXT(ctx);
1513 FLUSH_FOR_DRAW(ctx);
1514
1515 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1516 ctx->VertexProgram._VPModeInputFilter);
1517
1518 if (ctx->NewState)
1519 _mesa_update_state(ctx);
1520
1521 if (!_mesa_is_no_error_enabled(ctx) &&
1522 !_mesa_validate_DrawArrays(ctx, mode, count))
1523 return;
1524
1525 if (0)
1526 check_draw_arrays_data(ctx, start, count);
1527
1528 _mesa_draw_arrays(ctx, mode, start, count, 1, 0);
1529
1530 if (0)
1531 print_draw_arrays(ctx, mode, start, count);
1532 }
1533
1534
1535 /**
1536 * Called from glDrawArraysInstanced when in immediate mode (not
1537 * display list mode).
1538 */
1539 void GLAPIENTRY
_mesa_DrawArraysInstancedARB(GLenum mode,GLint start,GLsizei count,GLsizei numInstances)1540 _mesa_DrawArraysInstancedARB(GLenum mode, GLint start, GLsizei count,
1541 GLsizei numInstances)
1542 {
1543 GET_CURRENT_CONTEXT(ctx);
1544 FLUSH_FOR_DRAW(ctx);
1545
1546 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1547 ctx->VertexProgram._VPModeInputFilter);
1548
1549 if (ctx->NewState)
1550 _mesa_update_state(ctx);
1551
1552 if (!_mesa_is_no_error_enabled(ctx) &&
1553 !_mesa_validate_DrawArraysInstanced(ctx, mode, start, count,
1554 numInstances))
1555 return;
1556
1557 if (0)
1558 check_draw_arrays_data(ctx, start, count);
1559
1560 _mesa_draw_arrays(ctx, mode, start, count, numInstances, 0);
1561
1562 if (0)
1563 print_draw_arrays(ctx, mode, start, count);
1564 }
1565
1566
1567 /**
1568 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
1569 */
1570 void GLAPIENTRY
_mesa_DrawArraysInstancedBaseInstance(GLenum mode,GLint first,GLsizei count,GLsizei numInstances,GLuint baseInstance)1571 _mesa_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
1572 GLsizei count, GLsizei numInstances,
1573 GLuint baseInstance)
1574 {
1575 GET_CURRENT_CONTEXT(ctx);
1576 FLUSH_FOR_DRAW(ctx);
1577
1578 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1579 ctx->VertexProgram._VPModeInputFilter);
1580
1581 if (ctx->NewState)
1582 _mesa_update_state(ctx);
1583
1584 if (!_mesa_is_no_error_enabled(ctx) &&
1585 !_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
1586 numInstances))
1587 return;
1588
1589 if (0)
1590 check_draw_arrays_data(ctx, first, count);
1591
1592 _mesa_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
1593
1594 if (0)
1595 print_draw_arrays(ctx, mode, first, count);
1596 }
1597
1598
1599 /**
1600 * Called from glMultiDrawArrays when in immediate mode.
1601 */
1602 void GLAPIENTRY
_mesa_MultiDrawArrays(GLenum mode,const GLint * first,const GLsizei * count,GLsizei primcount)1603 _mesa_MultiDrawArrays(GLenum mode, const GLint *first,
1604 const GLsizei *count, GLsizei primcount)
1605 {
1606 GET_CURRENT_CONTEXT(ctx);
1607 FLUSH_FOR_DRAW(ctx);
1608
1609 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1610 ctx->VertexProgram._VPModeInputFilter);
1611
1612 if (ctx->NewState)
1613 _mesa_update_state(ctx);
1614
1615 if (!_mesa_is_no_error_enabled(ctx) &&
1616 !_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount))
1617 return;
1618
1619 if (primcount == 0)
1620 return;
1621
1622 struct pipe_draw_info info;
1623 struct pipe_draw_start_count_bias *draw;
1624
1625 ALLOC_PRIMS(draw, primcount, "glMultiDrawElements");
1626
1627 info.mode = mode;
1628 info.index_size = 0;
1629 /* Packed section begin. */
1630 info.primitive_restart = false;
1631 info.has_user_indices = false;
1632 info.index_bounds_valid = false;
1633 info.increment_draw_id = primcount > 1;
1634 info.take_index_buffer_ownership = false;
1635 info.index_bias_varies = false;
1636 /* Packed section end. */
1637 info.start_instance = 0;
1638 info.instance_count = 1;
1639 info.view_mask = 0;
1640
1641 for (int i = 0; i < primcount; i++) {
1642 draw[i].start = first[i];
1643 draw[i].count = count[i];
1644 }
1645
1646 ctx->Driver.DrawGallium(ctx, &info, 0, draw, primcount);
1647
1648 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1649 _mesa_flush(ctx);
1650
1651 FREE_PRIMS(draw, primcount);
1652 }
1653
1654
1655
1656 /**
1657 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
1658 * For debugging.
1659 */
1660 #if 0
1661 static void
1662 dump_element_buffer(struct gl_context *ctx, GLenum type)
1663 {
1664 const GLvoid *map =
1665 ctx->Driver.MapBufferRange(ctx, 0,
1666 ctx->Array.VAO->IndexBufferObj->Size,
1667 GL_MAP_READ_BIT,
1668 ctx->Array.VAO->IndexBufferObj,
1669 MAP_INTERNAL);
1670 switch (type) {
1671 case GL_UNSIGNED_BYTE:
1672 {
1673 const GLubyte *us = (const GLubyte *) map;
1674 GLint i;
1675 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) {
1676 printf("%02x ", us[i]);
1677 if (i % 32 == 31)
1678 printf("\n");
1679 }
1680 printf("\n");
1681 }
1682 break;
1683 case GL_UNSIGNED_SHORT:
1684 {
1685 const GLushort *us = (const GLushort *) map;
1686 GLint i;
1687 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) {
1688 printf("%04x ", us[i]);
1689 if (i % 16 == 15)
1690 printf("\n");
1691 }
1692 printf("\n");
1693 }
1694 break;
1695 case GL_UNSIGNED_INT:
1696 {
1697 const GLuint *us = (const GLuint *) map;
1698 GLint i;
1699 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) {
1700 printf("%08x ", us[i]);
1701 if (i % 8 == 7)
1702 printf("\n");
1703 }
1704 printf("\n");
1705 }
1706 break;
1707 default:
1708 ;
1709 }
1710
1711 ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL);
1712 }
1713 #endif
1714
1715
1716 /**
1717 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
1718 * Do the rendering for a glDrawElements or glDrawRangeElements call after
1719 * we've validated buffer bounds, etc.
1720 */
1721 static void
_mesa_validated_drawrangeelements(struct gl_context * ctx,GLenum mode,bool index_bounds_valid,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex,GLuint numInstances,GLuint baseInstance)1722 _mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
1723 bool index_bounds_valid,
1724 GLuint start, GLuint end,
1725 GLsizei count, GLenum type,
1726 const GLvoid * indices,
1727 GLint basevertex, GLuint numInstances,
1728 GLuint baseInstance)
1729 {
1730 if (!index_bounds_valid) {
1731 assert(start == 0u);
1732 assert(end == ~0u);
1733 }
1734
1735 struct pipe_draw_info info;
1736 struct pipe_draw_start_count_bias draw;
1737 unsigned index_size_shift = get_index_size_shift(type);
1738 struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
1739
1740 if (index_bo && !indices_aligned(index_size_shift, indices))
1741 return;
1742
1743 info.mode = mode;
1744 info.index_size = 1 << index_size_shift;
1745 /* Packed section begin. */
1746 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
1747 info.has_user_indices = index_bo == NULL;
1748 info.index_bounds_valid = index_bounds_valid;
1749 info.increment_draw_id = false;
1750 info.take_index_buffer_ownership = false;
1751 info.index_bias_varies = false;
1752 /* Packed section end. */
1753 info.start_instance = baseInstance;
1754 info.instance_count = numInstances;
1755 info.view_mask = 0;
1756 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
1757
1758 if (info.has_user_indices) {
1759 info.index.user = indices;
1760 draw.start = 0;
1761 } else {
1762 info.index.gl_bo = index_bo;
1763 draw.start = (uintptr_t)indices >> index_size_shift;
1764 }
1765 draw.index_bias = basevertex;
1766
1767 info.min_index = start;
1768 info.max_index = end;
1769 draw.count = count;
1770
1771 /* Need to give special consideration to rendering a range of
1772 * indices starting somewhere above zero. Typically the
1773 * application is issuing multiple DrawRangeElements() to draw
1774 * successive primitives layed out linearly in the vertex arrays.
1775 * Unless the vertex arrays are all in a VBO (or locked as with
1776 * CVA), the OpenGL semantics imply that we need to re-read or
1777 * re-upload the vertex data on each draw call.
1778 *
1779 * In the case of hardware tnl, we want to avoid starting the
1780 * upload at zero, as it will mean every draw call uploads an
1781 * increasing amount of not-used vertex data. Worse - in the
1782 * software tnl module, all those vertices might be transformed and
1783 * lit but never rendered.
1784 *
1785 * If we just upload or transform the vertices in start..end,
1786 * however, the indices will be incorrect.
1787 *
1788 * At this level, we don't know exactly what the requirements of
1789 * the backend are going to be, though it will likely boil down to
1790 * either:
1791 *
1792 * 1) Do nothing, everything is in a VBO and is processed once
1793 * only.
1794 *
1795 * 2) Adjust the indices and vertex arrays so that start becomes
1796 * zero.
1797 *
1798 * Rather than doing anything here, I'll provide a helper function
1799 * for the latter case elsewhere.
1800 */
1801
1802 ctx->Driver.DrawGallium(ctx, &info, 0, &draw, 1);
1803
1804 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1805 _mesa_flush(ctx);
1806 }
1807 }
1808
1809
1810 /**
1811 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
1812 */
1813 void GLAPIENTRY
_mesa_DrawRangeElementsBaseVertex(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1814 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1815 GLsizei count, GLenum type,
1816 const GLvoid * indices, GLint basevertex)
1817 {
1818 static GLuint warnCount = 0;
1819 bool index_bounds_valid = true;
1820
1821 /* This is only useful to catch invalid values in the "end" parameter
1822 * like ~0.
1823 */
1824 GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
1825
1826 GET_CURRENT_CONTEXT(ctx);
1827 FLUSH_FOR_DRAW(ctx);
1828
1829 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1830 ctx->VertexProgram._VPModeInputFilter);
1831
1832 if (ctx->NewState)
1833 _mesa_update_state(ctx);
1834
1835 if (!_mesa_is_no_error_enabled(ctx) &&
1836 !_mesa_validate_DrawRangeElements(ctx, mode, start, end, count,
1837 type))
1838 return;
1839
1840 if ((int) end + basevertex < 0 || start + basevertex >= max_element) {
1841 /* The application requested we draw using a range of indices that's
1842 * outside the bounds of the current VBO. This is invalid and appears
1843 * to give undefined results. The safest thing to do is to simply
1844 * ignore the range, in case the application botched their range tracking
1845 * but did provide valid indices. Also issue a warning indicating that
1846 * the application is broken.
1847 */
1848 if (warnCount++ < 10) {
1849 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
1850 "basevertex %d, count %d, type 0x%x, indices=%p):\n"
1851 "\trange is outside VBO bounds (max=%u); ignoring.\n"
1852 "\tThis should be fixed in the application.",
1853 start, end, basevertex, count, type, indices,
1854 max_element - 1);
1855 }
1856 index_bounds_valid = false;
1857 }
1858
1859 /* NOTE: It's important that 'end' is a reasonable value.
1860 * in _tnl_draw_prims(), we use end to determine how many vertices
1861 * to transform. If it's too large, we can unnecessarily split prims
1862 * or we can read/write out of memory in several different places!
1863 */
1864
1865 /* Catch/fix some potential user errors */
1866 if (type == GL_UNSIGNED_BYTE) {
1867 start = MIN2(start, 0xff);
1868 end = MIN2(end, 0xff);
1869 }
1870 else if (type == GL_UNSIGNED_SHORT) {
1871 start = MIN2(start, 0xffff);
1872 end = MIN2(end, 0xffff);
1873 }
1874
1875 if (0) {
1876 printf("glDraw[Range]Elements{,BaseVertex}"
1877 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
1878 "base %d\n",
1879 start, end, type, count,
1880 ctx->Array.VAO->IndexBufferObj ?
1881 ctx->Array.VAO->IndexBufferObj->Name : 0, basevertex);
1882 }
1883
1884 if ((int) start + basevertex < 0 || end + basevertex >= max_element)
1885 index_bounds_valid = false;
1886
1887 #if 0
1888 check_draw_elements_data(ctx, count, type, indices, basevertex);
1889 #else
1890 (void) check_draw_elements_data;
1891 #endif
1892
1893 if (!index_bounds_valid) {
1894 start = 0;
1895 end = ~0;
1896 }
1897
1898 _mesa_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
1899 count, type, indices, basevertex, 1, 0);
1900 }
1901
1902
1903 /**
1904 * Called by glDrawRangeElements() in immediate mode.
1905 */
1906 void GLAPIENTRY
_mesa_DrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)1907 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1908 GLsizei count, GLenum type, const GLvoid * indices)
1909 {
1910 _mesa_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1911 indices, 0);
1912 }
1913
1914
1915 /**
1916 * Called by glDrawElements() in immediate mode.
1917 */
1918 void GLAPIENTRY
_mesa_DrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)1919 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1920 const GLvoid * indices)
1921 {
1922 GET_CURRENT_CONTEXT(ctx);
1923 FLUSH_FOR_DRAW(ctx);
1924
1925 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1926 ctx->VertexProgram._VPModeInputFilter);
1927
1928 if (ctx->NewState)
1929 _mesa_update_state(ctx);
1930
1931 if (!_mesa_is_no_error_enabled(ctx) &&
1932 !_mesa_validate_DrawElements(ctx, mode, count, type))
1933 return;
1934
1935 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
1936 count, type, indices, 0, 1, 0);
1937 }
1938
1939
1940 /**
1941 * Called by glDrawElementsBaseVertex() in immediate mode.
1942 */
1943 void GLAPIENTRY
_mesa_DrawElementsBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1944 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1945 const GLvoid * indices, GLint basevertex)
1946 {
1947 GET_CURRENT_CONTEXT(ctx);
1948 FLUSH_FOR_DRAW(ctx);
1949
1950 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1951 ctx->VertexProgram._VPModeInputFilter);
1952
1953 if (ctx->NewState)
1954 _mesa_update_state(ctx);
1955
1956 if (!_mesa_is_no_error_enabled(ctx) &&
1957 !_mesa_validate_DrawElements(ctx, mode, count, type))
1958 return;
1959
1960 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
1961 count, type, indices, basevertex, 1, 0);
1962 }
1963
1964
1965 /**
1966 * Called by glDrawElementsInstanced() in immediate mode.
1967 */
1968 void GLAPIENTRY
_mesa_DrawElementsInstancedARB(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances)1969 _mesa_DrawElementsInstancedARB(GLenum mode, GLsizei count, GLenum type,
1970 const GLvoid * indices, GLsizei numInstances)
1971 {
1972 GET_CURRENT_CONTEXT(ctx);
1973 FLUSH_FOR_DRAW(ctx);
1974
1975 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1976 ctx->VertexProgram._VPModeInputFilter);
1977
1978 if (ctx->NewState)
1979 _mesa_update_state(ctx);
1980
1981 if (!_mesa_is_no_error_enabled(ctx) &&
1982 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1983 numInstances))
1984 return;
1985
1986 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
1987 count, type, indices, 0, numInstances, 0);
1988 }
1989
1990
1991 /**
1992 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1993 */
1994 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLint basevertex)1995 _mesa_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count,
1996 GLenum type, const GLvoid * indices,
1997 GLsizei numInstances,
1998 GLint basevertex)
1999 {
2000 GET_CURRENT_CONTEXT(ctx);
2001 FLUSH_FOR_DRAW(ctx);
2002
2003 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2004 ctx->VertexProgram._VPModeInputFilter);
2005
2006 if (ctx->NewState)
2007 _mesa_update_state(ctx);
2008
2009 if (!_mesa_is_no_error_enabled(ctx) &&
2010 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
2011 numInstances))
2012 return;
2013
2014 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
2015 count, type, indices,
2016 basevertex, numInstances, 0);
2017 }
2018
2019
2020 /**
2021 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
2022 */
2023 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLuint baseInstance)2024 _mesa_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,
2025 GLenum type,
2026 const GLvoid *indices,
2027 GLsizei numInstances,
2028 GLuint baseInstance)
2029 {
2030 GET_CURRENT_CONTEXT(ctx);
2031 FLUSH_FOR_DRAW(ctx);
2032
2033 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2034 ctx->VertexProgram._VPModeInputFilter);
2035
2036 if (ctx->NewState)
2037 _mesa_update_state(ctx);
2038
2039 if (!_mesa_is_no_error_enabled(ctx) &&
2040 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
2041 numInstances))
2042 return;
2043
2044 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
2045 count, type, indices, 0, numInstances,
2046 baseInstance);
2047 }
2048
2049
2050 /**
2051 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
2052 */
2053 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLint basevertex,GLuint baseInstance)2054 _mesa_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
2055 GLsizei count,
2056 GLenum type,
2057 const GLvoid *indices,
2058 GLsizei numInstances,
2059 GLint basevertex,
2060 GLuint baseInstance)
2061 {
2062 GET_CURRENT_CONTEXT(ctx);
2063 FLUSH_FOR_DRAW(ctx);
2064
2065 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2066 ctx->VertexProgram._VPModeInputFilter);
2067
2068 if (ctx->NewState)
2069 _mesa_update_state(ctx);
2070
2071 if (!_mesa_is_no_error_enabled(ctx) &&
2072 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
2073 numInstances))
2074 return;
2075
2076 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
2077 count, type, indices, basevertex,
2078 numInstances, baseInstance);
2079 }
2080
2081
2082 /**
2083 * Inner support for both _mesa_MultiDrawElements() and
2084 * _mesa_MultiDrawRangeElements().
2085 * This does the actual rendering after we've checked array indexes, etc.
2086 */
2087 static void
_mesa_validated_multidrawelements(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,const GLint * basevertex)2088 _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
2089 const GLsizei *count, GLenum type,
2090 const GLvoid * const *indices,
2091 GLsizei primcount, const GLint *basevertex)
2092 {
2093 uintptr_t min_index_ptr, max_index_ptr;
2094 bool fallback = false;
2095 int i;
2096
2097 if (primcount == 0)
2098 return;
2099
2100 unsigned index_size_shift = get_index_size_shift(type);
2101
2102 min_index_ptr = (uintptr_t) indices[0];
2103 max_index_ptr = 0;
2104 for (i = 0; i < primcount; i++) {
2105 min_index_ptr = MIN2(min_index_ptr, (uintptr_t) indices[i]);
2106 max_index_ptr = MAX2(max_index_ptr, (uintptr_t) indices[i] +
2107 (count[i] << index_size_shift));
2108 }
2109
2110 /* Check if we can handle this thing as a bunch of index offsets from the
2111 * same index pointer. If we can't, then we have to fall back to doing
2112 * a draw_prims per primitive.
2113 * Check that the difference between each prim's indexes is a multiple of
2114 * the index/element size.
2115 */
2116 if (index_size_shift) {
2117 for (i = 0; i < primcount; i++) {
2118 if ((((uintptr_t) indices[i] - min_index_ptr) &
2119 ((1 << index_size_shift) - 1)) != 0) {
2120 fallback = true;
2121 break;
2122 }
2123 }
2124 }
2125
2126 struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
2127 struct pipe_draw_info info;
2128
2129 info.mode = mode;
2130 info.index_size = 1 << index_size_shift;
2131 /* Packed section begin. */
2132 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
2133 info.has_user_indices = index_bo == NULL;
2134 info.index_bounds_valid = false;
2135 info.increment_draw_id = primcount > 1;
2136 info.take_index_buffer_ownership = false;
2137 info.index_bias_varies = !!basevertex;
2138 /* Packed section end. */
2139 info.start_instance = 0;
2140 info.instance_count = 1;
2141 info.view_mask = 0;
2142 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
2143
2144 if (info.has_user_indices)
2145 info.index.user = (void*)min_index_ptr;
2146 else
2147 info.index.gl_bo = index_bo;
2148
2149 if (!fallback &&
2150 (!info.has_user_indices ||
2151 /* "max_index_ptr - min_index_ptr >> index_size_shift" is stored
2152 * in draw[i].start. The driver will multiply it later by index_size
2153 * so make sure the final value won't overflow.
2154 *
2155 * For real index buffers, gallium doesn't support index buffer offsets
2156 * greater than UINT32_MAX bytes.
2157 */
2158 max_index_ptr - min_index_ptr <= UINT32_MAX)) {
2159 struct pipe_draw_start_count_bias *draw;
2160
2161 ALLOC_PRIMS(draw, primcount, "glMultiDrawElements");
2162
2163 if (info.has_user_indices) {
2164 for (int i = 0; i < primcount; i++) {
2165 draw[i].start =
2166 ((uintptr_t)indices[i] - min_index_ptr) >> index_size_shift;
2167 draw[i].count = count[i];
2168 draw[i].index_bias = basevertex ? basevertex[i] : 0;
2169 }
2170 } else {
2171 for (int i = 0; i < primcount; i++) {
2172 draw[i].start = (uintptr_t)indices[i] >> index_size_shift;
2173 draw[i].count =
2174 indices_aligned(index_size_shift, indices[i]) ? count[i] : 0;
2175 draw[i].index_bias = basevertex ? basevertex[i] : 0;
2176 }
2177 }
2178
2179 ctx->Driver.DrawGallium(ctx, &info, 0, draw, primcount);
2180 FREE_PRIMS(draw, primcount);
2181 } else {
2182 /* draw[i].start would overflow. Draw one at a time. */
2183 assert(info.has_user_indices);
2184 info.increment_draw_id = false;
2185
2186 for (int i = 0; i < primcount; i++) {
2187 struct pipe_draw_start_count_bias draw;
2188
2189 if (!count[i])
2190 continue;
2191
2192 /* Reset these, because the callee can change them. */
2193 info.index_bounds_valid = false;
2194 info.index.user = indices[i];
2195 draw.start = 0;
2196 draw.index_bias = basevertex ? basevertex[i] : 0;
2197 draw.count = count[i];
2198
2199 ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1);
2200 }
2201 }
2202
2203 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
2204 _mesa_flush(ctx);
2205 }
2206 }
2207
2208
2209 void GLAPIENTRY
_mesa_MultiDrawElementsEXT(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount)2210 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
2211 const GLvoid * const *indices, GLsizei primcount)
2212 {
2213 GET_CURRENT_CONTEXT(ctx);
2214 FLUSH_FOR_DRAW(ctx);
2215
2216 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2217 ctx->VertexProgram._VPModeInputFilter);
2218
2219 if (ctx->NewState)
2220 _mesa_update_state(ctx);
2221
2222 if (!_mesa_is_no_error_enabled(ctx) &&
2223 !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
2224 primcount))
2225 return;
2226
2227 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
2228 NULL);
2229 }
2230
2231
2232 void GLAPIENTRY
_mesa_MultiDrawElementsBaseVertex(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,const GLsizei * basevertex)2233 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
2234 const GLsizei *count, GLenum type,
2235 const GLvoid * const *indices,
2236 GLsizei primcount,
2237 const GLsizei *basevertex)
2238 {
2239 GET_CURRENT_CONTEXT(ctx);
2240 FLUSH_FOR_DRAW(ctx);
2241
2242 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2243 ctx->VertexProgram._VPModeInputFilter);
2244
2245 if (ctx->NewState)
2246 _mesa_update_state(ctx);
2247
2248 if (!_mesa_is_no_error_enabled(ctx) &&
2249 !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
2250 primcount))
2251 return;
2252
2253 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
2254 basevertex);
2255 }
2256
2257
2258 /**
2259 * Draw a GL primitive using a vertex count obtained from transform feedback.
2260 * \param mode the type of GL primitive to draw
2261 * \param obj the transform feedback object to use
2262 * \param stream index of the transform feedback stream from which to
2263 * get the primitive count.
2264 * \param numInstances number of instances to draw
2265 */
2266 static void
_mesa_draw_transform_feedback(struct gl_context * ctx,GLenum mode,struct gl_transform_feedback_object * obj,GLuint stream,GLuint numInstances)2267 _mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
2268 struct gl_transform_feedback_object *obj,
2269 GLuint stream, GLuint numInstances)
2270 {
2271 FLUSH_FOR_DRAW(ctx);
2272
2273 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2274 ctx->VertexProgram._VPModeInputFilter);
2275
2276 if (ctx->NewState)
2277 _mesa_update_state(ctx);
2278
2279 if (!_mesa_is_no_error_enabled(ctx) &&
2280 !_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
2281 numInstances))
2282 return;
2283
2284 if (ctx->Driver.GetTransformFeedbackVertexCount &&
2285 (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
2286 !_mesa_all_varyings_in_vbos(ctx->Array.VAO))) {
2287 GLsizei n =
2288 ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
2289 _mesa_draw_arrays(ctx, mode, 0, n, numInstances, 0);
2290 return;
2291 }
2292
2293 /* Maybe we should do some primitive splitting for primitive restart
2294 * (like in DrawArrays), but we have no way to know how many vertices
2295 * will be rendered. */
2296
2297 ctx->Driver.DrawTransformFeedback(ctx, mode, numInstances, stream, obj);
2298
2299 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
2300 _mesa_flush(ctx);
2301 }
2302 }
2303
2304
2305 /**
2306 * Like DrawArrays, but take the count from a transform feedback object.
2307 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
2308 * \param name the transform feedback object
2309 * User still has to setup of the vertex attribute info with
2310 * glVertexPointer, glColorPointer, etc.
2311 * Part of GL_ARB_transform_feedback2.
2312 */
2313 void GLAPIENTRY
_mesa_DrawTransformFeedback(GLenum mode,GLuint name)2314 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
2315 {
2316 GET_CURRENT_CONTEXT(ctx);
2317 struct gl_transform_feedback_object *obj =
2318 _mesa_lookup_transform_feedback_object(ctx, name);
2319
2320 _mesa_draw_transform_feedback(ctx, mode, obj, 0, 1);
2321 }
2322
2323
2324 void GLAPIENTRY
_mesa_DrawTransformFeedbackStream(GLenum mode,GLuint name,GLuint stream)2325 _mesa_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
2326 {
2327 GET_CURRENT_CONTEXT(ctx);
2328 struct gl_transform_feedback_object *obj =
2329 _mesa_lookup_transform_feedback_object(ctx, name);
2330
2331 _mesa_draw_transform_feedback(ctx, mode, obj, stream, 1);
2332 }
2333
2334
2335 void GLAPIENTRY
_mesa_DrawTransformFeedbackInstanced(GLenum mode,GLuint name,GLsizei primcount)2336 _mesa_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
2337 GLsizei primcount)
2338 {
2339 GET_CURRENT_CONTEXT(ctx);
2340 struct gl_transform_feedback_object *obj =
2341 _mesa_lookup_transform_feedback_object(ctx, name);
2342
2343 _mesa_draw_transform_feedback(ctx, mode, obj, 0, primcount);
2344 }
2345
2346
2347 void GLAPIENTRY
_mesa_DrawTransformFeedbackStreamInstanced(GLenum mode,GLuint name,GLuint stream,GLsizei primcount)2348 _mesa_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
2349 GLuint stream,
2350 GLsizei primcount)
2351 {
2352 GET_CURRENT_CONTEXT(ctx);
2353 struct gl_transform_feedback_object *obj =
2354 _mesa_lookup_transform_feedback_object(ctx, name);
2355
2356 _mesa_draw_transform_feedback(ctx, mode, obj, stream, primcount);
2357 }
2358
2359
2360 static void
_mesa_validated_multidrawarraysindirect(struct gl_context * ctx,GLenum mode,GLintptr indirect,GLintptr drawcount_offset,GLsizei drawcount,GLsizei stride,struct gl_buffer_object * drawcount_buffer)2361 _mesa_validated_multidrawarraysindirect(struct gl_context *ctx, GLenum mode,
2362 GLintptr indirect,
2363 GLintptr drawcount_offset,
2364 GLsizei drawcount, GLsizei stride,
2365 struct gl_buffer_object *drawcount_buffer)
2366 {
2367 /* If drawcount_buffer is set, drawcount is the maximum draw count.*/
2368 if (drawcount == 0)
2369 return;
2370
2371 ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, indirect,
2372 drawcount, stride, drawcount_buffer,
2373 drawcount_offset, NULL, false, 0);
2374
2375 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
2376 _mesa_flush(ctx);
2377 }
2378
2379
2380 static void
_mesa_validated_multidrawelementsindirect(struct gl_context * ctx,GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount_offset,GLsizei drawcount,GLsizei stride,struct gl_buffer_object * drawcount_buffer)2381 _mesa_validated_multidrawelementsindirect(struct gl_context *ctx,
2382 GLenum mode, GLenum type,
2383 GLintptr indirect,
2384 GLintptr drawcount_offset,
2385 GLsizei drawcount, GLsizei stride,
2386 struct gl_buffer_object *drawcount_buffer)
2387 {
2388 /* If drawcount_buffer is set, drawcount is the maximum draw count.*/
2389 if (drawcount == 0)
2390 return;
2391
2392 /* NOTE: IndexBufferObj is guaranteed to be a VBO. */
2393 struct _mesa_index_buffer ib;
2394 ib.count = 0; /* unknown */
2395 ib.obj = ctx->Array.VAO->IndexBufferObj;
2396 ib.ptr = NULL;
2397 ib.index_size_shift = get_index_size_shift(type);
2398
2399 ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, indirect,
2400 drawcount, stride, drawcount_buffer,
2401 drawcount_offset, &ib,
2402 ctx->Array._PrimitiveRestart[ib.index_size_shift],
2403 ctx->Array._RestartIndex[ib.index_size_shift]);
2404
2405 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
2406 _mesa_flush(ctx);
2407 }
2408
2409
2410 /**
2411 * Like [Multi]DrawArrays/Elements, but they take most arguments from
2412 * a buffer object.
2413 */
2414 void GLAPIENTRY
_mesa_DrawArraysIndirect(GLenum mode,const GLvoid * indirect)2415 _mesa_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
2416 {
2417 GET_CURRENT_CONTEXT(ctx);
2418
2419 /* From the ARB_draw_indirect spec:
2420 *
2421 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2422 * compatibility profile, this indicates that DrawArraysIndirect and
2423 * DrawElementsIndirect are to source their arguments directly from the
2424 * pointer passed as their <indirect> parameters."
2425 */
2426 if (ctx->API == API_OPENGL_COMPAT &&
2427 !ctx->DrawIndirectBuffer) {
2428 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect;
2429
2430 _mesa_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count,
2431 cmd->primCount,
2432 cmd->baseInstance);
2433 return;
2434 }
2435
2436 FLUSH_FOR_DRAW(ctx);
2437
2438 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2439 ctx->VertexProgram._VPModeInputFilter);
2440
2441 if (ctx->NewState)
2442 _mesa_update_state(ctx);
2443
2444 if (!_mesa_is_no_error_enabled(ctx) &&
2445 !_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
2446 return;
2447
2448 _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect,
2449 0, 1, 16, NULL);
2450 }
2451
2452
2453 void GLAPIENTRY
_mesa_DrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect)2454 _mesa_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
2455 {
2456 GET_CURRENT_CONTEXT(ctx);
2457
2458 /* From the ARB_draw_indirect spec:
2459 *
2460 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2461 * compatibility profile, this indicates that DrawArraysIndirect and
2462 * DrawElementsIndirect are to source their arguments directly from the
2463 * pointer passed as their <indirect> parameters."
2464 */
2465 if (ctx->API == API_OPENGL_COMPAT &&
2466 !ctx->DrawIndirectBuffer) {
2467 /*
2468 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
2469 * may not come from a client array and must come from an index buffer.
2470 * If no element array buffer is bound, an INVALID_OPERATION error is
2471 * generated.
2472 */
2473 if (!ctx->Array.VAO->IndexBufferObj) {
2474 _mesa_error(ctx, GL_INVALID_OPERATION,
2475 "glDrawElementsIndirect(no buffer bound "
2476 "to GL_ELEMENT_ARRAY_BUFFER)");
2477 } else {
2478 DrawElementsIndirectCommand *cmd =
2479 (DrawElementsIndirectCommand *) indirect;
2480
2481 /* Convert offset to pointer */
2482 void *offset = (void *)
2483 (uintptr_t)((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL);
2484
2485 _mesa_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count,
2486 type, offset,
2487 cmd->primCount,
2488 cmd->baseVertex,
2489 cmd->baseInstance);
2490 }
2491
2492 return;
2493 }
2494
2495 FLUSH_FOR_DRAW(ctx);
2496
2497 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2498 ctx->VertexProgram._VPModeInputFilter);
2499
2500 if (ctx->NewState)
2501 _mesa_update_state(ctx);
2502
2503 if (!_mesa_is_no_error_enabled(ctx) &&
2504 !_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
2505 return;
2506
2507 _mesa_validated_multidrawelementsindirect(ctx, mode, type,
2508 (GLintptr)indirect, 0,
2509 1, 20, NULL);
2510 }
2511
2512
2513 void GLAPIENTRY
_mesa_MultiDrawArraysIndirect(GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)2514 _mesa_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
2515 GLsizei primcount, GLsizei stride)
2516 {
2517 GET_CURRENT_CONTEXT(ctx);
2518
2519 /* If <stride> is zero, the array elements are treated as tightly packed. */
2520 if (stride == 0)
2521 stride = sizeof(DrawArraysIndirectCommand);
2522
2523 FLUSH_FOR_DRAW(ctx);
2524
2525 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2526 ctx->VertexProgram._VPModeInputFilter);
2527
2528 if (ctx->NewState)
2529 _mesa_update_state(ctx);
2530
2531 /* From the ARB_draw_indirect spec:
2532 *
2533 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2534 * compatibility profile, this indicates that DrawArraysIndirect and
2535 * DrawElementsIndirect are to source their arguments directly from the
2536 * pointer passed as their <indirect> parameters."
2537 */
2538 if (ctx->API == API_OPENGL_COMPAT &&
2539 !ctx->DrawIndirectBuffer) {
2540
2541 if (!_mesa_is_no_error_enabled(ctx) &&
2542 (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
2543 "glMultiDrawArraysIndirect") ||
2544 !_mesa_validate_DrawArrays(ctx, mode, 1)))
2545 return;
2546
2547 struct pipe_draw_info info;
2548 info.mode = mode;
2549 info.index_size = 0;
2550 info.view_mask = 0;
2551 /* Packed section begin. */
2552 info.primitive_restart = false;
2553 info.has_user_indices = false;
2554 info.index_bounds_valid = false;
2555 info.increment_draw_id = primcount > 1;
2556 info.take_index_buffer_ownership = false;
2557 info.index_bias_varies = false;
2558 /* Packed section end. */
2559
2560 const uint8_t *ptr = (const uint8_t *) indirect;
2561 for (unsigned i = 0; i < primcount; i++) {
2562 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr;
2563
2564 info.start_instance = cmd->baseInstance;
2565 info.instance_count = cmd->primCount;
2566
2567 struct pipe_draw_start_count_bias draw;
2568 draw.start = cmd->first;
2569 draw.count = cmd->count;
2570
2571 ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1);
2572 ptr += stride;
2573 }
2574
2575 return;
2576 }
2577
2578 if (!_mesa_is_no_error_enabled(ctx) &&
2579 !_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect,
2580 primcount, stride))
2581 return;
2582
2583 _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect, 0,
2584 primcount, stride, NULL);
2585 }
2586
2587
2588 void GLAPIENTRY
_mesa_MultiDrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)2589 _mesa_MultiDrawElementsIndirect(GLenum mode, GLenum type,
2590 const GLvoid *indirect,
2591 GLsizei primcount, GLsizei stride)
2592 {
2593 GET_CURRENT_CONTEXT(ctx);
2594
2595 FLUSH_FOR_DRAW(ctx);
2596
2597 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2598 ctx->VertexProgram._VPModeInputFilter);
2599
2600 if (ctx->NewState)
2601 _mesa_update_state(ctx);
2602
2603 /* If <stride> is zero, the array elements are treated as tightly packed. */
2604 if (stride == 0)
2605 stride = sizeof(DrawElementsIndirectCommand);
2606
2607 /* From the ARB_draw_indirect spec:
2608 *
2609 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2610 * compatibility profile, this indicates that DrawArraysIndirect and
2611 * DrawElementsIndirect are to source their arguments directly from the
2612 * pointer passed as their <indirect> parameters."
2613 */
2614 if (ctx->API == API_OPENGL_COMPAT &&
2615 !ctx->DrawIndirectBuffer) {
2616 /*
2617 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
2618 * may not come from a client array and must come from an index buffer.
2619 * If no element array buffer is bound, an INVALID_OPERATION error is
2620 * generated.
2621 */
2622 if (!ctx->Array.VAO->IndexBufferObj) {
2623 _mesa_error(ctx, GL_INVALID_OPERATION,
2624 "glMultiDrawElementsIndirect(no buffer bound "
2625 "to GL_ELEMENT_ARRAY_BUFFER)");
2626
2627 return;
2628 }
2629
2630 if (!_mesa_is_no_error_enabled(ctx) &&
2631 (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
2632 "glMultiDrawArraysIndirect") ||
2633 !_mesa_validate_DrawElements(ctx, mode, 1, type)))
2634 return;
2635
2636 unsigned index_size_shift = get_index_size_shift(type);
2637
2638 struct pipe_draw_info info;
2639 info.mode = mode;
2640 info.index_size = 1 << index_size_shift;
2641 info.view_mask = 0;
2642 /* Packed section begin. */
2643 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
2644 info.has_user_indices = false;
2645 info.index_bounds_valid = false;
2646 info.increment_draw_id = primcount > 1;
2647 info.take_index_buffer_ownership = false;
2648 info.index_bias_varies = false;
2649 /* Packed section end. */
2650 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
2651
2652 const uint8_t *ptr = (const uint8_t *) indirect;
2653 for (unsigned i = 0; i < primcount; i++) {
2654 DrawElementsIndirectCommand *cmd = (DrawElementsIndirectCommand*)ptr;
2655
2656 info.index.gl_bo = ctx->Array.VAO->IndexBufferObj;
2657 info.start_instance = cmd->baseInstance;
2658 info.instance_count = cmd->primCount;
2659
2660 struct pipe_draw_start_count_bias draw;
2661 draw.start = cmd->firstIndex;
2662 draw.count = cmd->count;
2663 draw.index_bias = cmd->baseVertex;
2664
2665 ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1);
2666 ptr += stride;
2667 }
2668
2669 return;
2670 }
2671
2672 if (!_mesa_is_no_error_enabled(ctx) &&
2673 !_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect,
2674 primcount, stride))
2675 return;
2676
2677 _mesa_validated_multidrawelementsindirect(ctx, mode, type,
2678 (GLintptr)indirect, 0, primcount,
2679 stride, NULL);
2680 }
2681
2682
2683 void GLAPIENTRY
_mesa_MultiDrawArraysIndirectCountARB(GLenum mode,GLintptr indirect,GLintptr drawcount_offset,GLsizei maxdrawcount,GLsizei stride)2684 _mesa_MultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect,
2685 GLintptr drawcount_offset,
2686 GLsizei maxdrawcount, GLsizei stride)
2687 {
2688 GET_CURRENT_CONTEXT(ctx);
2689 FLUSH_FOR_DRAW(ctx);
2690
2691 /* If <stride> is zero, the array elements are treated as tightly packed. */
2692 if (stride == 0)
2693 stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
2694
2695 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2696 ctx->VertexProgram._VPModeInputFilter);
2697
2698 if (ctx->NewState)
2699 _mesa_update_state(ctx);
2700
2701 if (!_mesa_is_no_error_enabled(ctx) &&
2702 !_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode, indirect,
2703 drawcount_offset,
2704 maxdrawcount, stride))
2705 return;
2706
2707 _mesa_validated_multidrawarraysindirect(ctx, mode, indirect,
2708 drawcount_offset, maxdrawcount,
2709 stride, ctx->ParameterBuffer);
2710 }
2711
2712
2713 void GLAPIENTRY
_mesa_MultiDrawElementsIndirectCountARB(GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount_offset,GLsizei maxdrawcount,GLsizei stride)2714 _mesa_MultiDrawElementsIndirectCountARB(GLenum mode, GLenum type,
2715 GLintptr indirect,
2716 GLintptr drawcount_offset,
2717 GLsizei maxdrawcount, GLsizei stride)
2718 {
2719 GET_CURRENT_CONTEXT(ctx);
2720 FLUSH_FOR_DRAW(ctx);
2721
2722 /* If <stride> is zero, the array elements are treated as tightly packed. */
2723 if (stride == 0)
2724 stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
2725
2726 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2727 ctx->VertexProgram._VPModeInputFilter);
2728
2729 if (ctx->NewState)
2730 _mesa_update_state(ctx);
2731
2732 if (!_mesa_is_no_error_enabled(ctx) &&
2733 !_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type,
2734 indirect,
2735 drawcount_offset,
2736 maxdrawcount, stride))
2737 return;
2738
2739 _mesa_validated_multidrawelementsindirect(ctx, mode, type, indirect,
2740 drawcount_offset, maxdrawcount,
2741 stride, ctx->ParameterBuffer);
2742 }
2743
2744
2745 /* GL_IBM_multimode_draw_arrays */
2746 void GLAPIENTRY
_mesa_MultiModeDrawArraysIBM(const GLenum * mode,const GLint * first,const GLsizei * count,GLsizei primcount,GLint modestride)2747 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
2748 const GLsizei * count,
2749 GLsizei primcount, GLint modestride )
2750 {
2751 GET_CURRENT_CONTEXT(ctx);
2752 GLint i;
2753
2754 for ( i = 0 ; i < primcount ; i++ ) {
2755 if ( count[i] > 0 ) {
2756 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2757 CALL_DrawArrays(ctx->CurrentServerDispatch, ( m, first[i], count[i] ));
2758 }
2759 }
2760 }
2761
2762
2763 /* GL_IBM_multimode_draw_arrays */
2764 void GLAPIENTRY
_mesa_MultiModeDrawElementsIBM(const GLenum * mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,GLint modestride)2765 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
2766 GLenum type, const GLvoid * const * indices,
2767 GLsizei primcount, GLint modestride )
2768 {
2769 GET_CURRENT_CONTEXT(ctx);
2770 GLint i;
2771
2772 for ( i = 0 ; i < primcount ; i++ ) {
2773 if ( count[i] > 0 ) {
2774 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2775 CALL_DrawElements(ctx->CurrentServerDispatch, ( m, count[i], type,
2776 indices[i] ));
2777 }
2778 }
2779 }
2780