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