xref: /aosp_15_r20/external/mesa3d/src/mesa/main/glthread_draw.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2020 Advanced Micro Devices, Inc.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker /* Draw function marshalling for glthread.
25*61046927SAndroid Build Coastguard Worker  *
26*61046927SAndroid Build Coastguard Worker  * The purpose of these glDraw wrappers is to upload non-VBO vertex and
27*61046927SAndroid Build Coastguard Worker  * index data, so that glthread doesn't have to execute synchronously.
28*61046927SAndroid Build Coastguard Worker  */
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "c99_alloca.h"
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #include "api_exec_decl.h"
33*61046927SAndroid Build Coastguard Worker #include "main/glthread_marshal.h"
34*61046927SAndroid Build Coastguard Worker #include "main/dispatch.h"
35*61046927SAndroid Build Coastguard Worker #include "main/varray.h"
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker static inline unsigned
get_index_size(GLenum type)38*61046927SAndroid Build Coastguard Worker get_index_size(GLenum type)
39*61046927SAndroid Build Coastguard Worker {
40*61046927SAndroid Build Coastguard Worker    return 1 << _mesa_get_index_size_shift(type);
41*61046927SAndroid Build Coastguard Worker }
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker static inline GLindextype
encode_index_type(GLenum type)44*61046927SAndroid Build Coastguard Worker encode_index_type(GLenum type)
45*61046927SAndroid Build Coastguard Worker {
46*61046927SAndroid Build Coastguard Worker    /* Map invalid values less than GL_UNSIGNED_BYTE to GL_UNSIGNED_BYTE - 1,
47*61046927SAndroid Build Coastguard Worker     * and invalid values greater than GL_UNSIGNED_INT to GL_UNSIGNED_INT + 1,
48*61046927SAndroid Build Coastguard Worker     * Then subtract GL_UNSIGNED_BYTE - 1. Final encoding:
49*61046927SAndroid Build Coastguard Worker     *    0 = invalid value
50*61046927SAndroid Build Coastguard Worker     *    1 = GL_UNSIGNED_BYTE
51*61046927SAndroid Build Coastguard Worker     *    2 = invalid value
52*61046927SAndroid Build Coastguard Worker     *    3 = GL_UNSIGNED_SHORT
53*61046927SAndroid Build Coastguard Worker     *    4 = invalid value
54*61046927SAndroid Build Coastguard Worker     *    5 = GL_UNSIGNED_INT
55*61046927SAndroid Build Coastguard Worker     *    6 = invalid value
56*61046927SAndroid Build Coastguard Worker     */
57*61046927SAndroid Build Coastguard Worker    const unsigned min = GL_UNSIGNED_BYTE - 1;
58*61046927SAndroid Build Coastguard Worker    const unsigned max = GL_UNSIGNED_INT + 1;
59*61046927SAndroid Build Coastguard Worker    return (GLindextype){CLAMP(type, min, max) - min};
60*61046927SAndroid Build Coastguard Worker }
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE struct gl_buffer_object *
upload_indices(struct gl_context * ctx,unsigned count,unsigned index_size,const GLvoid ** indices)63*61046927SAndroid Build Coastguard Worker upload_indices(struct gl_context *ctx, unsigned count, unsigned index_size,
64*61046927SAndroid Build Coastguard Worker                const GLvoid **indices)
65*61046927SAndroid Build Coastguard Worker {
66*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *upload_buffer = NULL;
67*61046927SAndroid Build Coastguard Worker    unsigned upload_offset = 0;
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker    assert(count);
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker    _mesa_glthread_upload(ctx, *indices, index_size * count,
72*61046927SAndroid Build Coastguard Worker                          &upload_offset, &upload_buffer, NULL, 0);
73*61046927SAndroid Build Coastguard Worker    *indices = (const GLvoid*)(intptr_t)upload_offset;
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    if (!upload_buffer)
76*61046927SAndroid Build Coastguard Worker       _mesa_marshal_InternalSetError(GL_OUT_OF_MEMORY);
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker    return upload_buffer;
79*61046927SAndroid Build Coastguard Worker }
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE struct gl_buffer_object *
upload_multi_indices(struct gl_context * ctx,unsigned total_count,unsigned index_size,unsigned draw_count,const GLsizei * count,const GLvoid * const * indices,const GLvoid ** out_indices)82*61046927SAndroid Build Coastguard Worker upload_multi_indices(struct gl_context *ctx, unsigned total_count,
83*61046927SAndroid Build Coastguard Worker                      unsigned index_size, unsigned draw_count,
84*61046927SAndroid Build Coastguard Worker                      const GLsizei *count, const GLvoid *const *indices,
85*61046927SAndroid Build Coastguard Worker                      const GLvoid **out_indices)
86*61046927SAndroid Build Coastguard Worker {
87*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *upload_buffer = NULL;
88*61046927SAndroid Build Coastguard Worker    unsigned upload_offset = 0;
89*61046927SAndroid Build Coastguard Worker    uint8_t *upload_ptr = NULL;
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    assert(total_count);
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    _mesa_glthread_upload(ctx, NULL, index_size * total_count,
94*61046927SAndroid Build Coastguard Worker                          &upload_offset, &upload_buffer, &upload_ptr, 0);
95*61046927SAndroid Build Coastguard Worker    if (!upload_buffer) {
96*61046927SAndroid Build Coastguard Worker       _mesa_marshal_InternalSetError(GL_OUT_OF_MEMORY);
97*61046927SAndroid Build Coastguard Worker       return NULL;
98*61046927SAndroid Build Coastguard Worker    }
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0, offset = 0; i < draw_count; i++) {
101*61046927SAndroid Build Coastguard Worker       if (!count[i]) {
102*61046927SAndroid Build Coastguard Worker          /* Set some valid value so as not to leave it uninitialized. */
103*61046927SAndroid Build Coastguard Worker          out_indices[i] = (const GLvoid*)(intptr_t)upload_offset;
104*61046927SAndroid Build Coastguard Worker          continue;
105*61046927SAndroid Build Coastguard Worker       }
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker       unsigned size = count[i] * index_size;
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker       memcpy(upload_ptr + offset, indices[i], size);
110*61046927SAndroid Build Coastguard Worker       out_indices[i] = (const GLvoid*)(intptr_t)(upload_offset + offset);
111*61046927SAndroid Build Coastguard Worker       offset += size;
112*61046927SAndroid Build Coastguard Worker    }
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker    return upload_buffer;
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE bool
upload_vertices(struct gl_context * ctx,unsigned user_buffer_mask,unsigned start_vertex,unsigned num_vertices,unsigned start_instance,unsigned num_instances,struct gl_buffer_object ** buffers,int * offsets)118*61046927SAndroid Build Coastguard Worker upload_vertices(struct gl_context *ctx, unsigned user_buffer_mask,
119*61046927SAndroid Build Coastguard Worker                 unsigned start_vertex, unsigned num_vertices,
120*61046927SAndroid Build Coastguard Worker                 unsigned start_instance, unsigned num_instances,
121*61046927SAndroid Build Coastguard Worker                 struct gl_buffer_object **buffers, int *offsets)
122*61046927SAndroid Build Coastguard Worker {
123*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
124*61046927SAndroid Build Coastguard Worker    unsigned attrib_mask_iter = vao->Enabled;
125*61046927SAndroid Build Coastguard Worker    unsigned num_buffers = 0;
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker    assert((num_vertices || !(user_buffer_mask & ~vao->NonZeroDivisorMask)) &&
128*61046927SAndroid Build Coastguard Worker           (num_instances || !(user_buffer_mask & vao->NonZeroDivisorMask)));
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    if (unlikely(vao->BufferInterleaved & user_buffer_mask)) {
131*61046927SAndroid Build Coastguard Worker       /* Slower upload path where some buffers reference multiple attribs,
132*61046927SAndroid Build Coastguard Worker        * so we have to use 2 while loops instead of 1.
133*61046927SAndroid Build Coastguard Worker        */
134*61046927SAndroid Build Coastguard Worker       unsigned start_offset[VERT_ATTRIB_MAX];
135*61046927SAndroid Build Coastguard Worker       unsigned end_offset[VERT_ATTRIB_MAX];
136*61046927SAndroid Build Coastguard Worker       uint32_t buffer_mask = 0;
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker       while (attrib_mask_iter) {
139*61046927SAndroid Build Coastguard Worker          unsigned i = u_bit_scan(&attrib_mask_iter);
140*61046927SAndroid Build Coastguard Worker          unsigned binding_index = vao->Attrib[i].BufferIndex;
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker          if (!(user_buffer_mask & (1 << binding_index)))
143*61046927SAndroid Build Coastguard Worker             continue;
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker          unsigned stride = vao->Attrib[binding_index].Stride;
146*61046927SAndroid Build Coastguard Worker          unsigned instance_div = vao->Attrib[binding_index].Divisor;
147*61046927SAndroid Build Coastguard Worker          unsigned element_size = vao->Attrib[i].ElementSize;
148*61046927SAndroid Build Coastguard Worker          unsigned offset = vao->Attrib[i].RelativeOffset;
149*61046927SAndroid Build Coastguard Worker          unsigned size;
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker          if (instance_div) {
152*61046927SAndroid Build Coastguard Worker             /* Per-instance attrib. */
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker             /* Figure out how many instances we'll render given instance_div.  We
155*61046927SAndroid Build Coastguard Worker              * can't use the typical div_round_up() pattern because the CTS uses
156*61046927SAndroid Build Coastguard Worker              * instance_div = ~0 for a test, which overflows div_round_up()'s
157*61046927SAndroid Build Coastguard Worker              * addition.
158*61046927SAndroid Build Coastguard Worker              */
159*61046927SAndroid Build Coastguard Worker             unsigned count = num_instances / instance_div;
160*61046927SAndroid Build Coastguard Worker             if (count * instance_div != num_instances)
161*61046927SAndroid Build Coastguard Worker                count++;
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker             offset += stride * start_instance;
164*61046927SAndroid Build Coastguard Worker             size = stride * (count - 1) + element_size;
165*61046927SAndroid Build Coastguard Worker          } else {
166*61046927SAndroid Build Coastguard Worker             /* Per-vertex attrib. */
167*61046927SAndroid Build Coastguard Worker             offset += stride * start_vertex;
168*61046927SAndroid Build Coastguard Worker             size = stride * (num_vertices - 1) + element_size;
169*61046927SAndroid Build Coastguard Worker          }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker          unsigned binding_index_bit = 1u << binding_index;
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker          /* Update upload offsets. */
174*61046927SAndroid Build Coastguard Worker          if (!(buffer_mask & binding_index_bit)) {
175*61046927SAndroid Build Coastguard Worker             start_offset[binding_index] = offset;
176*61046927SAndroid Build Coastguard Worker             end_offset[binding_index] = offset + size;
177*61046927SAndroid Build Coastguard Worker          } else {
178*61046927SAndroid Build Coastguard Worker             if (offset < start_offset[binding_index])
179*61046927SAndroid Build Coastguard Worker                start_offset[binding_index] = offset;
180*61046927SAndroid Build Coastguard Worker             if (offset + size > end_offset[binding_index])
181*61046927SAndroid Build Coastguard Worker                end_offset[binding_index] = offset + size;
182*61046927SAndroid Build Coastguard Worker          }
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker          buffer_mask |= binding_index_bit;
185*61046927SAndroid Build Coastguard Worker       }
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker       /* Upload buffers. */
188*61046927SAndroid Build Coastguard Worker       while (buffer_mask) {
189*61046927SAndroid Build Coastguard Worker          struct gl_buffer_object *upload_buffer = NULL;
190*61046927SAndroid Build Coastguard Worker          unsigned upload_offset = 0;
191*61046927SAndroid Build Coastguard Worker          unsigned start, end;
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker          unsigned binding_index = u_bit_scan(&buffer_mask);
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker          start = start_offset[binding_index];
196*61046927SAndroid Build Coastguard Worker          end = end_offset[binding_index];
197*61046927SAndroid Build Coastguard Worker          assert(start < end);
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker          /* If the draw start index is non-zero, glthread can upload to offset 0,
200*61046927SAndroid Build Coastguard Worker          * which means the attrib offset has to be -(first * stride).
201*61046927SAndroid Build Coastguard Worker          * So use signed vertex buffer offsets when possible to save memory.
202*61046927SAndroid Build Coastguard Worker          */
203*61046927SAndroid Build Coastguard Worker          const void *ptr = vao->Attrib[binding_index].Pointer;
204*61046927SAndroid Build Coastguard Worker          _mesa_glthread_upload(ctx, (uint8_t*)ptr + start,
205*61046927SAndroid Build Coastguard Worker                                end - start, &upload_offset,
206*61046927SAndroid Build Coastguard Worker                                &upload_buffer, NULL, ctx->Const.VertexBufferOffsetIsInt32 ? 0 : start);
207*61046927SAndroid Build Coastguard Worker          if (!upload_buffer) {
208*61046927SAndroid Build Coastguard Worker             for (unsigned i = 0; i < num_buffers; i++)
209*61046927SAndroid Build Coastguard Worker                _mesa_reference_buffer_object(ctx, &buffers[i], NULL);
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker             _mesa_marshal_InternalSetError(GL_OUT_OF_MEMORY);
212*61046927SAndroid Build Coastguard Worker             return false;
213*61046927SAndroid Build Coastguard Worker          }
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker          buffers[num_buffers] = upload_buffer;
216*61046927SAndroid Build Coastguard Worker          offsets[num_buffers] = upload_offset - start;
217*61046927SAndroid Build Coastguard Worker          num_buffers++;
218*61046927SAndroid Build Coastguard Worker       }
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker       return true;
221*61046927SAndroid Build Coastguard Worker    }
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker    /* Faster path where all attribs are separate. */
224*61046927SAndroid Build Coastguard Worker    while (attrib_mask_iter) {
225*61046927SAndroid Build Coastguard Worker       unsigned i = u_bit_scan(&attrib_mask_iter);
226*61046927SAndroid Build Coastguard Worker       unsigned binding_index = vao->Attrib[i].BufferIndex;
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker       if (!(user_buffer_mask & (1 << binding_index)))
229*61046927SAndroid Build Coastguard Worker          continue;
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker       struct gl_buffer_object *upload_buffer = NULL;
232*61046927SAndroid Build Coastguard Worker       unsigned upload_offset = 0;
233*61046927SAndroid Build Coastguard Worker       unsigned stride = vao->Attrib[binding_index].Stride;
234*61046927SAndroid Build Coastguard Worker       unsigned instance_div = vao->Attrib[binding_index].Divisor;
235*61046927SAndroid Build Coastguard Worker       unsigned element_size = vao->Attrib[i].ElementSize;
236*61046927SAndroid Build Coastguard Worker       unsigned offset = vao->Attrib[i].RelativeOffset;
237*61046927SAndroid Build Coastguard Worker       unsigned size;
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker       if (instance_div) {
240*61046927SAndroid Build Coastguard Worker          /* Per-instance attrib. */
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker          /* Figure out how many instances we'll render given instance_div.  We
243*61046927SAndroid Build Coastguard Worker           * can't use the typical div_round_up() pattern because the CTS uses
244*61046927SAndroid Build Coastguard Worker           * instance_div = ~0 for a test, which overflows div_round_up()'s
245*61046927SAndroid Build Coastguard Worker           * addition.
246*61046927SAndroid Build Coastguard Worker           */
247*61046927SAndroid Build Coastguard Worker          unsigned count = num_instances / instance_div;
248*61046927SAndroid Build Coastguard Worker          if (count * instance_div != num_instances)
249*61046927SAndroid Build Coastguard Worker             count++;
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker          offset += stride * start_instance;
252*61046927SAndroid Build Coastguard Worker          size = stride * (count - 1) + element_size;
253*61046927SAndroid Build Coastguard Worker       } else {
254*61046927SAndroid Build Coastguard Worker          /* Per-vertex attrib. */
255*61046927SAndroid Build Coastguard Worker          offset += stride * start_vertex;
256*61046927SAndroid Build Coastguard Worker          size = stride * (num_vertices - 1) + element_size;
257*61046927SAndroid Build Coastguard Worker       }
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker       /* If the draw start index is non-zero, glthread can upload to offset 0,
260*61046927SAndroid Build Coastguard Worker        * which means the attrib offset has to be -(first * stride).
261*61046927SAndroid Build Coastguard Worker        * So use signed vertex buffer offsets when possible to save memory.
262*61046927SAndroid Build Coastguard Worker        */
263*61046927SAndroid Build Coastguard Worker       const void *ptr = vao->Attrib[binding_index].Pointer;
264*61046927SAndroid Build Coastguard Worker       _mesa_glthread_upload(ctx, (uint8_t*)ptr + offset,
265*61046927SAndroid Build Coastguard Worker                             size, &upload_offset, &upload_buffer, NULL,
266*61046927SAndroid Build Coastguard Worker                             ctx->Const.VertexBufferOffsetIsInt32 ? 0 : offset);
267*61046927SAndroid Build Coastguard Worker       if (!upload_buffer) {
268*61046927SAndroid Build Coastguard Worker          for (unsigned i = 0; i < num_buffers; i++)
269*61046927SAndroid Build Coastguard Worker             _mesa_reference_buffer_object(ctx, &buffers[i], NULL);
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker          _mesa_marshal_InternalSetError(GL_OUT_OF_MEMORY);
272*61046927SAndroid Build Coastguard Worker          return false;
273*61046927SAndroid Build Coastguard Worker       }
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker       buffers[num_buffers] = upload_buffer;
276*61046927SAndroid Build Coastguard Worker       offsets[num_buffers] = upload_offset - offset;
277*61046927SAndroid Build Coastguard Worker       num_buffers++;
278*61046927SAndroid Build Coastguard Worker    }
279*61046927SAndroid Build Coastguard Worker 
280*61046927SAndroid Build Coastguard Worker    return true;
281*61046927SAndroid Build Coastguard Worker }
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker /* DrawArraysInstanced without user buffers. */
284*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawArraysInstanced(struct gl_context * ctx,const struct marshal_cmd_DrawArraysInstanced * restrict cmd)285*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawArraysInstanced(struct gl_context *ctx,
286*61046927SAndroid Build Coastguard Worker                                     const struct marshal_cmd_DrawArraysInstanced *restrict cmd)
287*61046927SAndroid Build Coastguard Worker {
288*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
289*61046927SAndroid Build Coastguard Worker    const GLint first = cmd->first;
290*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
291*61046927SAndroid Build Coastguard Worker    const GLsizei instance_count = cmd->primcount;
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    CALL_DrawArraysInstanced(ctx->Dispatch.Current, (mode, first, count, instance_count));
294*61046927SAndroid Build Coastguard Worker    return align(sizeof(*cmd), 8) / 8;
295*61046927SAndroid Build Coastguard Worker }
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker struct marshal_cmd_DrawArraysInstancedBaseInstanceDrawID
298*61046927SAndroid Build Coastguard Worker {
299*61046927SAndroid Build Coastguard Worker    struct marshal_cmd_base cmd_base;
300*61046927SAndroid Build Coastguard Worker    GLenum8 mode;
301*61046927SAndroid Build Coastguard Worker    GLint first;
302*61046927SAndroid Build Coastguard Worker    GLsizei count;
303*61046927SAndroid Build Coastguard Worker    GLsizei instance_count;
304*61046927SAndroid Build Coastguard Worker    GLuint baseinstance;
305*61046927SAndroid Build Coastguard Worker    GLuint drawid;
306*61046927SAndroid Build Coastguard Worker };
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawArraysInstancedBaseInstanceDrawID(struct gl_context * ctx,const struct marshal_cmd_DrawArraysInstancedBaseInstanceDrawID * cmd)309*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawArraysInstancedBaseInstanceDrawID(struct gl_context *ctx,
310*61046927SAndroid Build Coastguard Worker                                                 const struct marshal_cmd_DrawArraysInstancedBaseInstanceDrawID *cmd)
311*61046927SAndroid Build Coastguard Worker {
312*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
313*61046927SAndroid Build Coastguard Worker    const GLint first = cmd->first;
314*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
315*61046927SAndroid Build Coastguard Worker    const GLsizei instance_count = cmd->instance_count;
316*61046927SAndroid Build Coastguard Worker    const GLuint baseinstance = cmd->baseinstance;
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker    ctx->DrawID = cmd->drawid;
319*61046927SAndroid Build Coastguard Worker    CALL_DrawArraysInstancedBaseInstance(ctx->Dispatch.Current,
320*61046927SAndroid Build Coastguard Worker                                         (mode, first, count, instance_count,
321*61046927SAndroid Build Coastguard Worker                                          baseinstance));
322*61046927SAndroid Build Coastguard Worker    ctx->DrawID = 0;
323*61046927SAndroid Build Coastguard Worker    return align(sizeof(*cmd), 8) / 8;
324*61046927SAndroid Build Coastguard Worker }
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker /* DrawArraysInstancedBaseInstance with user buffers. */
327*61046927SAndroid Build Coastguard Worker struct marshal_cmd_DrawArraysUserBuf
328*61046927SAndroid Build Coastguard Worker {
329*61046927SAndroid Build Coastguard Worker    struct marshal_cmd_base cmd_base;
330*61046927SAndroid Build Coastguard Worker    GLenum8 mode;
331*61046927SAndroid Build Coastguard Worker    uint16_t num_slots;
332*61046927SAndroid Build Coastguard Worker    GLint first;
333*61046927SAndroid Build Coastguard Worker    GLsizei count;
334*61046927SAndroid Build Coastguard Worker    GLsizei instance_count;
335*61046927SAndroid Build Coastguard Worker    GLuint baseinstance;
336*61046927SAndroid Build Coastguard Worker    GLuint drawid;
337*61046927SAndroid Build Coastguard Worker    GLuint user_buffer_mask;
338*61046927SAndroid Build Coastguard Worker };
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawArraysUserBuf(struct gl_context * ctx,const struct marshal_cmd_DrawArraysUserBuf * restrict cmd)341*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawArraysUserBuf(struct gl_context *ctx,
342*61046927SAndroid Build Coastguard Worker                                   const struct marshal_cmd_DrawArraysUserBuf *restrict cmd)
343*61046927SAndroid Build Coastguard Worker {
344*61046927SAndroid Build Coastguard Worker    const GLuint user_buffer_mask = cmd->user_buffer_mask;
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker    /* Bind uploaded buffers if needed. */
347*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
348*61046927SAndroid Build Coastguard Worker       struct gl_buffer_object **buffers = (struct gl_buffer_object **)(cmd + 1);
349*61046927SAndroid Build Coastguard Worker       const int *offsets = (const int *)(buffers + util_bitcount(user_buffer_mask));
350*61046927SAndroid Build Coastguard Worker 
351*61046927SAndroid Build Coastguard Worker       _mesa_InternalBindVertexBuffers(ctx, buffers, offsets, user_buffer_mask);
352*61046927SAndroid Build Coastguard Worker    }
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
355*61046927SAndroid Build Coastguard Worker    const GLint first = cmd->first;
356*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
357*61046927SAndroid Build Coastguard Worker    const GLsizei instance_count = cmd->instance_count;
358*61046927SAndroid Build Coastguard Worker    const GLuint baseinstance = cmd->baseinstance;
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker    ctx->DrawID = cmd->drawid;
361*61046927SAndroid Build Coastguard Worker    CALL_DrawArraysInstancedBaseInstance(ctx->Dispatch.Current,
362*61046927SAndroid Build Coastguard Worker                                         (mode, first, count, instance_count,
363*61046927SAndroid Build Coastguard Worker                                          baseinstance));
364*61046927SAndroid Build Coastguard Worker    ctx->DrawID = 0;
365*61046927SAndroid Build Coastguard Worker    return cmd->num_slots;
366*61046927SAndroid Build Coastguard Worker }
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker static inline unsigned
get_user_buffer_mask(struct gl_context * ctx)369*61046927SAndroid Build Coastguard Worker get_user_buffer_mask(struct gl_context *ctx)
370*61046927SAndroid Build Coastguard Worker {
371*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker    /* BufferEnabled means which attribs are enabled in terms of buffer
374*61046927SAndroid Build Coastguard Worker     * binding slots (not attrib slots).
375*61046927SAndroid Build Coastguard Worker     *
376*61046927SAndroid Build Coastguard Worker     * UserPointerMask means which buffer bindings don't have a buffer bound.
377*61046927SAndroid Build Coastguard Worker     *
378*61046927SAndroid Build Coastguard Worker     * NonNullPointerMask means which buffer bindings have a NULL pointer.
379*61046927SAndroid Build Coastguard Worker     * Those are not uploaded. This can happen when an attrib is enabled, but
380*61046927SAndroid Build Coastguard Worker     * the shader doesn't use it, so it's ignored by mesa/state_tracker.
381*61046927SAndroid Build Coastguard Worker     */
382*61046927SAndroid Build Coastguard Worker    return vao->BufferEnabled & vao->UserPointerMask & vao->NonNullPointerMask;
383*61046927SAndroid Build Coastguard Worker }
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
draw_arrays(GLuint drawid,GLenum mode,GLint first,GLsizei count,GLsizei instance_count,GLuint baseinstance,bool compiled_into_dlist,bool no_error)386*61046927SAndroid Build Coastguard Worker draw_arrays(GLuint drawid, GLenum mode, GLint first, GLsizei count,
387*61046927SAndroid Build Coastguard Worker             GLsizei instance_count, GLuint baseinstance,
388*61046927SAndroid Build Coastguard Worker             bool compiled_into_dlist, bool no_error)
389*61046927SAndroid Build Coastguard Worker {
390*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker    /* The main benefit of no_error is that we can discard no-op draws
393*61046927SAndroid Build Coastguard Worker     * immediately.
394*61046927SAndroid Build Coastguard Worker     */
395*61046927SAndroid Build Coastguard Worker    if (no_error && (count <= 0 || instance_count <= 0))
396*61046927SAndroid Build Coastguard Worker       return;
397*61046927SAndroid Build Coastguard Worker 
398*61046927SAndroid Build Coastguard Worker    if (unlikely(compiled_into_dlist && ctx->GLThread.ListMode)) {
399*61046927SAndroid Build Coastguard Worker       _mesa_glthread_finish_before(ctx, "DrawArrays");
400*61046927SAndroid Build Coastguard Worker       /* Use the function that's compiled into a display list. */
401*61046927SAndroid Build Coastguard Worker       CALL_DrawArrays(ctx->Dispatch.Current, (mode, first, count));
402*61046927SAndroid Build Coastguard Worker       return;
403*61046927SAndroid Build Coastguard Worker    }
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
406*61046927SAndroid Build Coastguard Worker       _mesa_is_desktop_gl_core(ctx) ? 0 : get_user_buffer_mask(ctx);
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker    /* Fast path when nothing needs to be done.
409*61046927SAndroid Build Coastguard Worker     *
410*61046927SAndroid Build Coastguard Worker     * This is also an error path. Zero counts should still call the driver
411*61046927SAndroid Build Coastguard Worker     * for possible GL errors.
412*61046927SAndroid Build Coastguard Worker     */
413*61046927SAndroid Build Coastguard Worker    if (!user_buffer_mask ||
414*61046927SAndroid Build Coastguard Worker        (!no_error &&
415*61046927SAndroid Build Coastguard Worker         (count <= 0 || instance_count <= 0 ||   /* GL_INVALID_VALUE / no-op */
416*61046927SAndroid Build Coastguard Worker          ctx->GLThread.inside_begin_end ||      /* GL_INVALID_OPERATION */
417*61046927SAndroid Build Coastguard Worker          ctx->Dispatch.Current == ctx->Dispatch.ContextLost || /* GL_INVALID_OPERATION */
418*61046927SAndroid Build Coastguard Worker          ctx->GLThread.ListMode))) {            /* GL_INVALID_OPERATION */
419*61046927SAndroid Build Coastguard Worker       if (baseinstance == 0 && drawid == 0) {
420*61046927SAndroid Build Coastguard Worker          int cmd_size = sizeof(struct marshal_cmd_DrawArraysInstanced);
421*61046927SAndroid Build Coastguard Worker          struct marshal_cmd_DrawArraysInstanced *cmd =
422*61046927SAndroid Build Coastguard Worker             _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArraysInstanced, cmd_size);
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker          cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
425*61046927SAndroid Build Coastguard Worker          cmd->first = first;
426*61046927SAndroid Build Coastguard Worker          cmd->count = count;
427*61046927SAndroid Build Coastguard Worker          cmd->primcount = instance_count;
428*61046927SAndroid Build Coastguard Worker       } else {
429*61046927SAndroid Build Coastguard Worker          int cmd_size = sizeof(struct marshal_cmd_DrawArraysInstancedBaseInstanceDrawID);
430*61046927SAndroid Build Coastguard Worker          struct marshal_cmd_DrawArraysInstancedBaseInstanceDrawID *cmd =
431*61046927SAndroid Build Coastguard Worker             _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArraysInstancedBaseInstanceDrawID, cmd_size);
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker          cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
434*61046927SAndroid Build Coastguard Worker          cmd->first = first;
435*61046927SAndroid Build Coastguard Worker          cmd->count = count;
436*61046927SAndroid Build Coastguard Worker          cmd->instance_count = instance_count;
437*61046927SAndroid Build Coastguard Worker          cmd->baseinstance = baseinstance;
438*61046927SAndroid Build Coastguard Worker          cmd->drawid = drawid;
439*61046927SAndroid Build Coastguard Worker       }
440*61046927SAndroid Build Coastguard Worker       return;
441*61046927SAndroid Build Coastguard Worker    }
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker    /* Upload and draw. */
444*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *buffers[VERT_ATTRIB_MAX];
445*61046927SAndroid Build Coastguard Worker    int offsets[VERT_ATTRIB_MAX];
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker    if (!upload_vertices(ctx, user_buffer_mask, first, count, baseinstance,
448*61046927SAndroid Build Coastguard Worker                         instance_count, buffers, offsets))
449*61046927SAndroid Build Coastguard Worker       return; /* the error is set by upload_vertices */
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker    unsigned num_buffers = util_bitcount(user_buffer_mask);
452*61046927SAndroid Build Coastguard Worker    int buffers_size = num_buffers * sizeof(buffers[0]);
453*61046927SAndroid Build Coastguard Worker    int offsets_size = num_buffers * sizeof(int);
454*61046927SAndroid Build Coastguard Worker    int cmd_size = sizeof(struct marshal_cmd_DrawArraysUserBuf) +
455*61046927SAndroid Build Coastguard Worker                   buffers_size + offsets_size;
456*61046927SAndroid Build Coastguard Worker    struct marshal_cmd_DrawArraysUserBuf *cmd;
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker    cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArraysUserBuf,
459*61046927SAndroid Build Coastguard Worker                                          cmd_size);
460*61046927SAndroid Build Coastguard Worker    cmd->num_slots = align(cmd_size, 8) / 8;
461*61046927SAndroid Build Coastguard Worker    cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
462*61046927SAndroid Build Coastguard Worker    cmd->first = first;
463*61046927SAndroid Build Coastguard Worker    cmd->count = count;
464*61046927SAndroid Build Coastguard Worker    cmd->instance_count = instance_count;
465*61046927SAndroid Build Coastguard Worker    cmd->baseinstance = baseinstance;
466*61046927SAndroid Build Coastguard Worker    cmd->drawid = drawid;
467*61046927SAndroid Build Coastguard Worker    cmd->user_buffer_mask = user_buffer_mask;
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
470*61046927SAndroid Build Coastguard Worker       char *variable_data = (char*)(cmd + 1);
471*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, buffers, buffers_size);
472*61046927SAndroid Build Coastguard Worker       variable_data += buffers_size;
473*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, offsets, offsets_size);
474*61046927SAndroid Build Coastguard Worker    }
475*61046927SAndroid Build Coastguard Worker }
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker /* MultiDrawArrays with user buffers. */
478*61046927SAndroid Build Coastguard Worker struct marshal_cmd_MultiDrawArraysUserBuf
479*61046927SAndroid Build Coastguard Worker {
480*61046927SAndroid Build Coastguard Worker    struct marshal_cmd_base cmd_base;
481*61046927SAndroid Build Coastguard Worker    GLenum8 mode;
482*61046927SAndroid Build Coastguard Worker    uint16_t num_slots;
483*61046927SAndroid Build Coastguard Worker    GLsizei draw_count;
484*61046927SAndroid Build Coastguard Worker    GLuint user_buffer_mask;
485*61046927SAndroid Build Coastguard Worker };
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawArraysUserBuf(struct gl_context * ctx,const struct marshal_cmd_MultiDrawArraysUserBuf * restrict cmd)488*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawArraysUserBuf(struct gl_context *ctx,
489*61046927SAndroid Build Coastguard Worker                                        const struct marshal_cmd_MultiDrawArraysUserBuf *restrict cmd)
490*61046927SAndroid Build Coastguard Worker {
491*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
492*61046927SAndroid Build Coastguard Worker    const GLsizei draw_count = cmd->draw_count;
493*61046927SAndroid Build Coastguard Worker    const GLsizei real_draw_count = MAX2(draw_count, 0);
494*61046927SAndroid Build Coastguard Worker    const GLuint user_buffer_mask = cmd->user_buffer_mask;
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    const char *variable_data = (const char *)(cmd + 1);
497*61046927SAndroid Build Coastguard Worker    const GLint *first = (GLint *)variable_data;
498*61046927SAndroid Build Coastguard Worker    variable_data += sizeof(GLint) * real_draw_count;
499*61046927SAndroid Build Coastguard Worker    const GLsizei *count = (GLsizei *)variable_data;
500*61046927SAndroid Build Coastguard Worker 
501*61046927SAndroid Build Coastguard Worker    /* Bind uploaded buffers if needed. */
502*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
503*61046927SAndroid Build Coastguard Worker       variable_data += sizeof(GLsizei) * real_draw_count;
504*61046927SAndroid Build Coastguard Worker       const int *offsets = (const int *)variable_data;
505*61046927SAndroid Build Coastguard Worker       variable_data += sizeof(int) * util_bitcount(user_buffer_mask);
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker       /* Align for pointers. */
508*61046927SAndroid Build Coastguard Worker       if ((uintptr_t)variable_data % sizeof(uintptr_t))
509*61046927SAndroid Build Coastguard Worker          variable_data += 4;
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker       struct gl_buffer_object **buffers = (struct gl_buffer_object **)variable_data;
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker       _mesa_InternalBindVertexBuffers(ctx, buffers, offsets, user_buffer_mask);
514*61046927SAndroid Build Coastguard Worker    }
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker    CALL_MultiDrawArrays(ctx->Dispatch.Current,
517*61046927SAndroid Build Coastguard Worker                         (mode, first, count, draw_count));
518*61046927SAndroid Build Coastguard Worker    return cmd->num_slots;
519*61046927SAndroid Build Coastguard Worker }
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawArrays(GLenum mode,const GLint * first,const GLsizei * count,GLsizei draw_count)522*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawArrays(GLenum mode, const GLint *first,
523*61046927SAndroid Build Coastguard Worker                               const GLsizei *count, GLsizei draw_count)
524*61046927SAndroid Build Coastguard Worker {
525*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker    if (unlikely(ctx->GLThread.ListMode)) {
528*61046927SAndroid Build Coastguard Worker       _mesa_glthread_finish_before(ctx, "MultiDrawArrays");
529*61046927SAndroid Build Coastguard Worker       CALL_MultiDrawArrays(ctx->Dispatch.Current,
530*61046927SAndroid Build Coastguard Worker                            (mode, first, count, draw_count));
531*61046927SAndroid Build Coastguard Worker       return;
532*61046927SAndroid Build Coastguard Worker    }
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *buffers[VERT_ATTRIB_MAX];
535*61046927SAndroid Build Coastguard Worker    int offsets[VERT_ATTRIB_MAX];
536*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
537*61046927SAndroid Build Coastguard Worker       _mesa_is_desktop_gl_core(ctx) || draw_count <= 0 ||
538*61046927SAndroid Build Coastguard Worker       ctx->Dispatch.Current == ctx->Dispatch.ContextLost ||
539*61046927SAndroid Build Coastguard Worker       ctx->GLThread.inside_begin_end ? 0 : get_user_buffer_mask(ctx);
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
542*61046927SAndroid Build Coastguard Worker       unsigned min_index = ~0;
543*61046927SAndroid Build Coastguard Worker       unsigned max_index_exclusive = 0;
544*61046927SAndroid Build Coastguard Worker 
545*61046927SAndroid Build Coastguard Worker       for (int i = 0; i < draw_count; i++) {
546*61046927SAndroid Build Coastguard Worker          GLsizei vertex_count = count[i];
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker          if (vertex_count < 0) {
549*61046927SAndroid Build Coastguard Worker             /* This will just call the driver to set the GL error. */
550*61046927SAndroid Build Coastguard Worker             min_index = ~0;
551*61046927SAndroid Build Coastguard Worker             break;
552*61046927SAndroid Build Coastguard Worker          }
553*61046927SAndroid Build Coastguard Worker          if (vertex_count == 0)
554*61046927SAndroid Build Coastguard Worker             continue;
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker          min_index = MIN2(min_index, first[i]);
557*61046927SAndroid Build Coastguard Worker          max_index_exclusive = MAX2(max_index_exclusive, first[i] + vertex_count);
558*61046927SAndroid Build Coastguard Worker       }
559*61046927SAndroid Build Coastguard Worker 
560*61046927SAndroid Build Coastguard Worker       if (min_index >= max_index_exclusive) {
561*61046927SAndroid Build Coastguard Worker          /* Nothing to do, but call the driver to set possible GL errors. */
562*61046927SAndroid Build Coastguard Worker          user_buffer_mask = 0;
563*61046927SAndroid Build Coastguard Worker       } else {
564*61046927SAndroid Build Coastguard Worker          /* Upload. */
565*61046927SAndroid Build Coastguard Worker          unsigned num_vertices = max_index_exclusive - min_index;
566*61046927SAndroid Build Coastguard Worker 
567*61046927SAndroid Build Coastguard Worker          if (!upload_vertices(ctx, user_buffer_mask, min_index, num_vertices,
568*61046927SAndroid Build Coastguard Worker                               0, 1, buffers, offsets))
569*61046927SAndroid Build Coastguard Worker             return; /* the error is set by upload_vertices */
570*61046927SAndroid Build Coastguard Worker       }
571*61046927SAndroid Build Coastguard Worker    }
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker    /* Add the call into the batch buffer. */
574*61046927SAndroid Build Coastguard Worker    int real_draw_count = MAX2(draw_count, 0);
575*61046927SAndroid Build Coastguard Worker    int first_size = sizeof(GLint) * real_draw_count;
576*61046927SAndroid Build Coastguard Worker    int count_size = sizeof(GLsizei) * real_draw_count;
577*61046927SAndroid Build Coastguard Worker    unsigned num_buffers = util_bitcount(user_buffer_mask);
578*61046927SAndroid Build Coastguard Worker    int buffers_size = num_buffers * sizeof(buffers[0]);
579*61046927SAndroid Build Coastguard Worker    int offsets_size = num_buffers * sizeof(int);
580*61046927SAndroid Build Coastguard Worker    int cmd_size = sizeof(struct marshal_cmd_MultiDrawArraysUserBuf) +
581*61046927SAndroid Build Coastguard Worker                   first_size + count_size + buffers_size + offsets_size;
582*61046927SAndroid Build Coastguard Worker    struct marshal_cmd_MultiDrawArraysUserBuf *cmd;
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker    /* Make sure cmd can fit in the batch buffer */
585*61046927SAndroid Build Coastguard Worker    if (cmd_size <= MARSHAL_MAX_CMD_SIZE) {
586*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArraysUserBuf,
587*61046927SAndroid Build Coastguard Worker                                             cmd_size);
588*61046927SAndroid Build Coastguard Worker       cmd->num_slots = align(cmd_size, 8) / 8;
589*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
590*61046927SAndroid Build Coastguard Worker       cmd->draw_count = draw_count;
591*61046927SAndroid Build Coastguard Worker       cmd->user_buffer_mask = user_buffer_mask;
592*61046927SAndroid Build Coastguard Worker 
593*61046927SAndroid Build Coastguard Worker       char *variable_data = (char*)(cmd + 1);
594*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, first, first_size);
595*61046927SAndroid Build Coastguard Worker       variable_data += first_size;
596*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, count, count_size);
597*61046927SAndroid Build Coastguard Worker 
598*61046927SAndroid Build Coastguard Worker       if (user_buffer_mask) {
599*61046927SAndroid Build Coastguard Worker          variable_data += count_size;
600*61046927SAndroid Build Coastguard Worker          memcpy(variable_data, offsets, offsets_size);
601*61046927SAndroid Build Coastguard Worker          variable_data += offsets_size;
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker          /* Align for pointers. */
604*61046927SAndroid Build Coastguard Worker          if ((uintptr_t)variable_data % sizeof(uintptr_t))
605*61046927SAndroid Build Coastguard Worker             variable_data += 4;
606*61046927SAndroid Build Coastguard Worker 
607*61046927SAndroid Build Coastguard Worker          memcpy(variable_data, buffers, buffers_size);
608*61046927SAndroid Build Coastguard Worker       }
609*61046927SAndroid Build Coastguard Worker    } else {
610*61046927SAndroid Build Coastguard Worker       /* The call is too large, so sync and execute the unmarshal code here. */
611*61046927SAndroid Build Coastguard Worker       _mesa_glthread_finish_before(ctx, "MultiDrawArrays");
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker       if (user_buffer_mask) {
614*61046927SAndroid Build Coastguard Worker          _mesa_InternalBindVertexBuffers(ctx, buffers, offsets,
615*61046927SAndroid Build Coastguard Worker                                          user_buffer_mask);
616*61046927SAndroid Build Coastguard Worker       }
617*61046927SAndroid Build Coastguard Worker 
618*61046927SAndroid Build Coastguard Worker       CALL_MultiDrawArrays(ctx->Dispatch.Current,
619*61046927SAndroid Build Coastguard Worker                            (mode, first, count, draw_count));
620*61046927SAndroid Build Coastguard Worker    }
621*61046927SAndroid Build Coastguard Worker }
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElements(struct gl_context * ctx,const struct marshal_cmd_DrawElements * restrict cmd)624*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElements(struct gl_context *ctx,
625*61046927SAndroid Build Coastguard Worker                              const struct marshal_cmd_DrawElements *restrict cmd)
626*61046927SAndroid Build Coastguard Worker {
627*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
628*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
629*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
630*61046927SAndroid Build Coastguard Worker    const GLvoid *indices = cmd->indices;
631*61046927SAndroid Build Coastguard Worker 
632*61046927SAndroid Build Coastguard Worker    CALL_DrawElements(ctx->Dispatch.Current, (mode, count, type, indices));
633*61046927SAndroid Build Coastguard Worker    return align(sizeof(*cmd), 8) / 8;
634*61046927SAndroid Build Coastguard Worker }
635*61046927SAndroid Build Coastguard Worker 
636*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsPacked(struct gl_context * ctx,const struct marshal_cmd_DrawElementsPacked * restrict cmd)637*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsPacked(struct gl_context *ctx,
638*61046927SAndroid Build Coastguard Worker                                    const struct marshal_cmd_DrawElementsPacked *restrict cmd)
639*61046927SAndroid Build Coastguard Worker {
640*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
641*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
642*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
643*61046927SAndroid Build Coastguard Worker    const GLvoid *indices = (void*)(uintptr_t)cmd->indices;
644*61046927SAndroid Build Coastguard Worker 
645*61046927SAndroid Build Coastguard Worker    CALL_DrawElements(ctx->Dispatch.Current, (mode, count, type, indices));
646*61046927SAndroid Build Coastguard Worker    return align(sizeof(*cmd), 8) / 8;
647*61046927SAndroid Build Coastguard Worker }
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsInstancedBaseVertex(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedBaseVertex * restrict cmd)650*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsInstancedBaseVertex(struct gl_context *ctx,
651*61046927SAndroid Build Coastguard Worker                                                 const struct marshal_cmd_DrawElementsInstancedBaseVertex *restrict cmd)
652*61046927SAndroid Build Coastguard Worker {
653*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
654*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
655*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
656*61046927SAndroid Build Coastguard Worker    const GLvoid *indices = cmd->indices;
657*61046927SAndroid Build Coastguard Worker    const GLsizei instance_count = cmd->primcount;
658*61046927SAndroid Build Coastguard Worker    const GLint basevertex = cmd->basevertex;
659*61046927SAndroid Build Coastguard Worker 
660*61046927SAndroid Build Coastguard Worker    CALL_DrawElementsInstancedBaseVertex(ctx->Dispatch.Current,
661*61046927SAndroid Build Coastguard Worker                                         (mode, count, type, indices,
662*61046927SAndroid Build Coastguard Worker                                          instance_count, basevertex));
663*61046927SAndroid Build Coastguard Worker    return align(sizeof(*cmd), 8) / 8;
664*61046927SAndroid Build Coastguard Worker }
665*61046927SAndroid Build Coastguard Worker 
666*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsInstancedBaseInstance(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedBaseInstance * restrict cmd)667*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsInstancedBaseInstance(struct gl_context *ctx,
668*61046927SAndroid Build Coastguard Worker                                                   const struct marshal_cmd_DrawElementsInstancedBaseInstance *restrict cmd)
669*61046927SAndroid Build Coastguard Worker {
670*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
671*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
672*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
673*61046927SAndroid Build Coastguard Worker    const GLvoid *indices = cmd->indices;
674*61046927SAndroid Build Coastguard Worker    const GLsizei instance_count = cmd->primcount;
675*61046927SAndroid Build Coastguard Worker    const GLint baseinstance = cmd->baseinstance;
676*61046927SAndroid Build Coastguard Worker 
677*61046927SAndroid Build Coastguard Worker    CALL_DrawElementsInstancedBaseInstance(ctx->Dispatch.Current,
678*61046927SAndroid Build Coastguard Worker                                           (mode, count, type, indices,
679*61046927SAndroid Build Coastguard Worker                                            instance_count, baseinstance));
680*61046927SAndroid Build Coastguard Worker    return align(sizeof(*cmd), 8) / 8;
681*61046927SAndroid Build Coastguard Worker }
682*61046927SAndroid Build Coastguard Worker 
683*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsInstancedBaseVertexBaseInstanceDrawID(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstanceDrawID * restrict cmd)684*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsInstancedBaseVertexBaseInstanceDrawID(struct gl_context *ctx,
685*61046927SAndroid Build Coastguard Worker                                                                   const struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstanceDrawID *restrict cmd)
686*61046927SAndroid Build Coastguard Worker {
687*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
688*61046927SAndroid Build Coastguard Worker    const GLsizei count = cmd->count;
689*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
690*61046927SAndroid Build Coastguard Worker    const GLvoid *indices = cmd->indices;
691*61046927SAndroid Build Coastguard Worker    const GLsizei instance_count = cmd->instance_count;
692*61046927SAndroid Build Coastguard Worker    const GLint basevertex = cmd->basevertex;
693*61046927SAndroid Build Coastguard Worker    const GLuint baseinstance = cmd->baseinstance;
694*61046927SAndroid Build Coastguard Worker 
695*61046927SAndroid Build Coastguard Worker    ctx->DrawID = cmd->drawid;
696*61046927SAndroid Build Coastguard Worker    CALL_DrawElementsInstancedBaseVertexBaseInstance(ctx->Dispatch.Current,
697*61046927SAndroid Build Coastguard Worker                                                     (mode, count, type, indices,
698*61046927SAndroid Build Coastguard Worker                                                      instance_count, basevertex,
699*61046927SAndroid Build Coastguard Worker                                                      baseinstance));
700*61046927SAndroid Build Coastguard Worker    ctx->DrawID = 0;
701*61046927SAndroid Build Coastguard Worker 
702*61046927SAndroid Build Coastguard Worker    return align(sizeof(*cmd), 8) / 8;
703*61046927SAndroid Build Coastguard Worker }
704*61046927SAndroid Build Coastguard Worker 
705*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsUserBuf(struct gl_context * ctx,const struct marshal_cmd_DrawElementsUserBuf * restrict cmd)706*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsUserBuf(struct gl_context *ctx,
707*61046927SAndroid Build Coastguard Worker                                     const struct marshal_cmd_DrawElementsUserBuf *restrict cmd)
708*61046927SAndroid Build Coastguard Worker {
709*61046927SAndroid Build Coastguard Worker    const GLuint user_buffer_mask = cmd->user_buffer_mask;
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker    /* Bind uploaded buffers if needed. */
712*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
713*61046927SAndroid Build Coastguard Worker       struct gl_buffer_object **buffers = (struct gl_buffer_object **)(cmd + 1);
714*61046927SAndroid Build Coastguard Worker       const int *offsets = (const int *)(buffers + util_bitcount(user_buffer_mask));
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker       _mesa_InternalBindVertexBuffers(ctx, buffers, offsets, user_buffer_mask);
717*61046927SAndroid Build Coastguard Worker    }
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker    /* Draw. */
720*61046927SAndroid Build Coastguard Worker    CALL_DrawElementsUserBuf(ctx->Dispatch.Current, (cmd));
721*61046927SAndroid Build Coastguard Worker 
722*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *index_buffer = cmd->index_buffer;
723*61046927SAndroid Build Coastguard Worker    _mesa_reference_buffer_object(ctx, &index_buffer, NULL);
724*61046927SAndroid Build Coastguard Worker    return cmd->num_slots;
725*61046927SAndroid Build Coastguard Worker }
726*61046927SAndroid Build Coastguard Worker 
727*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsUserBufPacked(struct gl_context * ctx,const struct marshal_cmd_DrawElementsUserBufPacked * restrict cmd)728*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsUserBufPacked(struct gl_context *ctx,
729*61046927SAndroid Build Coastguard Worker                                     const struct marshal_cmd_DrawElementsUserBufPacked *restrict cmd)
730*61046927SAndroid Build Coastguard Worker {
731*61046927SAndroid Build Coastguard Worker    const GLuint user_buffer_mask = cmd->user_buffer_mask;
732*61046927SAndroid Build Coastguard Worker 
733*61046927SAndroid Build Coastguard Worker    /* Bind uploaded buffers if needed. */
734*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
735*61046927SAndroid Build Coastguard Worker       struct gl_buffer_object **buffers = (struct gl_buffer_object **)(cmd + 1);
736*61046927SAndroid Build Coastguard Worker       const int *offsets = (const int *)(buffers + util_bitcount(user_buffer_mask));
737*61046927SAndroid Build Coastguard Worker 
738*61046927SAndroid Build Coastguard Worker       _mesa_InternalBindVertexBuffers(ctx, buffers, offsets, user_buffer_mask);
739*61046927SAndroid Build Coastguard Worker    }
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker    /* Draw. */
742*61046927SAndroid Build Coastguard Worker    CALL_DrawElementsUserBufPacked(ctx->Dispatch.Current, (cmd));
743*61046927SAndroid Build Coastguard Worker 
744*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *index_buffer = cmd->index_buffer;
745*61046927SAndroid Build Coastguard Worker    _mesa_reference_buffer_object(ctx, &index_buffer, NULL);
746*61046927SAndroid Build Coastguard Worker    return cmd->num_slots;
747*61046927SAndroid Build Coastguard Worker }
748*61046927SAndroid Build Coastguard Worker 
749*61046927SAndroid Build Coastguard Worker static inline bool
should_convert_to_begin_end(struct gl_context * ctx,unsigned count,unsigned num_upload_vertices,unsigned instance_count,struct glthread_vao * vao)750*61046927SAndroid Build Coastguard Worker should_convert_to_begin_end(struct gl_context *ctx, unsigned count,
751*61046927SAndroid Build Coastguard Worker                             unsigned num_upload_vertices,
752*61046927SAndroid Build Coastguard Worker                             unsigned instance_count, struct glthread_vao *vao)
753*61046927SAndroid Build Coastguard Worker {
754*61046927SAndroid Build Coastguard Worker    /* Some of these are limitations of _mesa_glthread_UnrollDrawElements.
755*61046927SAndroid Build Coastguard Worker     * Others prevent syncing, such as disallowing buffer objects because we
756*61046927SAndroid Build Coastguard Worker     * can't map them without syncing.
757*61046927SAndroid Build Coastguard Worker     */
758*61046927SAndroid Build Coastguard Worker    return ctx->API == API_OPENGL_COMPAT &&
759*61046927SAndroid Build Coastguard Worker           util_is_vbo_upload_ratio_too_large(count, num_upload_vertices) &&
760*61046927SAndroid Build Coastguard Worker           instance_count == 1 &&                /* no instancing */
761*61046927SAndroid Build Coastguard Worker           vao->CurrentElementBufferName == 0 && /* only user indices */
762*61046927SAndroid Build Coastguard Worker           !ctx->GLThread._PrimitiveRestart &&   /* no primitive restart */
763*61046927SAndroid Build Coastguard Worker           vao->UserPointerMask == vao->BufferEnabled && /* no VBOs */
764*61046927SAndroid Build Coastguard Worker           !(vao->NonZeroDivisorMask & vao->BufferEnabled); /* no instanced attribs */
765*61046927SAndroid Build Coastguard Worker }
766*61046927SAndroid Build Coastguard Worker 
767*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
draw_elements(GLuint drawid,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex,GLuint baseinstance,bool index_bounds_valid,GLuint min_index,GLuint max_index,bool compiled_into_dlist,bool no_error)768*61046927SAndroid Build Coastguard Worker draw_elements(GLuint drawid, GLenum mode, GLsizei count, GLenum type,
769*61046927SAndroid Build Coastguard Worker               const GLvoid *indices, GLsizei instance_count, GLint basevertex,
770*61046927SAndroid Build Coastguard Worker               GLuint baseinstance, bool index_bounds_valid, GLuint min_index,
771*61046927SAndroid Build Coastguard Worker               GLuint max_index, bool compiled_into_dlist, bool no_error)
772*61046927SAndroid Build Coastguard Worker {
773*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
774*61046927SAndroid Build Coastguard Worker 
775*61046927SAndroid Build Coastguard Worker    /* The main benefit of no_error is that we can discard no-op draws
776*61046927SAndroid Build Coastguard Worker     * immediately. These are plentiful in Viewperf2020/Catia1.
777*61046927SAndroid Build Coastguard Worker     */
778*61046927SAndroid Build Coastguard Worker    if (no_error && (count <= 0 || instance_count <= 0))
779*61046927SAndroid Build Coastguard Worker       return;
780*61046927SAndroid Build Coastguard Worker 
781*61046927SAndroid Build Coastguard Worker    if (unlikely(compiled_into_dlist && ctx->GLThread.ListMode)) {
782*61046927SAndroid Build Coastguard Worker       _mesa_glthread_finish_before(ctx, "DrawElements");
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker       /* Only use the ones that are compiled into display lists. */
785*61046927SAndroid Build Coastguard Worker       if (basevertex) {
786*61046927SAndroid Build Coastguard Worker          CALL_DrawElementsBaseVertex(ctx->Dispatch.Current,
787*61046927SAndroid Build Coastguard Worker                                      (mode, count, type, indices, basevertex));
788*61046927SAndroid Build Coastguard Worker       } else if (index_bounds_valid) {
789*61046927SAndroid Build Coastguard Worker          CALL_DrawRangeElements(ctx->Dispatch.Current,
790*61046927SAndroid Build Coastguard Worker                                 (mode, min_index, max_index, count, type, indices));
791*61046927SAndroid Build Coastguard Worker       } else {
792*61046927SAndroid Build Coastguard Worker          CALL_DrawElements(ctx->Dispatch.Current, (mode, count, type, indices));
793*61046927SAndroid Build Coastguard Worker       }
794*61046927SAndroid Build Coastguard Worker       return;
795*61046927SAndroid Build Coastguard Worker    }
796*61046927SAndroid Build Coastguard Worker 
797*61046927SAndroid Build Coastguard Worker    if (unlikely(!no_error && index_bounds_valid && max_index < min_index)) {
798*61046927SAndroid Build Coastguard Worker       _mesa_marshal_InternalSetError(GL_INVALID_VALUE);
799*61046927SAndroid Build Coastguard Worker       return;
800*61046927SAndroid Build Coastguard Worker    }
801*61046927SAndroid Build Coastguard Worker 
802*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
803*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
804*61046927SAndroid Build Coastguard Worker       _mesa_is_desktop_gl_core(ctx) ? 0 : get_user_buffer_mask(ctx);
805*61046927SAndroid Build Coastguard Worker    bool has_user_indices = vao->CurrentElementBufferName == 0 && indices;
806*61046927SAndroid Build Coastguard Worker 
807*61046927SAndroid Build Coastguard Worker    /* Fast path when nothing needs to be done.
808*61046927SAndroid Build Coastguard Worker     *
809*61046927SAndroid Build Coastguard Worker     * This is also an error path. Zero counts should still call the driver
810*61046927SAndroid Build Coastguard Worker     * for possible GL errors.
811*61046927SAndroid Build Coastguard Worker     */
812*61046927SAndroid Build Coastguard Worker    if ((!user_buffer_mask && !has_user_indices) ||
813*61046927SAndroid Build Coastguard Worker        (!no_error &&
814*61046927SAndroid Build Coastguard Worker         /* zeros are discarded for no_error at the beginning */
815*61046927SAndroid Build Coastguard Worker         (count <= 0 || instance_count <= 0 ||   /* GL_INVALID_VALUE / no-op */
816*61046927SAndroid Build Coastguard Worker          !_mesa_is_index_type_valid(type) ||    /* GL_INVALID_VALUE */
817*61046927SAndroid Build Coastguard Worker          ctx->Dispatch.Current == ctx->Dispatch.ContextLost || /* GL_INVALID_OPERATION */
818*61046927SAndroid Build Coastguard Worker          ctx->GLThread.inside_begin_end ||      /* GL_INVALID_OPERATION */
819*61046927SAndroid Build Coastguard Worker          ctx->GLThread.ListMode ||              /* GL_INVALID_OPERATION */
820*61046927SAndroid Build Coastguard Worker          mode >= 32 || !((1u << mode) & ctx->SupportedPrimMask) /* GL_INVALID_ENUM */
821*61046927SAndroid Build Coastguard Worker          ))) {
822*61046927SAndroid Build Coastguard Worker       if (drawid == 0 && baseinstance == 0) {
823*61046927SAndroid Build Coastguard Worker          if (instance_count == 1 && basevertex == 0) {
824*61046927SAndroid Build Coastguard Worker             if ((count & 0xffff) == count && (uintptr_t)indices <= UINT16_MAX) {
825*61046927SAndroid Build Coastguard Worker                /* Packed version of DrawElements: 16-bit count and 16-bit index offset,
826*61046927SAndroid Build Coastguard Worker                 * reducing the call size by 8 bytes.
827*61046927SAndroid Build Coastguard Worker                 * This is the most common case in Viewperf2020/Catia1.
828*61046927SAndroid Build Coastguard Worker                 */
829*61046927SAndroid Build Coastguard Worker                int cmd_size = sizeof(struct marshal_cmd_DrawElementsPacked);
830*61046927SAndroid Build Coastguard Worker                struct marshal_cmd_DrawElementsPacked *cmd =
831*61046927SAndroid Build Coastguard Worker                      _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsPacked, cmd_size);
832*61046927SAndroid Build Coastguard Worker 
833*61046927SAndroid Build Coastguard Worker                cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
834*61046927SAndroid Build Coastguard Worker                cmd->type = encode_index_type(type);
835*61046927SAndroid Build Coastguard Worker                cmd->count = count;
836*61046927SAndroid Build Coastguard Worker                cmd->indices = (uintptr_t)indices;
837*61046927SAndroid Build Coastguard Worker             } else {
838*61046927SAndroid Build Coastguard Worker                int cmd_size = sizeof(struct marshal_cmd_DrawElements);
839*61046927SAndroid Build Coastguard Worker                struct marshal_cmd_DrawElements *cmd =
840*61046927SAndroid Build Coastguard Worker                      _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElements, cmd_size);
841*61046927SAndroid Build Coastguard Worker 
842*61046927SAndroid Build Coastguard Worker                cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
843*61046927SAndroid Build Coastguard Worker                cmd->type = encode_index_type(type);
844*61046927SAndroid Build Coastguard Worker                cmd->count = count;
845*61046927SAndroid Build Coastguard Worker                cmd->indices = indices;
846*61046927SAndroid Build Coastguard Worker             }
847*61046927SAndroid Build Coastguard Worker          } else {
848*61046927SAndroid Build Coastguard Worker             int cmd_size = sizeof(struct marshal_cmd_DrawElementsInstancedBaseVertex);
849*61046927SAndroid Build Coastguard Worker             struct marshal_cmd_DrawElementsInstancedBaseVertex *cmd =
850*61046927SAndroid Build Coastguard Worker                   _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsInstancedBaseVertex, cmd_size);
851*61046927SAndroid Build Coastguard Worker 
852*61046927SAndroid Build Coastguard Worker             cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
853*61046927SAndroid Build Coastguard Worker             cmd->type = encode_index_type(type);
854*61046927SAndroid Build Coastguard Worker             cmd->count = count;
855*61046927SAndroid Build Coastguard Worker             cmd->primcount = instance_count;
856*61046927SAndroid Build Coastguard Worker             cmd->basevertex = basevertex;
857*61046927SAndroid Build Coastguard Worker             cmd->indices = indices;
858*61046927SAndroid Build Coastguard Worker          }
859*61046927SAndroid Build Coastguard Worker       } else if (drawid == 0 && basevertex == 0) {
860*61046927SAndroid Build Coastguard Worker          int cmd_size = sizeof(struct marshal_cmd_DrawElementsInstancedBaseInstance);
861*61046927SAndroid Build Coastguard Worker          struct marshal_cmd_DrawElementsInstancedBaseInstance *cmd =
862*61046927SAndroid Build Coastguard Worker                _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsInstancedBaseInstance, cmd_size);
863*61046927SAndroid Build Coastguard Worker 
864*61046927SAndroid Build Coastguard Worker          cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
865*61046927SAndroid Build Coastguard Worker          cmd->type = encode_index_type(type);
866*61046927SAndroid Build Coastguard Worker          cmd->count = count;
867*61046927SAndroid Build Coastguard Worker          cmd->primcount = instance_count;
868*61046927SAndroid Build Coastguard Worker          cmd->baseinstance = baseinstance;
869*61046927SAndroid Build Coastguard Worker          cmd->indices = indices;
870*61046927SAndroid Build Coastguard Worker       } else {
871*61046927SAndroid Build Coastguard Worker          int cmd_size = sizeof(struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstanceDrawID);
872*61046927SAndroid Build Coastguard Worker          struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstanceDrawID *cmd =
873*61046927SAndroid Build Coastguard Worker             _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsInstancedBaseVertexBaseInstanceDrawID, cmd_size);
874*61046927SAndroid Build Coastguard Worker 
875*61046927SAndroid Build Coastguard Worker          cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
876*61046927SAndroid Build Coastguard Worker          cmd->type = encode_index_type(type);
877*61046927SAndroid Build Coastguard Worker          cmd->count = count;
878*61046927SAndroid Build Coastguard Worker          cmd->instance_count = instance_count;
879*61046927SAndroid Build Coastguard Worker          cmd->basevertex = basevertex;
880*61046927SAndroid Build Coastguard Worker          cmd->baseinstance = baseinstance;
881*61046927SAndroid Build Coastguard Worker          cmd->drawid = drawid;
882*61046927SAndroid Build Coastguard Worker          cmd->indices = indices;
883*61046927SAndroid Build Coastguard Worker       }
884*61046927SAndroid Build Coastguard Worker       return;
885*61046927SAndroid Build Coastguard Worker    }
886*61046927SAndroid Build Coastguard Worker 
887*61046927SAndroid Build Coastguard Worker    bool need_index_bounds = user_buffer_mask & ~vao->NonZeroDivisorMask;
888*61046927SAndroid Build Coastguard Worker    unsigned index_size = get_index_size(type);
889*61046927SAndroid Build Coastguard Worker 
890*61046927SAndroid Build Coastguard Worker    if (need_index_bounds && !index_bounds_valid) {
891*61046927SAndroid Build Coastguard Worker       /* Compute the index bounds. */
892*61046927SAndroid Build Coastguard Worker       if (has_user_indices) {
893*61046927SAndroid Build Coastguard Worker          min_index = ~0;
894*61046927SAndroid Build Coastguard Worker          max_index = 0;
895*61046927SAndroid Build Coastguard Worker          vbo_get_minmax_index_mapped(count, index_size,
896*61046927SAndroid Build Coastguard Worker                                      ctx->GLThread._RestartIndex[index_size - 1],
897*61046927SAndroid Build Coastguard Worker                                      ctx->GLThread._PrimitiveRestart, indices,
898*61046927SAndroid Build Coastguard Worker                                      &min_index, &max_index);
899*61046927SAndroid Build Coastguard Worker       } else {
900*61046927SAndroid Build Coastguard Worker          /* Indices in a buffer. */
901*61046927SAndroid Build Coastguard Worker          _mesa_glthread_finish_before(ctx, "DrawElements - need index bounds");
902*61046927SAndroid Build Coastguard Worker          vbo_get_minmax_index(ctx, ctx->Array.VAO->IndexBufferObj,
903*61046927SAndroid Build Coastguard Worker                               NULL, (intptr_t)indices, count, index_size,
904*61046927SAndroid Build Coastguard Worker                               ctx->GLThread._PrimitiveRestart,
905*61046927SAndroid Build Coastguard Worker                               ctx->GLThread._RestartIndex[index_size - 1],
906*61046927SAndroid Build Coastguard Worker                               &min_index, &max_index);
907*61046927SAndroid Build Coastguard Worker       }
908*61046927SAndroid Build Coastguard Worker       index_bounds_valid = true;
909*61046927SAndroid Build Coastguard Worker    }
910*61046927SAndroid Build Coastguard Worker 
911*61046927SAndroid Build Coastguard Worker    unsigned start_vertex = min_index + basevertex;
912*61046927SAndroid Build Coastguard Worker    unsigned num_vertices = max_index + 1 - min_index;
913*61046927SAndroid Build Coastguard Worker 
914*61046927SAndroid Build Coastguard Worker    /* If the vertex range to upload is much greater than the vertex count (e.g.
915*61046927SAndroid Build Coastguard Worker     * only 3 vertices with indices 0, 1, 999999), uploading the whole range
916*61046927SAndroid Build Coastguard Worker     * would take too much time. If all buffers are user buffers, have glthread
917*61046927SAndroid Build Coastguard Worker     * fetch all indices and vertices and convert the draw into glBegin/glEnd.
918*61046927SAndroid Build Coastguard Worker     * For such pathological cases, it's the fastest way.
919*61046927SAndroid Build Coastguard Worker     *
920*61046927SAndroid Build Coastguard Worker     * The game Cogs benefits from this - its FPS increases from 0 to 197.
921*61046927SAndroid Build Coastguard Worker     */
922*61046927SAndroid Build Coastguard Worker    if (should_convert_to_begin_end(ctx, count, num_vertices, instance_count,
923*61046927SAndroid Build Coastguard Worker                                    vao)) {
924*61046927SAndroid Build Coastguard Worker       _mesa_glthread_UnrollDrawElements(ctx, mode, count, type, indices,
925*61046927SAndroid Build Coastguard Worker                                         basevertex);
926*61046927SAndroid Build Coastguard Worker       return;
927*61046927SAndroid Build Coastguard Worker    }
928*61046927SAndroid Build Coastguard Worker 
929*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *buffers[VERT_ATTRIB_MAX];
930*61046927SAndroid Build Coastguard Worker    int offsets[VERT_ATTRIB_MAX];
931*61046927SAndroid Build Coastguard Worker 
932*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
933*61046927SAndroid Build Coastguard Worker       if (!upload_vertices(ctx, user_buffer_mask, start_vertex, num_vertices,
934*61046927SAndroid Build Coastguard Worker                            baseinstance, instance_count, buffers, offsets))
935*61046927SAndroid Build Coastguard Worker          return; /* the error is set by upload_vertices */
936*61046927SAndroid Build Coastguard Worker    }
937*61046927SAndroid Build Coastguard Worker 
938*61046927SAndroid Build Coastguard Worker    /* Upload indices. */
939*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *index_buffer = NULL;
940*61046927SAndroid Build Coastguard Worker    if (has_user_indices) {
941*61046927SAndroid Build Coastguard Worker       index_buffer = upload_indices(ctx, count, index_size, &indices);
942*61046927SAndroid Build Coastguard Worker       if (!index_buffer)
943*61046927SAndroid Build Coastguard Worker          return; /* the error is set by upload_indices */
944*61046927SAndroid Build Coastguard Worker    }
945*61046927SAndroid Build Coastguard Worker 
946*61046927SAndroid Build Coastguard Worker    /* Draw asynchronously. */
947*61046927SAndroid Build Coastguard Worker    unsigned num_buffers = util_bitcount(user_buffer_mask);
948*61046927SAndroid Build Coastguard Worker    int buffers_size = num_buffers * sizeof(buffers[0]);
949*61046927SAndroid Build Coastguard Worker    int offsets_size = num_buffers * sizeof(int);
950*61046927SAndroid Build Coastguard Worker    char *variable_data;
951*61046927SAndroid Build Coastguard Worker 
952*61046927SAndroid Build Coastguard Worker    if (instance_count == 1 && basevertex == 0 && baseinstance == 0 &&
953*61046927SAndroid Build Coastguard Worker        drawid == 0 && (count & 0xffff) == count &&
954*61046927SAndroid Build Coastguard Worker        (uintptr_t)indices <= UINT32_MAX) {
955*61046927SAndroid Build Coastguard Worker       int cmd_size = sizeof(struct marshal_cmd_DrawElementsUserBufPacked) +
956*61046927SAndroid Build Coastguard Worker                      buffers_size + offsets_size;
957*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_DrawElementsUserBufPacked *cmd;
958*61046927SAndroid Build Coastguard Worker 
959*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsUserBufPacked, cmd_size);
960*61046927SAndroid Build Coastguard Worker       cmd->num_slots = align(cmd_size, 8) / 8;
961*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
962*61046927SAndroid Build Coastguard Worker       cmd->type = encode_index_type(type);
963*61046927SAndroid Build Coastguard Worker       cmd->count = count; /* truncated */
964*61046927SAndroid Build Coastguard Worker       cmd->indices = (uintptr_t)indices; /* truncated */
965*61046927SAndroid Build Coastguard Worker       cmd->user_buffer_mask = user_buffer_mask;
966*61046927SAndroid Build Coastguard Worker       cmd->index_buffer = index_buffer;
967*61046927SAndroid Build Coastguard Worker       variable_data = (char*)(cmd + 1);
968*61046927SAndroid Build Coastguard Worker    } else {
969*61046927SAndroid Build Coastguard Worker       int cmd_size = sizeof(struct marshal_cmd_DrawElementsUserBuf) +
970*61046927SAndroid Build Coastguard Worker                      buffers_size + offsets_size;
971*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_DrawElementsUserBuf *cmd;
972*61046927SAndroid Build Coastguard Worker 
973*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsUserBuf, cmd_size);
974*61046927SAndroid Build Coastguard Worker       cmd->num_slots = align(cmd_size, 8) / 8;
975*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
976*61046927SAndroid Build Coastguard Worker       cmd->type = encode_index_type(type);
977*61046927SAndroid Build Coastguard Worker       cmd->count = count;
978*61046927SAndroid Build Coastguard Worker       cmd->indices = indices;
979*61046927SAndroid Build Coastguard Worker       cmd->instance_count = instance_count;
980*61046927SAndroid Build Coastguard Worker       cmd->basevertex = basevertex;
981*61046927SAndroid Build Coastguard Worker       cmd->baseinstance = baseinstance;
982*61046927SAndroid Build Coastguard Worker       cmd->user_buffer_mask = user_buffer_mask;
983*61046927SAndroid Build Coastguard Worker       cmd->index_buffer = index_buffer;
984*61046927SAndroid Build Coastguard Worker       cmd->drawid = drawid;
985*61046927SAndroid Build Coastguard Worker       variable_data = (char*)(cmd + 1);
986*61046927SAndroid Build Coastguard Worker    }
987*61046927SAndroid Build Coastguard Worker 
988*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
989*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, buffers, buffers_size);
990*61046927SAndroid Build Coastguard Worker       variable_data += buffers_size;
991*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, offsets, offsets_size);
992*61046927SAndroid Build Coastguard Worker    }
993*61046927SAndroid Build Coastguard Worker }
994*61046927SAndroid Build Coastguard Worker 
995*61046927SAndroid Build Coastguard Worker struct marshal_cmd_MultiDrawElementsUserBuf
996*61046927SAndroid Build Coastguard Worker {
997*61046927SAndroid Build Coastguard Worker    struct marshal_cmd_base cmd_base;
998*61046927SAndroid Build Coastguard Worker    bool has_base_vertex;
999*61046927SAndroid Build Coastguard Worker    GLenum8 mode;
1000*61046927SAndroid Build Coastguard Worker    GLindextype type;
1001*61046927SAndroid Build Coastguard Worker    uint16_t num_slots;
1002*61046927SAndroid Build Coastguard Worker    GLsizei draw_count;
1003*61046927SAndroid Build Coastguard Worker    GLuint user_buffer_mask;
1004*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *index_buffer;
1005*61046927SAndroid Build Coastguard Worker };
1006*61046927SAndroid Build Coastguard Worker 
1007*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawElementsUserBuf(struct gl_context * ctx,const struct marshal_cmd_MultiDrawElementsUserBuf * restrict cmd)1008*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawElementsUserBuf(struct gl_context *ctx,
1009*61046927SAndroid Build Coastguard Worker                                          const struct marshal_cmd_MultiDrawElementsUserBuf *restrict cmd)
1010*61046927SAndroid Build Coastguard Worker {
1011*61046927SAndroid Build Coastguard Worker    const GLsizei draw_count = cmd->draw_count;
1012*61046927SAndroid Build Coastguard Worker    const GLsizei real_draw_count = MAX2(draw_count, 0);
1013*61046927SAndroid Build Coastguard Worker    const GLuint user_buffer_mask = cmd->user_buffer_mask;
1014*61046927SAndroid Build Coastguard Worker    const bool has_base_vertex = cmd->has_base_vertex;
1015*61046927SAndroid Build Coastguard Worker 
1016*61046927SAndroid Build Coastguard Worker    const char *variable_data = (const char *)(cmd + 1);
1017*61046927SAndroid Build Coastguard Worker    const GLsizei *count = (GLsizei *)variable_data;
1018*61046927SAndroid Build Coastguard Worker    variable_data += sizeof(GLsizei) * real_draw_count;
1019*61046927SAndroid Build Coastguard Worker    const GLsizei *basevertex = NULL;
1020*61046927SAndroid Build Coastguard Worker    if (has_base_vertex) {
1021*61046927SAndroid Build Coastguard Worker       basevertex = (GLsizei *)variable_data;
1022*61046927SAndroid Build Coastguard Worker       variable_data += sizeof(GLsizei) * real_draw_count;
1023*61046927SAndroid Build Coastguard Worker    }
1024*61046927SAndroid Build Coastguard Worker    const int *offsets = NULL;
1025*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
1026*61046927SAndroid Build Coastguard Worker       offsets = (const int *)variable_data;
1027*61046927SAndroid Build Coastguard Worker       variable_data += sizeof(int) * util_bitcount(user_buffer_mask);
1028*61046927SAndroid Build Coastguard Worker    }
1029*61046927SAndroid Build Coastguard Worker 
1030*61046927SAndroid Build Coastguard Worker    /* Align for pointers. */
1031*61046927SAndroid Build Coastguard Worker    if ((uintptr_t)variable_data % sizeof(uintptr_t))
1032*61046927SAndroid Build Coastguard Worker       variable_data += 4;
1033*61046927SAndroid Build Coastguard Worker 
1034*61046927SAndroid Build Coastguard Worker    const GLvoid *const *indices = (const GLvoid *const *)variable_data;
1035*61046927SAndroid Build Coastguard Worker    variable_data += sizeof(const GLvoid *const *) * real_draw_count;
1036*61046927SAndroid Build Coastguard Worker 
1037*61046927SAndroid Build Coastguard Worker    /* Bind uploaded buffers if needed. */
1038*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
1039*61046927SAndroid Build Coastguard Worker       struct gl_buffer_object **buffers = (struct gl_buffer_object **)variable_data;
1040*61046927SAndroid Build Coastguard Worker 
1041*61046927SAndroid Build Coastguard Worker       _mesa_InternalBindVertexBuffers(ctx, buffers, offsets, user_buffer_mask);
1042*61046927SAndroid Build Coastguard Worker    }
1043*61046927SAndroid Build Coastguard Worker 
1044*61046927SAndroid Build Coastguard Worker    /* Draw. */
1045*61046927SAndroid Build Coastguard Worker    const GLenum mode = cmd->mode;
1046*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
1047*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *index_buffer = cmd->index_buffer;
1048*61046927SAndroid Build Coastguard Worker 
1049*61046927SAndroid Build Coastguard Worker    CALL_MultiDrawElementsUserBuf(ctx->Dispatch.Current,
1050*61046927SAndroid Build Coastguard Worker                                  ((GLintptr)index_buffer, mode, count, type,
1051*61046927SAndroid Build Coastguard Worker                                   indices, draw_count, basevertex));
1052*61046927SAndroid Build Coastguard Worker    _mesa_reference_buffer_object(ctx, &index_buffer, NULL);
1053*61046927SAndroid Build Coastguard Worker    return cmd->num_slots;
1054*61046927SAndroid Build Coastguard Worker }
1055*61046927SAndroid Build Coastguard Worker 
1056*61046927SAndroid Build Coastguard Worker static void
multi_draw_elements_async(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei draw_count,const GLsizei * basevertex,struct gl_buffer_object * index_buffer,unsigned user_buffer_mask,struct gl_buffer_object ** buffers,const int * offsets)1057*61046927SAndroid Build Coastguard Worker multi_draw_elements_async(struct gl_context *ctx, GLenum mode,
1058*61046927SAndroid Build Coastguard Worker                           const GLsizei *count, GLenum type,
1059*61046927SAndroid Build Coastguard Worker                           const GLvoid *const *indices, GLsizei draw_count,
1060*61046927SAndroid Build Coastguard Worker                           const GLsizei *basevertex,
1061*61046927SAndroid Build Coastguard Worker                           struct gl_buffer_object *index_buffer,
1062*61046927SAndroid Build Coastguard Worker                           unsigned user_buffer_mask,
1063*61046927SAndroid Build Coastguard Worker                           struct gl_buffer_object **buffers,
1064*61046927SAndroid Build Coastguard Worker                           const int *offsets)
1065*61046927SAndroid Build Coastguard Worker {
1066*61046927SAndroid Build Coastguard Worker    int real_draw_count = MAX2(draw_count, 0);
1067*61046927SAndroid Build Coastguard Worker    int count_size = sizeof(GLsizei) * real_draw_count;
1068*61046927SAndroid Build Coastguard Worker    int indices_size = sizeof(indices[0]) * real_draw_count;
1069*61046927SAndroid Build Coastguard Worker    int basevertex_size = basevertex ? sizeof(GLsizei) * real_draw_count : 0;
1070*61046927SAndroid Build Coastguard Worker    unsigned num_buffers = util_bitcount(user_buffer_mask);
1071*61046927SAndroid Build Coastguard Worker    int buffers_size = num_buffers * sizeof(buffers[0]);
1072*61046927SAndroid Build Coastguard Worker    int offsets_size = num_buffers * sizeof(int);
1073*61046927SAndroid Build Coastguard Worker    int cmd_size = sizeof(struct marshal_cmd_MultiDrawElementsUserBuf) +
1074*61046927SAndroid Build Coastguard Worker                   count_size + indices_size + basevertex_size + buffers_size +
1075*61046927SAndroid Build Coastguard Worker                   offsets_size;
1076*61046927SAndroid Build Coastguard Worker    struct marshal_cmd_MultiDrawElementsUserBuf *cmd;
1077*61046927SAndroid Build Coastguard Worker 
1078*61046927SAndroid Build Coastguard Worker    /* Make sure cmd can fit the queue buffer */
1079*61046927SAndroid Build Coastguard Worker    if (cmd_size <= MARSHAL_MAX_CMD_SIZE) {
1080*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsUserBuf, cmd_size);
1081*61046927SAndroid Build Coastguard Worker       cmd->num_slots = align(cmd_size, 8) / 8;
1082*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* primitive types go from 0 to 14 */
1083*61046927SAndroid Build Coastguard Worker       cmd->type = encode_index_type(type);
1084*61046927SAndroid Build Coastguard Worker       cmd->draw_count = draw_count;
1085*61046927SAndroid Build Coastguard Worker       cmd->user_buffer_mask = user_buffer_mask;
1086*61046927SAndroid Build Coastguard Worker       cmd->index_buffer = index_buffer;
1087*61046927SAndroid Build Coastguard Worker       cmd->has_base_vertex = basevertex != NULL;
1088*61046927SAndroid Build Coastguard Worker 
1089*61046927SAndroid Build Coastguard Worker       char *variable_data = (char*)(cmd + 1);
1090*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, count, count_size);
1091*61046927SAndroid Build Coastguard Worker       variable_data += count_size;
1092*61046927SAndroid Build Coastguard Worker       if (basevertex) {
1093*61046927SAndroid Build Coastguard Worker          memcpy(variable_data, basevertex, basevertex_size);
1094*61046927SAndroid Build Coastguard Worker          variable_data += basevertex_size;
1095*61046927SAndroid Build Coastguard Worker       }
1096*61046927SAndroid Build Coastguard Worker       if (user_buffer_mask) {
1097*61046927SAndroid Build Coastguard Worker          memcpy(variable_data, offsets, offsets_size);
1098*61046927SAndroid Build Coastguard Worker          variable_data += offsets_size;
1099*61046927SAndroid Build Coastguard Worker       }
1100*61046927SAndroid Build Coastguard Worker 
1101*61046927SAndroid Build Coastguard Worker       /* Align for pointers. */
1102*61046927SAndroid Build Coastguard Worker       if ((uintptr_t)variable_data % sizeof(uintptr_t))
1103*61046927SAndroid Build Coastguard Worker          variable_data += 4;
1104*61046927SAndroid Build Coastguard Worker 
1105*61046927SAndroid Build Coastguard Worker       memcpy(variable_data, indices, indices_size);
1106*61046927SAndroid Build Coastguard Worker       variable_data += indices_size;
1107*61046927SAndroid Build Coastguard Worker 
1108*61046927SAndroid Build Coastguard Worker       if (user_buffer_mask)
1109*61046927SAndroid Build Coastguard Worker          memcpy(variable_data, buffers, buffers_size);
1110*61046927SAndroid Build Coastguard Worker    } else {
1111*61046927SAndroid Build Coastguard Worker       /* The call is too large, so sync and execute the unmarshal code here. */
1112*61046927SAndroid Build Coastguard Worker       _mesa_glthread_finish_before(ctx, "DrawElements");
1113*61046927SAndroid Build Coastguard Worker 
1114*61046927SAndroid Build Coastguard Worker       /* Bind uploaded buffers if needed. */
1115*61046927SAndroid Build Coastguard Worker       if (user_buffer_mask) {
1116*61046927SAndroid Build Coastguard Worker          _mesa_InternalBindVertexBuffers(ctx, buffers, offsets,
1117*61046927SAndroid Build Coastguard Worker                                          user_buffer_mask);
1118*61046927SAndroid Build Coastguard Worker       }
1119*61046927SAndroid Build Coastguard Worker 
1120*61046927SAndroid Build Coastguard Worker       /* Draw. */
1121*61046927SAndroid Build Coastguard Worker       CALL_MultiDrawElementsUserBuf(ctx->Dispatch.Current,
1122*61046927SAndroid Build Coastguard Worker                                     ((GLintptr)index_buffer, mode, count,
1123*61046927SAndroid Build Coastguard Worker                                      type, indices, draw_count, basevertex));
1124*61046927SAndroid Build Coastguard Worker       _mesa_reference_buffer_object(ctx, &index_buffer, NULL);
1125*61046927SAndroid Build Coastguard Worker    }
1126*61046927SAndroid Build Coastguard Worker }
1127*61046927SAndroid Build Coastguard Worker 
1128*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei draw_count,const GLsizei * basevertex)1129*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
1130*61046927SAndroid Build Coastguard Worker                                           GLenum type,
1131*61046927SAndroid Build Coastguard Worker                                           const GLvoid *const *indices,
1132*61046927SAndroid Build Coastguard Worker                                           GLsizei draw_count,
1133*61046927SAndroid Build Coastguard Worker                                           const GLsizei *basevertex)
1134*61046927SAndroid Build Coastguard Worker {
1135*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1136*61046927SAndroid Build Coastguard Worker 
1137*61046927SAndroid Build Coastguard Worker    if (unlikely(ctx->GLThread.ListMode)) {
1138*61046927SAndroid Build Coastguard Worker       _mesa_glthread_finish_before(ctx, "MultiDrawElements");
1139*61046927SAndroid Build Coastguard Worker 
1140*61046927SAndroid Build Coastguard Worker       if (basevertex) {
1141*61046927SAndroid Build Coastguard Worker          CALL_MultiDrawElementsBaseVertex(ctx->Dispatch.Current,
1142*61046927SAndroid Build Coastguard Worker                                           (mode, count, type, indices, draw_count,
1143*61046927SAndroid Build Coastguard Worker                                            basevertex));
1144*61046927SAndroid Build Coastguard Worker       } else {
1145*61046927SAndroid Build Coastguard Worker          CALL_MultiDrawElements(ctx->Dispatch.Current,
1146*61046927SAndroid Build Coastguard Worker                                 (mode, count, type, indices, draw_count));
1147*61046927SAndroid Build Coastguard Worker       }
1148*61046927SAndroid Build Coastguard Worker       return;
1149*61046927SAndroid Build Coastguard Worker    }
1150*61046927SAndroid Build Coastguard Worker 
1151*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
1152*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask = 0;
1153*61046927SAndroid Build Coastguard Worker    bool has_user_indices = false;
1154*61046927SAndroid Build Coastguard Worker 
1155*61046927SAndroid Build Coastguard Worker    /* Non-VBO vertex arrays are used only if this is true.
1156*61046927SAndroid Build Coastguard Worker     * When nothing needs to be uploaded or the draw is no-op or generates
1157*61046927SAndroid Build Coastguard Worker     * a GL error, we don't upload anything.
1158*61046927SAndroid Build Coastguard Worker     */
1159*61046927SAndroid Build Coastguard Worker    if (draw_count > 0 && _mesa_is_index_type_valid(type) &&
1160*61046927SAndroid Build Coastguard Worker        ctx->Dispatch.Current != ctx->Dispatch.ContextLost &&
1161*61046927SAndroid Build Coastguard Worker        !ctx->GLThread.inside_begin_end &&
1162*61046927SAndroid Build Coastguard Worker        !(mode >= 32 || !((1u << mode) & ctx->SupportedPrimMask))) {
1163*61046927SAndroid Build Coastguard Worker       user_buffer_mask = _mesa_is_desktop_gl_core(ctx) ? 0 : get_user_buffer_mask(ctx);
1164*61046927SAndroid Build Coastguard Worker       has_user_indices = vao->CurrentElementBufferName == 0;
1165*61046927SAndroid Build Coastguard Worker    }
1166*61046927SAndroid Build Coastguard Worker 
1167*61046927SAndroid Build Coastguard Worker    /* Fast path when we don't need to upload anything. */
1168*61046927SAndroid Build Coastguard Worker    if (!user_buffer_mask && !has_user_indices) {
1169*61046927SAndroid Build Coastguard Worker       multi_draw_elements_async(ctx, mode, count, type, indices,
1170*61046927SAndroid Build Coastguard Worker                                 draw_count, basevertex, NULL, 0, NULL, NULL);
1171*61046927SAndroid Build Coastguard Worker       return;
1172*61046927SAndroid Build Coastguard Worker    }
1173*61046927SAndroid Build Coastguard Worker 
1174*61046927SAndroid Build Coastguard Worker    bool need_index_bounds = user_buffer_mask & ~vao->NonZeroDivisorMask;
1175*61046927SAndroid Build Coastguard Worker    unsigned index_size = get_index_size(type);
1176*61046927SAndroid Build Coastguard Worker    unsigned min_index = ~0;
1177*61046927SAndroid Build Coastguard Worker    unsigned max_index = 0;
1178*61046927SAndroid Build Coastguard Worker    unsigned total_count = 0;
1179*61046927SAndroid Build Coastguard Worker    unsigned num_vertices = 0;
1180*61046927SAndroid Build Coastguard Worker 
1181*61046927SAndroid Build Coastguard Worker    /* This is always true if there is per-vertex data that needs to be
1182*61046927SAndroid Build Coastguard Worker     * uploaded.
1183*61046927SAndroid Build Coastguard Worker     */
1184*61046927SAndroid Build Coastguard Worker    if (need_index_bounds) {
1185*61046927SAndroid Build Coastguard Worker       bool synced = false;
1186*61046927SAndroid Build Coastguard Worker 
1187*61046927SAndroid Build Coastguard Worker       /* Compute the index bounds. */
1188*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < draw_count; i++) {
1189*61046927SAndroid Build Coastguard Worker          GLsizei vertex_count = count[i];
1190*61046927SAndroid Build Coastguard Worker 
1191*61046927SAndroid Build Coastguard Worker          if (vertex_count < 0) {
1192*61046927SAndroid Build Coastguard Worker             /* Just call the driver to set the error. */
1193*61046927SAndroid Build Coastguard Worker             multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1194*61046927SAndroid Build Coastguard Worker                                       basevertex, NULL, 0, NULL, NULL);
1195*61046927SAndroid Build Coastguard Worker             return;
1196*61046927SAndroid Build Coastguard Worker          }
1197*61046927SAndroid Build Coastguard Worker          if (vertex_count == 0)
1198*61046927SAndroid Build Coastguard Worker             continue;
1199*61046927SAndroid Build Coastguard Worker 
1200*61046927SAndroid Build Coastguard Worker          unsigned min = ~0, max = 0;
1201*61046927SAndroid Build Coastguard Worker          if (has_user_indices) {
1202*61046927SAndroid Build Coastguard Worker             vbo_get_minmax_index_mapped(vertex_count, index_size,
1203*61046927SAndroid Build Coastguard Worker                                         ctx->GLThread._RestartIndex[index_size - 1],
1204*61046927SAndroid Build Coastguard Worker                                         ctx->GLThread._PrimitiveRestart, indices[i],
1205*61046927SAndroid Build Coastguard Worker                                         &min, &max);
1206*61046927SAndroid Build Coastguard Worker          } else {
1207*61046927SAndroid Build Coastguard Worker             if (!synced) {
1208*61046927SAndroid Build Coastguard Worker                _mesa_glthread_finish_before(ctx, "MultiDrawElements - need index bounds");
1209*61046927SAndroid Build Coastguard Worker                synced = true;
1210*61046927SAndroid Build Coastguard Worker             }
1211*61046927SAndroid Build Coastguard Worker             vbo_get_minmax_index(ctx, ctx->Array.VAO->IndexBufferObj,
1212*61046927SAndroid Build Coastguard Worker                                  NULL, (intptr_t)indices[i], vertex_count,
1213*61046927SAndroid Build Coastguard Worker                                  index_size, ctx->GLThread._PrimitiveRestart,
1214*61046927SAndroid Build Coastguard Worker                                  ctx->GLThread._RestartIndex[index_size - 1],
1215*61046927SAndroid Build Coastguard Worker                                  &min, &max);
1216*61046927SAndroid Build Coastguard Worker          }
1217*61046927SAndroid Build Coastguard Worker 
1218*61046927SAndroid Build Coastguard Worker          if (basevertex) {
1219*61046927SAndroid Build Coastguard Worker             min += basevertex[i];
1220*61046927SAndroid Build Coastguard Worker             max += basevertex[i];
1221*61046927SAndroid Build Coastguard Worker          }
1222*61046927SAndroid Build Coastguard Worker          min_index = MIN2(min_index, min);
1223*61046927SAndroid Build Coastguard Worker          max_index = MAX2(max_index, max);
1224*61046927SAndroid Build Coastguard Worker          total_count += vertex_count;
1225*61046927SAndroid Build Coastguard Worker       }
1226*61046927SAndroid Build Coastguard Worker 
1227*61046927SAndroid Build Coastguard Worker       num_vertices = max_index + 1 - min_index;
1228*61046927SAndroid Build Coastguard Worker 
1229*61046927SAndroid Build Coastguard Worker       if (total_count == 0 || num_vertices == 0) {
1230*61046927SAndroid Build Coastguard Worker          /* Nothing to do, but call the driver to set possible GL errors. */
1231*61046927SAndroid Build Coastguard Worker          multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1232*61046927SAndroid Build Coastguard Worker                                    basevertex, NULL, 0, NULL, NULL);
1233*61046927SAndroid Build Coastguard Worker          return;
1234*61046927SAndroid Build Coastguard Worker       }
1235*61046927SAndroid Build Coastguard Worker    } else if (has_user_indices) {
1236*61046927SAndroid Build Coastguard Worker       /* Only compute total_count for the upload of indices. */
1237*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < draw_count; i++) {
1238*61046927SAndroid Build Coastguard Worker          GLsizei vertex_count = count[i];
1239*61046927SAndroid Build Coastguard Worker 
1240*61046927SAndroid Build Coastguard Worker          if (vertex_count < 0) {
1241*61046927SAndroid Build Coastguard Worker             /* Just call the driver to set the error. */
1242*61046927SAndroid Build Coastguard Worker             multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1243*61046927SAndroid Build Coastguard Worker                                       basevertex, NULL, 0, NULL, NULL);
1244*61046927SAndroid Build Coastguard Worker             return;
1245*61046927SAndroid Build Coastguard Worker          }
1246*61046927SAndroid Build Coastguard Worker          if (vertex_count == 0)
1247*61046927SAndroid Build Coastguard Worker             continue;
1248*61046927SAndroid Build Coastguard Worker 
1249*61046927SAndroid Build Coastguard Worker          total_count += vertex_count;
1250*61046927SAndroid Build Coastguard Worker       }
1251*61046927SAndroid Build Coastguard Worker 
1252*61046927SAndroid Build Coastguard Worker       if (total_count == 0) {
1253*61046927SAndroid Build Coastguard Worker          /* Nothing to do, but call the driver to set possible GL errors. */
1254*61046927SAndroid Build Coastguard Worker          multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1255*61046927SAndroid Build Coastguard Worker                                    basevertex, NULL, 0, NULL, NULL);
1256*61046927SAndroid Build Coastguard Worker          return;
1257*61046927SAndroid Build Coastguard Worker       }
1258*61046927SAndroid Build Coastguard Worker    }
1259*61046927SAndroid Build Coastguard Worker 
1260*61046927SAndroid Build Coastguard Worker    /* Upload vertices. */
1261*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *buffers[VERT_ATTRIB_MAX];
1262*61046927SAndroid Build Coastguard Worker    int offsets[VERT_ATTRIB_MAX];
1263*61046927SAndroid Build Coastguard Worker 
1264*61046927SAndroid Build Coastguard Worker    if (user_buffer_mask) {
1265*61046927SAndroid Build Coastguard Worker       if (!upload_vertices(ctx, user_buffer_mask, min_index, num_vertices,
1266*61046927SAndroid Build Coastguard Worker                            0, 1, buffers, offsets))
1267*61046927SAndroid Build Coastguard Worker          return; /* the error is set by upload_vertices */
1268*61046927SAndroid Build Coastguard Worker    }
1269*61046927SAndroid Build Coastguard Worker 
1270*61046927SAndroid Build Coastguard Worker    /* Upload indices. */
1271*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *index_buffer = NULL;
1272*61046927SAndroid Build Coastguard Worker    if (has_user_indices) {
1273*61046927SAndroid Build Coastguard Worker       const GLvoid **out_indices = alloca(sizeof(indices[0]) * draw_count);
1274*61046927SAndroid Build Coastguard Worker 
1275*61046927SAndroid Build Coastguard Worker       index_buffer = upload_multi_indices(ctx, total_count, index_size,
1276*61046927SAndroid Build Coastguard Worker                                           draw_count, count, indices,
1277*61046927SAndroid Build Coastguard Worker                                           out_indices);
1278*61046927SAndroid Build Coastguard Worker       if (!index_buffer)
1279*61046927SAndroid Build Coastguard Worker          return; /* the error is set by upload_multi_indices */
1280*61046927SAndroid Build Coastguard Worker 
1281*61046927SAndroid Build Coastguard Worker       indices = out_indices;
1282*61046927SAndroid Build Coastguard Worker    }
1283*61046927SAndroid Build Coastguard Worker 
1284*61046927SAndroid Build Coastguard Worker    /* Draw asynchronously. */
1285*61046927SAndroid Build Coastguard Worker    multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1286*61046927SAndroid Build Coastguard Worker                              basevertex, index_buffer, user_buffer_mask,
1287*61046927SAndroid Build Coastguard Worker                              buffers, offsets);
1288*61046927SAndroid Build Coastguard Worker }
1289*61046927SAndroid Build Coastguard Worker 
1290*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiModeDrawArraysIBM(const GLenum * mode,const GLint * first,const GLsizei * count,GLsizei primcount,GLint modestride)1291*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiModeDrawArraysIBM(const GLenum *mode, const GLint *first,
1292*61046927SAndroid Build Coastguard Worker                                      const GLsizei *count, GLsizei primcount,
1293*61046927SAndroid Build Coastguard Worker                                      GLint modestride)
1294*61046927SAndroid Build Coastguard Worker {
1295*61046927SAndroid Build Coastguard Worker    for (int i = 0 ; i < primcount; i++) {
1296*61046927SAndroid Build Coastguard Worker       if (count[i] > 0) {
1297*61046927SAndroid Build Coastguard Worker          GLenum m = *((GLenum *)((GLubyte *)mode + i * modestride));
1298*61046927SAndroid Build Coastguard Worker          _mesa_marshal_DrawArrays(m, first[i], count[i]);
1299*61046927SAndroid Build Coastguard Worker       }
1300*61046927SAndroid Build Coastguard Worker    }
1301*61046927SAndroid Build Coastguard Worker }
1302*61046927SAndroid Build Coastguard Worker 
1303*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiModeDrawElementsIBM(const GLenum * mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,GLint modestride)1304*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiModeDrawElementsIBM(const GLenum *mode,
1305*61046927SAndroid Build Coastguard Worker                                        const GLsizei *count, GLenum type,
1306*61046927SAndroid Build Coastguard Worker                                        const GLvoid * const *indices,
1307*61046927SAndroid Build Coastguard Worker                                        GLsizei primcount, GLint modestride)
1308*61046927SAndroid Build Coastguard Worker {
1309*61046927SAndroid Build Coastguard Worker    for (int i = 0 ; i < primcount; i++) {
1310*61046927SAndroid Build Coastguard Worker       if (count[i] > 0) {
1311*61046927SAndroid Build Coastguard Worker          GLenum m = *((GLenum *)((GLubyte *)mode + i * modestride));
1312*61046927SAndroid Build Coastguard Worker          _mesa_marshal_DrawElements(m, count[i], type, indices[i]);
1313*61046927SAndroid Build Coastguard Worker       }
1314*61046927SAndroid Build Coastguard Worker    }
1315*61046927SAndroid Build Coastguard Worker }
1316*61046927SAndroid Build Coastguard Worker 
1317*61046927SAndroid Build Coastguard Worker static const void *
map_draw_indirect_params(struct gl_context * ctx,GLintptr offset,unsigned count,unsigned stride)1318*61046927SAndroid Build Coastguard Worker map_draw_indirect_params(struct gl_context *ctx, GLintptr offset,
1319*61046927SAndroid Build Coastguard Worker                          unsigned count, unsigned stride)
1320*61046927SAndroid Build Coastguard Worker {
1321*61046927SAndroid Build Coastguard Worker    struct gl_buffer_object *obj = ctx->DrawIndirectBuffer;
1322*61046927SAndroid Build Coastguard Worker 
1323*61046927SAndroid Build Coastguard Worker    if (!obj)
1324*61046927SAndroid Build Coastguard Worker       return (void*)offset;
1325*61046927SAndroid Build Coastguard Worker 
1326*61046927SAndroid Build Coastguard Worker    return _mesa_bufferobj_map_range(ctx, offset,
1327*61046927SAndroid Build Coastguard Worker                                     MIN2((size_t)count * stride, obj->Size),
1328*61046927SAndroid Build Coastguard Worker                                     GL_MAP_READ_BIT, obj, MAP_INTERNAL);
1329*61046927SAndroid Build Coastguard Worker }
1330*61046927SAndroid Build Coastguard Worker 
1331*61046927SAndroid Build Coastguard Worker static void
unmap_draw_indirect_params(struct gl_context * ctx)1332*61046927SAndroid Build Coastguard Worker unmap_draw_indirect_params(struct gl_context *ctx)
1333*61046927SAndroid Build Coastguard Worker {
1334*61046927SAndroid Build Coastguard Worker    if (ctx->DrawIndirectBuffer)
1335*61046927SAndroid Build Coastguard Worker       _mesa_bufferobj_unmap(ctx, ctx->DrawIndirectBuffer, MAP_INTERNAL);
1336*61046927SAndroid Build Coastguard Worker }
1337*61046927SAndroid Build Coastguard Worker 
1338*61046927SAndroid Build Coastguard Worker static unsigned
read_draw_indirect_count(struct gl_context * ctx,GLintptr offset)1339*61046927SAndroid Build Coastguard Worker read_draw_indirect_count(struct gl_context *ctx, GLintptr offset)
1340*61046927SAndroid Build Coastguard Worker {
1341*61046927SAndroid Build Coastguard Worker    unsigned result = 0;
1342*61046927SAndroid Build Coastguard Worker 
1343*61046927SAndroid Build Coastguard Worker    if (ctx->ParameterBuffer) {
1344*61046927SAndroid Build Coastguard Worker       _mesa_bufferobj_get_subdata(ctx, offset, sizeof(result), &result,
1345*61046927SAndroid Build Coastguard Worker                                   ctx->ParameterBuffer);
1346*61046927SAndroid Build Coastguard Worker    }
1347*61046927SAndroid Build Coastguard Worker    return result;
1348*61046927SAndroid Build Coastguard Worker }
1349*61046927SAndroid Build Coastguard Worker 
1350*61046927SAndroid Build Coastguard Worker static void
lower_draw_arrays_indirect(struct gl_context * ctx,GLenum mode,GLintptr indirect,GLsizei stride,unsigned draw_count)1351*61046927SAndroid Build Coastguard Worker lower_draw_arrays_indirect(struct gl_context *ctx, GLenum mode,
1352*61046927SAndroid Build Coastguard Worker                            GLintptr indirect, GLsizei stride,
1353*61046927SAndroid Build Coastguard Worker                            unsigned draw_count)
1354*61046927SAndroid Build Coastguard Worker {
1355*61046927SAndroid Build Coastguard Worker    /* If <stride> is zero, the elements are tightly packed. */
1356*61046927SAndroid Build Coastguard Worker    if (stride == 0)
1357*61046927SAndroid Build Coastguard Worker       stride = 4 * sizeof(GLuint);      /* sizeof(DrawArraysIndirectCommand) */
1358*61046927SAndroid Build Coastguard Worker 
1359*61046927SAndroid Build Coastguard Worker    const uint32_t *params =
1360*61046927SAndroid Build Coastguard Worker       map_draw_indirect_params(ctx, indirect, draw_count, stride);
1361*61046927SAndroid Build Coastguard Worker 
1362*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < draw_count; i++) {
1363*61046927SAndroid Build Coastguard Worker       draw_arrays(i, mode,
1364*61046927SAndroid Build Coastguard Worker                   params[i * stride / 4 + 2],
1365*61046927SAndroid Build Coastguard Worker                   params[i * stride / 4 + 0],
1366*61046927SAndroid Build Coastguard Worker                   params[i * stride / 4 + 1],
1367*61046927SAndroid Build Coastguard Worker                   params[i * stride / 4 + 3], false, false);
1368*61046927SAndroid Build Coastguard Worker    }
1369*61046927SAndroid Build Coastguard Worker 
1370*61046927SAndroid Build Coastguard Worker    unmap_draw_indirect_params(ctx);
1371*61046927SAndroid Build Coastguard Worker }
1372*61046927SAndroid Build Coastguard Worker 
1373*61046927SAndroid Build Coastguard Worker static void
lower_draw_elements_indirect(struct gl_context * ctx,GLenum mode,GLenum type,GLintptr indirect,GLsizei stride,unsigned draw_count)1374*61046927SAndroid Build Coastguard Worker lower_draw_elements_indirect(struct gl_context *ctx, GLenum mode, GLenum type,
1375*61046927SAndroid Build Coastguard Worker                              GLintptr indirect, GLsizei stride,
1376*61046927SAndroid Build Coastguard Worker                              unsigned draw_count)
1377*61046927SAndroid Build Coastguard Worker {
1378*61046927SAndroid Build Coastguard Worker    /* If <stride> is zero, the elements are tightly packed. */
1379*61046927SAndroid Build Coastguard Worker    if (stride == 0)
1380*61046927SAndroid Build Coastguard Worker       stride = 5 * sizeof(GLuint);      /* sizeof(DrawArraysIndirectCommand) */
1381*61046927SAndroid Build Coastguard Worker 
1382*61046927SAndroid Build Coastguard Worker    const uint32_t *params =
1383*61046927SAndroid Build Coastguard Worker       map_draw_indirect_params(ctx, indirect, draw_count, stride);
1384*61046927SAndroid Build Coastguard Worker 
1385*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < draw_count; i++) {
1386*61046927SAndroid Build Coastguard Worker       draw_elements(i, mode,
1387*61046927SAndroid Build Coastguard Worker                     params[i * stride / 4 + 0],
1388*61046927SAndroid Build Coastguard Worker                     type,
1389*61046927SAndroid Build Coastguard Worker                     (GLvoid*)((uintptr_t)params[i * stride / 4 + 2] *
1390*61046927SAndroid Build Coastguard Worker                               get_index_size(type)),
1391*61046927SAndroid Build Coastguard Worker                     params[i * stride / 4 + 1],
1392*61046927SAndroid Build Coastguard Worker                     params[i * stride / 4 + 3],
1393*61046927SAndroid Build Coastguard Worker                     params[i * stride / 4 + 4],
1394*61046927SAndroid Build Coastguard Worker                     false, 0, 0, false, false);
1395*61046927SAndroid Build Coastguard Worker    }
1396*61046927SAndroid Build Coastguard Worker    unmap_draw_indirect_params(ctx);
1397*61046927SAndroid Build Coastguard Worker }
1398*61046927SAndroid Build Coastguard Worker 
1399*61046927SAndroid Build Coastguard Worker static inline bool
draw_indirect_async_allowed(struct gl_context * ctx,unsigned user_buffer_mask)1400*61046927SAndroid Build Coastguard Worker draw_indirect_async_allowed(struct gl_context *ctx, unsigned user_buffer_mask)
1401*61046927SAndroid Build Coastguard Worker {
1402*61046927SAndroid Build Coastguard Worker    return ctx->API != API_OPENGL_COMPAT ||
1403*61046927SAndroid Build Coastguard Worker           /* This will just generate GL_INVALID_OPERATION, as it should. */
1404*61046927SAndroid Build Coastguard Worker           ctx->GLThread.inside_begin_end ||
1405*61046927SAndroid Build Coastguard Worker           ctx->GLThread.ListMode ||
1406*61046927SAndroid Build Coastguard Worker           ctx->Dispatch.Current == ctx->Dispatch.ContextLost ||
1407*61046927SAndroid Build Coastguard Worker           /* If the DrawIndirect buffer is bound, it behaves like profile != compat
1408*61046927SAndroid Build Coastguard Worker            * if there are no user VBOs. */
1409*61046927SAndroid Build Coastguard Worker           (ctx->GLThread.CurrentDrawIndirectBufferName && !user_buffer_mask);
1410*61046927SAndroid Build Coastguard Worker }
1411*61046927SAndroid Build Coastguard Worker 
1412*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawArraysIndirect(struct gl_context * ctx,const struct marshal_cmd_DrawArraysIndirect * cmd)1413*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawArraysIndirect(struct gl_context *ctx,
1414*61046927SAndroid Build Coastguard Worker                                    const struct marshal_cmd_DrawArraysIndirect *cmd)
1415*61046927SAndroid Build Coastguard Worker {
1416*61046927SAndroid Build Coastguard Worker    GLenum mode = cmd->mode;
1417*61046927SAndroid Build Coastguard Worker    const GLvoid * indirect = cmd->indirect;
1418*61046927SAndroid Build Coastguard Worker 
1419*61046927SAndroid Build Coastguard Worker    CALL_DrawArraysIndirect(ctx->Dispatch.Current, (mode, indirect));
1420*61046927SAndroid Build Coastguard Worker 
1421*61046927SAndroid Build Coastguard Worker    return align(sizeof(struct marshal_cmd_DrawArraysIndirect), 8) / 8;
1422*61046927SAndroid Build Coastguard Worker }
1423*61046927SAndroid Build Coastguard Worker 
1424*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArraysIndirect(GLenum mode,const GLvoid * indirect)1425*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
1426*61046927SAndroid Build Coastguard Worker {
1427*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1428*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
1429*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
1430*61046927SAndroid Build Coastguard Worker       _mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
1431*61046927SAndroid Build Coastguard Worker 
1432*61046927SAndroid Build Coastguard Worker    if (draw_indirect_async_allowed(ctx, user_buffer_mask)) {
1433*61046927SAndroid Build Coastguard Worker       int cmd_size = sizeof(struct marshal_cmd_DrawArraysIndirect);
1434*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_DrawArraysIndirect *cmd;
1435*61046927SAndroid Build Coastguard Worker 
1436*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArraysIndirect, cmd_size);
1437*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
1438*61046927SAndroid Build Coastguard Worker       cmd->indirect = indirect;
1439*61046927SAndroid Build Coastguard Worker       return;
1440*61046927SAndroid Build Coastguard Worker    }
1441*61046927SAndroid Build Coastguard Worker 
1442*61046927SAndroid Build Coastguard Worker    _mesa_glthread_finish_before(ctx, "DrawArraysIndirect");
1443*61046927SAndroid Build Coastguard Worker    lower_draw_arrays_indirect(ctx, mode, (GLintptr)indirect, 0, 1);
1444*61046927SAndroid Build Coastguard Worker }
1445*61046927SAndroid Build Coastguard Worker 
1446*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsIndirect(struct gl_context * ctx,const struct marshal_cmd_DrawElementsIndirect * cmd)1447*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsIndirect(struct gl_context *ctx,
1448*61046927SAndroid Build Coastguard Worker                                      const struct marshal_cmd_DrawElementsIndirect *cmd)
1449*61046927SAndroid Build Coastguard Worker {
1450*61046927SAndroid Build Coastguard Worker    GLenum mode = cmd->mode;
1451*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
1452*61046927SAndroid Build Coastguard Worker    const GLvoid * indirect = cmd->indirect;
1453*61046927SAndroid Build Coastguard Worker 
1454*61046927SAndroid Build Coastguard Worker    CALL_DrawElementsIndirect(ctx->Dispatch.Current, (mode, type, indirect));
1455*61046927SAndroid Build Coastguard Worker    return align(sizeof(struct marshal_cmd_DrawElementsIndirect), 8) / 8;
1456*61046927SAndroid Build Coastguard Worker }
1457*61046927SAndroid Build Coastguard Worker 
1458*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect)1459*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
1460*61046927SAndroid Build Coastguard Worker {
1461*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1462*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
1463*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
1464*61046927SAndroid Build Coastguard Worker       _mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
1465*61046927SAndroid Build Coastguard Worker 
1466*61046927SAndroid Build Coastguard Worker    if (draw_indirect_async_allowed(ctx, user_buffer_mask) ||
1467*61046927SAndroid Build Coastguard Worker        !_mesa_is_index_type_valid(type)) {
1468*61046927SAndroid Build Coastguard Worker       int cmd_size = sizeof(struct marshal_cmd_DrawElementsIndirect);
1469*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_DrawElementsIndirect *cmd;
1470*61046927SAndroid Build Coastguard Worker 
1471*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsIndirect, cmd_size);
1472*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
1473*61046927SAndroid Build Coastguard Worker       cmd->type = encode_index_type(type);
1474*61046927SAndroid Build Coastguard Worker       cmd->indirect = indirect;
1475*61046927SAndroid Build Coastguard Worker       return;
1476*61046927SAndroid Build Coastguard Worker    }
1477*61046927SAndroid Build Coastguard Worker 
1478*61046927SAndroid Build Coastguard Worker    _mesa_glthread_finish_before(ctx, "DrawElementsIndirect");
1479*61046927SAndroid Build Coastguard Worker    lower_draw_elements_indirect(ctx, mode, type, (GLintptr)indirect, 0, 1);
1480*61046927SAndroid Build Coastguard Worker }
1481*61046927SAndroid Build Coastguard Worker 
1482*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawArraysIndirect(struct gl_context * ctx,const struct marshal_cmd_MultiDrawArraysIndirect * cmd)1483*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawArraysIndirect(struct gl_context *ctx,
1484*61046927SAndroid Build Coastguard Worker                                         const struct marshal_cmd_MultiDrawArraysIndirect *cmd)
1485*61046927SAndroid Build Coastguard Worker {
1486*61046927SAndroid Build Coastguard Worker    GLenum mode = cmd->mode;
1487*61046927SAndroid Build Coastguard Worker    const GLvoid * indirect = cmd->indirect;
1488*61046927SAndroid Build Coastguard Worker    GLsizei primcount = cmd->primcount;
1489*61046927SAndroid Build Coastguard Worker    GLsizei stride = cmd->stride;
1490*61046927SAndroid Build Coastguard Worker 
1491*61046927SAndroid Build Coastguard Worker    CALL_MultiDrawArraysIndirect(ctx->Dispatch.Current,
1492*61046927SAndroid Build Coastguard Worker                                 (mode, indirect, primcount, stride));
1493*61046927SAndroid Build Coastguard Worker    return align(sizeof(struct marshal_cmd_MultiDrawArraysIndirect), 8) / 8;
1494*61046927SAndroid Build Coastguard Worker }
1495*61046927SAndroid Build Coastguard Worker 
1496*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawArraysIndirect(GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)1497*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
1498*61046927SAndroid Build Coastguard Worker                                       GLsizei primcount, GLsizei stride)
1499*61046927SAndroid Build Coastguard Worker {
1500*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1501*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
1502*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
1503*61046927SAndroid Build Coastguard Worker       _mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
1504*61046927SAndroid Build Coastguard Worker 
1505*61046927SAndroid Build Coastguard Worker    if (draw_indirect_async_allowed(ctx, user_buffer_mask) ||
1506*61046927SAndroid Build Coastguard Worker        primcount <= 0) {
1507*61046927SAndroid Build Coastguard Worker       int cmd_size = sizeof(struct marshal_cmd_MultiDrawArraysIndirect);
1508*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_MultiDrawArraysIndirect *cmd;
1509*61046927SAndroid Build Coastguard Worker 
1510*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArraysIndirect,
1511*61046927SAndroid Build Coastguard Worker                                             cmd_size);
1512*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
1513*61046927SAndroid Build Coastguard Worker       cmd->indirect = indirect;
1514*61046927SAndroid Build Coastguard Worker       cmd->primcount = primcount;
1515*61046927SAndroid Build Coastguard Worker       cmd->stride = stride;
1516*61046927SAndroid Build Coastguard Worker       return;
1517*61046927SAndroid Build Coastguard Worker    }
1518*61046927SAndroid Build Coastguard Worker 
1519*61046927SAndroid Build Coastguard Worker    /* Lower the draw to direct due to non-VBO vertex arrays. */
1520*61046927SAndroid Build Coastguard Worker    _mesa_glthread_finish_before(ctx, "MultiDrawArraysIndirect");
1521*61046927SAndroid Build Coastguard Worker    lower_draw_arrays_indirect(ctx, mode, (GLintptr)indirect, stride, primcount);
1522*61046927SAndroid Build Coastguard Worker }
1523*61046927SAndroid Build Coastguard Worker 
1524*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawElementsIndirect(struct gl_context * ctx,const struct marshal_cmd_MultiDrawElementsIndirect * cmd)1525*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawElementsIndirect(struct gl_context *ctx,
1526*61046927SAndroid Build Coastguard Worker                                           const struct marshal_cmd_MultiDrawElementsIndirect *cmd)
1527*61046927SAndroid Build Coastguard Worker {
1528*61046927SAndroid Build Coastguard Worker    GLenum mode = cmd->mode;
1529*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
1530*61046927SAndroid Build Coastguard Worker    const GLvoid * indirect = cmd->indirect;
1531*61046927SAndroid Build Coastguard Worker    GLsizei primcount = cmd->primcount;
1532*61046927SAndroid Build Coastguard Worker    GLsizei stride = cmd->stride;
1533*61046927SAndroid Build Coastguard Worker 
1534*61046927SAndroid Build Coastguard Worker    CALL_MultiDrawElementsIndirect(ctx->Dispatch.Current,
1535*61046927SAndroid Build Coastguard Worker                                   (mode, type, indirect, primcount, stride));
1536*61046927SAndroid Build Coastguard Worker    return align(sizeof(struct marshal_cmd_MultiDrawElementsIndirect), 8) / 8;
1537*61046927SAndroid Build Coastguard Worker }
1538*61046927SAndroid Build Coastguard Worker 
1539*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)1540*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawElementsIndirect(GLenum mode, GLenum type,
1541*61046927SAndroid Build Coastguard Worker                                         const GLvoid *indirect,
1542*61046927SAndroid Build Coastguard Worker                                         GLsizei primcount, GLsizei stride)
1543*61046927SAndroid Build Coastguard Worker {
1544*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1545*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
1546*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
1547*61046927SAndroid Build Coastguard Worker       _mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
1548*61046927SAndroid Build Coastguard Worker 
1549*61046927SAndroid Build Coastguard Worker    if (draw_indirect_async_allowed(ctx, user_buffer_mask) ||
1550*61046927SAndroid Build Coastguard Worker        primcount <= 0 ||
1551*61046927SAndroid Build Coastguard Worker        !_mesa_is_index_type_valid(type)) {
1552*61046927SAndroid Build Coastguard Worker       int cmd_size = sizeof(struct marshal_cmd_MultiDrawElementsIndirect);
1553*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_MultiDrawElementsIndirect *cmd;
1554*61046927SAndroid Build Coastguard Worker 
1555*61046927SAndroid Build Coastguard Worker       cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsIndirect,
1556*61046927SAndroid Build Coastguard Worker                                             cmd_size);
1557*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
1558*61046927SAndroid Build Coastguard Worker       cmd->type = encode_index_type(type);
1559*61046927SAndroid Build Coastguard Worker       cmd->indirect = indirect;
1560*61046927SAndroid Build Coastguard Worker       cmd->primcount = primcount;
1561*61046927SAndroid Build Coastguard Worker       cmd->stride = stride;
1562*61046927SAndroid Build Coastguard Worker       return;
1563*61046927SAndroid Build Coastguard Worker    }
1564*61046927SAndroid Build Coastguard Worker 
1565*61046927SAndroid Build Coastguard Worker    /* Lower the draw to direct due to non-VBO vertex arrays. */
1566*61046927SAndroid Build Coastguard Worker    _mesa_glthread_finish_before(ctx, "MultiDrawElementsIndirect");
1567*61046927SAndroid Build Coastguard Worker    lower_draw_elements_indirect(ctx, mode, type, (GLintptr)indirect, stride,
1568*61046927SAndroid Build Coastguard Worker                                 primcount);
1569*61046927SAndroid Build Coastguard Worker }
1570*61046927SAndroid Build Coastguard Worker 
1571*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawArraysIndirectCountARB(struct gl_context * ctx,const struct marshal_cmd_MultiDrawArraysIndirectCountARB * cmd)1572*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawArraysIndirectCountARB(struct gl_context *ctx,
1573*61046927SAndroid Build Coastguard Worker                                                 const struct marshal_cmd_MultiDrawArraysIndirectCountARB *cmd)
1574*61046927SAndroid Build Coastguard Worker {
1575*61046927SAndroid Build Coastguard Worker    GLenum mode = cmd->mode;
1576*61046927SAndroid Build Coastguard Worker    GLintptr indirect = cmd->indirect;
1577*61046927SAndroid Build Coastguard Worker    GLintptr drawcount = cmd->drawcount;
1578*61046927SAndroid Build Coastguard Worker    GLsizei maxdrawcount = cmd->maxdrawcount;
1579*61046927SAndroid Build Coastguard Worker    GLsizei stride = cmd->stride;
1580*61046927SAndroid Build Coastguard Worker 
1581*61046927SAndroid Build Coastguard Worker    CALL_MultiDrawArraysIndirectCountARB(ctx->Dispatch.Current,
1582*61046927SAndroid Build Coastguard Worker                                         (mode, indirect, drawcount,
1583*61046927SAndroid Build Coastguard Worker                                          maxdrawcount, stride));
1584*61046927SAndroid Build Coastguard Worker    return align(sizeof(struct marshal_cmd_MultiDrawArraysIndirectCountARB), 8) / 8;
1585*61046927SAndroid Build Coastguard Worker }
1586*61046927SAndroid Build Coastguard Worker 
1587*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawArraysIndirectCountARB(GLenum mode,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)1588*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect,
1589*61046927SAndroid Build Coastguard Worker                                               GLintptr drawcount,
1590*61046927SAndroid Build Coastguard Worker                                               GLsizei maxdrawcount,
1591*61046927SAndroid Build Coastguard Worker                                               GLsizei stride)
1592*61046927SAndroid Build Coastguard Worker {
1593*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1594*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
1595*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
1596*61046927SAndroid Build Coastguard Worker       _mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
1597*61046927SAndroid Build Coastguard Worker 
1598*61046927SAndroid Build Coastguard Worker    if (draw_indirect_async_allowed(ctx, user_buffer_mask) ||
1599*61046927SAndroid Build Coastguard Worker        /* This will just generate GL_INVALID_OPERATION because Draw*IndirectCount
1600*61046927SAndroid Build Coastguard Worker         * functions forbid a user indirect buffer in the Compat profile. */
1601*61046927SAndroid Build Coastguard Worker        !ctx->GLThread.CurrentDrawIndirectBufferName) {
1602*61046927SAndroid Build Coastguard Worker       int cmd_size =
1603*61046927SAndroid Build Coastguard Worker          sizeof(struct marshal_cmd_MultiDrawArraysIndirectCountARB);
1604*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_MultiDrawArraysIndirectCountARB *cmd =
1605*61046927SAndroid Build Coastguard Worker          _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArraysIndirectCountARB,
1606*61046927SAndroid Build Coastguard Worker                                          cmd_size);
1607*61046927SAndroid Build Coastguard Worker 
1608*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
1609*61046927SAndroid Build Coastguard Worker       cmd->indirect = indirect;
1610*61046927SAndroid Build Coastguard Worker       cmd->drawcount = drawcount;
1611*61046927SAndroid Build Coastguard Worker       cmd->maxdrawcount = maxdrawcount;
1612*61046927SAndroid Build Coastguard Worker       cmd->stride = stride;
1613*61046927SAndroid Build Coastguard Worker       return;
1614*61046927SAndroid Build Coastguard Worker    }
1615*61046927SAndroid Build Coastguard Worker 
1616*61046927SAndroid Build Coastguard Worker    /* Lower the draw to direct due to non-VBO vertex arrays. */
1617*61046927SAndroid Build Coastguard Worker    _mesa_glthread_finish_before(ctx, "MultiDrawArraysIndirectCountARB");
1618*61046927SAndroid Build Coastguard Worker    lower_draw_arrays_indirect(ctx, mode, indirect, stride,
1619*61046927SAndroid Build Coastguard Worker                               read_draw_indirect_count(ctx, drawcount));
1620*61046927SAndroid Build Coastguard Worker }
1621*61046927SAndroid Build Coastguard Worker 
1622*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawElementsIndirectCountARB(struct gl_context * ctx,const struct marshal_cmd_MultiDrawElementsIndirectCountARB * cmd)1623*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawElementsIndirectCountARB(struct gl_context *ctx,
1624*61046927SAndroid Build Coastguard Worker                                                   const struct marshal_cmd_MultiDrawElementsIndirectCountARB *cmd)
1625*61046927SAndroid Build Coastguard Worker {
1626*61046927SAndroid Build Coastguard Worker    GLenum mode = cmd->mode;
1627*61046927SAndroid Build Coastguard Worker    const GLenum type = _mesa_decode_index_type(cmd->type);
1628*61046927SAndroid Build Coastguard Worker    GLintptr indirect = cmd->indirect;
1629*61046927SAndroid Build Coastguard Worker    GLintptr drawcount = cmd->drawcount;
1630*61046927SAndroid Build Coastguard Worker    GLsizei maxdrawcount = cmd->maxdrawcount;
1631*61046927SAndroid Build Coastguard Worker    GLsizei stride = cmd->stride;
1632*61046927SAndroid Build Coastguard Worker 
1633*61046927SAndroid Build Coastguard Worker    CALL_MultiDrawElementsIndirectCountARB(ctx->Dispatch.Current, (mode, type, indirect, drawcount, maxdrawcount, stride));
1634*61046927SAndroid Build Coastguard Worker 
1635*61046927SAndroid Build Coastguard Worker    return align(sizeof(struct marshal_cmd_MultiDrawElementsIndirectCountARB), 8) / 8;
1636*61046927SAndroid Build Coastguard Worker }
1637*61046927SAndroid Build Coastguard Worker 
1638*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawElementsIndirectCountARB(GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)1639*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawElementsIndirectCountARB(GLenum mode, GLenum type,
1640*61046927SAndroid Build Coastguard Worker                                                 GLintptr indirect,
1641*61046927SAndroid Build Coastguard Worker                                                 GLintptr drawcount,
1642*61046927SAndroid Build Coastguard Worker                                                 GLsizei maxdrawcount,
1643*61046927SAndroid Build Coastguard Worker                                                 GLsizei stride)
1644*61046927SAndroid Build Coastguard Worker {
1645*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1646*61046927SAndroid Build Coastguard Worker    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
1647*61046927SAndroid Build Coastguard Worker    unsigned user_buffer_mask =
1648*61046927SAndroid Build Coastguard Worker       _mesa_is_gles31(ctx) ? 0 : vao->UserPointerMask & vao->BufferEnabled;
1649*61046927SAndroid Build Coastguard Worker 
1650*61046927SAndroid Build Coastguard Worker    if (draw_indirect_async_allowed(ctx, user_buffer_mask) ||
1651*61046927SAndroid Build Coastguard Worker        /* This will just generate GL_INVALID_OPERATION because Draw*IndirectCount
1652*61046927SAndroid Build Coastguard Worker         * functions forbid a user indirect buffer in the Compat profile. */
1653*61046927SAndroid Build Coastguard Worker        !ctx->GLThread.CurrentDrawIndirectBufferName ||
1654*61046927SAndroid Build Coastguard Worker        !_mesa_is_index_type_valid(type)) {
1655*61046927SAndroid Build Coastguard Worker       int cmd_size = sizeof(struct marshal_cmd_MultiDrawElementsIndirectCountARB);
1656*61046927SAndroid Build Coastguard Worker       struct marshal_cmd_MultiDrawElementsIndirectCountARB *cmd =
1657*61046927SAndroid Build Coastguard Worker          _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsIndirectCountARB, cmd_size);
1658*61046927SAndroid Build Coastguard Worker 
1659*61046927SAndroid Build Coastguard Worker       cmd->mode = MIN2(mode, 0xff); /* clamped to 0xff (invalid enum) */
1660*61046927SAndroid Build Coastguard Worker       cmd->type = encode_index_type(type);
1661*61046927SAndroid Build Coastguard Worker       cmd->indirect = indirect;
1662*61046927SAndroid Build Coastguard Worker       cmd->drawcount = drawcount;
1663*61046927SAndroid Build Coastguard Worker       cmd->maxdrawcount = maxdrawcount;
1664*61046927SAndroid Build Coastguard Worker       cmd->stride = stride;
1665*61046927SAndroid Build Coastguard Worker       return;
1666*61046927SAndroid Build Coastguard Worker    }
1667*61046927SAndroid Build Coastguard Worker 
1668*61046927SAndroid Build Coastguard Worker    /* Lower the draw to direct due to non-VBO vertex arrays. */
1669*61046927SAndroid Build Coastguard Worker    _mesa_glthread_finish_before(ctx, "MultiDrawElementsIndirectCountARB");
1670*61046927SAndroid Build Coastguard Worker    lower_draw_elements_indirect(ctx, mode, type, indirect, stride,
1671*61046927SAndroid Build Coastguard Worker                                 read_draw_indirect_count(ctx, drawcount));
1672*61046927SAndroid Build Coastguard Worker }
1673*61046927SAndroid Build Coastguard Worker 
1674*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArrays(GLenum mode,GLint first,GLsizei count)1675*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArrays(GLenum mode, GLint first, GLsizei count)
1676*61046927SAndroid Build Coastguard Worker {
1677*61046927SAndroid Build Coastguard Worker    draw_arrays(0, mode, first, count, 1, 0, true, false);
1678*61046927SAndroid Build Coastguard Worker }
1679*61046927SAndroid Build Coastguard Worker 
1680*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArrays_no_error(GLenum mode,GLint first,GLsizei count)1681*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArrays_no_error(GLenum mode, GLint first, GLsizei count)
1682*61046927SAndroid Build Coastguard Worker {
1683*61046927SAndroid Build Coastguard Worker    draw_arrays(0, mode, first, count, 1, 0, true, true);
1684*61046927SAndroid Build Coastguard Worker }
1685*61046927SAndroid Build Coastguard Worker 
1686*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArraysInstanced(GLenum mode,GLint first,GLsizei count,GLsizei instance_count)1687*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
1688*61046927SAndroid Build Coastguard Worker                                   GLsizei instance_count)
1689*61046927SAndroid Build Coastguard Worker {
1690*61046927SAndroid Build Coastguard Worker    draw_arrays(0, mode, first, count, instance_count, 0, false, false);
1691*61046927SAndroid Build Coastguard Worker }
1692*61046927SAndroid Build Coastguard Worker 
1693*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArraysInstanced_no_error(GLenum mode,GLint first,GLsizei count,GLsizei instance_count)1694*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArraysInstanced_no_error(GLenum mode, GLint first, GLsizei count,
1695*61046927SAndroid Build Coastguard Worker                                            GLsizei instance_count)
1696*61046927SAndroid Build Coastguard Worker {
1697*61046927SAndroid Build Coastguard Worker    draw_arrays(0, mode, first, count, instance_count, 0, false, true);
1698*61046927SAndroid Build Coastguard Worker }
1699*61046927SAndroid Build Coastguard Worker 
1700*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArraysInstancedBaseInstance(GLenum mode,GLint first,GLsizei count,GLsizei instance_count,GLuint baseinstance)1701*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
1702*61046927SAndroid Build Coastguard Worker                                               GLsizei count, GLsizei instance_count,
1703*61046927SAndroid Build Coastguard Worker                                               GLuint baseinstance)
1704*61046927SAndroid Build Coastguard Worker {
1705*61046927SAndroid Build Coastguard Worker    draw_arrays(0, mode, first, count, instance_count, baseinstance, false, false);
1706*61046927SAndroid Build Coastguard Worker }
1707*61046927SAndroid Build Coastguard Worker 
1708*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArraysInstancedBaseInstance_no_error(GLenum mode,GLint first,GLsizei count,GLsizei instance_count,GLuint baseinstance)1709*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArraysInstancedBaseInstance_no_error(GLenum mode, GLint first,
1710*61046927SAndroid Build Coastguard Worker                                                        GLsizei count, GLsizei instance_count,
1711*61046927SAndroid Build Coastguard Worker                                                        GLuint baseinstance)
1712*61046927SAndroid Build Coastguard Worker {
1713*61046927SAndroid Build Coastguard Worker    draw_arrays(0, mode, first, count, instance_count, baseinstance, false, true);
1714*61046927SAndroid Build Coastguard Worker }
1715*61046927SAndroid Build Coastguard Worker 
1716*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)1717*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElements(GLenum mode, GLsizei count, GLenum type,
1718*61046927SAndroid Build Coastguard Worker                            const GLvoid *indices)
1719*61046927SAndroid Build Coastguard Worker {
1720*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, 0,
1721*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, true, false);
1722*61046927SAndroid Build Coastguard Worker }
1723*61046927SAndroid Build Coastguard Worker 
1724*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElements_no_error(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)1725*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElements_no_error(GLenum mode, GLsizei count, GLenum type,
1726*61046927SAndroid Build Coastguard Worker                                     const GLvoid *indices)
1727*61046927SAndroid Build Coastguard Worker {
1728*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, 0,
1729*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, true, true);
1730*61046927SAndroid Build Coastguard Worker }
1731*61046927SAndroid Build Coastguard Worker 
1732*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)1733*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1734*61046927SAndroid Build Coastguard Worker                                 GLsizei count, GLenum type,
1735*61046927SAndroid Build Coastguard Worker                                 const GLvoid *indices)
1736*61046927SAndroid Build Coastguard Worker {
1737*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, 0,
1738*61046927SAndroid Build Coastguard Worker                  0, true, start, end, true, false);
1739*61046927SAndroid Build Coastguard Worker }
1740*61046927SAndroid Build Coastguard Worker 
1741*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawRangeElements_no_error(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)1742*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawRangeElements_no_error(GLenum mode, GLuint start, GLuint end,
1743*61046927SAndroid Build Coastguard Worker                                          GLsizei count, GLenum type,
1744*61046927SAndroid Build Coastguard Worker                                          const GLvoid *indices)
1745*61046927SAndroid Build Coastguard Worker {
1746*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, 0,
1747*61046927SAndroid Build Coastguard Worker                  0, true, start, end, true, true);
1748*61046927SAndroid Build Coastguard Worker }
1749*61046927SAndroid Build Coastguard Worker 
1750*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstanced(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count)1751*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1752*61046927SAndroid Build Coastguard Worker                                     const GLvoid *indices, GLsizei instance_count)
1753*61046927SAndroid Build Coastguard Worker {
1754*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, 0,
1755*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, false, false);
1756*61046927SAndroid Build Coastguard Worker }
1757*61046927SAndroid Build Coastguard Worker 
1758*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstanced_no_error(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count)1759*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstanced_no_error(GLenum mode, GLsizei count,
1760*61046927SAndroid Build Coastguard Worker                                              GLenum type, const GLvoid *indices,
1761*61046927SAndroid Build Coastguard Worker                                              GLsizei instance_count)
1762*61046927SAndroid Build Coastguard Worker {
1763*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, 0,
1764*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, false, true);
1765*61046927SAndroid Build Coastguard Worker }
1766*61046927SAndroid Build Coastguard Worker 
1767*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1768*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1769*61046927SAndroid Build Coastguard Worker                                      const GLvoid *indices, GLint basevertex)
1770*61046927SAndroid Build Coastguard Worker {
1771*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, basevertex,
1772*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, true, false);
1773*61046927SAndroid Build Coastguard Worker }
1774*61046927SAndroid Build Coastguard Worker 
1775*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsBaseVertex_no_error(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1776*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsBaseVertex_no_error(GLenum mode, GLsizei count,
1777*61046927SAndroid Build Coastguard Worker                                               GLenum type, const GLvoid *indices,
1778*61046927SAndroid Build Coastguard Worker                                               GLint basevertex)
1779*61046927SAndroid Build Coastguard Worker {
1780*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, basevertex,
1781*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, true, true);
1782*61046927SAndroid Build Coastguard Worker }
1783*61046927SAndroid Build Coastguard Worker 
1784*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawRangeElementsBaseVertex(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1785*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1786*61046927SAndroid Build Coastguard Worker                                           GLsizei count, GLenum type,
1787*61046927SAndroid Build Coastguard Worker                                           const GLvoid *indices, GLint basevertex)
1788*61046927SAndroid Build Coastguard Worker {
1789*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, basevertex,
1790*61046927SAndroid Build Coastguard Worker                  0, true, start, end, true, false);
1791*61046927SAndroid Build Coastguard Worker }
1792*61046927SAndroid Build Coastguard Worker 
1793*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawRangeElementsBaseVertex_no_error(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1794*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawRangeElementsBaseVertex_no_error(GLenum mode, GLuint start,
1795*61046927SAndroid Build Coastguard Worker                                                    GLuint end, GLsizei count, GLenum type,
1796*61046927SAndroid Build Coastguard Worker                                                    const GLvoid *indices, GLint basevertex)
1797*61046927SAndroid Build Coastguard Worker {
1798*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, 1, basevertex,
1799*61046927SAndroid Build Coastguard Worker                  0, true, start, end, true, true);
1800*61046927SAndroid Build Coastguard Worker }
1801*61046927SAndroid Build Coastguard Worker 
1802*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex)1803*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count,
1804*61046927SAndroid Build Coastguard Worker                                               GLenum type, const GLvoid *indices,
1805*61046927SAndroid Build Coastguard Worker                                               GLsizei instance_count, GLint basevertex)
1806*61046927SAndroid Build Coastguard Worker {
1807*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, basevertex,
1808*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, false, false);
1809*61046927SAndroid Build Coastguard Worker }
1810*61046927SAndroid Build Coastguard Worker 
1811*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseVertex_no_error(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex)1812*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstancedBaseVertex_no_error(GLenum mode, GLsizei count,
1813*61046927SAndroid Build Coastguard Worker                                                        GLenum type, const GLvoid *indices,
1814*61046927SAndroid Build Coastguard Worker                                                        GLsizei instance_count, GLint basevertex)
1815*61046927SAndroid Build Coastguard Worker {
1816*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, basevertex,
1817*61046927SAndroid Build Coastguard Worker                  0, false, 0, 0, false, true);
1818*61046927SAndroid Build Coastguard Worker }
1819*61046927SAndroid Build Coastguard Worker 
1820*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLuint baseinstance)1821*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,
1822*61046927SAndroid Build Coastguard Worker                                                 GLenum type, const GLvoid *indices,
1823*61046927SAndroid Build Coastguard Worker                                                 GLsizei instance_count, GLuint baseinstance)
1824*61046927SAndroid Build Coastguard Worker {
1825*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, 0,
1826*61046927SAndroid Build Coastguard Worker                  baseinstance, false, 0, 0, false, false);
1827*61046927SAndroid Build Coastguard Worker }
1828*61046927SAndroid Build Coastguard Worker 
1829*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseInstance_no_error(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLuint baseinstance)1830*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstancedBaseInstance_no_error(GLenum mode, GLsizei count,
1831*61046927SAndroid Build Coastguard Worker                                                          GLenum type, const GLvoid *indices,
1832*61046927SAndroid Build Coastguard Worker                                                          GLsizei instance_count, GLuint baseinstance)
1833*61046927SAndroid Build Coastguard Worker {
1834*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, 0,
1835*61046927SAndroid Build Coastguard Worker                  baseinstance, false, 0, 0, false, true);
1836*61046927SAndroid Build Coastguard Worker }
1837*61046927SAndroid Build Coastguard Worker 
1838*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex,GLuint baseinstance)1839*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count,
1840*61046927SAndroid Build Coastguard Worker                                                           GLenum type, const GLvoid *indices,
1841*61046927SAndroid Build Coastguard Worker                                                           GLsizei instance_count, GLint basevertex,
1842*61046927SAndroid Build Coastguard Worker                                                           GLuint baseinstance)
1843*61046927SAndroid Build Coastguard Worker {
1844*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, basevertex,
1845*61046927SAndroid Build Coastguard Worker                  baseinstance, false, 0, 0, false, false);
1846*61046927SAndroid Build Coastguard Worker }
1847*61046927SAndroid Build Coastguard Worker 
1848*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseVertexBaseInstance_no_error(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex,GLuint baseinstance)1849*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstancedBaseVertexBaseInstance_no_error(GLenum mode, GLsizei count,
1850*61046927SAndroid Build Coastguard Worker                                                                    GLenum type, const GLvoid *indices,
1851*61046927SAndroid Build Coastguard Worker                                                                    GLsizei instance_count,
1852*61046927SAndroid Build Coastguard Worker                                                                    GLint basevertex, GLuint baseinstance)
1853*61046927SAndroid Build Coastguard Worker {
1854*61046927SAndroid Build Coastguard Worker    draw_elements(0, mode, count, type, indices, instance_count, basevertex,
1855*61046927SAndroid Build Coastguard Worker                  baseinstance, false, 0, 0, false, true);
1856*61046927SAndroid Build Coastguard Worker }
1857*61046927SAndroid Build Coastguard Worker 
1858*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawElements(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei draw_count)1859*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawElements(GLenum mode, const GLsizei *count,
1860*61046927SAndroid Build Coastguard Worker                                 GLenum type, const GLvoid *const *indices,
1861*61046927SAndroid Build Coastguard Worker                                 GLsizei draw_count)
1862*61046927SAndroid Build Coastguard Worker {
1863*61046927SAndroid Build Coastguard Worker    _mesa_marshal_MultiDrawElementsBaseVertex(mode, count, type, indices,
1864*61046927SAndroid Build Coastguard Worker                                              draw_count, NULL);
1865*61046927SAndroid Build Coastguard Worker }
1866*61046927SAndroid Build Coastguard Worker 
1867*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawArrays(struct gl_context * ctx,const struct marshal_cmd_DrawArrays * restrict cmd)1868*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawArrays(struct gl_context *ctx,
1869*61046927SAndroid Build Coastguard Worker                            const struct marshal_cmd_DrawArrays *restrict cmd)
1870*61046927SAndroid Build Coastguard Worker {
1871*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1872*61046927SAndroid Build Coastguard Worker    return 0;
1873*61046927SAndroid Build Coastguard Worker }
1874*61046927SAndroid Build Coastguard Worker 
1875*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawArraysInstancedBaseInstance(struct gl_context * ctx,const struct marshal_cmd_DrawArraysInstancedBaseInstance * restrict cmd)1876*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawArraysInstancedBaseInstance(struct gl_context *ctx,
1877*61046927SAndroid Build Coastguard Worker                                                 const struct marshal_cmd_DrawArraysInstancedBaseInstance *restrict cmd)
1878*61046927SAndroid Build Coastguard Worker {
1879*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1880*61046927SAndroid Build Coastguard Worker    return 0;
1881*61046927SAndroid Build Coastguard Worker }
1882*61046927SAndroid Build Coastguard Worker 
1883*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawArrays(struct gl_context * ctx,const struct marshal_cmd_MultiDrawArrays * restrict cmd)1884*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawArrays(struct gl_context *ctx,
1885*61046927SAndroid Build Coastguard Worker                                 const struct marshal_cmd_MultiDrawArrays *restrict cmd)
1886*61046927SAndroid Build Coastguard Worker {
1887*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1888*61046927SAndroid Build Coastguard Worker    return 0;
1889*61046927SAndroid Build Coastguard Worker }
1890*61046927SAndroid Build Coastguard Worker 
1891*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawRangeElements(struct gl_context * ctx,const struct marshal_cmd_DrawRangeElements * restrict cmd)1892*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawRangeElements(struct gl_context *ctx,
1893*61046927SAndroid Build Coastguard Worker                                   const struct marshal_cmd_DrawRangeElements *restrict cmd)
1894*61046927SAndroid Build Coastguard Worker {
1895*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1896*61046927SAndroid Build Coastguard Worker    return 0;
1897*61046927SAndroid Build Coastguard Worker }
1898*61046927SAndroid Build Coastguard Worker 
1899*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawRangeElementsBaseVertex(struct gl_context * ctx,const struct marshal_cmd_DrawRangeElementsBaseVertex * cmd)1900*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawRangeElementsBaseVertex(struct gl_context *ctx,
1901*61046927SAndroid Build Coastguard Worker                                             const struct marshal_cmd_DrawRangeElementsBaseVertex *cmd)
1902*61046927SAndroid Build Coastguard Worker {
1903*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1904*61046927SAndroid Build Coastguard Worker    return 0;
1905*61046927SAndroid Build Coastguard Worker }
1906*61046927SAndroid Build Coastguard Worker 
1907*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsInstanced(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstanced * restrict cmd)1908*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsInstanced(struct gl_context *ctx,
1909*61046927SAndroid Build Coastguard Worker                                       const struct marshal_cmd_DrawElementsInstanced *restrict cmd)
1910*61046927SAndroid Build Coastguard Worker {
1911*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1912*61046927SAndroid Build Coastguard Worker    return 0;
1913*61046927SAndroid Build Coastguard Worker }
1914*61046927SAndroid Build Coastguard Worker 
1915*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsBaseVertex(struct gl_context * ctx,const struct marshal_cmd_DrawElementsBaseVertex * restrict cmd)1916*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsBaseVertex(struct gl_context *ctx,
1917*61046927SAndroid Build Coastguard Worker                                        const struct marshal_cmd_DrawElementsBaseVertex *restrict cmd)
1918*61046927SAndroid Build Coastguard Worker {
1919*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1920*61046927SAndroid Build Coastguard Worker    return 0;
1921*61046927SAndroid Build Coastguard Worker }
1922*61046927SAndroid Build Coastguard Worker 
1923*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_DrawElementsInstancedBaseVertexBaseInstance(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance * restrict cmd)1924*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_DrawElementsInstancedBaseVertexBaseInstance(struct gl_context *ctx,
1925*61046927SAndroid Build Coastguard Worker                                                             const struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance *restrict cmd)
1926*61046927SAndroid Build Coastguard Worker {
1927*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1928*61046927SAndroid Build Coastguard Worker    return 0;
1929*61046927SAndroid Build Coastguard Worker }
1930*61046927SAndroid Build Coastguard Worker 
1931*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawElements(struct gl_context * ctx,const struct marshal_cmd_MultiDrawElements * restrict cmd)1932*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawElements(struct gl_context *ctx,
1933*61046927SAndroid Build Coastguard Worker                                   const struct marshal_cmd_MultiDrawElements *restrict cmd)
1934*61046927SAndroid Build Coastguard Worker {
1935*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1936*61046927SAndroid Build Coastguard Worker    return 0;
1937*61046927SAndroid Build Coastguard Worker }
1938*61046927SAndroid Build Coastguard Worker 
1939*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiDrawElementsBaseVertex(struct gl_context * ctx,const struct marshal_cmd_MultiDrawElementsBaseVertex * restrict cmd)1940*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiDrawElementsBaseVertex(struct gl_context *ctx,
1941*61046927SAndroid Build Coastguard Worker                                             const struct marshal_cmd_MultiDrawElementsBaseVertex *restrict cmd)
1942*61046927SAndroid Build Coastguard Worker {
1943*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1944*61046927SAndroid Build Coastguard Worker    return 0;
1945*61046927SAndroid Build Coastguard Worker }
1946*61046927SAndroid Build Coastguard Worker 
1947*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiModeDrawArraysIBM(struct gl_context * ctx,const struct marshal_cmd_MultiModeDrawArraysIBM * cmd)1948*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiModeDrawArraysIBM(struct gl_context *ctx,
1949*61046927SAndroid Build Coastguard Worker                                        const struct marshal_cmd_MultiModeDrawArraysIBM *cmd)
1950*61046927SAndroid Build Coastguard Worker {
1951*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1952*61046927SAndroid Build Coastguard Worker    return 0;
1953*61046927SAndroid Build Coastguard Worker }
1954*61046927SAndroid Build Coastguard Worker 
1955*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_MultiModeDrawElementsIBM(struct gl_context * ctx,const struct marshal_cmd_MultiModeDrawElementsIBM * cmd)1956*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_MultiModeDrawElementsIBM(struct gl_context *ctx,
1957*61046927SAndroid Build Coastguard Worker                                          const struct marshal_cmd_MultiModeDrawElementsIBM *cmd)
1958*61046927SAndroid Build Coastguard Worker {
1959*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1960*61046927SAndroid Build Coastguard Worker    return 0;
1961*61046927SAndroid Build Coastguard Worker }
1962*61046927SAndroid Build Coastguard Worker 
1963*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArraysUserBuf(void)1964*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArraysUserBuf(void)
1965*61046927SAndroid Build Coastguard Worker {
1966*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1967*61046927SAndroid Build Coastguard Worker }
1968*61046927SAndroid Build Coastguard Worker 
1969*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsUserBuf(const GLvoid * cmd)1970*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsUserBuf(const GLvoid *cmd)
1971*61046927SAndroid Build Coastguard Worker {
1972*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1973*61046927SAndroid Build Coastguard Worker }
1974*61046927SAndroid Build Coastguard Worker 
1975*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsUserBufPacked(const GLvoid * cmd)1976*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsUserBufPacked(const GLvoid *cmd)
1977*61046927SAndroid Build Coastguard Worker {
1978*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1979*61046927SAndroid Build Coastguard Worker }
1980*61046927SAndroid Build Coastguard Worker 
1981*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawArraysUserBuf(void)1982*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawArraysUserBuf(void)
1983*61046927SAndroid Build Coastguard Worker {
1984*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1985*61046927SAndroid Build Coastguard Worker }
1986*61046927SAndroid Build Coastguard Worker 
1987*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_MultiDrawElementsUserBuf(GLintptr indexBuf,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,const GLint * basevertex)1988*61046927SAndroid Build Coastguard Worker _mesa_marshal_MultiDrawElementsUserBuf(GLintptr indexBuf, GLenum mode,
1989*61046927SAndroid Build Coastguard Worker                                        const GLsizei *count, GLenum type,
1990*61046927SAndroid Build Coastguard Worker                                        const GLvoid * const *indices,
1991*61046927SAndroid Build Coastguard Worker                                        GLsizei primcount,
1992*61046927SAndroid Build Coastguard Worker                                        const GLint *basevertex)
1993*61046927SAndroid Build Coastguard Worker {
1994*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
1995*61046927SAndroid Build Coastguard Worker }
1996*61046927SAndroid Build Coastguard Worker 
1997*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawArraysInstancedBaseInstanceDrawID(void)1998*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawArraysInstancedBaseInstanceDrawID(void)
1999*61046927SAndroid Build Coastguard Worker {
2000*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2001*61046927SAndroid Build Coastguard Worker }
2002*61046927SAndroid Build Coastguard Worker 
_mesa_marshal_DrawElementsPacked(GLenum mode,GLenum type,GLushort count,GLushort indices)2003*61046927SAndroid Build Coastguard Worker void GLAPIENTRY _mesa_marshal_DrawElementsPacked(GLenum mode, GLenum type,
2004*61046927SAndroid Build Coastguard Worker                                                  GLushort count, GLushort indices)
2005*61046927SAndroid Build Coastguard Worker {
2006*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2007*61046927SAndroid Build Coastguard Worker }
2008*61046927SAndroid Build Coastguard Worker 
2009*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseVertexBaseInstanceDrawID(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex,GLuint baseinstance,GLuint drawid)2010*61046927SAndroid Build Coastguard Worker _mesa_marshal_DrawElementsInstancedBaseVertexBaseInstanceDrawID(GLenum mode, GLsizei count,
2011*61046927SAndroid Build Coastguard Worker                                                                 GLenum type, const GLvoid *indices,
2012*61046927SAndroid Build Coastguard Worker                                                                 GLsizei instance_count, GLint basevertex,
2013*61046927SAndroid Build Coastguard Worker                                                                 GLuint baseinstance, GLuint drawid)
2014*61046927SAndroid Build Coastguard Worker {
2015*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2016*61046927SAndroid Build Coastguard Worker }
2017*61046927SAndroid Build Coastguard Worker 
2018*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DrawArraysUserBuf(void)2019*61046927SAndroid Build Coastguard Worker _mesa_DrawArraysUserBuf(void)
2020*61046927SAndroid Build Coastguard Worker {
2021*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2022*61046927SAndroid Build Coastguard Worker }
2023*61046927SAndroid Build Coastguard Worker 
2024*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_MultiDrawArraysUserBuf(void)2025*61046927SAndroid Build Coastguard Worker _mesa_MultiDrawArraysUserBuf(void)
2026*61046927SAndroid Build Coastguard Worker {
2027*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2028*61046927SAndroid Build Coastguard Worker }
2029*61046927SAndroid Build Coastguard Worker 
2030*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DrawArraysInstancedBaseInstanceDrawID(void)2031*61046927SAndroid Build Coastguard Worker _mesa_DrawArraysInstancedBaseInstanceDrawID(void)
2032*61046927SAndroid Build Coastguard Worker {
2033*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2034*61046927SAndroid Build Coastguard Worker }
2035*61046927SAndroid Build Coastguard Worker 
_mesa_DrawElementsPacked(GLenum mode,GLenum type,GLushort count,GLushort indices)2036*61046927SAndroid Build Coastguard Worker void GLAPIENTRY _mesa_DrawElementsPacked(GLenum mode, GLenum type,
2037*61046927SAndroid Build Coastguard Worker                                          GLushort count, GLushort indices)
2038*61046927SAndroid Build Coastguard Worker {
2039*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2040*61046927SAndroid Build Coastguard Worker }
2041*61046927SAndroid Build Coastguard Worker 
2042*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DrawElementsInstancedBaseVertexBaseInstanceDrawID(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex,GLuint baseinstance,GLuint drawid)2043*61046927SAndroid Build Coastguard Worker _mesa_DrawElementsInstancedBaseVertexBaseInstanceDrawID(GLenum mode, GLsizei count,
2044*61046927SAndroid Build Coastguard Worker                                                         GLenum type, const GLvoid *indices,
2045*61046927SAndroid Build Coastguard Worker                                                         GLsizei instance_count, GLint basevertex,
2046*61046927SAndroid Build Coastguard Worker                                                         GLuint baseinstance, GLuint drawid)
2047*61046927SAndroid Build Coastguard Worker {
2048*61046927SAndroid Build Coastguard Worker    unreachable("should never end up here");
2049*61046927SAndroid Build Coastguard Worker }
2050*61046927SAndroid Build Coastguard Worker 
2051*61046927SAndroid Build Coastguard Worker uint32_t
_mesa_unmarshal_PushMatrix(struct gl_context * ctx,const struct marshal_cmd_PushMatrix * restrict cmd)2052*61046927SAndroid Build Coastguard Worker _mesa_unmarshal_PushMatrix(struct gl_context *ctx,
2053*61046927SAndroid Build Coastguard Worker                            const struct marshal_cmd_PushMatrix *restrict cmd)
2054*61046927SAndroid Build Coastguard Worker {
2055*61046927SAndroid Build Coastguard Worker    const unsigned push_matrix_size = 1;
2056*61046927SAndroid Build Coastguard Worker    const unsigned mult_matrixf_size = 9;
2057*61046927SAndroid Build Coastguard Worker    const unsigned draw_elements_size =
2058*61046927SAndroid Build Coastguard Worker       (align(sizeof(struct marshal_cmd_DrawElements), 8) / 8);
2059*61046927SAndroid Build Coastguard Worker    const unsigned draw_elements_packed_size =
2060*61046927SAndroid Build Coastguard Worker       (align(sizeof(struct marshal_cmd_DrawElementsPacked), 8) / 8);
2061*61046927SAndroid Build Coastguard Worker    const unsigned pop_matrix_size = 1;
2062*61046927SAndroid Build Coastguard Worker    uint64_t *next1 = _mesa_glthread_next_cmd((uint64_t *)cmd, push_matrix_size);
2063*61046927SAndroid Build Coastguard Worker    uint64_t *next2;
2064*61046927SAndroid Build Coastguard Worker 
2065*61046927SAndroid Build Coastguard Worker    /* Viewperf has these call patterns. */
2066*61046927SAndroid Build Coastguard Worker    switch (_mesa_glthread_get_cmd(next1)->cmd_id) {
2067*61046927SAndroid Build Coastguard Worker    case DISPATCH_CMD_DrawElements:
2068*61046927SAndroid Build Coastguard Worker       /* Execute this sequence:
2069*61046927SAndroid Build Coastguard Worker        *    glPushMatrix
2070*61046927SAndroid Build Coastguard Worker        *    (glMultMatrixf with identity is eliminated by the marshal function)
2071*61046927SAndroid Build Coastguard Worker        *    glDrawElements
2072*61046927SAndroid Build Coastguard Worker        *    glPopMatrix
2073*61046927SAndroid Build Coastguard Worker        * as:
2074*61046927SAndroid Build Coastguard Worker        *    glDrawElements
2075*61046927SAndroid Build Coastguard Worker        */
2076*61046927SAndroid Build Coastguard Worker       next2 = _mesa_glthread_next_cmd(next1, draw_elements_size);
2077*61046927SAndroid Build Coastguard Worker 
2078*61046927SAndroid Build Coastguard Worker       if (_mesa_glthread_get_cmd(next2)->cmd_id == DISPATCH_CMD_PopMatrix) {
2079*61046927SAndroid Build Coastguard Worker          /* The beauty of this is that this is inlined. */
2080*61046927SAndroid Build Coastguard Worker          _mesa_unmarshal_DrawElements(ctx, (void*)next1);
2081*61046927SAndroid Build Coastguard Worker          return push_matrix_size + draw_elements_size + pop_matrix_size;
2082*61046927SAndroid Build Coastguard Worker       }
2083*61046927SAndroid Build Coastguard Worker       break;
2084*61046927SAndroid Build Coastguard Worker 
2085*61046927SAndroid Build Coastguard Worker    case DISPATCH_CMD_DrawElementsPacked:
2086*61046927SAndroid Build Coastguard Worker       next2 = _mesa_glthread_next_cmd(next1, draw_elements_packed_size);
2087*61046927SAndroid Build Coastguard Worker 
2088*61046927SAndroid Build Coastguard Worker       if (_mesa_glthread_get_cmd(next2)->cmd_id == DISPATCH_CMD_PopMatrix) {
2089*61046927SAndroid Build Coastguard Worker          /* The beauty of this is that this is inlined. */
2090*61046927SAndroid Build Coastguard Worker          _mesa_unmarshal_DrawElementsPacked(ctx, (void*)next1);
2091*61046927SAndroid Build Coastguard Worker          return push_matrix_size + draw_elements_packed_size + pop_matrix_size;
2092*61046927SAndroid Build Coastguard Worker       }
2093*61046927SAndroid Build Coastguard Worker       break;
2094*61046927SAndroid Build Coastguard Worker 
2095*61046927SAndroid Build Coastguard Worker    case DISPATCH_CMD_MultMatrixf:
2096*61046927SAndroid Build Coastguard Worker       /* Skip this sequence:
2097*61046927SAndroid Build Coastguard Worker        *    glPushMatrix
2098*61046927SAndroid Build Coastguard Worker        *    glMultMatrixf
2099*61046927SAndroid Build Coastguard Worker        *    glPopMatrix
2100*61046927SAndroid Build Coastguard Worker        */
2101*61046927SAndroid Build Coastguard Worker       next2 = _mesa_glthread_next_cmd(next1, mult_matrixf_size);
2102*61046927SAndroid Build Coastguard Worker 
2103*61046927SAndroid Build Coastguard Worker       if (_mesa_glthread_get_cmd(next2)->cmd_id == DISPATCH_CMD_PopMatrix)
2104*61046927SAndroid Build Coastguard Worker          return push_matrix_size + mult_matrixf_size + pop_matrix_size;
2105*61046927SAndroid Build Coastguard Worker       break;
2106*61046927SAndroid Build Coastguard Worker    }
2107*61046927SAndroid Build Coastguard Worker 
2108*61046927SAndroid Build Coastguard Worker    CALL_PushMatrix(ctx->Dispatch.Current, ());
2109*61046927SAndroid Build Coastguard Worker    return push_matrix_size;
2110*61046927SAndroid Build Coastguard Worker }
2111*61046927SAndroid Build Coastguard Worker 
2112*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_marshal_PushMatrix(void)2113*61046927SAndroid Build Coastguard Worker _mesa_marshal_PushMatrix(void)
2114*61046927SAndroid Build Coastguard Worker {
2115*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
2116*61046927SAndroid Build Coastguard Worker 
2117*61046927SAndroid Build Coastguard Worker    _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_PushMatrix,
2118*61046927SAndroid Build Coastguard Worker                                    sizeof(struct marshal_cmd_PushMatrix));
2119*61046927SAndroid Build Coastguard Worker    _mesa_glthread_PushMatrix(ctx);
2120*61046927SAndroid Build Coastguard Worker }
2121