1 /*
2  * Copyright © 2020 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 /* Draw function marshalling for glthread.
25  *
26  * The purpose of these glDraw wrappers is to upload non-VBO vertex and
27  * index data, so that glthread doesn't have to execute synchronously.
28  */
29 
30 #include "c99_alloca.h"
31 
32 #include "main/glthread_marshal.h"
33 #include "main/dispatch.h"
34 #include "main/varray.h"
35 
36 static inline unsigned
get_index_size(GLenum type)37 get_index_size(GLenum type)
38 {
39    /* GL_UNSIGNED_BYTE  - GL_UNSIGNED_BYTE = 0
40     * GL_UNSIGNED_SHORT - GL_UNSIGNED_BYTE = 2
41     * GL_UNSIGNED_INT   - GL_UNSIGNED_BYTE = 4
42     *
43     * Divide by 2 to get n=0,1,2, then the index size is: 1 << n
44     */
45    return 1 << ((type - GL_UNSIGNED_BYTE) >> 1);
46 }
47 
48 static inline bool
is_index_type_valid(GLenum type)49 is_index_type_valid(GLenum type)
50 {
51    /* GL_UNSIGNED_BYTE  = 0x1401
52     * GL_UNSIGNED_SHORT = 0x1403
53     * GL_UNSIGNED_INT   = 0x1405
54     *
55     * The trick is that bit 1 and bit 2 mean USHORT and UINT, respectively.
56     * After clearing those two bits (with ~6), we should get UBYTE.
57     * Both bits can't be set, because the enum would be greater than UINT.
58     */
59    return type <= GL_UNSIGNED_INT && (type & ~6) == GL_UNSIGNED_BYTE;
60 }
61 
62 static ALWAYS_INLINE struct gl_buffer_object *
upload_indices(struct gl_context * ctx,unsigned count,unsigned index_size,const GLvoid ** indices)63 upload_indices(struct gl_context *ctx, unsigned count, unsigned index_size,
64                const GLvoid **indices)
65 {
66    struct gl_buffer_object *upload_buffer = NULL;
67    unsigned upload_offset = 0;
68 
69    assert(count);
70 
71    _mesa_glthread_upload(ctx, *indices, index_size * count,
72                          &upload_offset, &upload_buffer, NULL);
73    assert(upload_buffer);
74    *indices = (const GLvoid*)(intptr_t)upload_offset;
75 
76    return upload_buffer;
77 }
78 
79 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)80 upload_multi_indices(struct gl_context *ctx, unsigned total_count,
81                      unsigned index_size, unsigned draw_count,
82                      const GLsizei *count, const GLvoid *const *indices,
83                      const GLvoid **out_indices)
84 {
85    struct gl_buffer_object *upload_buffer = NULL;
86    unsigned upload_offset = 0;
87    uint8_t *upload_ptr = NULL;
88 
89    assert(total_count);
90 
91    _mesa_glthread_upload(ctx, NULL, index_size * total_count,
92                          &upload_offset, &upload_buffer, &upload_ptr);
93    assert(upload_buffer);
94 
95    for (unsigned i = 0, offset = 0; i < draw_count; i++) {
96       if (count[i] == 0)
97          continue;
98 
99       unsigned size = count[i] * index_size;
100 
101       memcpy(upload_ptr + offset, indices[i], size);
102       out_indices[i] = (const GLvoid*)(intptr_t)(upload_offset + offset);
103       offset += size;
104    }
105 
106    return upload_buffer;
107 }
108 
109 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 glthread_attrib_binding * buffers)110 upload_vertices(struct gl_context *ctx, unsigned user_buffer_mask,
111                 unsigned start_vertex, unsigned num_vertices,
112                 unsigned start_instance, unsigned num_instances,
113                 struct glthread_attrib_binding *buffers)
114 {
115    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
116    unsigned attrib_mask_iter = vao->Enabled;
117    unsigned num_buffers = 0;
118 
119    assert((num_vertices || !(user_buffer_mask & ~vao->NonZeroDivisorMask)) &&
120           (num_instances || !(user_buffer_mask & vao->NonZeroDivisorMask)));
121 
122    if (unlikely(vao->BufferInterleaved & user_buffer_mask)) {
123       /* Slower upload path where some buffers reference multiple attribs,
124        * so we have to use 2 while loops instead of 1.
125        */
126       unsigned start_offset[VERT_ATTRIB_MAX];
127       unsigned end_offset[VERT_ATTRIB_MAX];
128       uint32_t buffer_mask = 0;
129 
130       while (attrib_mask_iter) {
131          unsigned i = u_bit_scan(&attrib_mask_iter);
132          unsigned binding_index = vao->Attrib[i].BufferIndex;
133 
134          if (!(user_buffer_mask & (1 << binding_index)))
135             continue;
136 
137          unsigned stride = vao->Attrib[binding_index].Stride;
138          unsigned instance_div = vao->Attrib[binding_index].Divisor;
139          unsigned element_size = vao->Attrib[i].ElementSize;
140          unsigned offset = vao->Attrib[i].RelativeOffset;
141          unsigned size;
142 
143          if (instance_div) {
144             /* Per-instance attrib. */
145 
146             /* Figure out how many instances we'll render given instance_div.  We
147              * can't use the typical div_round_up() pattern because the CTS uses
148              * instance_div = ~0 for a test, which overflows div_round_up()'s
149              * addition.
150              */
151             unsigned count = num_instances / instance_div;
152             if (count * instance_div != num_instances)
153                count++;
154 
155             offset += stride * start_instance;
156             size = stride * (count - 1) + element_size;
157          } else {
158             /* Per-vertex attrib. */
159             offset += stride * start_vertex;
160             size = stride * (num_vertices - 1) + element_size;
161          }
162 
163          unsigned binding_index_bit = 1u << binding_index;
164 
165          /* Update upload offsets. */
166          if (!(buffer_mask & binding_index_bit)) {
167             start_offset[binding_index] = offset;
168             end_offset[binding_index] = offset + size;
169          } else {
170             if (offset < start_offset[binding_index])
171                start_offset[binding_index] = offset;
172             if (offset + size > end_offset[binding_index])
173                end_offset[binding_index] = offset + size;
174          }
175 
176          buffer_mask |= binding_index_bit;
177       }
178 
179       /* Upload buffers. */
180       while (buffer_mask) {
181          struct gl_buffer_object *upload_buffer = NULL;
182          unsigned upload_offset = 0;
183          unsigned start, end;
184 
185          unsigned binding_index = u_bit_scan(&buffer_mask);
186 
187          start = start_offset[binding_index];
188          end = end_offset[binding_index];
189          assert(start < end);
190 
191          const void *ptr = vao->Attrib[binding_index].Pointer;
192          _mesa_glthread_upload(ctx, (uint8_t*)ptr + start,
193                                end - start, &upload_offset,
194                                &upload_buffer, NULL);
195          assert(upload_buffer);
196 
197          buffers[num_buffers].buffer = upload_buffer;
198          buffers[num_buffers].offset = upload_offset - start;
199          buffers[num_buffers].original_pointer = ptr;
200          num_buffers++;
201       }
202 
203       return true;
204    }
205 
206    /* Faster path where all attribs are separate. */
207    while (attrib_mask_iter) {
208       unsigned i = u_bit_scan(&attrib_mask_iter);
209       unsigned binding_index = vao->Attrib[i].BufferIndex;
210 
211       if (!(user_buffer_mask & (1 << binding_index)))
212          continue;
213 
214       struct gl_buffer_object *upload_buffer = NULL;
215       unsigned upload_offset = 0;
216       unsigned stride = vao->Attrib[binding_index].Stride;
217       unsigned instance_div = vao->Attrib[binding_index].Divisor;
218       unsigned element_size = vao->Attrib[i].ElementSize;
219       unsigned offset = vao->Attrib[i].RelativeOffset;
220       unsigned size;
221 
222       if (instance_div) {
223          /* Per-instance attrib. */
224 
225          /* Figure out how many instances we'll render given instance_div.  We
226           * can't use the typical div_round_up() pattern because the CTS uses
227           * instance_div = ~0 for a test, which overflows div_round_up()'s
228           * addition.
229           */
230          unsigned count = num_instances / instance_div;
231          if (count * instance_div != num_instances)
232             count++;
233 
234          offset += stride * start_instance;
235          size = stride * (count - 1) + element_size;
236       } else {
237          /* Per-vertex attrib. */
238          offset += stride * start_vertex;
239          size = stride * (num_vertices - 1) + element_size;
240       }
241 
242       const void *ptr = vao->Attrib[binding_index].Pointer;
243       _mesa_glthread_upload(ctx, (uint8_t*)ptr + offset,
244                             size, &upload_offset, &upload_buffer, NULL);
245       assert(upload_buffer);
246 
247       buffers[num_buffers].buffer = upload_buffer;
248       buffers[num_buffers].offset = upload_offset - offset;
249       buffers[num_buffers].original_pointer = ptr;
250       num_buffers++;
251    }
252 
253    return true;
254 }
255 
256 /* Generic DrawArrays structure NOT supporting user buffers. Ignore the name. */
257 struct marshal_cmd_DrawArrays
258 {
259    struct marshal_cmd_base cmd_base;
260    GLenum mode;
261    GLint first;
262    GLsizei count;
263    GLsizei instance_count;
264    GLuint baseinstance;
265 };
266 
267 uint32_t
_mesa_unmarshal_DrawArrays(struct gl_context * ctx,const struct marshal_cmd_DrawArrays * cmd,const uint64_t * last)268 _mesa_unmarshal_DrawArrays(struct gl_context *ctx,
269                            const struct marshal_cmd_DrawArrays *cmd,
270                            const uint64_t *last)
271 {
272    /* Ignore the function name. We use DISPATCH_CMD_DrawArrays
273     * for all DrawArrays variants without user buffers, and
274     * DISPATCH_CMD_DrawArraysInstancedBaseInstance for all DrawArrays
275     * variants with user buffrs.
276     */
277    const GLenum mode = cmd->mode;
278    const GLint first = cmd->first;
279    const GLsizei count = cmd->count;
280    const GLsizei instance_count = cmd->instance_count;
281    const GLuint baseinstance = cmd->baseinstance;
282 
283    CALL_DrawArraysInstancedBaseInstance(ctx->CurrentServerDispatch,
284                                         (mode, first, count, instance_count,
285                                          baseinstance));
286    return cmd->cmd_base.cmd_size;
287 }
288 
289 static ALWAYS_INLINE void
draw_arrays_async(struct gl_context * ctx,GLenum mode,GLint first,GLsizei count,GLsizei instance_count,GLuint baseinstance)290 draw_arrays_async(struct gl_context *ctx, GLenum mode, GLint first,
291                   GLsizei count, GLsizei instance_count, GLuint baseinstance)
292 {
293    int cmd_size = sizeof(struct marshal_cmd_DrawArrays);
294    struct marshal_cmd_DrawArrays *cmd =
295       _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArrays, cmd_size);
296 
297    cmd->mode = mode;
298    cmd->first = first;
299    cmd->count = count;
300    cmd->instance_count = instance_count;
301    cmd->baseinstance = baseinstance;
302 }
303 
304 /* Generic DrawArrays structure supporting user buffers. Ignore the name. */
305 struct marshal_cmd_DrawArraysInstancedBaseInstance
306 {
307    struct marshal_cmd_base cmd_base;
308    GLenum mode;
309    GLint first;
310    GLsizei count;
311    GLsizei instance_count;
312    GLuint baseinstance;
313    GLuint user_buffer_mask;
314 };
315 
316 uint32_t
_mesa_unmarshal_DrawArraysInstancedBaseInstance(struct gl_context * ctx,const struct marshal_cmd_DrawArraysInstancedBaseInstance * cmd,const uint64_t * last)317 _mesa_unmarshal_DrawArraysInstancedBaseInstance(struct gl_context *ctx,
318                                                 const struct marshal_cmd_DrawArraysInstancedBaseInstance *cmd,
319                                                 const uint64_t *last)
320 {
321    /* Ignore the function name. We use DISPATCH_CMD_DrawArrays
322     * for all DrawArrays variants without user buffers, and
323     * DISPATCH_CMD_DrawArraysInstancedBaseInstance for all DrawArrays
324     * variants with user buffrs.
325     */
326    const GLenum mode = cmd->mode;
327    const GLint first = cmd->first;
328    const GLsizei count = cmd->count;
329    const GLsizei instance_count = cmd->instance_count;
330    const GLuint baseinstance = cmd->baseinstance;
331    const GLuint user_buffer_mask = cmd->user_buffer_mask;
332    const struct glthread_attrib_binding *buffers =
333       (const struct glthread_attrib_binding *)(cmd + 1);
334 
335    /* Bind uploaded buffers if needed. */
336    if (user_buffer_mask) {
337       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
338                                       false);
339    }
340 
341    CALL_DrawArraysInstancedBaseInstance(ctx->CurrentServerDispatch,
342                                         (mode, first, count, instance_count,
343                                          baseinstance));
344 
345    /* Restore states. */
346    if (user_buffer_mask) {
347       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
348                                       true);
349    }
350    return cmd->cmd_base.cmd_size;
351 }
352 
353 static ALWAYS_INLINE void
draw_arrays_async_user(struct gl_context * ctx,GLenum mode,GLint first,GLsizei count,GLsizei instance_count,GLuint baseinstance,unsigned user_buffer_mask,const struct glthread_attrib_binding * buffers)354 draw_arrays_async_user(struct gl_context *ctx, GLenum mode, GLint first,
355                        GLsizei count, GLsizei instance_count, GLuint baseinstance,
356                        unsigned user_buffer_mask,
357                        const struct glthread_attrib_binding *buffers)
358 {
359    int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]);
360    int cmd_size = sizeof(struct marshal_cmd_DrawArraysInstancedBaseInstance) +
361                   buffers_size;
362    struct marshal_cmd_DrawArraysInstancedBaseInstance *cmd;
363 
364    cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArraysInstancedBaseInstance,
365                                          cmd_size);
366    cmd->mode = mode;
367    cmd->first = first;
368    cmd->count = count;
369    cmd->instance_count = instance_count;
370    cmd->baseinstance = baseinstance;
371    cmd->user_buffer_mask = user_buffer_mask;
372 
373    if (user_buffer_mask)
374       memcpy(cmd + 1, buffers, buffers_size);
375 }
376 
377 static ALWAYS_INLINE void
draw_arrays(GLenum mode,GLint first,GLsizei count,GLsizei instance_count,GLuint baseinstance,bool compiled_into_dlist)378 draw_arrays(GLenum mode, GLint first, GLsizei count, GLsizei instance_count,
379             GLuint baseinstance, bool compiled_into_dlist)
380 {
381    GET_CURRENT_CONTEXT(ctx);
382 
383    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
384    unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
385 
386    if (compiled_into_dlist && ctx->GLThread.ListMode) {
387       _mesa_glthread_finish_before(ctx, "DrawArrays");
388       /* Use the function that's compiled into a display list. */
389       CALL_DrawArrays(ctx->CurrentServerDispatch, (mode, first, count));
390       return;
391    }
392 
393    /* Fast path when nothing needs to be done.
394     *
395     * This is also an error path. Zero counts should still call the driver
396     * for possible GL errors.
397     */
398    if (ctx->API == API_OPENGL_CORE || !user_buffer_mask ||
399        count <= 0 || instance_count <= 0) {
400       draw_arrays_async(ctx, mode, first, count, instance_count, baseinstance);
401       return;
402    }
403 
404    /* Upload and draw. */
405    struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX];
406    if (!ctx->GLThread.SupportsNonVBOUploads ||
407        !upload_vertices(ctx, user_buffer_mask, first, count, baseinstance,
408                         instance_count, buffers)) {
409       _mesa_glthread_finish_before(ctx, "DrawArrays");
410       CALL_DrawArraysInstancedBaseInstance(ctx->CurrentServerDispatch,
411                                            (mode, first, count, instance_count,
412                                             baseinstance));
413       return;
414    }
415 
416    draw_arrays_async_user(ctx, mode, first, count, instance_count, baseinstance,
417                           user_buffer_mask, buffers);
418 }
419 
420 struct marshal_cmd_MultiDrawArrays
421 {
422    struct marshal_cmd_base cmd_base;
423    GLenum mode;
424    GLsizei draw_count;
425    GLuint user_buffer_mask;
426 };
427 
428 uint32_t
_mesa_unmarshal_MultiDrawArrays(struct gl_context * ctx,const struct marshal_cmd_MultiDrawArrays * cmd,const uint64_t * last)429 _mesa_unmarshal_MultiDrawArrays(struct gl_context *ctx,
430                                 const struct marshal_cmd_MultiDrawArrays *cmd,
431                                 const uint64_t *last)
432 {
433    const GLenum mode = cmd->mode;
434    const GLsizei draw_count = cmd->draw_count;
435    const GLuint user_buffer_mask = cmd->user_buffer_mask;
436 
437    const char *variable_data = (const char *)(cmd + 1);
438    const GLint *first = (GLint *)variable_data;
439    variable_data += sizeof(GLint) * draw_count;
440    const GLsizei *count = (GLsizei *)variable_data;
441    variable_data += sizeof(GLsizei) * draw_count;
442    const struct glthread_attrib_binding *buffers =
443       (const struct glthread_attrib_binding *)variable_data;
444 
445    /* Bind uploaded buffers if needed. */
446    if (user_buffer_mask) {
447       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
448                                       false);
449    }
450 
451    CALL_MultiDrawArrays(ctx->CurrentServerDispatch,
452                         (mode, first, count, draw_count));
453 
454    /* Restore states. */
455    if (user_buffer_mask) {
456       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
457                                       true);
458    }
459    return cmd->cmd_base.cmd_size;
460 }
461 
462 static ALWAYS_INLINE void
multi_draw_arrays_async(struct gl_context * ctx,GLenum mode,const GLint * first,const GLsizei * count,GLsizei draw_count,unsigned user_buffer_mask,const struct glthread_attrib_binding * buffers)463 multi_draw_arrays_async(struct gl_context *ctx, GLenum mode,
464                         const GLint *first, const GLsizei *count,
465                         GLsizei draw_count, unsigned user_buffer_mask,
466                         const struct glthread_attrib_binding *buffers)
467 {
468    int first_size = sizeof(GLint) * draw_count;
469    int count_size = sizeof(GLsizei) * draw_count;
470    int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]);
471    int cmd_size = sizeof(struct marshal_cmd_MultiDrawArrays) +
472                   first_size + count_size + buffers_size;
473    struct marshal_cmd_MultiDrawArrays *cmd;
474 
475    cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArrays,
476                                          cmd_size);
477    cmd->mode = mode;
478    cmd->draw_count = draw_count;
479    cmd->user_buffer_mask = user_buffer_mask;
480 
481    char *variable_data = (char*)(cmd + 1);
482    memcpy(variable_data, first, first_size);
483    variable_data += first_size;
484    memcpy(variable_data, count, count_size);
485 
486    if (user_buffer_mask) {
487       variable_data += count_size;
488       memcpy(variable_data, buffers, buffers_size);
489    }
490 }
491 
492 void GLAPIENTRY
_mesa_marshal_MultiDrawArrays(GLenum mode,const GLint * first,const GLsizei * count,GLsizei draw_count)493 _mesa_marshal_MultiDrawArrays(GLenum mode, const GLint *first,
494                               const GLsizei *count, GLsizei draw_count)
495 {
496    GET_CURRENT_CONTEXT(ctx);
497 
498    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
499    unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
500 
501    if (ctx->GLThread.ListMode)
502       goto sync;
503 
504    if (draw_count >= 0 &&
505        (ctx->API == API_OPENGL_CORE || !user_buffer_mask)) {
506       multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL);
507       return;
508    }
509 
510    /* If the draw count is too high or negative, the queue can't be used. */
511    if (!ctx->GLThread.SupportsNonVBOUploads ||
512        draw_count < 0 || draw_count > MARSHAL_MAX_CMD_SIZE / 16)
513       goto sync;
514 
515    unsigned min_index = ~0;
516    unsigned max_index_exclusive = 0;
517 
518    for (unsigned i = 0; i < draw_count; i++) {
519       GLsizei vertex_count = count[i];
520 
521       if (vertex_count < 0) {
522          /* Just call the driver to set the error. */
523          multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL);
524          return;
525       }
526       if (vertex_count == 0)
527          continue;
528 
529       min_index = MIN2(min_index, first[i]);
530       max_index_exclusive = MAX2(max_index_exclusive, first[i] + vertex_count);
531    }
532 
533    unsigned num_vertices = max_index_exclusive - min_index;
534    if (num_vertices == 0) {
535       /* Nothing to do, but call the driver to set possible GL errors. */
536       multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL);
537       return;
538    }
539 
540    /* Upload and draw. */
541    struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX];
542    if (!upload_vertices(ctx, user_buffer_mask, min_index, num_vertices,
543                         0, 1, buffers))
544       goto sync;
545 
546    multi_draw_arrays_async(ctx, mode, first, count, draw_count,
547                            user_buffer_mask, buffers);
548    return;
549 
550 sync:
551    _mesa_glthread_finish_before(ctx, "MultiDrawArrays");
552    CALL_MultiDrawArrays(ctx->CurrentServerDispatch,
553                         (mode, first, count, draw_count));
554 }
555 
556 /* DrawElementsInstancedBaseVertexBaseInstance not supporting user buffers.
557  * Ignore the name.
558  */
559 struct marshal_cmd_DrawElementsInstancedARB
560 {
561    struct marshal_cmd_base cmd_base;
562    GLenum mode;
563    GLenum type;
564    GLsizei count;
565    GLsizei instance_count;
566    GLint basevertex;
567    GLuint baseinstance;
568    const GLvoid *indices;
569 };
570 
571 uint32_t
_mesa_unmarshal_DrawElementsInstancedARB(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedARB * cmd,const uint64_t * last)572 _mesa_unmarshal_DrawElementsInstancedARB(struct gl_context *ctx,
573                                          const struct marshal_cmd_DrawElementsInstancedARB *cmd,
574                                          const uint64_t *last)
575 {
576    /* Ignore the function name. We use DISPATCH_CMD_DrawElementsInstanced-
577     * BaseVertexBaseInstance for all DrawElements variants with user buffers,
578     * and both DISPATCH_CMD_DrawElementsInstancedARB and DISPATCH_CMD_Draw-
579     * RangeElementsBaseVertex for all draw elements variants without user
580     * buffers.
581     */
582    const GLenum mode = cmd->mode;
583    const GLsizei count = cmd->count;
584    const GLenum type = cmd->type;
585    const GLvoid *indices = cmd->indices;
586    const GLsizei instance_count = cmd->instance_count;
587    const GLint basevertex = cmd->basevertex;
588    const GLuint baseinstance = cmd->baseinstance;
589 
590    CALL_DrawElementsInstancedBaseVertexBaseInstance(ctx->CurrentServerDispatch,
591                                                     (mode, count, type, indices,
592                                                      instance_count, basevertex,
593                                                      baseinstance));
594    return cmd->cmd_base.cmd_size;
595 }
596 
597 struct marshal_cmd_DrawRangeElementsBaseVertex
598 {
599    struct marshal_cmd_base cmd_base;
600    GLenum mode;
601    GLenum type;
602    GLsizei count;
603    GLint basevertex;
604    GLuint min_index;
605    GLuint max_index;
606    const GLvoid *indices;
607 };
608 
609 uint32_t
_mesa_unmarshal_DrawRangeElementsBaseVertex(struct gl_context * ctx,const struct marshal_cmd_DrawRangeElementsBaseVertex * cmd,const uint64_t * last)610 _mesa_unmarshal_DrawRangeElementsBaseVertex(struct gl_context *ctx,
611                                             const struct marshal_cmd_DrawRangeElementsBaseVertex *cmd,
612                                             const uint64_t *last)
613 {
614    const GLenum mode = cmd->mode;
615    const GLsizei count = cmd->count;
616    const GLenum type = cmd->type;
617    const GLvoid *indices = cmd->indices;
618    const GLint basevertex = cmd->basevertex;
619    const GLuint min_index = cmd->min_index;
620    const GLuint max_index = cmd->max_index;
621 
622    CALL_DrawRangeElementsBaseVertex(ctx->CurrentServerDispatch,
623                                     (mode, min_index, max_index, count,
624                                      type, indices, basevertex));
625    return cmd->cmd_base.cmd_size;
626 }
627 
628 static ALWAYS_INLINE void
draw_elements_async(struct gl_context * ctx,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)629 draw_elements_async(struct gl_context *ctx, GLenum mode, GLsizei count,
630                     GLenum type, const GLvoid *indices, GLsizei instance_count,
631                     GLint basevertex, GLuint baseinstance,
632                     bool index_bounds_valid, GLuint min_index, GLuint max_index)
633 {
634    if (index_bounds_valid) {
635       int cmd_size = sizeof(struct marshal_cmd_DrawRangeElementsBaseVertex);
636       struct marshal_cmd_DrawRangeElementsBaseVertex *cmd =
637          _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawRangeElementsBaseVertex, cmd_size);
638 
639       cmd->mode = mode;
640       cmd->count = count;
641       cmd->type = type;
642       cmd->indices = indices;
643       cmd->basevertex = basevertex;
644       cmd->min_index = min_index;
645       cmd->max_index = max_index;
646    } else {
647       int cmd_size = sizeof(struct marshal_cmd_DrawElementsInstancedARB);
648       struct marshal_cmd_DrawElementsInstancedARB *cmd =
649          _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsInstancedARB, cmd_size);
650 
651       cmd->mode = mode;
652       cmd->count = count;
653       cmd->type = type;
654       cmd->indices = indices;
655       cmd->instance_count = instance_count;
656       cmd->basevertex = basevertex;
657       cmd->baseinstance = baseinstance;
658    }
659 }
660 
661 struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance
662 {
663    struct marshal_cmd_base cmd_base;
664    bool index_bounds_valid;
665    GLenum mode;
666    GLenum type;
667    GLsizei count;
668    GLsizei instance_count;
669    GLint basevertex;
670    GLuint baseinstance;
671    GLuint min_index;
672    GLuint max_index;
673    GLuint user_buffer_mask;
674    const GLvoid *indices;
675    struct gl_buffer_object *index_buffer;
676 };
677 
678 uint32_t
_mesa_unmarshal_DrawElementsInstancedBaseVertexBaseInstance(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance * cmd,const uint64_t * last)679 _mesa_unmarshal_DrawElementsInstancedBaseVertexBaseInstance(struct gl_context *ctx,
680                                                             const struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance *cmd,
681                                                             const uint64_t *last)
682 {
683    /* Ignore the function name. We use DISPATCH_CMD_DrawElementsInstanced-
684     * BaseVertexBaseInstance for all DrawElements variants with user buffers,
685     * and both DISPATCH_CMD_DrawElementsInstancedARB and DISPATCH_CMD_Draw-
686     * RangeElementsBaseVertex for all draw elements variants without user
687     * buffers.
688     */
689    const GLenum mode = cmd->mode;
690    const GLsizei count = cmd->count;
691    const GLenum type = cmd->type;
692    const GLvoid *indices = cmd->indices;
693    const GLsizei instance_count = cmd->instance_count;
694    const GLint basevertex = cmd->basevertex;
695    const GLuint baseinstance = cmd->baseinstance;
696    const GLuint min_index = cmd->min_index;
697    const GLuint max_index = cmd->max_index;
698    const GLuint user_buffer_mask = cmd->user_buffer_mask;
699    struct gl_buffer_object *index_buffer = cmd->index_buffer;
700    const struct glthread_attrib_binding *buffers =
701       (const struct glthread_attrib_binding *)(cmd + 1);
702 
703    /* Bind uploaded buffers if needed. */
704    if (user_buffer_mask) {
705       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
706                                       false);
707    }
708    if (index_buffer) {
709       _mesa_InternalBindElementBuffer(ctx, index_buffer);
710    }
711 
712    /* Draw. */
713    if (cmd->index_bounds_valid && instance_count == 1 && baseinstance == 0) {
714       CALL_DrawRangeElementsBaseVertex(ctx->CurrentServerDispatch,
715                                        (mode, min_index, max_index, count,
716                                         type, indices, basevertex));
717    } else {
718       CALL_DrawElementsInstancedBaseVertexBaseInstance(ctx->CurrentServerDispatch,
719                                                        (mode, count, type, indices,
720                                                         instance_count, basevertex,
721                                                         baseinstance));
722    }
723 
724    /* Restore states. */
725    if (index_buffer) {
726       _mesa_InternalBindElementBuffer(ctx, NULL);
727    }
728    if (user_buffer_mask) {
729       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
730                                       true);
731    }
732    return cmd->cmd_base.cmd_size;
733 }
734 
735 static ALWAYS_INLINE void
draw_elements_async_user(struct gl_context * ctx,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,struct gl_buffer_object * index_buffer,unsigned user_buffer_mask,const struct glthread_attrib_binding * buffers)736 draw_elements_async_user(struct gl_context *ctx, GLenum mode, GLsizei count,
737                          GLenum type, const GLvoid *indices, GLsizei instance_count,
738                          GLint basevertex, GLuint baseinstance,
739                          bool index_bounds_valid, GLuint min_index, GLuint max_index,
740                          struct gl_buffer_object *index_buffer,
741                          unsigned user_buffer_mask,
742                          const struct glthread_attrib_binding *buffers)
743 {
744    int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]);
745    int cmd_size = sizeof(struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance) +
746                   buffers_size;
747    struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance *cmd;
748 
749    cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsInstancedBaseVertexBaseInstance, cmd_size);
750    cmd->mode = mode;
751    cmd->count = count;
752    cmd->type = type;
753    cmd->indices = indices;
754    cmd->instance_count = instance_count;
755    cmd->basevertex = basevertex;
756    cmd->baseinstance = baseinstance;
757    cmd->min_index = min_index;
758    cmd->max_index = max_index;
759    cmd->user_buffer_mask = user_buffer_mask;
760    cmd->index_bounds_valid = index_bounds_valid;
761    cmd->index_buffer = index_buffer;
762 
763    if (user_buffer_mask)
764       memcpy(cmd + 1, buffers, buffers_size);
765 }
766 
767 static void
draw_elements(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)768 draw_elements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
769               GLsizei instance_count, GLint basevertex, GLuint baseinstance,
770               bool index_bounds_valid, GLuint min_index, GLuint max_index,
771               bool compiled_into_dlist)
772 {
773    GET_CURRENT_CONTEXT(ctx);
774 
775    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
776    unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
777    bool has_user_indices = vao->CurrentElementBufferName == 0;
778 
779    if (compiled_into_dlist && ctx->GLThread.ListMode)
780       goto sync;
781 
782    /* Fast path when nothing needs to be done.
783     *
784     * This is also an error path. Zero counts should still call the driver
785     * for possible GL errors.
786     */
787    if (ctx->API == API_OPENGL_CORE ||
788        count <= 0 || instance_count <= 0 || max_index < min_index ||
789        !is_index_type_valid(type) ||
790        (!user_buffer_mask && !has_user_indices)) {
791       draw_elements_async(ctx, mode, count, type, indices, instance_count,
792                           basevertex, baseinstance, index_bounds_valid,
793                           min_index, max_index);
794       return;
795    }
796 
797    if (!ctx->GLThread.SupportsNonVBOUploads)
798       goto sync;
799 
800    bool need_index_bounds = user_buffer_mask & ~vao->NonZeroDivisorMask;
801    unsigned index_size = get_index_size(type);
802 
803    if (need_index_bounds && !index_bounds_valid) {
804       /* Sync if indices come from a buffer and vertices come from memory
805        * and index bounds are not valid.
806        *
807        * We would have to map the indices to compute the index bounds, and
808        * for that we would have to sync anyway.
809        */
810       if (!has_user_indices)
811          goto sync;
812 
813       /* Compute the index bounds. */
814       min_index = ~0;
815       max_index = 0;
816       vbo_get_minmax_index_mapped(count, index_size,
817                                   ctx->GLThread._RestartIndex[index_size - 1],
818                                   ctx->GLThread._PrimitiveRestart, indices,
819                                   &min_index, &max_index);
820       index_bounds_valid = true;
821    }
822 
823    unsigned start_vertex = min_index + basevertex;
824    unsigned num_vertices = max_index + 1 - min_index;
825 
826    /* If there is too much data to upload, sync and let the driver unroll
827     * indices. */
828    if (util_is_vbo_upload_ratio_too_large(count, num_vertices))
829       goto sync;
830 
831    struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX];
832    if (user_buffer_mask &&
833        !upload_vertices(ctx, user_buffer_mask, start_vertex, num_vertices,
834                         baseinstance, instance_count, buffers))
835       goto sync;
836 
837    /* Upload indices. */
838    struct gl_buffer_object *index_buffer = NULL;
839    if (has_user_indices)
840       index_buffer = upload_indices(ctx, count, index_size, &indices);
841 
842    /* Draw asynchronously. */
843    draw_elements_async_user(ctx, mode, count, type, indices, instance_count,
844                             basevertex, baseinstance, index_bounds_valid,
845                             min_index, max_index, index_buffer,
846                             user_buffer_mask, buffers);
847    return;
848 
849 sync:
850    _mesa_glthread_finish_before(ctx, "DrawElements");
851 
852    if (compiled_into_dlist && ctx->GLThread.ListMode) {
853       /* Only use the ones that are compiled into display lists. */
854       if (basevertex) {
855          CALL_DrawElementsBaseVertex(ctx->CurrentServerDispatch,
856                                      (mode, count, type, indices, basevertex));
857       } else if (index_bounds_valid) {
858          CALL_DrawRangeElements(ctx->CurrentServerDispatch,
859                                 (mode, min_index, max_index, count, type, indices));
860       } else {
861          CALL_DrawElements(ctx->CurrentServerDispatch, (mode, count, type, indices));
862       }
863    } else if (index_bounds_valid && instance_count == 1 && baseinstance == 0) {
864       CALL_DrawRangeElementsBaseVertex(ctx->CurrentServerDispatch,
865                                        (mode, min_index, max_index, count,
866                                         type, indices, basevertex));
867    } else {
868       CALL_DrawElementsInstancedBaseVertexBaseInstance(ctx->CurrentServerDispatch,
869                                                        (mode, count, type, indices,
870                                                         instance_count, basevertex,
871                                                         baseinstance));
872    }
873 }
874 
875 struct marshal_cmd_MultiDrawElementsBaseVertex
876 {
877    struct marshal_cmd_base cmd_base;
878    bool has_base_vertex;
879    GLenum mode;
880    GLenum type;
881    GLsizei draw_count;
882    GLuint user_buffer_mask;
883    struct gl_buffer_object *index_buffer;
884 };
885 
886 uint32_t
_mesa_unmarshal_MultiDrawElementsBaseVertex(struct gl_context * ctx,const struct marshal_cmd_MultiDrawElementsBaseVertex * cmd,const uint64_t * last)887 _mesa_unmarshal_MultiDrawElementsBaseVertex(struct gl_context *ctx,
888                                             const struct marshal_cmd_MultiDrawElementsBaseVertex *cmd,
889                                             const uint64_t *last)
890 {
891    const GLenum mode = cmd->mode;
892    const GLenum type = cmd->type;
893    const GLsizei draw_count = cmd->draw_count;
894    const GLuint user_buffer_mask = cmd->user_buffer_mask;
895    struct gl_buffer_object *index_buffer = cmd->index_buffer;
896    const bool has_base_vertex = cmd->has_base_vertex;
897 
898    const char *variable_data = (const char *)(cmd + 1);
899    const GLsizei *count = (GLsizei *)variable_data;
900    variable_data += sizeof(GLsizei) * draw_count;
901    const GLvoid *const *indices = (const GLvoid *const *)variable_data;
902    variable_data += sizeof(const GLvoid *const *) * draw_count;
903    const GLsizei *basevertex = NULL;
904    if (has_base_vertex) {
905       basevertex = (GLsizei *)variable_data;
906       variable_data += sizeof(GLsizei) * draw_count;
907    }
908    const struct glthread_attrib_binding *buffers =
909       (const struct glthread_attrib_binding *)variable_data;
910 
911    /* Bind uploaded buffers if needed. */
912    if (user_buffer_mask) {
913       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
914                                       false);
915    }
916    if (index_buffer) {
917       _mesa_InternalBindElementBuffer(ctx, index_buffer);
918    }
919 
920    /* Draw. */
921    if (has_base_vertex) {
922       CALL_MultiDrawElementsBaseVertex(ctx->CurrentServerDispatch,
923                                        (mode, count, type, indices, draw_count,
924                                         basevertex));
925    } else {
926       CALL_MultiDrawElementsEXT(ctx->CurrentServerDispatch,
927                                 (mode, count, type, indices, draw_count));
928    }
929 
930    /* Restore states. */
931    if (index_buffer) {
932       _mesa_InternalBindElementBuffer(ctx, NULL);
933    }
934    if (user_buffer_mask) {
935       _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask,
936                                       true);
937    }
938    return cmd->cmd_base.cmd_size;
939 }
940 
941 static ALWAYS_INLINE 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,const struct glthread_attrib_binding * buffers)942 multi_draw_elements_async(struct gl_context *ctx, GLenum mode,
943                           const GLsizei *count, GLenum type,
944                           const GLvoid *const *indices, GLsizei draw_count,
945                           const GLsizei *basevertex,
946                           struct gl_buffer_object *index_buffer,
947                           unsigned user_buffer_mask,
948                           const struct glthread_attrib_binding *buffers)
949 {
950    int count_size = sizeof(GLsizei) * draw_count;
951    int indices_size = sizeof(indices[0]) * draw_count;
952    int basevertex_size = basevertex ? sizeof(GLsizei) * draw_count : 0;
953    int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]);
954    int cmd_size = sizeof(struct marshal_cmd_MultiDrawElementsBaseVertex) +
955                   count_size + indices_size + basevertex_size + buffers_size;
956    struct marshal_cmd_MultiDrawElementsBaseVertex *cmd;
957 
958    cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsBaseVertex, cmd_size);
959    cmd->mode = mode;
960    cmd->type = type;
961    cmd->draw_count = draw_count;
962    cmd->user_buffer_mask = user_buffer_mask;
963    cmd->index_buffer = index_buffer;
964    cmd->has_base_vertex = basevertex != NULL;
965 
966    char *variable_data = (char*)(cmd + 1);
967    memcpy(variable_data, count, count_size);
968    variable_data += count_size;
969    memcpy(variable_data, indices, indices_size);
970    variable_data += indices_size;
971 
972    if (basevertex) {
973       memcpy(variable_data, basevertex, basevertex_size);
974       variable_data += basevertex_size;
975    }
976 
977    if (user_buffer_mask)
978       memcpy(variable_data, buffers, buffers_size);
979 }
980 
981 void GLAPIENTRY
_mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei draw_count,const GLsizei * basevertex)982 _mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
983                                           GLenum type,
984                                           const GLvoid *const *indices,
985                                           GLsizei draw_count,
986                                           const GLsizei *basevertex)
987 {
988    GET_CURRENT_CONTEXT(ctx);
989 
990    struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
991    unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
992    bool has_user_indices = vao->CurrentElementBufferName == 0;
993 
994    if (ctx->GLThread.ListMode)
995       goto sync;
996 
997    /* Fast path when nothing needs to be done. */
998    if (draw_count >= 0 &&
999        (ctx->API == API_OPENGL_CORE ||
1000         !is_index_type_valid(type) ||
1001         (!user_buffer_mask && !has_user_indices))) {
1002       multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1003                                 basevertex, 0, 0, NULL);
1004       return;
1005    }
1006 
1007    bool need_index_bounds = user_buffer_mask & ~vao->NonZeroDivisorMask;
1008 
1009    /* If the draw count is too high or negative, the queue can't be used.
1010     *
1011     * Sync if indices come from a buffer and vertices come from memory
1012     * and index bounds are not valid. We would have to map the indices
1013     * to compute the index bounds, and for that we would have to sync anyway.
1014     */
1015    if (!ctx->GLThread.SupportsNonVBOUploads ||
1016        draw_count < 0 || draw_count > MARSHAL_MAX_CMD_SIZE / 32 ||
1017        (need_index_bounds && !has_user_indices))
1018       goto sync;
1019 
1020    unsigned index_size = get_index_size(type);
1021    unsigned min_index = ~0;
1022    unsigned max_index = 0;
1023    unsigned total_count = 0;
1024    unsigned num_vertices = 0;
1025 
1026    /* This is always true if there is per-vertex data that needs to be
1027     * uploaded.
1028     */
1029    if (need_index_bounds) {
1030       /* Compute the index bounds. */
1031       for (unsigned i = 0; i < draw_count; i++) {
1032          GLsizei vertex_count = count[i];
1033 
1034          if (vertex_count < 0) {
1035             /* Just call the driver to set the error. */
1036             multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1037                                       basevertex, 0, 0, NULL);
1038             return;
1039          }
1040          if (vertex_count == 0)
1041             continue;
1042 
1043          unsigned min = ~0, max = 0;
1044          vbo_get_minmax_index_mapped(vertex_count, index_size,
1045                                      ctx->GLThread._RestartIndex[index_size - 1],
1046                                      ctx->GLThread._PrimitiveRestart, indices[i],
1047                                      &min, &max);
1048          if (basevertex) {
1049             min += basevertex[i];
1050             max += basevertex[i];
1051          }
1052          min_index = MIN2(min_index, min);
1053          max_index = MAX2(max_index, max);
1054          total_count += vertex_count;
1055       }
1056 
1057       num_vertices = max_index + 1 - min_index;
1058 
1059       if (total_count == 0 || num_vertices == 0) {
1060          /* Nothing to do, but call the driver to set possible GL errors. */
1061          multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1062                                    basevertex, 0, 0, NULL);
1063          return;
1064       }
1065 
1066       /* If there is too much data to upload, sync and let the driver unroll
1067        * indices. */
1068       if (util_is_vbo_upload_ratio_too_large(total_count, num_vertices))
1069          goto sync;
1070    } else if (has_user_indices) {
1071       /* Only compute total_count for the upload of indices. */
1072       for (unsigned i = 0; i < draw_count; i++) {
1073          GLsizei vertex_count = count[i];
1074 
1075          if (vertex_count < 0) {
1076             /* Just call the driver to set the error. */
1077             multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1078                                       basevertex, 0, 0, NULL);
1079             return;
1080          }
1081          if (vertex_count == 0)
1082             continue;
1083 
1084          total_count += vertex_count;
1085       }
1086 
1087       if (total_count == 0) {
1088          /* Nothing to do, but call the driver to set possible GL errors. */
1089          multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1090                                    basevertex, 0, 0, NULL);
1091          return;
1092       }
1093    }
1094 
1095    /* Upload vertices. */
1096    struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX];
1097    if (user_buffer_mask &&
1098        !upload_vertices(ctx, user_buffer_mask, min_index, num_vertices,
1099                         0, 1, buffers))
1100       goto sync;
1101 
1102    /* Upload indices. */
1103    struct gl_buffer_object *index_buffer = NULL;
1104    if (has_user_indices) {
1105       const GLvoid **out_indices = alloca(sizeof(indices[0]) * draw_count);
1106 
1107       index_buffer = upload_multi_indices(ctx, total_count, index_size,
1108                                           draw_count, count, indices,
1109                                           out_indices);
1110       indices = out_indices;
1111    }
1112 
1113    /* Draw asynchronously. */
1114    multi_draw_elements_async(ctx, mode, count, type, indices, draw_count,
1115                              basevertex, index_buffer, user_buffer_mask,
1116                              buffers);
1117    return;
1118 
1119 sync:
1120    _mesa_glthread_finish_before(ctx, "DrawElements");
1121 
1122    if (basevertex) {
1123       CALL_MultiDrawElementsBaseVertex(ctx->CurrentServerDispatch,
1124                                        (mode, count, type, indices, draw_count,
1125                                         basevertex));
1126    } else {
1127       CALL_MultiDrawElementsEXT(ctx->CurrentServerDispatch,
1128                                 (mode, count, type, indices, draw_count));
1129    }
1130 }
1131 
1132 void GLAPIENTRY
_mesa_marshal_DrawArrays(GLenum mode,GLint first,GLsizei count)1133 _mesa_marshal_DrawArrays(GLenum mode, GLint first, GLsizei count)
1134 {
1135    draw_arrays(mode, first, count, 1, 0, true);
1136 }
1137 
1138 void GLAPIENTRY
_mesa_marshal_DrawArraysInstancedARB(GLenum mode,GLint first,GLsizei count,GLsizei instance_count)1139 _mesa_marshal_DrawArraysInstancedARB(GLenum mode, GLint first, GLsizei count,
1140                                      GLsizei instance_count)
1141 {
1142    draw_arrays(mode, first, count, instance_count, 0, false);
1143 }
1144 
1145 void GLAPIENTRY
_mesa_marshal_DrawArraysInstancedBaseInstance(GLenum mode,GLint first,GLsizei count,GLsizei instance_count,GLuint baseinstance)1146 _mesa_marshal_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
1147                                               GLsizei count, GLsizei instance_count,
1148                                               GLuint baseinstance)
1149 {
1150    draw_arrays(mode, first, count, instance_count, baseinstance, false);
1151 }
1152 
1153 void GLAPIENTRY
_mesa_marshal_DrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)1154 _mesa_marshal_DrawElements(GLenum mode, GLsizei count, GLenum type,
1155                            const GLvoid *indices)
1156 {
1157    draw_elements(mode, count, type, indices, 1, 0, 0, false, 0, 0, true);
1158 }
1159 
1160 void GLAPIENTRY
_mesa_marshal_DrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)1161 _mesa_marshal_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1162                                 GLsizei count, GLenum type,
1163                                 const GLvoid *indices)
1164 {
1165    draw_elements(mode, count, type, indices, 1, 0, 0, true, start, end, true);
1166 }
1167 
1168 void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedARB(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count)1169 _mesa_marshal_DrawElementsInstancedARB(GLenum mode, GLsizei count, GLenum type,
1170                                        const GLvoid *indices, GLsizei instance_count)
1171 {
1172    draw_elements(mode, count, type, indices, instance_count, 0, 0, false, 0, 0, false);
1173 }
1174 
1175 void GLAPIENTRY
_mesa_marshal_DrawElementsBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1176 _mesa_marshal_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1177                                      const GLvoid *indices, GLint basevertex)
1178 {
1179    draw_elements(mode, count, type, indices, 1, basevertex, 0, false, 0, 0, true);
1180 }
1181 
1182 void GLAPIENTRY
_mesa_marshal_DrawRangeElementsBaseVertex(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1183 _mesa_marshal_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1184                                           GLsizei count, GLenum type,
1185                                           const GLvoid *indices, GLint basevertex)
1186 {
1187    draw_elements(mode, count, type, indices, 1, basevertex, 0, true, start, end, false);
1188 }
1189 
1190 void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex)1191 _mesa_marshal_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count,
1192                                               GLenum type, const GLvoid *indices,
1193                                               GLsizei instance_count, GLint basevertex)
1194 {
1195    draw_elements(mode, count, type, indices, instance_count, basevertex, 0, false, 0, 0, false);
1196 }
1197 
1198 void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLuint baseinstance)1199 _mesa_marshal_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,
1200                                                 GLenum type, const GLvoid *indices,
1201                                                 GLsizei instance_count, GLuint baseinstance)
1202 {
1203    draw_elements(mode, count, type, indices, instance_count, 0, baseinstance, false, 0, 0, false);
1204 }
1205 
1206 void GLAPIENTRY
_mesa_marshal_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instance_count,GLint basevertex,GLuint baseinstance)1207 _mesa_marshal_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count,
1208                                                           GLenum type, const GLvoid *indices,
1209                                                           GLsizei instance_count, GLint basevertex,
1210                                                           GLuint baseinstance)
1211 {
1212    draw_elements(mode, count, type, indices, instance_count, basevertex, baseinstance, false, 0, 0, false);
1213 }
1214 
1215 void GLAPIENTRY
_mesa_marshal_MultiDrawElementsEXT(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei draw_count)1216 _mesa_marshal_MultiDrawElementsEXT(GLenum mode, const GLsizei *count,
1217                                    GLenum type, const GLvoid *const *indices,
1218                                    GLsizei draw_count)
1219 {
1220    _mesa_marshal_MultiDrawElementsBaseVertex(mode, count, type, indices,
1221                                              draw_count, NULL);
1222 }
1223 
1224 uint32_t
_mesa_unmarshal_DrawArraysInstancedARB(struct gl_context * ctx,const struct marshal_cmd_DrawArraysInstancedARB * cmd,const uint64_t * last)1225 _mesa_unmarshal_DrawArraysInstancedARB(struct gl_context *ctx, const struct marshal_cmd_DrawArraysInstancedARB *cmd, const uint64_t *last)
1226 {
1227    unreachable("never used - DrawArraysInstancedBaseInstance is used instead");
1228    return 0;
1229 }
1230 
1231 uint32_t
_mesa_unmarshal_DrawElements(struct gl_context * ctx,const struct marshal_cmd_DrawElements * cmd,const uint64_t * last)1232 _mesa_unmarshal_DrawElements(struct gl_context *ctx, const struct marshal_cmd_DrawElements *cmd, const uint64_t *last)
1233 {
1234    unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead");
1235    return 0;
1236 }
1237 
1238 uint32_t
_mesa_unmarshal_DrawRangeElements(struct gl_context * ctx,const struct marshal_cmd_DrawRangeElements * cmd,const uint64_t * last)1239 _mesa_unmarshal_DrawRangeElements(struct gl_context *ctx, const struct marshal_cmd_DrawRangeElements *cmd, const uint64_t *last)
1240 {
1241    unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead");
1242    return 0;
1243 }
1244 
1245 uint32_t
_mesa_unmarshal_DrawElementsBaseVertex(struct gl_context * ctx,const struct marshal_cmd_DrawElementsBaseVertex * cmd,const uint64_t * last)1246 _mesa_unmarshal_DrawElementsBaseVertex(struct gl_context *ctx, const struct marshal_cmd_DrawElementsBaseVertex *cmd, const uint64_t *last)
1247 {
1248    unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead");
1249    return 0;
1250 }
1251 
1252 uint32_t
_mesa_unmarshal_DrawElementsInstancedBaseVertex(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedBaseVertex * cmd,const uint64_t * last)1253 _mesa_unmarshal_DrawElementsInstancedBaseVertex(struct gl_context *ctx, const struct marshal_cmd_DrawElementsInstancedBaseVertex *cmd, const uint64_t *last)
1254 {
1255    unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead");
1256    return 0;
1257 }
1258 
1259 uint32_t
_mesa_unmarshal_DrawElementsInstancedBaseInstance(struct gl_context * ctx,const struct marshal_cmd_DrawElementsInstancedBaseInstance * cmd,const uint64_t * last)1260 _mesa_unmarshal_DrawElementsInstancedBaseInstance(struct gl_context *ctx, const struct marshal_cmd_DrawElementsInstancedBaseInstance *cmd, const uint64_t *last)
1261 {
1262    unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead");
1263    return 0;
1264 }
1265 
1266 uint32_t
_mesa_unmarshal_MultiDrawElementsEXT(struct gl_context * ctx,const struct marshal_cmd_MultiDrawElementsEXT * cmd,const uint64_t * last)1267 _mesa_unmarshal_MultiDrawElementsEXT(struct gl_context *ctx, const struct marshal_cmd_MultiDrawElementsEXT *cmd, const uint64_t *last)
1268 {
1269    unreachable("never used - MultiDrawElementsBaseVertex is used instead");
1270    return 0;
1271 }
1272