• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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