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