glthread: inline _mesa_unmarshal_dispatch_cmd and convert the switch to a table
[mesa.git] / src / mesa / main / marshal.c
1 /*
2 * Copyright © 2012 Intel Corporation
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 /** \file marshal.c
25 *
26 * Custom functions for marshalling GL calls from the main thread to a worker
27 * thread when automatic code generation isn't appropriate.
28 */
29
30 #include "main/enums.h"
31 #include "main/macros.h"
32 #include "marshal.h"
33 #include "dispatch.h"
34
35 struct marshal_cmd_Flush
36 {
37 struct marshal_cmd_base cmd_base;
38 };
39
40
41 void
42 _mesa_unmarshal_Flush(struct gl_context *ctx,
43 const struct marshal_cmd_Flush *cmd)
44 {
45 CALL_Flush(ctx->CurrentServerDispatch, ());
46 }
47
48
49 void GLAPIENTRY
50 _mesa_marshal_Flush(void)
51 {
52 GET_CURRENT_CONTEXT(ctx);
53 struct marshal_cmd_Flush *cmd =
54 _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_Flush,
55 sizeof(struct marshal_cmd_Flush));
56 (void) cmd;
57 _mesa_post_marshal_hook(ctx);
58
59 /* Flush() needs to be handled specially. In addition to telling the
60 * background thread to flush, we need to ensure that our own buffer is
61 * submitted to the background thread so that it will complete in a finite
62 * amount of time.
63 */
64 _mesa_glthread_flush_batch(ctx);
65 }
66
67 /* Enable: marshalled asynchronously */
68 struct marshal_cmd_Enable
69 {
70 struct marshal_cmd_base cmd_base;
71 GLenum cap;
72 };
73
74 void
75 _mesa_unmarshal_Enable(struct gl_context *ctx,
76 const struct marshal_cmd_Enable *cmd)
77 {
78 const GLenum cap = cmd->cap;
79 CALL_Enable(ctx->CurrentServerDispatch, (cap));
80 }
81
82 void GLAPIENTRY
83 _mesa_marshal_Enable(GLenum cap)
84 {
85 GET_CURRENT_CONTEXT(ctx);
86 struct marshal_cmd_Enable *cmd;
87 debug_print_marshal("Enable");
88
89 if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) {
90 _mesa_glthread_finish(ctx);
91 _mesa_glthread_restore_dispatch(ctx, "Enable(DEBUG_OUTPUT_SYNCHRONOUS)");
92 } else {
93 cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_Enable,
94 sizeof(*cmd));
95 cmd->cap = cap;
96 _mesa_post_marshal_hook(ctx);
97 return;
98 }
99
100 _mesa_glthread_finish(ctx);
101 debug_print_sync_fallback("Enable");
102 CALL_Enable(ctx->CurrentServerDispatch, (cap));
103 }
104
105 struct marshal_cmd_ShaderSource
106 {
107 struct marshal_cmd_base cmd_base;
108 GLuint shader;
109 GLsizei count;
110 /* Followed by GLint length[count], then the contents of all strings,
111 * concatenated.
112 */
113 };
114
115
116 void
117 _mesa_unmarshal_ShaderSource(struct gl_context *ctx,
118 const struct marshal_cmd_ShaderSource *cmd)
119 {
120 const GLint *cmd_length = (const GLint *) (cmd + 1);
121 const GLchar *cmd_strings = (const GLchar *) (cmd_length + cmd->count);
122 /* TODO: how to deal with malloc failure? */
123 const GLchar * *string = malloc(cmd->count * sizeof(const GLchar *));
124 int i;
125
126 for (i = 0; i < cmd->count; ++i) {
127 string[i] = cmd_strings;
128 cmd_strings += cmd_length[i];
129 }
130 CALL_ShaderSource(ctx->CurrentServerDispatch,
131 (cmd->shader, cmd->count, string, cmd_length));
132 free((void *)string);
133 }
134
135
136 static size_t
137 measure_ShaderSource_strings(GLsizei count, const GLchar * const *string,
138 const GLint *length_in, GLint *length_out)
139 {
140 int i;
141 size_t total_string_length = 0;
142
143 for (i = 0; i < count; ++i) {
144 if (length_in == NULL || length_in[i] < 0) {
145 if (string[i])
146 length_out[i] = strlen(string[i]);
147 } else {
148 length_out[i] = length_in[i];
149 }
150 total_string_length += length_out[i];
151 }
152 return total_string_length;
153 }
154
155
156 void GLAPIENTRY
157 _mesa_marshal_ShaderSource(GLuint shader, GLsizei count,
158 const GLchar * const *string, const GLint *length)
159 {
160 /* TODO: how to report an error if count < 0? */
161
162 GET_CURRENT_CONTEXT(ctx);
163 /* TODO: how to deal with malloc failure? */
164 const size_t fixed_cmd_size = sizeof(struct marshal_cmd_ShaderSource);
165 STATIC_ASSERT(sizeof(struct marshal_cmd_ShaderSource) % sizeof(GLint) == 0);
166 size_t length_size = count * sizeof(GLint);
167 GLint *length_tmp = malloc(length_size);
168 size_t total_string_length =
169 measure_ShaderSource_strings(count, string, length, length_tmp);
170 size_t total_cmd_size = fixed_cmd_size + length_size + total_string_length;
171
172 if (total_cmd_size <= MARSHAL_MAX_CMD_SIZE) {
173 struct marshal_cmd_ShaderSource *cmd =
174 _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_ShaderSource,
175 total_cmd_size);
176 GLint *cmd_length = (GLint *) (cmd + 1);
177 GLchar *cmd_strings = (GLchar *) (cmd_length + count);
178 int i;
179
180 cmd->shader = shader;
181 cmd->count = count;
182 memcpy(cmd_length, length_tmp, length_size);
183 for (i = 0; i < count; ++i) {
184 memcpy(cmd_strings, string[i], cmd_length[i]);
185 cmd_strings += cmd_length[i];
186 }
187 _mesa_post_marshal_hook(ctx);
188 } else {
189 _mesa_glthread_finish(ctx);
190 CALL_ShaderSource(ctx->CurrentServerDispatch,
191 (shader, count, string, length_tmp));
192 }
193 free(length_tmp);
194 }
195
196
197 /* BindBufferBase: marshalled asynchronously */
198 struct marshal_cmd_BindBufferBase
199 {
200 struct marshal_cmd_base cmd_base;
201 GLenum target;
202 GLuint index;
203 GLuint buffer;
204 };
205
206 /** Tracks the current bindings for the vertex array and index array buffers.
207 *
208 * This is part of what we need to enable glthread on compat-GL contexts that
209 * happen to use VBOs, without also supporting the full tracking of VBO vs
210 * user vertex array bindings per attribute on each vertex array for
211 * determining what to upload at draw call time.
212 *
213 * Note that GL core makes it so that a buffer binding with an invalid handle
214 * in the "buffer" parameter will throw an error, and then a
215 * glVertexAttribPointer() that followsmight not end up pointing at a VBO.
216 * However, in GL core the draw call would throw an error as well, so we don't
217 * really care if our tracking is wrong for this case -- we never need to
218 * marshal user data for draw calls, and the unmarshal will just generate an
219 * error or not as appropriate.
220 *
221 * For compatibility GL, we do need to accurately know whether the draw call
222 * on the unmarshal side will dereference a user pointer or load data from a
223 * VBO per vertex. That would make it seem like we need to track whether a
224 * "buffer" is valid, so that we can know when an error will be generated
225 * instead of updating the binding. However, compat GL has the ridiculous
226 * feature that if you pass a bad name, it just gens a buffer object for you,
227 * so we escape without having to know if things are valid or not.
228 */
229 static void
230 track_vbo_binding(struct gl_context *ctx, GLenum target, GLuint buffer)
231 {
232 struct glthread_state *glthread = ctx->GLThread;
233
234 switch (target) {
235 case GL_ARRAY_BUFFER:
236 glthread->vertex_array_is_vbo = (buffer != 0);
237 break;
238 case GL_ELEMENT_ARRAY_BUFFER:
239 /* The current element array buffer binding is actually tracked in the
240 * vertex array object instead of the context, so this would need to
241 * change on vertex array object updates.
242 */
243 glthread->element_array_is_vbo = (buffer != 0);
244 break;
245 }
246 }
247
248
249 struct marshal_cmd_BindBuffer
250 {
251 struct marshal_cmd_base cmd_base;
252 GLenum target;
253 GLuint buffer;
254 };
255
256 /**
257 * This is just like the code-generated glBindBuffer() support, except that we
258 * call track_vbo_binding().
259 */
260 void
261 _mesa_unmarshal_BindBuffer(struct gl_context *ctx,
262 const struct marshal_cmd_BindBuffer *cmd)
263 {
264 const GLenum target = cmd->target;
265 const GLuint buffer = cmd->buffer;
266 CALL_BindBuffer(ctx->CurrentServerDispatch, (target, buffer));
267 }
268 void GLAPIENTRY
269 _mesa_marshal_BindBuffer(GLenum target, GLuint buffer)
270 {
271 GET_CURRENT_CONTEXT(ctx);
272 size_t cmd_size = sizeof(struct marshal_cmd_BindBuffer);
273 struct marshal_cmd_BindBuffer *cmd;
274 debug_print_marshal("BindBuffer");
275
276 track_vbo_binding(ctx, target, buffer);
277
278 if (cmd_size <= MARSHAL_MAX_CMD_SIZE) {
279 cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BindBuffer,
280 cmd_size);
281 cmd->target = target;
282 cmd->buffer = buffer;
283 _mesa_post_marshal_hook(ctx);
284 } else {
285 _mesa_glthread_finish(ctx);
286 CALL_BindBuffer(ctx->CurrentServerDispatch, (target, buffer));
287 }
288 }
289
290 /* BufferData: marshalled asynchronously */
291 struct marshal_cmd_BufferData
292 {
293 struct marshal_cmd_base cmd_base;
294 GLenum target;
295 GLsizeiptr size;
296 GLenum usage;
297 bool data_null; /* If set, no data follows for "data" */
298 /* Next size bytes are GLubyte data[size] */
299 };
300
301 void
302 _mesa_unmarshal_BufferData(struct gl_context *ctx,
303 const struct marshal_cmd_BufferData *cmd)
304 {
305 const GLenum target = cmd->target;
306 const GLsizeiptr size = cmd->size;
307 const GLenum usage = cmd->usage;
308 const void *data;
309
310 if (cmd->data_null)
311 data = NULL;
312 else
313 data = (const void *) (cmd + 1);
314
315 CALL_BufferData(ctx->CurrentServerDispatch, (target, size, data, usage));
316 }
317
318 void GLAPIENTRY
319 _mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data,
320 GLenum usage)
321 {
322 GET_CURRENT_CONTEXT(ctx);
323 size_t cmd_size =
324 sizeof(struct marshal_cmd_BufferData) + (data ? size : 0);
325 debug_print_marshal("BufferData");
326
327 if (unlikely(size < 0)) {
328 _mesa_glthread_finish(ctx);
329 _mesa_error(ctx, GL_INVALID_VALUE, "BufferData(size < 0)");
330 return;
331 }
332
333 if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
334 cmd_size <= MARSHAL_MAX_CMD_SIZE) {
335 struct marshal_cmd_BufferData *cmd =
336 _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferData,
337 cmd_size);
338
339 cmd->target = target;
340 cmd->size = size;
341 cmd->usage = usage;
342 cmd->data_null = !data;
343 if (data) {
344 char *variable_data = (char *) (cmd + 1);
345 memcpy(variable_data, data, size);
346 }
347 _mesa_post_marshal_hook(ctx);
348 } else {
349 _mesa_glthread_finish(ctx);
350 CALL_BufferData(ctx->CurrentServerDispatch,
351 (target, size, data, usage));
352 }
353 }
354
355 /* BufferSubData: marshalled asynchronously */
356 struct marshal_cmd_BufferSubData
357 {
358 struct marshal_cmd_base cmd_base;
359 GLenum target;
360 GLintptr offset;
361 GLsizeiptr size;
362 /* Next size bytes are GLubyte data[size] */
363 };
364
365 void
366 _mesa_unmarshal_BufferSubData(struct gl_context *ctx,
367 const struct marshal_cmd_BufferSubData *cmd)
368 {
369 const GLenum target = cmd->target;
370 const GLintptr offset = cmd->offset;
371 const GLsizeiptr size = cmd->size;
372 const void *data = (const void *) (cmd + 1);
373
374 CALL_BufferSubData(ctx->CurrentServerDispatch,
375 (target, offset, size, data));
376 }
377
378 void GLAPIENTRY
379 _mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
380 const GLvoid * data)
381 {
382 GET_CURRENT_CONTEXT(ctx);
383 size_t cmd_size = sizeof(struct marshal_cmd_BufferSubData) + size;
384
385 debug_print_marshal("BufferSubData");
386 if (unlikely(size < 0)) {
387 _mesa_glthread_finish(ctx);
388 _mesa_error(ctx, GL_INVALID_VALUE, "BufferSubData(size < 0)");
389 return;
390 }
391
392 if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
393 cmd_size <= MARSHAL_MAX_CMD_SIZE) {
394 struct marshal_cmd_BufferSubData *cmd =
395 _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferSubData,
396 cmd_size);
397 cmd->target = target;
398 cmd->offset = offset;
399 cmd->size = size;
400 char *variable_data = (char *) (cmd + 1);
401 memcpy(variable_data, data, size);
402 _mesa_post_marshal_hook(ctx);
403 } else {
404 _mesa_glthread_finish(ctx);
405 CALL_BufferSubData(ctx->CurrentServerDispatch,
406 (target, offset, size, data));
407 }
408 }
409
410 /* NamedBufferData: marshalled asynchronously */
411 struct marshal_cmd_NamedBufferData
412 {
413 struct marshal_cmd_base cmd_base;
414 GLuint name;
415 GLsizei size;
416 GLenum usage;
417 bool data_null; /* If set, no data follows for "data" */
418 /* Next size bytes are GLubyte data[size] */
419 };
420
421 void
422 _mesa_unmarshal_NamedBufferData(struct gl_context *ctx,
423 const struct marshal_cmd_NamedBufferData *cmd)
424 {
425 const GLuint name = cmd->name;
426 const GLsizei size = cmd->size;
427 const GLenum usage = cmd->usage;
428 const void *data;
429
430 if (cmd->data_null)
431 data = NULL;
432 else
433 data = (const void *) (cmd + 1);
434
435 CALL_NamedBufferData(ctx->CurrentServerDispatch,
436 (name, size, data, usage));
437 }
438
439 void GLAPIENTRY
440 _mesa_marshal_NamedBufferData(GLuint buffer, GLsizeiptr size,
441 const GLvoid * data, GLenum usage)
442 {
443 GET_CURRENT_CONTEXT(ctx);
444 size_t cmd_size = sizeof(struct marshal_cmd_NamedBufferData) + (data ? size : 0);
445
446 debug_print_marshal("NamedBufferData");
447 if (unlikely(size < 0)) {
448 _mesa_glthread_finish(ctx);
449 _mesa_error(ctx, GL_INVALID_VALUE, "NamedBufferData(size < 0)");
450 return;
451 }
452
453 if (buffer > 0 && cmd_size <= MARSHAL_MAX_CMD_SIZE) {
454 struct marshal_cmd_NamedBufferData *cmd =
455 _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_NamedBufferData,
456 cmd_size);
457 cmd->name = buffer;
458 cmd->size = size;
459 cmd->usage = usage;
460 cmd->data_null = !data;
461 if (data) {
462 char *variable_data = (char *) (cmd + 1);
463 memcpy(variable_data, data, size);
464 }
465 _mesa_post_marshal_hook(ctx);
466 } else {
467 _mesa_glthread_finish(ctx);
468 CALL_NamedBufferData(ctx->CurrentServerDispatch,
469 (buffer, size, data, usage));
470 }
471 }
472
473 /* NamedBufferSubData: marshalled asynchronously */
474 struct marshal_cmd_NamedBufferSubData
475 {
476 struct marshal_cmd_base cmd_base;
477 GLuint name;
478 GLintptr offset;
479 GLsizei size;
480 /* Next size bytes are GLubyte data[size] */
481 };
482
483 void
484 _mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx,
485 const struct marshal_cmd_NamedBufferSubData *cmd)
486 {
487 const GLuint name = cmd->name;
488 const GLintptr offset = cmd->offset;
489 const GLsizei size = cmd->size;
490 const void *data = (const void *) (cmd + 1);
491
492 CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
493 (name, offset, size, data));
494 }
495
496 void GLAPIENTRY
497 _mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset,
498 GLsizeiptr size, const GLvoid * data)
499 {
500 GET_CURRENT_CONTEXT(ctx);
501 size_t cmd_size = sizeof(struct marshal_cmd_NamedBufferSubData) + size;
502
503 debug_print_marshal("NamedBufferSubData");
504 if (unlikely(size < 0)) {
505 _mesa_glthread_finish(ctx);
506 _mesa_error(ctx, GL_INVALID_VALUE, "NamedBufferSubData(size < 0)");
507 return;
508 }
509
510 if (buffer > 0 && cmd_size <= MARSHAL_MAX_CMD_SIZE) {
511 struct marshal_cmd_NamedBufferSubData *cmd =
512 _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_NamedBufferSubData,
513 cmd_size);
514 cmd->name = buffer;
515 cmd->offset = offset;
516 cmd->size = size;
517 char *variable_data = (char *) (cmd + 1);
518 memcpy(variable_data, data, size);
519 _mesa_post_marshal_hook(ctx);
520 } else {
521 _mesa_glthread_finish(ctx);
522 CALL_NamedBufferSubData(ctx->CurrentServerDispatch,
523 (buffer, offset, size, data));
524 }
525 }
526
527 /* ClearBuffer* (all variants): marshalled asynchronously */
528 struct marshal_cmd_ClearBuffer
529 {
530 struct marshal_cmd_base cmd_base;
531 GLenum buffer;
532 GLint drawbuffer;
533 };
534
535 void
536 _mesa_unmarshal_ClearBufferfv(struct gl_context *ctx,
537 const struct marshal_cmd_ClearBuffer *cmd)
538 {
539 const GLenum buffer = cmd->buffer;
540 const GLint drawbuffer = cmd->drawbuffer;
541 const char *variable_data = (const char *) (cmd + 1);
542 const GLfloat *value = (const GLfloat *) variable_data;
543
544 CALL_ClearBufferfv(ctx->CurrentServerDispatch,
545 (buffer, drawbuffer, value));
546 }
547
548 void
549 _mesa_unmarshal_ClearBufferiv(struct gl_context *ctx,
550 const struct marshal_cmd_ClearBuffer *cmd)
551 {
552 const GLenum buffer = cmd->buffer;
553 const GLint drawbuffer = cmd->drawbuffer;
554 const char *variable_data = (const char *) (cmd + 1);
555 const GLint *value = (const GLint *) variable_data;
556
557 CALL_ClearBufferiv(ctx->CurrentServerDispatch,
558 (buffer, drawbuffer, value));
559 }
560
561 void
562 _mesa_unmarshal_ClearBufferuiv(struct gl_context *ctx,
563 const struct marshal_cmd_ClearBuffer *cmd)
564 {
565 const GLenum buffer = cmd->buffer;
566 const GLint drawbuffer = cmd->drawbuffer;
567 const char *variable_data = (const char *) (cmd + 1);
568 const GLuint *value = (const GLuint *) variable_data;
569
570 CALL_ClearBufferuiv(ctx->CurrentServerDispatch,
571 (buffer, drawbuffer, value));
572 }
573
574 void
575 _mesa_unmarshal_ClearBufferfi(struct gl_context *ctx,
576 const struct marshal_cmd_ClearBuffer *cmd)
577 {
578 const GLenum buffer = cmd->buffer;
579 const GLint drawbuffer = cmd->drawbuffer;
580 const char *variable_data = (const char *) (cmd + 1);
581 const GLfloat *depth = (const GLfloat *) variable_data;
582 const GLint *stencil = (const GLint *) (variable_data + 4);
583
584 CALL_ClearBufferfi(ctx->CurrentServerDispatch,
585 (buffer, drawbuffer, *depth, *stencil));
586 }
587
588 static inline size_t buffer_to_size(GLenum buffer)
589 {
590 switch (buffer) {
591 case GL_COLOR:
592 return 4;
593 case GL_DEPTH_STENCIL:
594 return 2;
595 case GL_STENCIL:
596 case GL_DEPTH:
597 return 1;
598 default:
599 return 0;
600 }
601 }
602
603 static inline bool clear_buffer_add_command(struct gl_context *ctx, uint16_t id,
604 GLenum buffer, GLint drawbuffer,
605 const GLuint *value, size_t size)
606 {
607 size_t cmd_size = sizeof(struct marshal_cmd_ClearBuffer) + 4 * size;
608 if (cmd_size <= MARSHAL_MAX_CMD_SIZE) {
609 struct marshal_cmd_ClearBuffer *cmd =
610 _mesa_glthread_allocate_command(ctx, id,
611 cmd_size);
612 cmd->buffer = buffer;
613 cmd->drawbuffer = drawbuffer;
614 GLuint *variable_data = (GLuint *) (cmd + 1);
615 if (size == 4)
616 COPY_4V(variable_data, value);
617 else if (size == 2)
618 COPY_2V(variable_data, value);
619 else
620 *variable_data = *value;
621
622 _mesa_post_marshal_hook(ctx);
623 return true;
624 }
625
626 return false;
627 }
628
629 void GLAPIENTRY
630 _mesa_marshal_ClearBufferfv(GLenum buffer, GLint drawbuffer,
631 const GLfloat *value)
632 {
633 GET_CURRENT_CONTEXT(ctx);
634 debug_print_marshal("ClearBufferfv");
635
636 if (!(buffer == GL_DEPTH || buffer == GL_COLOR)) {
637 _mesa_glthread_finish(ctx);
638
639 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
640 * of the OpenGL 4.5 spec states:
641 *
642 * "An INVALID_ENUM error is generated by ClearBufferfv and
643 * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
644 */
645 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
646 _mesa_enum_to_string(buffer));
647 }
648
649 size_t size = buffer_to_size(buffer);
650 if (!clear_buffer_add_command(ctx, DISPATCH_CMD_ClearBufferfv, buffer,
651 drawbuffer, (GLuint *)value, size)) {
652 debug_print_sync("ClearBufferfv");
653 _mesa_glthread_finish(ctx);
654 CALL_ClearBufferfv(ctx->CurrentServerDispatch,
655 (buffer, drawbuffer, value));
656 }
657 }
658
659 void GLAPIENTRY
660 _mesa_marshal_ClearBufferiv(GLenum buffer, GLint drawbuffer,
661 const GLint *value)
662 {
663 GET_CURRENT_CONTEXT(ctx);
664 debug_print_marshal("ClearBufferiv");
665
666 if (!(buffer == GL_STENCIL || buffer == GL_COLOR)) {
667 _mesa_glthread_finish(ctx);
668
669 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
670 * of the OpenGL 4.5 spec states:
671 *
672 * "An INVALID_ENUM error is generated by ClearBufferiv and
673 * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
674 */
675 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferiv(buffer=%s)",
676 _mesa_enum_to_string(buffer));
677 }
678
679 size_t size = buffer_to_size(buffer);
680 if (!clear_buffer_add_command(ctx, DISPATCH_CMD_ClearBufferiv, buffer,
681 drawbuffer, (GLuint *)value, size)) {
682 debug_print_sync("ClearBufferiv");
683 _mesa_glthread_finish(ctx);
684 CALL_ClearBufferiv(ctx->CurrentServerDispatch,
685 (buffer, drawbuffer, value));
686 }
687 }
688
689 void GLAPIENTRY
690 _mesa_marshal_ClearBufferuiv(GLenum buffer, GLint drawbuffer,
691 const GLuint *value)
692 {
693 GET_CURRENT_CONTEXT(ctx);
694 debug_print_marshal("ClearBufferuiv");
695
696 if (buffer != GL_COLOR) {
697 _mesa_glthread_finish(ctx);
698
699 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
700 * of the OpenGL 4.5 spec states:
701 *
702 * "An INVALID_ENUM error is generated by ClearBufferuiv and
703 * ClearNamedFramebufferuiv if buffer is not COLOR."
704 */
705 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
706 _mesa_enum_to_string(buffer));
707 }
708
709 if (!clear_buffer_add_command(ctx, DISPATCH_CMD_ClearBufferuiv, buffer,
710 drawbuffer, (GLuint *)value, 4)) {
711 debug_print_sync("ClearBufferuiv");
712 _mesa_glthread_finish(ctx);
713 CALL_ClearBufferuiv(ctx->CurrentServerDispatch,
714 (buffer, drawbuffer, value));
715 }
716 }
717
718 void GLAPIENTRY
719 _mesa_marshal_ClearBufferfi(GLenum buffer, GLint drawbuffer,
720 const GLfloat depth, const GLint stencil)
721 {
722 GET_CURRENT_CONTEXT(ctx);
723 debug_print_marshal("ClearBufferfi");
724
725 if (buffer != GL_DEPTH_STENCIL) {
726 _mesa_glthread_finish(ctx);
727
728 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
729 * of the OpenGL 4.5 spec states:
730 *
731 * "An INVALID_ENUM error is generated by ClearBufferfi and
732 * ClearNamedFramebufferfi if buffer is not DEPTH_STENCIL."
733 */
734 _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfi(buffer=%s)",
735 _mesa_enum_to_string(buffer));
736 }
737
738 fi_type value[2];
739 value[0].f = depth;
740 value[1].i = stencil;
741 if (!clear_buffer_add_command(ctx, DISPATCH_CMD_ClearBufferfi, buffer,
742 drawbuffer, (GLuint *)value, 2)) {
743 debug_print_sync("ClearBufferfi");
744 _mesa_glthread_finish(ctx);
745 CALL_ClearBufferfi(ctx->CurrentServerDispatch,
746 (buffer, drawbuffer, depth, stencil));
747 }
748 }