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