2 * Copyright © 2012 Intel Corporation
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:
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
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
26 * Custom functions for marshalling GL calls from the main thread to a worker
27 * thread when automatic code generation isn't appropriate.
30 #include "main/enums.h"
31 #include "main/macros.h"
35 struct marshal_cmd_Flush
37 struct marshal_cmd_base cmd_base
;
42 _mesa_unmarshal_Flush(struct gl_context
*ctx
,
43 const struct marshal_cmd_Flush
*cmd
)
45 CALL_Flush(ctx
->CurrentServerDispatch
, ());
50 _mesa_marshal_Flush(void)
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
));
57 _mesa_post_marshal_hook(ctx
);
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
64 _mesa_glthread_flush_batch(ctx
);
67 /* Enable: marshalled asynchronously */
68 struct marshal_cmd_Enable
70 struct marshal_cmd_base cmd_base
;
75 _mesa_unmarshal_Enable(struct gl_context
*ctx
,
76 const struct marshal_cmd_Enable
*cmd
)
78 const GLenum cap
= cmd
->cap
;
79 CALL_Enable(ctx
->CurrentServerDispatch
, (cap
));
83 _mesa_marshal_Enable(GLenum cap
)
85 GET_CURRENT_CONTEXT(ctx
);
86 struct marshal_cmd_Enable
*cmd
;
87 debug_print_marshal("Enable");
89 if (cap
== GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
) {
90 _mesa_glthread_disable(ctx
, "Enable(DEBUG_OUTPUT_SYNCHRONOUS)");
92 cmd
= _mesa_glthread_allocate_command(ctx
, DISPATCH_CMD_Enable
,
95 _mesa_post_marshal_hook(ctx
);
99 _mesa_glthread_finish(ctx
);
100 debug_print_sync_fallback("Enable");
101 CALL_Enable(ctx
->CurrentServerDispatch
, (cap
));
104 struct marshal_cmd_ShaderSource
106 struct marshal_cmd_base cmd_base
;
109 /* Followed by GLint length[count], then the contents of all strings,
116 _mesa_unmarshal_ShaderSource(struct gl_context
*ctx
,
117 const struct marshal_cmd_ShaderSource
*cmd
)
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
*));
125 for (i
= 0; i
< cmd
->count
; ++i
) {
126 string
[i
] = cmd_strings
;
127 cmd_strings
+= cmd_length
[i
];
129 CALL_ShaderSource(ctx
->CurrentServerDispatch
,
130 (cmd
->shader
, cmd
->count
, string
, cmd_length
));
131 free((void *)string
);
136 measure_ShaderSource_strings(GLsizei count
, const GLchar
* const *string
,
137 const GLint
*length_in
, GLint
*length_out
)
140 size_t total_string_length
= 0;
142 for (i
= 0; i
< count
; ++i
) {
143 if (length_in
== NULL
|| length_in
[i
] < 0) {
145 length_out
[i
] = strlen(string
[i
]);
147 length_out
[i
] = length_in
[i
];
149 total_string_length
+= length_out
[i
];
151 return total_string_length
;
156 _mesa_marshal_ShaderSource(GLuint shader
, GLsizei count
,
157 const GLchar
* const *string
, const GLint
*length
)
159 /* TODO: how to report an error if count < 0? */
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
;
171 if (total_cmd_size
<= MARSHAL_MAX_CMD_SIZE
) {
172 struct marshal_cmd_ShaderSource
*cmd
=
173 _mesa_glthread_allocate_command(ctx
, DISPATCH_CMD_ShaderSource
,
175 GLint
*cmd_length
= (GLint
*) (cmd
+ 1);
176 GLchar
*cmd_strings
= (GLchar
*) (cmd_length
+ count
);
179 cmd
->shader
= shader
;
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
];
186 _mesa_post_marshal_hook(ctx
);
188 _mesa_glthread_finish(ctx
);
189 CALL_ShaderSource(ctx
->CurrentServerDispatch
,
190 (shader
, count
, string
, length_tmp
));
196 /* BindBufferBase: marshalled asynchronously */
197 struct marshal_cmd_BindBufferBase
199 struct marshal_cmd_base cmd_base
;
205 /** Tracks the current bindings for the vertex array and index array buffers.
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.
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.
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.
229 track_vbo_binding(struct gl_context
*ctx
, GLenum target
, GLuint buffer
)
231 struct glthread_state
*glthread
= ctx
->GLThread
;
234 case GL_ARRAY_BUFFER
:
235 glthread
->vertex_array_is_vbo
= (buffer
!= 0);
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.
242 glthread
->element_array_is_vbo
= (buffer
!= 0);
248 struct marshal_cmd_BindBuffer
250 struct marshal_cmd_base cmd_base
;
256 * This is just like the code-generated glBindBuffer() support, except that we
257 * call track_vbo_binding().
260 _mesa_unmarshal_BindBuffer(struct gl_context
*ctx
,
261 const struct marshal_cmd_BindBuffer
*cmd
)
263 const GLenum target
= cmd
->target
;
264 const GLuint buffer
= cmd
->buffer
;
265 CALL_BindBuffer(ctx
->CurrentServerDispatch
, (target
, buffer
));
268 _mesa_marshal_BindBuffer(GLenum target
, GLuint buffer
)
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");
275 track_vbo_binding(ctx
, target
, buffer
);
277 if (cmd_size
<= MARSHAL_MAX_CMD_SIZE
) {
278 cmd
= _mesa_glthread_allocate_command(ctx
, DISPATCH_CMD_BindBuffer
,
280 cmd
->target
= target
;
281 cmd
->buffer
= buffer
;
282 _mesa_post_marshal_hook(ctx
);
284 _mesa_glthread_finish(ctx
);
285 CALL_BindBuffer(ctx
->CurrentServerDispatch
, (target
, buffer
));
289 /* BufferData: marshalled asynchronously */
290 struct marshal_cmd_BufferData
292 struct marshal_cmd_base cmd_base
;
296 bool data_null
; /* If set, no data follows for "data" */
297 /* Next size bytes are GLubyte data[size] */
301 _mesa_unmarshal_BufferData(struct gl_context
*ctx
,
302 const struct marshal_cmd_BufferData
*cmd
)
304 const GLenum target
= cmd
->target
;
305 const GLsizeiptr size
= cmd
->size
;
306 const GLenum usage
= cmd
->usage
;
312 data
= (const void *) (cmd
+ 1);
314 CALL_BufferData(ctx
->CurrentServerDispatch
, (target
, size
, data
, usage
));
318 _mesa_marshal_BufferData(GLenum target
, GLsizeiptr size
, const GLvoid
* data
,
321 GET_CURRENT_CONTEXT(ctx
);
323 sizeof(struct marshal_cmd_BufferData
) + (data
? size
: 0);
324 debug_print_marshal("BufferData");
326 if (unlikely(size
< 0)) {
327 _mesa_glthread_finish(ctx
);
328 _mesa_error(ctx
, GL_INVALID_VALUE
, "BufferData(size < 0)");
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
,
338 cmd
->target
= target
;
341 cmd
->data_null
= !data
;
343 char *variable_data
= (char *) (cmd
+ 1);
344 memcpy(variable_data
, data
, size
);
346 _mesa_post_marshal_hook(ctx
);
348 _mesa_glthread_finish(ctx
);
349 CALL_BufferData(ctx
->CurrentServerDispatch
,
350 (target
, size
, data
, usage
));
354 /* BufferSubData: marshalled asynchronously */
355 struct marshal_cmd_BufferSubData
357 struct marshal_cmd_base cmd_base
;
361 /* Next size bytes are GLubyte data[size] */
365 _mesa_unmarshal_BufferSubData(struct gl_context
*ctx
,
366 const struct marshal_cmd_BufferSubData
*cmd
)
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);
373 CALL_BufferSubData(ctx
->CurrentServerDispatch
,
374 (target
, offset
, size
, data
));
378 _mesa_marshal_BufferSubData(GLenum target
, GLintptr offset
, GLsizeiptr size
,
381 GET_CURRENT_CONTEXT(ctx
);
382 size_t cmd_size
= sizeof(struct marshal_cmd_BufferSubData
) + size
;
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)");
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
,
396 cmd
->target
= target
;
397 cmd
->offset
= offset
;
399 char *variable_data
= (char *) (cmd
+ 1);
400 memcpy(variable_data
, data
, size
);
401 _mesa_post_marshal_hook(ctx
);
403 _mesa_glthread_finish(ctx
);
404 CALL_BufferSubData(ctx
->CurrentServerDispatch
,
405 (target
, offset
, size
, data
));
409 /* NamedBufferData: marshalled asynchronously */
410 struct marshal_cmd_NamedBufferData
412 struct marshal_cmd_base cmd_base
;
416 bool data_null
; /* If set, no data follows for "data" */
417 /* Next size bytes are GLubyte data[size] */
421 _mesa_unmarshal_NamedBufferData(struct gl_context
*ctx
,
422 const struct marshal_cmd_NamedBufferData
*cmd
)
424 const GLuint name
= cmd
->name
;
425 const GLsizei size
= cmd
->size
;
426 const GLenum usage
= cmd
->usage
;
432 data
= (const void *) (cmd
+ 1);
434 CALL_NamedBufferData(ctx
->CurrentServerDispatch
,
435 (name
, size
, data
, usage
));
439 _mesa_marshal_NamedBufferData(GLuint buffer
, GLsizeiptr size
,
440 const GLvoid
* data
, GLenum usage
)
442 GET_CURRENT_CONTEXT(ctx
);
443 size_t cmd_size
= sizeof(struct marshal_cmd_NamedBufferData
) + (data
? size
: 0);
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)");
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
,
459 cmd
->data_null
= !data
;
461 char *variable_data
= (char *) (cmd
+ 1);
462 memcpy(variable_data
, data
, size
);
464 _mesa_post_marshal_hook(ctx
);
466 _mesa_glthread_finish(ctx
);
467 CALL_NamedBufferData(ctx
->CurrentServerDispatch
,
468 (buffer
, size
, data
, usage
));
472 /* NamedBufferSubData: marshalled asynchronously */
473 struct marshal_cmd_NamedBufferSubData
475 struct marshal_cmd_base cmd_base
;
479 /* Next size bytes are GLubyte data[size] */
483 _mesa_unmarshal_NamedBufferSubData(struct gl_context
*ctx
,
484 const struct marshal_cmd_NamedBufferSubData
*cmd
)
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);
491 CALL_NamedBufferSubData(ctx
->CurrentServerDispatch
,
492 (name
, offset
, size
, data
));
496 _mesa_marshal_NamedBufferSubData(GLuint buffer
, GLintptr offset
,
497 GLsizeiptr size
, const GLvoid
* data
)
499 GET_CURRENT_CONTEXT(ctx
);
500 size_t cmd_size
= sizeof(struct marshal_cmd_NamedBufferSubData
) + size
;
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)");
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
,
514 cmd
->offset
= offset
;
516 char *variable_data
= (char *) (cmd
+ 1);
517 memcpy(variable_data
, data
, size
);
518 _mesa_post_marshal_hook(ctx
);
520 _mesa_glthread_finish(ctx
);
521 CALL_NamedBufferSubData(ctx
->CurrentServerDispatch
,
522 (buffer
, offset
, size
, data
));
526 /* ClearBuffer* (all variants): marshalled asynchronously */
527 struct marshal_cmd_ClearBuffer
529 struct marshal_cmd_base cmd_base
;
535 _mesa_unmarshal_ClearBufferfv(struct gl_context
*ctx
,
536 const struct marshal_cmd_ClearBuffer
*cmd
)
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
;
543 CALL_ClearBufferfv(ctx
->CurrentServerDispatch
,
544 (buffer
, drawbuffer
, value
));
548 _mesa_unmarshal_ClearBufferiv(struct gl_context
*ctx
,
549 const struct marshal_cmd_ClearBuffer
*cmd
)
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
;
556 CALL_ClearBufferiv(ctx
->CurrentServerDispatch
,
557 (buffer
, drawbuffer
, value
));
561 _mesa_unmarshal_ClearBufferuiv(struct gl_context
*ctx
,
562 const struct marshal_cmd_ClearBuffer
*cmd
)
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
;
569 CALL_ClearBufferuiv(ctx
->CurrentServerDispatch
,
570 (buffer
, drawbuffer
, value
));
574 _mesa_unmarshal_ClearBufferfi(struct gl_context
*ctx
,
575 const struct marshal_cmd_ClearBuffer
*cmd
)
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);
583 CALL_ClearBufferfi(ctx
->CurrentServerDispatch
,
584 (buffer
, drawbuffer
, *depth
, *stencil
));
587 static inline size_t buffer_to_size(GLenum buffer
)
592 case GL_DEPTH_STENCIL
:
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
)
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
,
611 cmd
->buffer
= buffer
;
612 cmd
->drawbuffer
= drawbuffer
;
613 GLuint
*variable_data
= (GLuint
*) (cmd
+ 1);
615 COPY_4V(variable_data
, value
);
617 COPY_2V(variable_data
, value
);
619 *variable_data
= *value
;
621 _mesa_post_marshal_hook(ctx
);
629 _mesa_marshal_ClearBufferfv(GLenum buffer
, GLint drawbuffer
,
630 const GLfloat
*value
)
632 GET_CURRENT_CONTEXT(ctx
);
633 debug_print_marshal("ClearBufferfv");
635 if (!(buffer
== GL_DEPTH
|| buffer
== GL_COLOR
)) {
636 _mesa_glthread_finish(ctx
);
638 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
639 * of the OpenGL 4.5 spec states:
641 * "An INVALID_ENUM error is generated by ClearBufferfv and
642 * ClearNamedFramebufferfv if buffer is not COLOR or DEPTH."
644 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfv(buffer=%s)",
645 _mesa_enum_to_string(buffer
));
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
));
659 _mesa_marshal_ClearBufferiv(GLenum buffer
, GLint drawbuffer
,
662 GET_CURRENT_CONTEXT(ctx
);
663 debug_print_marshal("ClearBufferiv");
665 if (!(buffer
== GL_STENCIL
|| buffer
== GL_COLOR
)) {
666 _mesa_glthread_finish(ctx
);
668 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
669 * of the OpenGL 4.5 spec states:
671 * "An INVALID_ENUM error is generated by ClearBufferiv and
672 * ClearNamedFramebufferiv if buffer is not COLOR or STENCIL."
674 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferiv(buffer=%s)",
675 _mesa_enum_to_string(buffer
));
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
));
689 _mesa_marshal_ClearBufferuiv(GLenum buffer
, GLint drawbuffer
,
692 GET_CURRENT_CONTEXT(ctx
);
693 debug_print_marshal("ClearBufferuiv");
695 if (buffer
!= GL_COLOR
) {
696 _mesa_glthread_finish(ctx
);
698 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
699 * of the OpenGL 4.5 spec states:
701 * "An INVALID_ENUM error is generated by ClearBufferuiv and
702 * ClearNamedFramebufferuiv if buffer is not COLOR."
704 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferuiv(buffer=%s)",
705 _mesa_enum_to_string(buffer
));
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
));
718 _mesa_marshal_ClearBufferfi(GLenum buffer
, GLint drawbuffer
,
719 const GLfloat depth
, const GLint stencil
)
721 GET_CURRENT_CONTEXT(ctx
);
722 debug_print_marshal("ClearBufferfi");
724 if (buffer
!= GL_DEPTH_STENCIL
) {
725 _mesa_glthread_finish(ctx
);
727 /* Page 498 of the PDF, section '17.4.3.1 Clearing Individual Buffers'
728 * of the OpenGL 4.5 spec states:
730 * "An INVALID_ENUM error is generated by ClearBufferfi and
731 * ClearNamedFramebufferfi if buffer is not DEPTH_STENCIL."
733 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClearBufferfi(buffer=%s)",
734 _mesa_enum_to_string(buffer
));
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
));