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