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