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