buffers.c revision 01e04c3f
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26/** 27 * \file buffers.c 28 * glReadBuffer, DrawBuffer functions. 29 */ 30 31 32 33#include "glheader.h" 34#include "buffers.h" 35#include "context.h" 36#include "enums.h" 37#include "fbobject.h" 38#include "mtypes.h" 39#include "util/bitscan.h" 40#include "util/u_math.h" 41 42 43#define BAD_MASK ~0u 44 45 46/** 47 * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are 48 * available to the rendering context (for drawing or reading). 49 * This depends on the type of framebuffer. For window system framebuffers 50 * we look at the framebuffer's visual. But for user-create framebuffers we 51 * look at the number of supported color attachments. 52 * \param fb the framebuffer to draw to, or read from 53 * \return bitmask of BUFFER_BIT_* flags 54 */ 55static GLbitfield 56supported_buffer_bitmask(const struct gl_context *ctx, 57 const struct gl_framebuffer *fb) 58{ 59 GLbitfield mask = 0x0; 60 61 if (_mesa_is_user_fbo(fb)) { 62 /* A user-created renderbuffer */ 63 mask = ((1 << ctx->Const.MaxColorAttachments) - 1) << BUFFER_COLOR0; 64 } 65 else { 66 /* A window system framebuffer */ 67 GLint i; 68 mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ 69 if (fb->Visual.stereoMode) { 70 mask |= BUFFER_BIT_FRONT_RIGHT; 71 if (fb->Visual.doubleBufferMode) { 72 mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 73 } 74 } 75 else if (fb->Visual.doubleBufferMode) { 76 mask |= BUFFER_BIT_BACK_LEFT; 77 } 78 79 for (i = 0; i < fb->Visual.numAuxBuffers; i++) { 80 mask |= (BUFFER_BIT_AUX0 << i); 81 } 82 } 83 84 return mask; 85} 86 87 88/** 89 * Helper routine used by glDrawBuffer and glDrawBuffersARB. 90 * Given a GLenum naming one or more color buffers (such as 91 * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. 92 */ 93static GLbitfield 94draw_buffer_enum_to_bitmask(const struct gl_context *ctx, GLenum buffer) 95{ 96 switch (buffer) { 97 case GL_NONE: 98 return 0; 99 case GL_FRONT: 100 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; 101 case GL_BACK: 102 if (_mesa_is_gles(ctx)) { 103 /* Page 181 (page 192 of the PDF) in section 4.2.1 of the OpenGL 104 * ES 3.0.1 specification says: 105 * 106 * "When draw buffer zero is BACK, color values are written 107 * into the sole buffer for single-buffered contexts, or into 108 * the back buffer for double-buffered contexts." 109 * 110 * Since there is no stereo rendering in ES 3.0, only return the 111 * LEFT bits. This also satisfies the "n must be 1" requirement. 112 * 113 * We also do this for GLES 1 and 2 because those APIs have no 114 * concept of selecting the front and back buffer anyway and it's 115 * convenient to be able to maintain the magic behaviour of 116 * GL_BACK in that case. 117 */ 118 if (ctx->DrawBuffer->Visual.doubleBufferMode) 119 return BUFFER_BIT_BACK_LEFT; 120 return BUFFER_BIT_FRONT_LEFT; 121 } 122 return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; 123 case GL_RIGHT: 124 return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 125 case GL_FRONT_RIGHT: 126 return BUFFER_BIT_FRONT_RIGHT; 127 case GL_BACK_RIGHT: 128 return BUFFER_BIT_BACK_RIGHT; 129 case GL_BACK_LEFT: 130 return BUFFER_BIT_BACK_LEFT; 131 case GL_FRONT_AND_BACK: 132 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT 133 | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; 134 case GL_LEFT: 135 return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; 136 case GL_FRONT_LEFT: 137 return BUFFER_BIT_FRONT_LEFT; 138 case GL_AUX0: 139 return BUFFER_BIT_AUX0; 140 case GL_AUX1: 141 case GL_AUX2: 142 case GL_AUX3: 143 return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */ 144 case GL_COLOR_ATTACHMENT0_EXT: 145 return BUFFER_BIT_COLOR0; 146 case GL_COLOR_ATTACHMENT1_EXT: 147 return BUFFER_BIT_COLOR1; 148 case GL_COLOR_ATTACHMENT2_EXT: 149 return BUFFER_BIT_COLOR2; 150 case GL_COLOR_ATTACHMENT3_EXT: 151 return BUFFER_BIT_COLOR3; 152 case GL_COLOR_ATTACHMENT4_EXT: 153 return BUFFER_BIT_COLOR4; 154 case GL_COLOR_ATTACHMENT5_EXT: 155 return BUFFER_BIT_COLOR5; 156 case GL_COLOR_ATTACHMENT6_EXT: 157 return BUFFER_BIT_COLOR6; 158 case GL_COLOR_ATTACHMENT7_EXT: 159 return BUFFER_BIT_COLOR7; 160 default: 161 /* not an error, but also not supported */ 162 if (buffer >= GL_COLOR_ATTACHMENT8 && buffer <= GL_COLOR_ATTACHMENT31) 163 return 1 << BUFFER_COUNT; 164 /* error */ 165 return BAD_MASK; 166 } 167} 168 169 170/** 171 * Helper routine used by glReadBuffer. 172 * Given a GLenum naming a color buffer, return the index of the corresponding 173 * renderbuffer (a BUFFER_* value). 174 * return BUFFER_NONE for an invalid buffer. 175 */ 176static gl_buffer_index 177read_buffer_enum_to_index(const struct gl_context *ctx, GLenum buffer) 178{ 179 switch (buffer) { 180 case GL_FRONT: 181 return BUFFER_FRONT_LEFT; 182 case GL_BACK: 183 if (_mesa_is_gles(ctx)) { 184 /* In draw_buffer_enum_to_bitmask, when GLES contexts draw to 185 * GL_BACK with a single-buffered configuration, we actually end 186 * up drawing to the sole front buffer in our internal 187 * representation. For consistency, we must read from that 188 * front left buffer too. 189 */ 190 if (!ctx->DrawBuffer->Visual.doubleBufferMode) 191 return BUFFER_FRONT_LEFT; 192 } 193 return BUFFER_BACK_LEFT; 194 case GL_RIGHT: 195 return BUFFER_FRONT_RIGHT; 196 case GL_FRONT_RIGHT: 197 return BUFFER_FRONT_RIGHT; 198 case GL_BACK_RIGHT: 199 return BUFFER_BACK_RIGHT; 200 case GL_BACK_LEFT: 201 return BUFFER_BACK_LEFT; 202 case GL_LEFT: 203 return BUFFER_FRONT_LEFT; 204 case GL_FRONT_LEFT: 205 return BUFFER_FRONT_LEFT; 206 case GL_AUX0: 207 return BUFFER_AUX0; 208 case GL_FRONT_AND_BACK: 209 return BUFFER_FRONT_LEFT; 210 case GL_AUX1: 211 case GL_AUX2: 212 case GL_AUX3: 213 return BUFFER_COUNT; /* invalid, but not -1 */ 214 case GL_COLOR_ATTACHMENT0_EXT: 215 return BUFFER_COLOR0; 216 case GL_COLOR_ATTACHMENT1_EXT: 217 return BUFFER_COLOR1; 218 case GL_COLOR_ATTACHMENT2_EXT: 219 return BUFFER_COLOR2; 220 case GL_COLOR_ATTACHMENT3_EXT: 221 return BUFFER_COLOR3; 222 case GL_COLOR_ATTACHMENT4_EXT: 223 return BUFFER_COLOR4; 224 case GL_COLOR_ATTACHMENT5_EXT: 225 return BUFFER_COLOR5; 226 case GL_COLOR_ATTACHMENT6_EXT: 227 return BUFFER_COLOR6; 228 case GL_COLOR_ATTACHMENT7_EXT: 229 return BUFFER_COLOR7; 230 default: 231 /* not an error, but also not supported */ 232 if (buffer >= GL_COLOR_ATTACHMENT8 && buffer <= GL_COLOR_ATTACHMENT31) 233 return BUFFER_COUNT; 234 /* error */ 235 return BUFFER_NONE; 236 } 237} 238 239static bool 240is_legal_es3_readbuffer_enum(GLenum buf) 241{ 242 return buf == GL_BACK || buf == GL_NONE || 243 (buf >= GL_COLOR_ATTACHMENT0 && buf <= GL_COLOR_ATTACHMENT31); 244} 245 246/** 247 * Called by glDrawBuffer() and glNamedFramebufferDrawBuffer(). 248 * Specify which renderbuffer(s) to draw into for the first color output. 249 * <buffer> can name zero, one, two or four renderbuffers! 250 * \sa _mesa_DrawBuffers 251 * 252 * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc. 253 * 254 * Note that the behaviour of this function depends on whether the 255 * current ctx->DrawBuffer is a window-system framebuffer or a user-created 256 * framebuffer object. 257 * In the former case, we update the per-context ctx->Color.DrawBuffer 258 * state var _and_ the FB's ColorDrawBuffer state. 259 * In the later case, we update the FB's ColorDrawBuffer state only. 260 * 261 * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the 262 * new FB is a window system FB, we need to re-update the FB's 263 * ColorDrawBuffer state to match the context. This is handled in 264 * _mesa_update_framebuffer(). 265 * 266 * See the GL_EXT_framebuffer_object spec for more info. 267 */ 268static ALWAYS_INLINE void 269draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, 270 GLenum buffer, const char *caller, bool no_error) 271{ 272 GLbitfield destMask; 273 274 FLUSH_VERTICES(ctx, 0); 275 276 if (MESA_VERBOSE & VERBOSE_API) { 277 _mesa_debug(ctx, "%s %s\n", caller, _mesa_enum_to_string(buffer)); 278 } 279 280 if (buffer == GL_NONE) { 281 destMask = 0x0; 282 } 283 else { 284 const GLbitfield supportedMask 285 = supported_buffer_bitmask(ctx, fb); 286 destMask = draw_buffer_enum_to_bitmask(ctx, buffer); 287 if (!no_error && destMask == BAD_MASK) { 288 /* totally bogus buffer */ 289 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", caller, 290 _mesa_enum_to_string(buffer)); 291 return; 292 } 293 destMask &= supportedMask; 294 if (!no_error && destMask == 0x0) { 295 /* none of the named color buffers exist! */ 296 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffer %s)", 297 caller, _mesa_enum_to_string(buffer)); 298 return; 299 } 300 } 301 302 /* if we get here, there's no error so set new state */ 303 const GLenum16 buffer16 = buffer; 304 _mesa_drawbuffers(ctx, fb, 1, &buffer16, &destMask); 305 306 /* Call device driver function only if fb is the bound draw buffer */ 307 if (fb == ctx->DrawBuffer) { 308 if (ctx->Driver.DrawBuffer) 309 ctx->Driver.DrawBuffer(ctx); 310 if (ctx->Driver.DrawBufferAllocate) 311 ctx->Driver.DrawBufferAllocate(ctx); 312 } 313} 314 315 316static void 317draw_buffer_error(struct gl_context *ctx, struct gl_framebuffer *fb, 318 GLenum buffer, const char *caller) 319{ 320 draw_buffer(ctx, fb, buffer, caller, false); 321} 322 323 324static void 325draw_buffer_no_error(struct gl_context *ctx, struct gl_framebuffer *fb, 326 GLenum buffer, const char *caller) 327{ 328 draw_buffer(ctx, fb, buffer, caller, true); 329} 330 331 332void GLAPIENTRY 333_mesa_DrawBuffer_no_error(GLenum buffer) 334{ 335 GET_CURRENT_CONTEXT(ctx); 336 draw_buffer_no_error(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer"); 337} 338 339 340void GLAPIENTRY 341_mesa_DrawBuffer(GLenum buffer) 342{ 343 GET_CURRENT_CONTEXT(ctx); 344 draw_buffer_error(ctx, ctx->DrawBuffer, buffer, "glDrawBuffer"); 345} 346 347 348void GLAPIENTRY 349_mesa_NamedFramebufferDrawBuffer_no_error(GLuint framebuffer, GLenum buf) 350{ 351 GET_CURRENT_CONTEXT(ctx); 352 struct gl_framebuffer *fb; 353 354 if (framebuffer) { 355 fb = _mesa_lookup_framebuffer(ctx, framebuffer); 356 } else { 357 fb = ctx->WinSysDrawBuffer; 358 } 359 360 draw_buffer_no_error(ctx, fb, buf, "glNamedFramebufferDrawBuffer"); 361} 362 363 364void GLAPIENTRY 365_mesa_NamedFramebufferDrawBuffer(GLuint framebuffer, GLenum buf) 366{ 367 GET_CURRENT_CONTEXT(ctx); 368 struct gl_framebuffer *fb; 369 370 if (framebuffer) { 371 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, 372 "glNamedFramebufferDrawBuffer"); 373 if (!fb) 374 return; 375 } 376 else 377 fb = ctx->WinSysDrawBuffer; 378 379 draw_buffer_error(ctx, fb, buf, "glNamedFramebufferDrawBuffer"); 380} 381 382 383/** 384 * Called by glDrawBuffersARB() and glNamedFramebufferDrawBuffers() to specify 385 * the destination color renderbuffers for N fragment program color outputs. 386 * \sa _mesa_DrawBuffer 387 * \param n number of outputs 388 * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the 389 * names cannot specify more than one buffer. For example, 390 * GL_FRONT_AND_BACK is illegal. The only exception is GL_BACK 391 * that is considered special and allowed as far as n is one 392 * since 4.5. 393 */ 394static ALWAYS_INLINE void 395draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, GLsizei n, 396 const GLenum *buffers, const char *caller, bool no_error) 397{ 398 GLuint output; 399 GLbitfield usedBufferMask, supportedMask; 400 GLbitfield destMask[MAX_DRAW_BUFFERS]; 401 402 FLUSH_VERTICES(ctx, 0); 403 404 if (!no_error) { 405 /* Turns out n==0 is a valid input that should not produce an error. 406 * The remaining code below correctly handles the n==0 case. 407 * 408 * From the OpenGL 3.0 specification, page 258: 409 * "An INVALID_VALUE error is generated if n is greater than 410 * MAX_DRAW_BUFFERS." 411 */ 412 if (n < 0) { 413 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller); 414 return; 415 } 416 417 if (n > (GLsizei) ctx->Const.MaxDrawBuffers) { 418 _mesa_error(ctx, GL_INVALID_VALUE, 419 "%s(n > maximum number of draw buffers)", caller); 420 return; 421 } 422 423 /* From the ES 3.0 specification, page 180: 424 * "If the GL is bound to the default framebuffer, then n must be 1 425 * and the constant must be BACK or NONE." 426 * (same restriction applies with GL_EXT_draw_buffers specification) 427 */ 428 if (ctx->API == API_OPENGLES2 && _mesa_is_winsys_fbo(fb) && 429 (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) { 430 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffers)", caller); 431 return; 432 } 433 } 434 435 supportedMask = supported_buffer_bitmask(ctx, fb); 436 usedBufferMask = 0x0; 437 438 /* complicated error checking... */ 439 for (output = 0; output < n; output++) { 440 destMask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]); 441 442 if (!no_error) { 443 /* From the OpenGL 3.0 specification, page 258: 444 * "Each buffer listed in bufs must be one of the values from tables 445 * 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated. 446 */ 447 if (destMask[output] == BAD_MASK) { 448 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", 449 caller, _mesa_enum_to_string(buffers[output])); 450 return; 451 } 452 453 /* From the OpenGL 4.5 specification, page 493 (page 515 of the PDF) 454 * "An INVALID_ENUM error is generated if any value in bufs is FRONT, 455 * LEFT, RIGHT, or FRONT_AND_BACK . This restriction applies to both 456 * the default framebuffer and framebuffer objects, and exists because 457 * these constants may themselves refer to multiple buffers, as shown 458 * in table 17.4." 459 * 460 * And on page 492 (page 514 of the PDF): 461 * "If the default framebuffer is affected, then each of the constants 462 * must be one of the values listed in table 17.6 or the special value 463 * BACK. When BACK is used, n must be 1 and color values are written 464 * into the left buffer for single-buffered contexts, or into the back 465 * left buffer for double-buffered contexts." 466 * 467 * Note "special value BACK". GL_BACK also refers to multiple buffers, 468 * but it is consider a special case here. This is a change on 4.5. 469 * For OpenGL 4.x we check that behaviour. For any previous version we 470 * keep considering it wrong (as INVALID_ENUM). 471 */ 472 if (util_bitcount(destMask[output]) > 1) { 473 if (_mesa_is_winsys_fbo(fb) && ctx->Version >= 40 && 474 buffers[output] == GL_BACK) { 475 if (n != 1) { 476 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(with GL_BACK n must be 1)", 477 caller); 478 return; 479 } 480 } else { 481 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid buffer %s)", 482 caller, _mesa_enum_to_string(buffers[output])); 483 return; 484 } 485 } 486 487 /* Section 4.2 (Whole Framebuffer Operations) of the OpenGL ES 3.0 488 * specification says: 489 * 490 * "If the GL is bound to a draw framebuffer object, the ith 491 * buffer listed in bufs must be COLOR_ATTACHMENTi or NONE . 492 * Specifying a buffer out of order, BACK , or COLOR_ATTACHMENTm 493 * where m is greater than or equal to the value of MAX_- 494 * COLOR_ATTACHMENTS , will generate the error INVALID_OPERATION . 495 */ 496 if (_mesa_is_gles3(ctx) && _mesa_is_user_fbo(fb) && 497 buffers[output] != GL_NONE && 498 (buffers[output] < GL_COLOR_ATTACHMENT0 || 499 buffers[output] >= GL_COLOR_ATTACHMENT0 + ctx->Const.MaxColorAttachments)) { 500 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); 501 return; 502 } 503 } 504 505 if (buffers[output] == GL_NONE) { 506 destMask[output] = 0x0; 507 } 508 else { 509 /* Page 259 (page 275 of the PDF) in section 4.2.1 of the OpenGL 3.0 510 * spec (20080923) says: 511 * 512 * "If the GL is bound to a framebuffer object and DrawBuffers is 513 * supplied with [...] COLOR_ATTACHMENTm where m is greater than 514 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error 515 * INVALID_OPERATION results." 516 */ 517 if (!no_error && _mesa_is_user_fbo(fb) && buffers[output] >= 518 GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) { 519 _mesa_error(ctx, GL_INVALID_OPERATION, 520 "%s(buffers[%d] >= maximum number of draw buffers)", 521 caller, output); 522 return; 523 } 524 525 /* From the OpenGL 3.0 specification, page 259: 526 * "If the GL is bound to the default framebuffer and DrawBuffers is 527 * supplied with a constant (other than NONE) that does not indicate 528 * any of the color buffers allocated to the GL context by the window 529 * system, the error INVALID_OPERATION will be generated. 530 * 531 * If the GL is bound to a framebuffer object and DrawBuffers is 532 * supplied with a constant from table 4.6 [...] then the error 533 * INVALID_OPERATION results." 534 */ 535 destMask[output] &= supportedMask; 536 if (!no_error) { 537 if (destMask[output] == 0) { 538 _mesa_error(ctx, GL_INVALID_OPERATION, 539 "%s(unsupported buffer %s)", 540 caller, _mesa_enum_to_string(buffers[output])); 541 return; 542 } 543 544 /* ES 3.0 is even more restrictive. From the ES 3.0 spec, page 180: 545 * "If the GL is bound to a framebuffer object, the ith buffer 546 * listed in bufs must be COLOR_ATTACHMENTi or NONE. [...] 547 * INVALID_OPERATION." (same restriction applies with 548 * GL_EXT_draw_buffers specification) 549 */ 550 if (ctx->API == API_OPENGLES2 && _mesa_is_user_fbo(fb) && 551 buffers[output] != GL_NONE && 552 buffers[output] != GL_COLOR_ATTACHMENT0 + output) { 553 _mesa_error(ctx, GL_INVALID_OPERATION, 554 "%s(unsupported buffer %s)", 555 caller, _mesa_enum_to_string(buffers[output])); 556 return; 557 } 558 559 /* From the OpenGL 3.0 specification, page 258: 560 * "Except for NONE, a buffer may not appear more than once in the 561 * array pointed to by bufs. Specifying a buffer more then once 562 * will result in the error INVALID_OPERATION." 563 */ 564 if (destMask[output] & usedBufferMask) { 565 _mesa_error(ctx, GL_INVALID_OPERATION, 566 "%s(duplicated buffer %s)", 567 caller, _mesa_enum_to_string(buffers[output])); 568 return; 569 } 570 } 571 572 /* update bitmask */ 573 usedBufferMask |= destMask[output]; 574 } 575 } 576 577 /* OK, if we get here, there were no errors so set the new state */ 578 GLenum16 buffers16[MAX_DRAW_BUFFERS]; 579 for (int i = 0; i < n; i++) 580 buffers16[i] = buffers[i]; 581 582 _mesa_drawbuffers(ctx, fb, n, buffers16, destMask); 583 584 /* 585 * Call device driver function if fb is the bound draw buffer. 586 * Note that n can be equal to 0, 587 * in which case we don't want to reference buffers[0], which 588 * may not be valid. 589 */ 590 if (fb == ctx->DrawBuffer) { 591 if (ctx->Driver.DrawBuffer) 592 ctx->Driver.DrawBuffer(ctx); 593 if (ctx->Driver.DrawBufferAllocate) 594 ctx->Driver.DrawBufferAllocate(ctx); 595 } 596} 597 598 599static void 600draw_buffers_error(struct gl_context *ctx, struct gl_framebuffer *fb, GLsizei n, 601 const GLenum *buffers, const char *caller) 602{ 603 draw_buffers(ctx, fb, n, buffers, caller, false); 604} 605 606 607static void 608draw_buffers_no_error(struct gl_context *ctx, struct gl_framebuffer *fb, 609 GLsizei n, const GLenum *buffers, const char *caller) 610{ 611 draw_buffers(ctx, fb, n, buffers, caller, true); 612} 613 614 615void GLAPIENTRY 616_mesa_DrawBuffers_no_error(GLsizei n, const GLenum *buffers) 617{ 618 GET_CURRENT_CONTEXT(ctx); 619 draw_buffers_no_error(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers"); 620} 621 622 623void GLAPIENTRY 624_mesa_DrawBuffers(GLsizei n, const GLenum *buffers) 625{ 626 GET_CURRENT_CONTEXT(ctx); 627 draw_buffers_error(ctx, ctx->DrawBuffer, n, buffers, "glDrawBuffers"); 628} 629 630 631void GLAPIENTRY 632_mesa_NamedFramebufferDrawBuffers_no_error(GLuint framebuffer, GLsizei n, 633 const GLenum *bufs) 634{ 635 GET_CURRENT_CONTEXT(ctx); 636 struct gl_framebuffer *fb; 637 638 if (framebuffer) { 639 fb = _mesa_lookup_framebuffer(ctx, framebuffer); 640 } else { 641 fb = ctx->WinSysDrawBuffer; 642 } 643 644 draw_buffers_no_error(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers"); 645} 646 647 648void GLAPIENTRY 649_mesa_NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n, 650 const GLenum *bufs) 651{ 652 GET_CURRENT_CONTEXT(ctx); 653 struct gl_framebuffer *fb; 654 655 if (framebuffer) { 656 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, 657 "glNamedFramebufferDrawBuffers"); 658 if (!fb) 659 return; 660 } 661 else 662 fb = ctx->WinSysDrawBuffer; 663 664 draw_buffers_error(ctx, fb, n, bufs, "glNamedFramebufferDrawBuffers"); 665} 666 667 668/** 669 * Performs necessary state updates when _mesa_drawbuffers makes an 670 * actual change. 671 */ 672static void 673updated_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb) 674{ 675 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 676 677 if (ctx->API == API_OPENGL_COMPAT && !ctx->Extensions.ARB_ES2_compatibility) { 678 /* Flag the FBO as requiring validation. */ 679 if (_mesa_is_user_fbo(fb)) { 680 fb->_Status = 0; 681 } 682 } 683} 684 685 686/** 687 * Helper function to set the GL_DRAW_BUFFER state for the given context and 688 * FBO. Called via glDrawBuffer(), glDrawBuffersARB() 689 * 690 * All error checking will have been done prior to calling this function 691 * so nothing should go wrong at this point. 692 * 693 * \param ctx current context 694 * \param fb the desired draw buffer 695 * \param n number of color outputs to set 696 * \param buffers array[n] of colorbuffer names, like GL_LEFT. 697 * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the 698 * colorbuffer names. (i.e. GL_FRONT_AND_BACK => 699 * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). 700 */ 701void 702_mesa_drawbuffers(struct gl_context *ctx, struct gl_framebuffer *fb, 703 GLuint n, const GLenum16 *buffers, 704 const GLbitfield *destMask) 705{ 706 GLbitfield mask[MAX_DRAW_BUFFERS]; 707 GLuint buf; 708 709 if (!destMask) { 710 /* compute destMask values now */ 711 const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb); 712 GLuint output; 713 for (output = 0; output < n; output++) { 714 mask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]); 715 assert(mask[output] != BAD_MASK); 716 mask[output] &= supportedMask; 717 } 718 destMask = mask; 719 } 720 721 /* 722 * destMask[0] may have up to four bits set 723 * (ex: glDrawBuffer(GL_FRONT_AND_BACK)). 724 * Otherwise, destMask[x] can only have one bit set. 725 */ 726 if (n > 0 && util_bitcount(destMask[0]) > 1) { 727 GLuint count = 0, destMask0 = destMask[0]; 728 while (destMask0) { 729 const gl_buffer_index bufIndex = u_bit_scan(&destMask0); 730 if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { 731 updated_drawbuffers(ctx, fb); 732 fb->_ColorDrawBufferIndexes[count] = bufIndex; 733 } 734 count++; 735 } 736 fb->ColorDrawBuffer[0] = buffers[0]; 737 fb->_NumColorDrawBuffers = count; 738 } 739 else { 740 GLuint count = 0; 741 for (buf = 0; buf < n; buf++ ) { 742 if (destMask[buf]) { 743 gl_buffer_index bufIndex = ffs(destMask[buf]) - 1; 744 /* only one bit should be set in the destMask[buf] field */ 745 assert(util_bitcount(destMask[buf]) == 1); 746 if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { 747 updated_drawbuffers(ctx, fb); 748 fb->_ColorDrawBufferIndexes[buf] = bufIndex; 749 } 750 count = buf + 1; 751 } 752 else { 753 if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) { 754 updated_drawbuffers(ctx, fb); 755 fb->_ColorDrawBufferIndexes[buf] = BUFFER_NONE; 756 } 757 } 758 fb->ColorDrawBuffer[buf] = buffers[buf]; 759 } 760 fb->_NumColorDrawBuffers = count; 761 } 762 763 /* set remaining outputs to BUFFER_NONE */ 764 for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) { 765 if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) { 766 updated_drawbuffers(ctx, fb); 767 fb->_ColorDrawBufferIndexes[buf] = BUFFER_NONE; 768 } 769 } 770 for (buf = n; buf < ctx->Const.MaxDrawBuffers; buf++) { 771 fb->ColorDrawBuffer[buf] = GL_NONE; 772 } 773 774 if (_mesa_is_winsys_fbo(fb)) { 775 /* also set context drawbuffer state */ 776 for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { 777 if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { 778 updated_drawbuffers(ctx, fb); 779 ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; 780 } 781 } 782 } 783} 784 785 786/** 787 * Update the current drawbuffer's _ColorDrawBufferIndex[] list, etc. 788 * from the context's Color.DrawBuffer[] state. 789 * Use when changing contexts. 790 */ 791void 792_mesa_update_draw_buffers(struct gl_context *ctx) 793{ 794 /* should be a window system FBO */ 795 assert(_mesa_is_winsys_fbo(ctx->DrawBuffer)); 796 797 _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers, 798 ctx->Color.DrawBuffer, NULL); 799} 800 801 802/** 803 * Like \sa _mesa_drawbuffers(), this is a helper function for setting 804 * GL_READ_BUFFER state for the given context and FBO. 805 * Note that all error checking should have been done before calling 806 * this function. 807 * \param ctx the rendering context 808 * \param fb the framebuffer object to update 809 * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc. 810 * \param bufferIndex the numerical index corresponding to 'buffer' 811 */ 812void 813_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 814 GLenum buffer, gl_buffer_index bufferIndex) 815{ 816 if ((fb == ctx->ReadBuffer) && _mesa_is_winsys_fbo(fb)) { 817 /* Only update the per-context READ_BUFFER state if we're bound to 818 * a window-system framebuffer. 819 */ 820 ctx->Pixel.ReadBuffer = buffer; 821 } 822 823 fb->ColorReadBuffer = buffer; 824 fb->_ColorReadBufferIndex = bufferIndex; 825 826 ctx->NewState |= _NEW_BUFFERS; 827} 828 829 830 831/** 832 * Called by glReadBuffer and glNamedFramebufferReadBuffer to set the source 833 * renderbuffer for reading pixels. 834 * \param mode color buffer such as GL_FRONT, GL_BACK, etc. 835 */ 836static ALWAYS_INLINE void 837read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, 838 GLenum buffer, const char *caller, bool no_error) 839{ 840 gl_buffer_index srcBuffer; 841 842 FLUSH_VERTICES(ctx, 0); 843 844 if (MESA_VERBOSE & VERBOSE_API) 845 _mesa_debug(ctx, "%s %s\n", caller, _mesa_enum_to_string(buffer)); 846 847 if (buffer == GL_NONE) { 848 /* This is legal--it means that no buffer should be bound for reading. */ 849 srcBuffer = BUFFER_NONE; 850 } 851 else { 852 /* general case / window-system framebuffer */ 853 if (!no_error &&_mesa_is_gles3(ctx) && 854 !is_legal_es3_readbuffer_enum(buffer)) 855 srcBuffer = BUFFER_NONE; 856 else 857 srcBuffer = read_buffer_enum_to_index(ctx, buffer); 858 859 if (!no_error) { 860 GLbitfield supportedMask; 861 862 if (srcBuffer == BUFFER_NONE) { 863 _mesa_error(ctx, GL_INVALID_ENUM, 864 "%s(invalid buffer %s)", caller, 865 _mesa_enum_to_string(buffer)); 866 return; 867 } 868 869 supportedMask = supported_buffer_bitmask(ctx, fb); 870 if (((1 << srcBuffer) & supportedMask) == 0) { 871 _mesa_error(ctx, GL_INVALID_OPERATION, 872 "%s(invalid buffer %s)", caller, 873 _mesa_enum_to_string(buffer)); 874 return; 875 } 876 } 877 } 878 879 /* OK, all error checking has been completed now */ 880 881 _mesa_readbuffer(ctx, fb, buffer, srcBuffer); 882 883 /* Call the device driver function only if fb is the bound read buffer */ 884 if (fb == ctx->ReadBuffer) { 885 if (ctx->Driver.ReadBuffer) 886 ctx->Driver.ReadBuffer(ctx, buffer); 887 } 888} 889 890 891static void 892read_buffer_err(struct gl_context *ctx, struct gl_framebuffer *fb, 893 GLenum buffer, const char *caller) 894{ 895 read_buffer(ctx, fb, buffer, caller, false); 896} 897 898 899static void 900read_buffer_no_error(struct gl_context *ctx, struct gl_framebuffer *fb, 901 GLenum buffer, const char *caller) 902{ 903 read_buffer(ctx, fb, buffer, caller, true); 904} 905 906 907void GLAPIENTRY 908_mesa_ReadBuffer_no_error(GLenum buffer) 909{ 910 GET_CURRENT_CONTEXT(ctx); 911 read_buffer_no_error(ctx, ctx->ReadBuffer, buffer, "glReadBuffer"); 912} 913 914 915void GLAPIENTRY 916_mesa_ReadBuffer(GLenum buffer) 917{ 918 GET_CURRENT_CONTEXT(ctx); 919 read_buffer_err(ctx, ctx->ReadBuffer, buffer, "glReadBuffer"); 920} 921 922 923void GLAPIENTRY 924_mesa_NamedFramebufferReadBuffer_no_error(GLuint framebuffer, GLenum src) 925{ 926 GET_CURRENT_CONTEXT(ctx); 927 928 struct gl_framebuffer *fb; 929 930 if (framebuffer) { 931 fb = _mesa_lookup_framebuffer(ctx, framebuffer); 932 } else { 933 fb = ctx->WinSysReadBuffer; 934 } 935 936 read_buffer_no_error(ctx, fb, src, "glNamedFramebufferReadBuffer"); 937} 938 939 940void GLAPIENTRY 941_mesa_NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src) 942{ 943 GET_CURRENT_CONTEXT(ctx); 944 struct gl_framebuffer *fb; 945 946 if (framebuffer) { 947 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, 948 "glNamedFramebufferReadBuffer"); 949 if (!fb) 950 return; 951 } 952 else 953 fb = ctx->WinSysReadBuffer; 954 955 read_buffer_err(ctx, fb, src, "glNamedFramebufferReadBuffer"); 956} 957