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