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