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