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