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