1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27 /* 28 * GL_EXT/ARB_framebuffer_object extensions 29 * 30 * Authors: 31 * Brian Paul 32 */ 33 34 35 #include "buffers.h" 36 #include "context.h" 37 #include "enums.h" 38 #include "fbobject.h" 39 #include "formats.h" 40 #include "framebuffer.h" 41 #include "glformats.h" 42 #include "hash.h" 43 #include "macros.h" 44 #include "mfeatures.h" 45 #include "mtypes.h" 46 #include "renderbuffer.h" 47 #include "state.h" 48 #include "teximage.h" 49 #include "texobj.h" 50 51 52 /** Set this to 1 to debug/log glBlitFramebuffer() calls */ 53 #define DEBUG_BLIT 0 54 55 56 /** 57 * Notes: 58 * 59 * None of the GL_EXT_framebuffer_object functions are compiled into 60 * display lists. 61 */ 62 63 64 65 /* 66 * When glGenRender/FramebuffersEXT() is called we insert pointers to 67 * these placeholder objects into the hash table. 68 * Later, when the object ID is first bound, we replace the placeholder 69 * with the real frame/renderbuffer. 70 */ 71 static struct gl_framebuffer DummyFramebuffer; 72 static struct gl_renderbuffer DummyRenderbuffer; 73 74 /* We bind this framebuffer when applications pass a NULL 75 * drawable/surface in make current. */ 76 static struct gl_framebuffer IncompleteFramebuffer; 77 78 79 static void 80 delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 81 { 82 /* no op */ 83 } 84 85 static void 86 delete_dummy_framebuffer(struct gl_framebuffer *fb) 87 { 88 /* no op */ 89 } 90 91 92 void 93 _mesa_init_fbobjects(struct gl_context *ctx) 94 { 95 _glthread_INIT_MUTEX(DummyFramebuffer.Mutex); 96 _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex); 97 _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex); 98 DummyFramebuffer.Delete = delete_dummy_framebuffer; 99 DummyRenderbuffer.Delete = delete_dummy_renderbuffer; 100 IncompleteFramebuffer.Delete = delete_dummy_framebuffer; 101 } 102 103 struct gl_framebuffer * 104 _mesa_get_incomplete_framebuffer(void) 105 { 106 return &IncompleteFramebuffer; 107 } 108 109 /** 110 * Helper routine for getting a gl_renderbuffer. 111 */ 112 struct gl_renderbuffer * 113 _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id) 114 { 115 struct gl_renderbuffer *rb; 116 117 if (id == 0) 118 return NULL; 119 120 rb = (struct gl_renderbuffer *) 121 _mesa_HashLookup(ctx->Shared->RenderBuffers, id); 122 return rb; 123 } 124 125 126 /** 127 * Helper routine for getting a gl_framebuffer. 128 */ 129 struct gl_framebuffer * 130 _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id) 131 { 132 struct gl_framebuffer *fb; 133 134 if (id == 0) 135 return NULL; 136 137 fb = (struct gl_framebuffer *) 138 _mesa_HashLookup(ctx->Shared->FrameBuffers, id); 139 return fb; 140 } 141 142 143 /** 144 * Mark the given framebuffer as invalid. This will force the 145 * test for framebuffer completeness to be done before the framebuffer 146 * is used. 147 */ 148 static void 149 invalidate_framebuffer(struct gl_framebuffer *fb) 150 { 151 fb->_Status = 0; /* "indeterminate" */ 152 } 153 154 155 /** 156 * Return the gl_framebuffer object which corresponds to the given 157 * framebuffer target, such as GL_DRAW_FRAMEBUFFER. 158 * Check support for GL_EXT_framebuffer_blit to determine if certain 159 * targets are legal. 160 * \return gl_framebuffer pointer or NULL if target is illegal 161 */ 162 static struct gl_framebuffer * 163 get_framebuffer_target(struct gl_context *ctx, GLenum target) 164 { 165 switch (target) { 166 case GL_DRAW_FRAMEBUFFER: 167 return ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx) 168 ? ctx->DrawBuffer : NULL; 169 case GL_READ_FRAMEBUFFER: 170 return ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx) 171 ? ctx->ReadBuffer : NULL; 172 case GL_FRAMEBUFFER_EXT: 173 return ctx->DrawBuffer; 174 default: 175 return NULL; 176 } 177 } 178 179 180 /** 181 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding 182 * gl_renderbuffer_attachment object. 183 * This function is only used for user-created FB objects, not the 184 * default / window-system FB object. 185 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to 186 * the depth buffer attachment point. 187 */ 188 struct gl_renderbuffer_attachment * 189 _mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, 190 GLenum attachment) 191 { 192 GLuint i; 193 194 assert(_mesa_is_user_fbo(fb)); 195 196 switch (attachment) { 197 case GL_COLOR_ATTACHMENT0_EXT: 198 case GL_COLOR_ATTACHMENT1_EXT: 199 case GL_COLOR_ATTACHMENT2_EXT: 200 case GL_COLOR_ATTACHMENT3_EXT: 201 case GL_COLOR_ATTACHMENT4_EXT: 202 case GL_COLOR_ATTACHMENT5_EXT: 203 case GL_COLOR_ATTACHMENT6_EXT: 204 case GL_COLOR_ATTACHMENT7_EXT: 205 case GL_COLOR_ATTACHMENT8_EXT: 206 case GL_COLOR_ATTACHMENT9_EXT: 207 case GL_COLOR_ATTACHMENT10_EXT: 208 case GL_COLOR_ATTACHMENT11_EXT: 209 case GL_COLOR_ATTACHMENT12_EXT: 210 case GL_COLOR_ATTACHMENT13_EXT: 211 case GL_COLOR_ATTACHMENT14_EXT: 212 case GL_COLOR_ATTACHMENT15_EXT: 213 /* Only OpenGL ES 1.x forbids color attachments other than 214 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the 215 * hardware is used. 216 */ 217 i = attachment - GL_COLOR_ATTACHMENT0_EXT; 218 if (i >= ctx->Const.MaxColorAttachments 219 || (i > 0 && ctx->API == API_OPENGLES)) { 220 return NULL; 221 } 222 return &fb->Attachment[BUFFER_COLOR0 + i]; 223 case GL_DEPTH_STENCIL_ATTACHMENT: 224 if (!_mesa_is_desktop_gl(ctx)) 225 return NULL; 226 /* fall-through */ 227 case GL_DEPTH_ATTACHMENT_EXT: 228 return &fb->Attachment[BUFFER_DEPTH]; 229 case GL_STENCIL_ATTACHMENT_EXT: 230 return &fb->Attachment[BUFFER_STENCIL]; 231 default: 232 return NULL; 233 } 234 } 235 236 237 /** 238 * As above, but only used for getting attachments of the default / 239 * window-system framebuffer (not user-created framebuffer objects). 240 */ 241 static struct gl_renderbuffer_attachment * 242 _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, 243 GLenum attachment) 244 { 245 assert(_mesa_is_winsys_fbo(fb)); 246 247 switch (attachment) { 248 case GL_FRONT_LEFT: 249 return &fb->Attachment[BUFFER_FRONT_LEFT]; 250 case GL_FRONT_RIGHT: 251 return &fb->Attachment[BUFFER_FRONT_RIGHT]; 252 case GL_BACK_LEFT: 253 return &fb->Attachment[BUFFER_BACK_LEFT]; 254 case GL_BACK_RIGHT: 255 return &fb->Attachment[BUFFER_BACK_RIGHT]; 256 case GL_AUX0: 257 if (fb->Visual.numAuxBuffers == 1) { 258 return &fb->Attachment[BUFFER_AUX0]; 259 } 260 return NULL; 261 262 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says: 263 * 264 * "If the default framebuffer is bound to target, then attachment must 265 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi, 266 * identifying a color buffer; DEPTH, identifying the depth buffer; or 267 * STENCIL, identifying the stencil buffer." 268 * 269 * Revision #34 of the ARB_framebuffer_object spec has essentially the same 270 * language. However, revision #33 of the ARB_framebuffer_object spec 271 * says: 272 * 273 * "If the default framebuffer is bound to <target>, then <attachment> 274 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi, 275 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the 276 * depth buffer, or the stencil buffer, and <pname> may be 277 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or 278 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME." 279 * 280 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed 281 * from glext.h, so shipping apps should not use those values. 282 * 283 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object 284 * support queries of the window system FBO. 285 */ 286 case GL_DEPTH: 287 return &fb->Attachment[BUFFER_DEPTH]; 288 case GL_STENCIL: 289 return &fb->Attachment[BUFFER_STENCIL]; 290 default: 291 return NULL; 292 } 293 } 294 295 296 297 /** 298 * Remove any texture or renderbuffer attached to the given attachment 299 * point. Update reference counts, etc. 300 */ 301 void 302 _mesa_remove_attachment(struct gl_context *ctx, 303 struct gl_renderbuffer_attachment *att) 304 { 305 if (att->Type == GL_TEXTURE) { 306 ASSERT(att->Texture); 307 if (ctx->Driver.FinishRenderTexture) { 308 /* tell driver that we're done rendering to this texture. */ 309 ctx->Driver.FinishRenderTexture(ctx, att); 310 } 311 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */ 312 ASSERT(!att->Texture); 313 } 314 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) { 315 ASSERT(!att->Texture); 316 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */ 317 ASSERT(!att->Renderbuffer); 318 } 319 att->Type = GL_NONE; 320 att->Complete = GL_TRUE; 321 } 322 323 324 /** 325 * Bind a texture object to an attachment point. 326 * The previous binding, if any, will be removed first. 327 */ 328 void 329 _mesa_set_texture_attachment(struct gl_context *ctx, 330 struct gl_framebuffer *fb, 331 struct gl_renderbuffer_attachment *att, 332 struct gl_texture_object *texObj, 333 GLenum texTarget, GLuint level, GLuint zoffset) 334 { 335 if (att->Texture == texObj) { 336 /* re-attaching same texture */ 337 ASSERT(att->Type == GL_TEXTURE); 338 if (ctx->Driver.FinishRenderTexture) 339 ctx->Driver.FinishRenderTexture(ctx, att); 340 } 341 else { 342 /* new attachment */ 343 if (ctx->Driver.FinishRenderTexture && att->Texture) 344 ctx->Driver.FinishRenderTexture(ctx, att); 345 _mesa_remove_attachment(ctx, att); 346 att->Type = GL_TEXTURE; 347 assert(!att->Texture); 348 _mesa_reference_texobj(&att->Texture, texObj); 349 } 350 351 /* always update these fields */ 352 att->TextureLevel = level; 353 att->CubeMapFace = _mesa_tex_target_to_face(texTarget); 354 att->Zoffset = zoffset; 355 att->Complete = GL_FALSE; 356 357 if (_mesa_get_attachment_teximage(att)) { 358 ctx->Driver.RenderTexture(ctx, fb, att); 359 } 360 361 invalidate_framebuffer(fb); 362 } 363 364 365 /** 366 * Bind a renderbuffer to an attachment point. 367 * The previous binding, if any, will be removed first. 368 */ 369 void 370 _mesa_set_renderbuffer_attachment(struct gl_context *ctx, 371 struct gl_renderbuffer_attachment *att, 372 struct gl_renderbuffer *rb) 373 { 374 /* XXX check if re-doing same attachment, exit early */ 375 _mesa_remove_attachment(ctx, att); 376 att->Type = GL_RENDERBUFFER_EXT; 377 att->Texture = NULL; /* just to be safe */ 378 att->Complete = GL_FALSE; 379 _mesa_reference_renderbuffer(&att->Renderbuffer, rb); 380 } 381 382 383 /** 384 * Fallback for ctx->Driver.FramebufferRenderbuffer() 385 * Attach a renderbuffer object to a framebuffer object. 386 */ 387 void 388 _mesa_framebuffer_renderbuffer(struct gl_context *ctx, 389 struct gl_framebuffer *fb, 390 GLenum attachment, struct gl_renderbuffer *rb) 391 { 392 struct gl_renderbuffer_attachment *att; 393 394 _glthread_LOCK_MUTEX(fb->Mutex); 395 396 att = _mesa_get_attachment(ctx, fb, attachment); 397 ASSERT(att); 398 if (rb) { 399 _mesa_set_renderbuffer_attachment(ctx, att, rb); 400 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 401 /* do stencil attachment here (depth already done above) */ 402 att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT); 403 assert(att); 404 _mesa_set_renderbuffer_attachment(ctx, att, rb); 405 } 406 rb->AttachedAnytime = GL_TRUE; 407 } 408 else { 409 _mesa_remove_attachment(ctx, att); 410 } 411 412 invalidate_framebuffer(fb); 413 414 _glthread_UNLOCK_MUTEX(fb->Mutex); 415 } 416 417 418 /** 419 * Fallback for ctx->Driver.ValidateFramebuffer() 420 * Check if the renderbuffer's formats are supported by the software 421 * renderer. 422 * Drivers should probably override this. 423 */ 424 void 425 _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 426 { 427 gl_buffer_index buf; 428 for (buf = 0; buf < BUFFER_COUNT; buf++) { 429 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer; 430 if (rb) { 431 switch (rb->_BaseFormat) { 432 case GL_ALPHA: 433 case GL_LUMINANCE_ALPHA: 434 case GL_LUMINANCE: 435 case GL_INTENSITY: 436 case GL_RED: 437 case GL_RG: 438 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; 439 return; 440 441 default: 442 switch (rb->Format) { 443 /* XXX This list is likely incomplete. */ 444 case MESA_FORMAT_RGB9_E5_FLOAT: 445 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; 446 return; 447 default:; 448 /* render buffer format is supported by software rendering */ 449 } 450 } 451 } 452 } 453 } 454 455 456 /** 457 * For debug only. 458 */ 459 static void 460 att_incomplete(const char *msg) 461 { 462 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) { 463 _mesa_debug(NULL, "attachment incomplete: %s\n", msg); 464 } 465 } 466 467 468 /** 469 * For debug only. 470 */ 471 static void 472 fbo_incomplete(const char *msg, int index) 473 { 474 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) { 475 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index); 476 } 477 } 478 479 480 /** 481 * Is the given base format a legal format for a color renderbuffer? 482 */ 483 GLboolean 484 _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat) 485 { 486 switch (baseFormat) { 487 case GL_RGB: 488 case GL_RGBA: 489 return GL_TRUE; 490 case GL_LUMINANCE: 491 case GL_LUMINANCE_ALPHA: 492 case GL_INTENSITY: 493 case GL_ALPHA: 494 return ctx->Extensions.ARB_framebuffer_object; 495 case GL_RED: 496 case GL_RG: 497 return ctx->Extensions.ARB_texture_rg; 498 default: 499 return GL_FALSE; 500 } 501 } 502 503 504 /** 505 * Is the given base format a legal format for a depth/stencil renderbuffer? 506 */ 507 static GLboolean 508 is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat) 509 { 510 switch (baseFormat) { 511 case GL_DEPTH_COMPONENT: 512 case GL_DEPTH_STENCIL_EXT: 513 return GL_TRUE; 514 default: 515 return GL_FALSE; 516 } 517 } 518 519 520 /** 521 * Test if an attachment point is complete and update its Complete field. 522 * \param format if GL_COLOR, this is a color attachment point, 523 * if GL_DEPTH, this is a depth component attachment point, 524 * if GL_STENCIL, this is a stencil component attachment point. 525 */ 526 static void 527 test_attachment_completeness(const struct gl_context *ctx, GLenum format, 528 struct gl_renderbuffer_attachment *att) 529 { 530 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL); 531 532 /* assume complete */ 533 att->Complete = GL_TRUE; 534 535 /* Look for reasons why the attachment might be incomplete */ 536 if (att->Type == GL_TEXTURE) { 537 const struct gl_texture_object *texObj = att->Texture; 538 struct gl_texture_image *texImage; 539 GLenum baseFormat; 540 541 if (!texObj) { 542 att_incomplete("no texobj"); 543 att->Complete = GL_FALSE; 544 return; 545 } 546 547 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel]; 548 if (!texImage) { 549 att_incomplete("no teximage"); 550 att->Complete = GL_FALSE; 551 return; 552 } 553 if (texImage->Width < 1 || texImage->Height < 1) { 554 att_incomplete("teximage width/height=0"); 555 printf("texobj = %u\n", texObj->Name); 556 printf("level = %d\n", att->TextureLevel); 557 att->Complete = GL_FALSE; 558 return; 559 } 560 if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) { 561 att_incomplete("bad z offset"); 562 att->Complete = GL_FALSE; 563 return; 564 } 565 566 baseFormat = _mesa_get_format_base_format(texImage->TexFormat); 567 568 if (format == GL_COLOR) { 569 if (!_mesa_is_legal_color_format(ctx, baseFormat)) { 570 att_incomplete("bad format"); 571 att->Complete = GL_FALSE; 572 return; 573 } 574 if (_mesa_is_format_compressed(texImage->TexFormat)) { 575 att_incomplete("compressed internalformat"); 576 att->Complete = GL_FALSE; 577 return; 578 } 579 } 580 else if (format == GL_DEPTH) { 581 if (baseFormat == GL_DEPTH_COMPONENT) { 582 /* OK */ 583 } 584 else if (ctx->Extensions.EXT_packed_depth_stencil && 585 ctx->Extensions.ARB_depth_texture && 586 baseFormat == GL_DEPTH_STENCIL_EXT) { 587 /* OK */ 588 } 589 else { 590 att->Complete = GL_FALSE; 591 att_incomplete("bad depth format"); 592 return; 593 } 594 } 595 else { 596 ASSERT(format == GL_STENCIL); 597 if (ctx->Extensions.EXT_packed_depth_stencil && 598 ctx->Extensions.ARB_depth_texture && 599 baseFormat == GL_DEPTH_STENCIL_EXT) { 600 /* OK */ 601 } 602 else { 603 /* no such thing as stencil-only textures */ 604 att_incomplete("illegal stencil texture"); 605 att->Complete = GL_FALSE; 606 return; 607 } 608 } 609 } 610 else if (att->Type == GL_RENDERBUFFER_EXT) { 611 const GLenum baseFormat = 612 _mesa_get_format_base_format(att->Renderbuffer->Format); 613 614 ASSERT(att->Renderbuffer); 615 if (!att->Renderbuffer->InternalFormat || 616 att->Renderbuffer->Width < 1 || 617 att->Renderbuffer->Height < 1) { 618 att_incomplete("0x0 renderbuffer"); 619 att->Complete = GL_FALSE; 620 return; 621 } 622 if (format == GL_COLOR) { 623 if (!_mesa_is_legal_color_format(ctx, baseFormat)) { 624 att_incomplete("bad renderbuffer color format"); 625 att->Complete = GL_FALSE; 626 return; 627 } 628 } 629 else if (format == GL_DEPTH) { 630 if (baseFormat == GL_DEPTH_COMPONENT) { 631 /* OK */ 632 } 633 else if (ctx->Extensions.EXT_packed_depth_stencil && 634 baseFormat == GL_DEPTH_STENCIL_EXT) { 635 /* OK */ 636 } 637 else { 638 att_incomplete("bad renderbuffer depth format"); 639 att->Complete = GL_FALSE; 640 return; 641 } 642 } 643 else { 644 assert(format == GL_STENCIL); 645 if (baseFormat == GL_STENCIL_INDEX) { 646 /* OK */ 647 } 648 else if (ctx->Extensions.EXT_packed_depth_stencil && 649 baseFormat == GL_DEPTH_STENCIL_EXT) { 650 /* OK */ 651 } 652 else { 653 att->Complete = GL_FALSE; 654 att_incomplete("bad renderbuffer stencil format"); 655 return; 656 } 657 } 658 } 659 else { 660 ASSERT(att->Type == GL_NONE); 661 /* complete */ 662 return; 663 } 664 } 665 666 667 /** 668 * Test if the given framebuffer object is complete and update its 669 * Status field with the results. 670 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the 671 * driver to make hardware-specific validation/completeness checks. 672 * Also update the framebuffer's Width and Height fields if the 673 * framebuffer is complete. 674 */ 675 void 676 _mesa_test_framebuffer_completeness(struct gl_context *ctx, 677 struct gl_framebuffer *fb) 678 { 679 GLuint numImages; 680 GLenum intFormat = GL_NONE; /* color buffers' internal format */ 681 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0; 682 GLint numSamples = -1; 683 GLint i; 684 GLuint j; 685 686 assert(_mesa_is_user_fbo(fb)); 687 688 /* we're changing framebuffer fields here */ 689 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 690 691 numImages = 0; 692 fb->Width = 0; 693 fb->Height = 0; 694 695 /* Start at -2 to more easily loop over all attachment points. 696 * -2: depth buffer 697 * -1: stencil buffer 698 * >=0: color buffer 699 */ 700 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { 701 struct gl_renderbuffer_attachment *att; 702 GLenum f; 703 gl_format attFormat; 704 705 /* 706 * XXX for ARB_fbo, only check color buffers that are named by 707 * GL_READ_BUFFER and GL_DRAW_BUFFERi. 708 */ 709 710 /* check for attachment completeness 711 */ 712 if (i == -2) { 713 att = &fb->Attachment[BUFFER_DEPTH]; 714 test_attachment_completeness(ctx, GL_DEPTH, att); 715 if (!att->Complete) { 716 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; 717 fbo_incomplete("depth attachment incomplete", -1); 718 return; 719 } 720 } 721 else if (i == -1) { 722 att = &fb->Attachment[BUFFER_STENCIL]; 723 test_attachment_completeness(ctx, GL_STENCIL, att); 724 if (!att->Complete) { 725 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; 726 fbo_incomplete("stencil attachment incomplete", -1); 727 return; 728 } 729 } 730 else { 731 att = &fb->Attachment[BUFFER_COLOR0 + i]; 732 test_attachment_completeness(ctx, GL_COLOR, att); 733 if (!att->Complete) { 734 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; 735 fbo_incomplete("color attachment incomplete", i); 736 return; 737 } 738 } 739 740 /* get width, height, format of the renderbuffer/texture 741 */ 742 if (att->Type == GL_TEXTURE) { 743 const struct gl_texture_image *texImg = 744 _mesa_get_attachment_teximage(att); 745 minWidth = MIN2(minWidth, texImg->Width); 746 maxWidth = MAX2(maxWidth, texImg->Width); 747 minHeight = MIN2(minHeight, texImg->Height); 748 maxHeight = MAX2(maxHeight, texImg->Height); 749 f = texImg->_BaseFormat; 750 attFormat = texImg->TexFormat; 751 numImages++; 752 if (!_mesa_is_legal_color_format(ctx, f) && 753 !is_legal_depth_format(ctx, f)) { 754 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; 755 fbo_incomplete("texture attachment incomplete", -1); 756 return; 757 } 758 } 759 else if (att->Type == GL_RENDERBUFFER_EXT) { 760 minWidth = MIN2(minWidth, att->Renderbuffer->Width); 761 maxWidth = MAX2(minWidth, att->Renderbuffer->Width); 762 minHeight = MIN2(minHeight, att->Renderbuffer->Height); 763 maxHeight = MAX2(minHeight, att->Renderbuffer->Height); 764 f = att->Renderbuffer->InternalFormat; 765 attFormat = att->Renderbuffer->Format; 766 numImages++; 767 } 768 else { 769 assert(att->Type == GL_NONE); 770 continue; 771 } 772 773 if (att->Renderbuffer && numSamples < 0) { 774 /* first buffer */ 775 numSamples = att->Renderbuffer->NumSamples; 776 } 777 778 /* check if integer color */ 779 fb->_IntegerColor = _mesa_is_format_integer_color(attFormat); 780 781 /* Error-check width, height, format, samples 782 */ 783 if (numImages == 1) { 784 /* save format, num samples */ 785 if (i >= 0) { 786 intFormat = f; 787 } 788 } 789 else { 790 if (!ctx->Extensions.ARB_framebuffer_object) { 791 /* check that width, height, format are same */ 792 if (minWidth != maxWidth || minHeight != maxHeight) { 793 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; 794 fbo_incomplete("width or height mismatch", -1); 795 return; 796 } 797 /* check that all color buffers are the same format */ 798 if (intFormat != GL_NONE && f != intFormat) { 799 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; 800 fbo_incomplete("format mismatch", -1); 801 return; 802 } 803 } 804 if (att->Renderbuffer && 805 att->Renderbuffer->NumSamples != numSamples) { 806 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE; 807 fbo_incomplete("inconsistant number of samples", i); 808 return; 809 } 810 } 811 812 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported) 813 */ 814 if (att->Type == GL_RENDERBUFFER && 815 att->Renderbuffer->Format == MESA_FORMAT_NONE) { 816 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; 817 fbo_incomplete("unsupported renderbuffer format", i); 818 return; 819 } 820 } 821 822 #if FEATURE_GL 823 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) { 824 /* Check that all DrawBuffers are present */ 825 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { 826 if (fb->ColorDrawBuffer[j] != GL_NONE) { 827 const struct gl_renderbuffer_attachment *att 828 = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); 829 assert(att); 830 if (att->Type == GL_NONE) { 831 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; 832 fbo_incomplete("missing drawbuffer", j); 833 return; 834 } 835 } 836 } 837 838 /* Check that the ReadBuffer is present */ 839 if (fb->ColorReadBuffer != GL_NONE) { 840 const struct gl_renderbuffer_attachment *att 841 = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer); 842 assert(att); 843 if (att->Type == GL_NONE) { 844 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; 845 fbo_incomplete("missing readbuffer", -1); 846 return; 847 } 848 } 849 } 850 #else 851 (void) j; 852 #endif 853 854 if (numImages == 0) { 855 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; 856 fbo_incomplete("no attachments", -1); 857 return; 858 } 859 860 /* Provisionally set status = COMPLETE ... */ 861 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; 862 863 /* ... but the driver may say the FB is incomplete. 864 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED 865 * if anything. 866 */ 867 if (ctx->Driver.ValidateFramebuffer) { 868 ctx->Driver.ValidateFramebuffer(ctx, fb); 869 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 870 fbo_incomplete("driver marked FBO as incomplete", -1); 871 } 872 } 873 874 if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) { 875 /* 876 * Note that if ARB_framebuffer_object is supported and the attached 877 * renderbuffers/textures are different sizes, the framebuffer 878 * width/height will be set to the smallest width/height. 879 */ 880 fb->Width = minWidth; 881 fb->Height = minHeight; 882 883 /* finally, update the visual info for the framebuffer */ 884 _mesa_update_framebuffer_visual(ctx, fb); 885 } 886 } 887 888 889 GLboolean GLAPIENTRY 890 _mesa_IsRenderbufferEXT(GLuint renderbuffer) 891 { 892 GET_CURRENT_CONTEXT(ctx); 893 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 894 if (renderbuffer) { 895 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 896 if (rb != NULL && rb != &DummyRenderbuffer) 897 return GL_TRUE; 898 } 899 return GL_FALSE; 900 } 901 902 903 void GLAPIENTRY 904 _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) 905 { 906 struct gl_renderbuffer *newRb; 907 GET_CURRENT_CONTEXT(ctx); 908 909 ASSERT_OUTSIDE_BEGIN_END(ctx); 910 911 if (target != GL_RENDERBUFFER_EXT) { 912 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)"); 913 return; 914 } 915 916 /* No need to flush here since the render buffer binding has no 917 * effect on rendering state. 918 */ 919 920 if (renderbuffer) { 921 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 922 if (newRb == &DummyRenderbuffer) { 923 /* ID was reserved, but no real renderbuffer object made yet */ 924 newRb = NULL; 925 } 926 else if (!newRb && ctx->Extensions.ARB_framebuffer_object) { 927 /* All RB IDs must be Gen'd */ 928 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)"); 929 return; 930 } 931 932 if (!newRb) { 933 /* create new renderbuffer object */ 934 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); 935 if (!newRb) { 936 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); 937 return; 938 } 939 ASSERT(newRb->AllocStorage); 940 _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); 941 newRb->RefCount = 1; /* referenced by hash table */ 942 } 943 } 944 else { 945 newRb = NULL; 946 } 947 948 ASSERT(newRb != &DummyRenderbuffer); 949 950 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb); 951 } 952 953 954 /** 955 * If the given renderbuffer is anywhere attached to the framebuffer, detach 956 * the renderbuffer. 957 * This is used when a renderbuffer object is deleted. 958 * The spec calls for unbinding. 959 */ 960 static void 961 detach_renderbuffer(struct gl_context *ctx, 962 struct gl_framebuffer *fb, 963 struct gl_renderbuffer *rb) 964 { 965 GLuint i; 966 for (i = 0; i < BUFFER_COUNT; i++) { 967 if (fb->Attachment[i].Renderbuffer == rb) { 968 _mesa_remove_attachment(ctx, &fb->Attachment[i]); 969 } 970 } 971 invalidate_framebuffer(fb); 972 } 973 974 975 void GLAPIENTRY 976 _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) 977 { 978 GLint i; 979 GET_CURRENT_CONTEXT(ctx); 980 981 ASSERT_OUTSIDE_BEGIN_END(ctx); 982 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 983 984 for (i = 0; i < n; i++) { 985 if (renderbuffers[i] > 0) { 986 struct gl_renderbuffer *rb; 987 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); 988 if (rb) { 989 /* check if deleting currently bound renderbuffer object */ 990 if (rb == ctx->CurrentRenderbuffer) { 991 /* bind default */ 992 ASSERT(rb->RefCount >= 2); 993 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); 994 } 995 996 if (_mesa_is_user_fbo(ctx->DrawBuffer)) { 997 detach_renderbuffer(ctx, ctx->DrawBuffer, rb); 998 } 999 if (_mesa_is_user_fbo(ctx->ReadBuffer) 1000 && ctx->ReadBuffer != ctx->DrawBuffer) { 1001 detach_renderbuffer(ctx, ctx->ReadBuffer, rb); 1002 } 1003 1004 /* Remove from hash table immediately, to free the ID. 1005 * But the object will not be freed until it's no longer 1006 * referenced anywhere else. 1007 */ 1008 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); 1009 1010 if (rb != &DummyRenderbuffer) { 1011 /* no longer referenced by hash table */ 1012 _mesa_reference_renderbuffer(&rb, NULL); 1013 } 1014 } 1015 } 1016 } 1017 } 1018 1019 1020 void GLAPIENTRY 1021 _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) 1022 { 1023 GET_CURRENT_CONTEXT(ctx); 1024 GLuint first; 1025 GLint i; 1026 1027 ASSERT_OUTSIDE_BEGIN_END(ctx); 1028 1029 if (n < 0) { 1030 _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); 1031 return; 1032 } 1033 1034 if (!renderbuffers) 1035 return; 1036 1037 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); 1038 1039 for (i = 0; i < n; i++) { 1040 GLuint name = first + i; 1041 renderbuffers[i] = name; 1042 /* insert dummy placeholder into hash table */ 1043 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1044 _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); 1045 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1046 } 1047 } 1048 1049 1050 /** 1051 * Given an internal format token for a render buffer, return the 1052 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, 1053 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE, 1054 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc). 1055 * 1056 * This is similar to _mesa_base_tex_format() but the set of valid 1057 * internal formats is different. 1058 * 1059 * Note that even if a format is determined to be legal here, validation 1060 * of the FBO may fail if the format is not supported by the driver/GPU. 1061 * 1062 * \param internalFormat as passed to glRenderbufferStorage() 1063 * \return the base internal format, or 0 if internalFormat is illegal 1064 */ 1065 GLenum 1066 _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) 1067 { 1068 /* 1069 * Notes: some formats such as alpha, luminance, etc. were added 1070 * with GL_ARB_framebuffer_object. 1071 */ 1072 switch (internalFormat) { 1073 case GL_ALPHA: 1074 case GL_ALPHA4: 1075 case GL_ALPHA8: 1076 case GL_ALPHA12: 1077 case GL_ALPHA16: 1078 return ctx->API == API_OPENGL && ctx->Extensions.ARB_framebuffer_object 1079 ? GL_ALPHA : 0; 1080 case GL_LUMINANCE: 1081 case GL_LUMINANCE4: 1082 case GL_LUMINANCE8: 1083 case GL_LUMINANCE12: 1084 case GL_LUMINANCE16: 1085 return ctx->API == API_OPENGL && ctx->Extensions.ARB_framebuffer_object 1086 ? GL_LUMINANCE : 0; 1087 case GL_LUMINANCE_ALPHA: 1088 case GL_LUMINANCE4_ALPHA4: 1089 case GL_LUMINANCE6_ALPHA2: 1090 case GL_LUMINANCE8_ALPHA8: 1091 case GL_LUMINANCE12_ALPHA4: 1092 case GL_LUMINANCE12_ALPHA12: 1093 case GL_LUMINANCE16_ALPHA16: 1094 return ctx->API == API_OPENGL && ctx->Extensions.ARB_framebuffer_object 1095 ? GL_LUMINANCE_ALPHA : 0; 1096 case GL_INTENSITY: 1097 case GL_INTENSITY4: 1098 case GL_INTENSITY8: 1099 case GL_INTENSITY12: 1100 case GL_INTENSITY16: 1101 return ctx->API == API_OPENGL && ctx->Extensions.ARB_framebuffer_object 1102 ? GL_INTENSITY : 0; 1103 case GL_RGB8: 1104 return GL_RGB; 1105 case GL_RGB: 1106 case GL_R3_G3_B2: 1107 case GL_RGB4: 1108 case GL_RGB5: 1109 case GL_RGB10: 1110 case GL_RGB12: 1111 case GL_RGB16: 1112 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0; 1113 case GL_SRGB8_EXT: 1114 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGB : 0; 1115 case GL_RGBA4: 1116 case GL_RGB5_A1: 1117 case GL_RGBA8: 1118 return GL_RGBA; 1119 case GL_RGBA: 1120 case GL_RGBA2: 1121 case GL_RGBA12: 1122 case GL_RGBA16: 1123 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0; 1124 case GL_RGB10_A2: 1125 case GL_SRGB8_ALPHA8_EXT: 1126 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0; 1127 case GL_STENCIL_INDEX: 1128 case GL_STENCIL_INDEX1_EXT: 1129 case GL_STENCIL_INDEX4_EXT: 1130 case GL_STENCIL_INDEX16_EXT: 1131 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in 1132 * OpenGL ES, but Mesa does not currently support them. 1133 */ 1134 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0; 1135 case GL_STENCIL_INDEX8_EXT: 1136 return GL_STENCIL_INDEX; 1137 case GL_DEPTH_COMPONENT: 1138 case GL_DEPTH_COMPONENT32: 1139 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0; 1140 case GL_DEPTH_COMPONENT16: 1141 case GL_DEPTH_COMPONENT24: 1142 return GL_DEPTH_COMPONENT; 1143 case GL_DEPTH_STENCIL_EXT: 1144 return _mesa_is_desktop_gl(ctx) 1145 && ctx->Extensions.EXT_packed_depth_stencil 1146 ? GL_DEPTH_STENCIL_EXT : 0; 1147 case GL_DEPTH24_STENCIL8_EXT: 1148 return ctx->Extensions.EXT_packed_depth_stencil 1149 ? GL_DEPTH_STENCIL_EXT : 0; 1150 case GL_DEPTH_COMPONENT32F: 1151 return ctx->Version >= 30 1152 || (ctx->API == API_OPENGL && ctx->Extensions.ARB_depth_buffer_float) 1153 ? GL_DEPTH_COMPONENT : 0; 1154 case GL_DEPTH32F_STENCIL8: 1155 return ctx->Version >= 30 1156 || (ctx->API == API_OPENGL && ctx->Extensions.ARB_depth_buffer_float) 1157 ? GL_DEPTH_STENCIL : 0; 1158 case GL_RED: 1159 case GL_R16: 1160 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg 1161 ? GL_RED : 0; 1162 case GL_R8: 1163 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg 1164 ? GL_RED : 0; 1165 case GL_RG: 1166 case GL_RG16: 1167 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg 1168 ? GL_RG : 0; 1169 case GL_RG8: 1170 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg 1171 ? GL_RG : 0; 1172 /* signed normalized texture formats */ 1173 case GL_R8_SNORM: 1174 return ctx->Version >= 30 1175 || (ctx->API == API_OPENGL && ctx->Extensions.EXT_texture_snorm) 1176 ? GL_RED : 0; 1177 case GL_RED_SNORM: 1178 case GL_R16_SNORM: 1179 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm 1180 ? GL_RED : 0; 1181 case GL_RG8_SNORM: 1182 return ctx->Version >= 30 1183 || (ctx->API == API_OPENGL && ctx->Extensions.EXT_texture_snorm) 1184 ? GL_RG : 0; 1185 case GL_RG_SNORM: 1186 case GL_RG16_SNORM: 1187 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm 1188 ? GL_RG : 0; 1189 case GL_RGB8_SNORM: 1190 return ctx->Version >= 30 1191 || (ctx->API == API_OPENGL && ctx->Extensions.EXT_texture_snorm) 1192 ? GL_RGB : 0; 1193 case GL_RGB_SNORM: 1194 case GL_RGB16_SNORM: 1195 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm 1196 ? GL_RGB : 0; 1197 case GL_RGBA8_SNORM: 1198 return ctx->Version >= 30 1199 || (ctx->API == API_OPENGL && ctx->Extensions.EXT_texture_snorm) 1200 ? GL_RGBA : 0; 1201 case GL_RGBA_SNORM: 1202 case GL_RGBA16_SNORM: 1203 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm 1204 ? GL_RGBA : 0; 1205 case GL_ALPHA_SNORM: 1206 case GL_ALPHA8_SNORM: 1207 case GL_ALPHA16_SNORM: 1208 return ctx->API == API_OPENGL && 1209 ctx->Extensions.EXT_texture_snorm && 1210 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; 1211 case GL_LUMINANCE_SNORM: 1212 case GL_LUMINANCE8_SNORM: 1213 case GL_LUMINANCE16_SNORM: 1214 return ctx->API == API_OPENGL && 1215 ctx->Extensions.EXT_texture_snorm && 1216 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; 1217 case GL_LUMINANCE_ALPHA_SNORM: 1218 case GL_LUMINANCE8_ALPHA8_SNORM: 1219 case GL_LUMINANCE16_ALPHA16_SNORM: 1220 return ctx->API == API_OPENGL && 1221 ctx->Extensions.EXT_texture_snorm && 1222 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; 1223 case GL_INTENSITY_SNORM: 1224 case GL_INTENSITY8_SNORM: 1225 case GL_INTENSITY16_SNORM: 1226 return ctx->API == API_OPENGL && 1227 ctx->Extensions.EXT_texture_snorm && 1228 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; 1229 case GL_R16F: 1230 case GL_R32F: 1231 return ctx->Version >= 30 1232 || (ctx->API == API_OPENGL && 1233 ctx->Extensions.ARB_texture_rg && 1234 ctx->Extensions.ARB_texture_float) ? GL_RED : 0; 1235 case GL_RG16F: 1236 case GL_RG32F: 1237 return ctx->Version >= 30 1238 || (ctx->API == API_OPENGL && 1239 ctx->Extensions.ARB_texture_rg && 1240 ctx->Extensions.ARB_texture_float) ? GL_RG : 0; 1241 case GL_RGB16F: 1242 case GL_RGB32F: 1243 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float) 1244 || _mesa_is_gles3(ctx) 1245 ? GL_RGB : 0; 1246 case GL_RGBA16F: 1247 case GL_RGBA32F: 1248 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float) 1249 || _mesa_is_gles3(ctx) 1250 ? GL_RGBA : 0; 1251 case GL_ALPHA16F_ARB: 1252 case GL_ALPHA32F_ARB: 1253 return ctx->API == API_OPENGL && 1254 ctx->Extensions.ARB_texture_float && 1255 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; 1256 case GL_LUMINANCE16F_ARB: 1257 case GL_LUMINANCE32F_ARB: 1258 return ctx->API == API_OPENGL && 1259 ctx->Extensions.ARB_texture_float && 1260 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; 1261 case GL_LUMINANCE_ALPHA16F_ARB: 1262 case GL_LUMINANCE_ALPHA32F_ARB: 1263 return ctx->API == API_OPENGL && 1264 ctx->Extensions.ARB_texture_float && 1265 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; 1266 case GL_INTENSITY16F_ARB: 1267 case GL_INTENSITY32F_ARB: 1268 return ctx->API == API_OPENGL && 1269 ctx->Extensions.ARB_texture_float && 1270 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; 1271 case GL_RGB9_E5: 1272 return (_mesa_is_desktop_gl(ctx) 1273 && ctx->Extensions.EXT_texture_shared_exponent) 1274 || _mesa_is_gles3(ctx) ? GL_RGB : 0; 1275 case GL_R11F_G11F_B10F: 1276 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) 1277 || _mesa_is_gles3(ctx) ? GL_RGB : 0; 1278 1279 case GL_RGBA8UI_EXT: 1280 case GL_RGBA16UI_EXT: 1281 case GL_RGBA32UI_EXT: 1282 case GL_RGBA8I_EXT: 1283 case GL_RGBA16I_EXT: 1284 case GL_RGBA32I_EXT: 1285 return ctx->Version >= 30 1286 || (_mesa_is_desktop_gl(ctx) && 1287 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0; 1288 1289 case GL_RGB8UI_EXT: 1290 case GL_RGB16UI_EXT: 1291 case GL_RGB32UI_EXT: 1292 case GL_RGB8I_EXT: 1293 case GL_RGB16I_EXT: 1294 case GL_RGB32I_EXT: 1295 return ctx->Version >= 30 1296 || (_mesa_is_desktop_gl(ctx) && 1297 ctx->Extensions.EXT_texture_integer) ? GL_RGB : 0; 1298 1299 case GL_R8UI: 1300 case GL_R8I: 1301 case GL_R16UI: 1302 case GL_R16I: 1303 case GL_R32UI: 1304 case GL_R32I: 1305 return ctx->Version >= 30 1306 || (_mesa_is_desktop_gl(ctx) && 1307 ctx->Extensions.ARB_texture_rg && 1308 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0; 1309 1310 case GL_RG8UI: 1311 case GL_RG8I: 1312 case GL_RG16UI: 1313 case GL_RG16I: 1314 case GL_RG32UI: 1315 case GL_RG32I: 1316 return ctx->Version >= 30 1317 || (_mesa_is_desktop_gl(ctx) && 1318 ctx->Extensions.ARB_texture_rg && 1319 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0; 1320 1321 case GL_INTENSITY8I_EXT: 1322 case GL_INTENSITY8UI_EXT: 1323 case GL_INTENSITY16I_EXT: 1324 case GL_INTENSITY16UI_EXT: 1325 case GL_INTENSITY32I_EXT: 1326 case GL_INTENSITY32UI_EXT: 1327 return ctx->API == API_OPENGL && 1328 ctx->Extensions.EXT_texture_integer && 1329 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; 1330 1331 case GL_LUMINANCE8I_EXT: 1332 case GL_LUMINANCE8UI_EXT: 1333 case GL_LUMINANCE16I_EXT: 1334 case GL_LUMINANCE16UI_EXT: 1335 case GL_LUMINANCE32I_EXT: 1336 case GL_LUMINANCE32UI_EXT: 1337 return ctx->API == API_OPENGL && 1338 ctx->Extensions.EXT_texture_integer && 1339 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; 1340 1341 case GL_LUMINANCE_ALPHA8I_EXT: 1342 case GL_LUMINANCE_ALPHA8UI_EXT: 1343 case GL_LUMINANCE_ALPHA16I_EXT: 1344 case GL_LUMINANCE_ALPHA16UI_EXT: 1345 case GL_LUMINANCE_ALPHA32I_EXT: 1346 case GL_LUMINANCE_ALPHA32UI_EXT: 1347 return ctx->API == API_OPENGL && 1348 ctx->Extensions.EXT_texture_integer && 1349 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; 1350 1351 case GL_ALPHA8I_EXT: 1352 case GL_ALPHA8UI_EXT: 1353 case GL_ALPHA16I_EXT: 1354 case GL_ALPHA16UI_EXT: 1355 case GL_ALPHA32I_EXT: 1356 case GL_ALPHA32UI_EXT: 1357 return ctx->API == API_OPENGL && 1358 ctx->Extensions.EXT_texture_integer && 1359 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; 1360 1361 case GL_RGB10_A2UI: 1362 return (_mesa_is_desktop_gl(ctx) && 1363 ctx->Extensions.ARB_texture_rgb10_a2ui) 1364 || _mesa_is_gles3(ctx) ? GL_RGBA : 0; 1365 1366 case GL_RGB565: 1367 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility 1368 ? GL_RGB : 0; 1369 default: 1370 return 0; 1371 } 1372 } 1373 1374 1375 /** 1376 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk(). 1377 */ 1378 static void 1379 invalidate_rb(GLuint key, void *data, void *userData) 1380 { 1381 struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 1382 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData; 1383 1384 /* If this is a user-created FBO */ 1385 if (_mesa_is_user_fbo(fb)) { 1386 GLuint i; 1387 for (i = 0; i < BUFFER_COUNT; i++) { 1388 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 1389 if (att->Type == GL_RENDERBUFFER && 1390 att->Renderbuffer == rb) { 1391 /* Mark fb status as indeterminate to force re-validation */ 1392 fb->_Status = 0; 1393 return; 1394 } 1395 } 1396 } 1397 } 1398 1399 1400 /** sentinal value, see below */ 1401 #define NO_SAMPLES 1000 1402 1403 1404 /** 1405 * Helper function used by _mesa_RenderbufferStorageEXT() and 1406 * _mesa_RenderbufferStorageMultisample(). 1407 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT(). 1408 */ 1409 static void 1410 renderbuffer_storage(GLenum target, GLenum internalFormat, 1411 GLsizei width, GLsizei height, GLsizei samples) 1412 { 1413 const char *func = samples == NO_SAMPLES ? 1414 "glRenderbufferStorage" : "RenderbufferStorageMultisample"; 1415 struct gl_renderbuffer *rb; 1416 GLenum baseFormat; 1417 GET_CURRENT_CONTEXT(ctx); 1418 1419 ASSERT_OUTSIDE_BEGIN_END(ctx); 1420 1421 if (target != GL_RENDERBUFFER_EXT) { 1422 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); 1423 return; 1424 } 1425 1426 baseFormat = _mesa_base_fbo_format(ctx, internalFormat); 1427 if (baseFormat == 0) { 1428 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func); 1429 return; 1430 } 1431 1432 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { 1433 _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); 1434 return; 1435 } 1436 1437 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) { 1438 _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func); 1439 return; 1440 } 1441 1442 if (samples == NO_SAMPLES) { 1443 /* NumSamples == 0 indicates non-multisampling */ 1444 samples = 0; 1445 } 1446 else if (samples > (GLsizei) ctx->Const.MaxSamples) { 1447 /* note: driver may choose to use more samples than what's requested */ 1448 _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func); 1449 return; 1450 } 1451 1452 rb = ctx->CurrentRenderbuffer; 1453 if (!rb) { 1454 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); 1455 return; 1456 } 1457 1458 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1459 1460 if (rb->InternalFormat == internalFormat && 1461 rb->Width == (GLuint) width && 1462 rb->Height == (GLuint) height && 1463 rb->NumSamples == samples) { 1464 /* no change in allocation needed */ 1465 return; 1466 } 1467 1468 /* These MUST get set by the AllocStorage func */ 1469 rb->Format = MESA_FORMAT_NONE; 1470 rb->NumSamples = samples; 1471 1472 /* Now allocate the storage */ 1473 ASSERT(rb->AllocStorage); 1474 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { 1475 /* No error - check/set fields now */ 1476 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */ 1477 assert(rb->Width == (GLuint) width); 1478 assert(rb->Height == (GLuint) height); 1479 rb->InternalFormat = internalFormat; 1480 rb->_BaseFormat = baseFormat; 1481 assert(rb->_BaseFormat != 0); 1482 } 1483 else { 1484 /* Probably ran out of memory - clear the fields */ 1485 rb->Width = 0; 1486 rb->Height = 0; 1487 rb->Format = MESA_FORMAT_NONE; 1488 rb->InternalFormat = GL_NONE; 1489 rb->_BaseFormat = GL_NONE; 1490 rb->NumSamples = 0; 1491 } 1492 1493 /* Invalidate the framebuffers the renderbuffer is attached in. */ 1494 if (rb->AttachedAnytime) { 1495 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb); 1496 } 1497 } 1498 1499 1500 #if FEATURE_OES_EGL_image 1501 void GLAPIENTRY 1502 _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) 1503 { 1504 struct gl_renderbuffer *rb; 1505 GET_CURRENT_CONTEXT(ctx); 1506 ASSERT_OUTSIDE_BEGIN_END(ctx); 1507 1508 if (!ctx->Extensions.OES_EGL_image) { 1509 _mesa_error(ctx, GL_INVALID_OPERATION, 1510 "glEGLImageTargetRenderbufferStorageOES(unsupported)"); 1511 return; 1512 } 1513 1514 if (target != GL_RENDERBUFFER) { 1515 _mesa_error(ctx, GL_INVALID_ENUM, 1516 "EGLImageTargetRenderbufferStorageOES"); 1517 return; 1518 } 1519 1520 rb = ctx->CurrentRenderbuffer; 1521 if (!rb) { 1522 _mesa_error(ctx, GL_INVALID_OPERATION, 1523 "EGLImageTargetRenderbufferStorageOES"); 1524 return; 1525 } 1526 1527 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1528 1529 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image); 1530 } 1531 #endif 1532 1533 1534 /** 1535 * Helper function for _mesa_GetRenderbufferParameterivEXT() and 1536 * _mesa_GetFramebufferAttachmentParameterivEXT() 1537 * We have to be careful to respect the base format. For example, if a 1538 * renderbuffer/texture was created with internalFormat=GL_RGB but the 1539 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE 1540 * we need to return zero. 1541 */ 1542 static GLint 1543 get_component_bits(GLenum pname, GLenum baseFormat, gl_format format) 1544 { 1545 if (_mesa_base_format_has_channel(baseFormat, pname)) 1546 return _mesa_get_format_bits(format, pname); 1547 else 1548 return 0; 1549 } 1550 1551 1552 1553 void GLAPIENTRY 1554 _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, 1555 GLsizei width, GLsizei height) 1556 { 1557 /* GL_ARB_fbo says calling this function is equivalent to calling 1558 * glRenderbufferStorageMultisample() with samples=0. We pass in 1559 * a token value here just for error reporting purposes. 1560 */ 1561 renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES); 1562 } 1563 1564 1565 void GLAPIENTRY 1566 _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, 1567 GLenum internalFormat, 1568 GLsizei width, GLsizei height) 1569 { 1570 renderbuffer_storage(target, internalFormat, width, height, samples); 1571 } 1572 1573 1574 /** 1575 * OpenGL ES version of glRenderBufferStorage. 1576 */ 1577 void GLAPIENTRY 1578 _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, 1579 GLsizei width, GLsizei height) 1580 { 1581 switch (internalFormat) { 1582 case GL_RGB565: 1583 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */ 1584 /* choose a closest format */ 1585 internalFormat = GL_RGB5; 1586 break; 1587 default: 1588 break; 1589 } 1590 1591 renderbuffer_storage(target, internalFormat, width, height, 0); 1592 } 1593 1594 1595 void GLAPIENTRY 1596 _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) 1597 { 1598 struct gl_renderbuffer *rb; 1599 GET_CURRENT_CONTEXT(ctx); 1600 1601 ASSERT_OUTSIDE_BEGIN_END(ctx); 1602 1603 if (target != GL_RENDERBUFFER_EXT) { 1604 _mesa_error(ctx, GL_INVALID_ENUM, 1605 "glGetRenderbufferParameterivEXT(target)"); 1606 return; 1607 } 1608 1609 rb = ctx->CurrentRenderbuffer; 1610 if (!rb) { 1611 _mesa_error(ctx, GL_INVALID_OPERATION, 1612 "glGetRenderbufferParameterivEXT"); 1613 return; 1614 } 1615 1616 /* No need to flush here since we're just quering state which is 1617 * not effected by rendering. 1618 */ 1619 1620 switch (pname) { 1621 case GL_RENDERBUFFER_WIDTH_EXT: 1622 *params = rb->Width; 1623 return; 1624 case GL_RENDERBUFFER_HEIGHT_EXT: 1625 *params = rb->Height; 1626 return; 1627 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT: 1628 *params = rb->InternalFormat; 1629 return; 1630 case GL_RENDERBUFFER_RED_SIZE_EXT: 1631 case GL_RENDERBUFFER_GREEN_SIZE_EXT: 1632 case GL_RENDERBUFFER_BLUE_SIZE_EXT: 1633 case GL_RENDERBUFFER_ALPHA_SIZE_EXT: 1634 case GL_RENDERBUFFER_DEPTH_SIZE_EXT: 1635 case GL_RENDERBUFFER_STENCIL_SIZE_EXT: 1636 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format); 1637 break; 1638 case GL_RENDERBUFFER_SAMPLES: 1639 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object) 1640 || _mesa_is_gles3(ctx)) { 1641 *params = rb->NumSamples; 1642 break; 1643 } 1644 /* fallthrough */ 1645 default: 1646 _mesa_error(ctx, GL_INVALID_ENUM, 1647 "glGetRenderbufferParameterivEXT(target)"); 1648 return; 1649 } 1650 } 1651 1652 1653 GLboolean GLAPIENTRY 1654 _mesa_IsFramebufferEXT(GLuint framebuffer) 1655 { 1656 GET_CURRENT_CONTEXT(ctx); 1657 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1658 if (framebuffer) { 1659 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer); 1660 if (rb != NULL && rb != &DummyFramebuffer) 1661 return GL_TRUE; 1662 } 1663 return GL_FALSE; 1664 } 1665 1666 1667 /** 1668 * Check if any of the attachments of the given framebuffer are textures 1669 * (render to texture). Call ctx->Driver.RenderTexture() for such 1670 * attachments. 1671 */ 1672 static void 1673 check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) 1674 { 1675 GLuint i; 1676 ASSERT(ctx->Driver.RenderTexture); 1677 1678 if (_mesa_is_winsys_fbo(fb)) 1679 return; /* can't render to texture with winsys framebuffers */ 1680 1681 for (i = 0; i < BUFFER_COUNT; i++) { 1682 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 1683 if (att->Texture && _mesa_get_attachment_teximage(att)) { 1684 ctx->Driver.RenderTexture(ctx, fb, att); 1685 } 1686 } 1687 } 1688 1689 1690 /** 1691 * Examine all the framebuffer's attachments to see if any are textures. 1692 * If so, call ctx->Driver.FinishRenderTexture() for each texture to 1693 * notify the device driver that the texture image may have changed. 1694 */ 1695 static void 1696 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) 1697 { 1698 if (_mesa_is_winsys_fbo(fb)) 1699 return; /* can't render to texture with winsys framebuffers */ 1700 1701 if (ctx->Driver.FinishRenderTexture) { 1702 GLuint i; 1703 for (i = 0; i < BUFFER_COUNT; i++) { 1704 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 1705 if (att->Texture && att->Renderbuffer) { 1706 ctx->Driver.FinishRenderTexture(ctx, att); 1707 } 1708 } 1709 } 1710 } 1711 1712 1713 void GLAPIENTRY 1714 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) 1715 { 1716 struct gl_framebuffer *newDrawFb, *newReadFb; 1717 struct gl_framebuffer *oldDrawFb, *oldReadFb; 1718 GLboolean bindReadBuf, bindDrawBuf; 1719 GET_CURRENT_CONTEXT(ctx); 1720 1721 #ifdef DEBUG 1722 if (ctx->Extensions.ARB_framebuffer_object) { 1723 ASSERT(ctx->Extensions.EXT_framebuffer_object); 1724 ASSERT(ctx->Extensions.EXT_framebuffer_blit); 1725 } 1726 #endif 1727 1728 ASSERT_OUTSIDE_BEGIN_END(ctx); 1729 1730 if (!ctx->Extensions.EXT_framebuffer_object) { 1731 _mesa_error(ctx, GL_INVALID_OPERATION, 1732 "glBindFramebufferEXT(unsupported)"); 1733 return; 1734 } 1735 1736 switch (target) { 1737 #if FEATURE_EXT_framebuffer_blit 1738 case GL_DRAW_FRAMEBUFFER_EXT: 1739 if (!ctx->Extensions.EXT_framebuffer_blit) { 1740 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); 1741 return; 1742 } 1743 bindDrawBuf = GL_TRUE; 1744 bindReadBuf = GL_FALSE; 1745 break; 1746 case GL_READ_FRAMEBUFFER_EXT: 1747 if (!ctx->Extensions.EXT_framebuffer_blit) { 1748 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); 1749 return; 1750 } 1751 bindDrawBuf = GL_FALSE; 1752 bindReadBuf = GL_TRUE; 1753 break; 1754 #endif 1755 case GL_FRAMEBUFFER_EXT: 1756 bindDrawBuf = GL_TRUE; 1757 bindReadBuf = GL_TRUE; 1758 break; 1759 default: 1760 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); 1761 return; 1762 } 1763 1764 if (framebuffer) { 1765 /* Binding a user-created framebuffer object */ 1766 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer); 1767 if (newDrawFb == &DummyFramebuffer) { 1768 /* ID was reserved, but no real framebuffer object made yet */ 1769 newDrawFb = NULL; 1770 } 1771 else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) { 1772 /* All FBO IDs must be Gen'd */ 1773 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)"); 1774 return; 1775 } 1776 1777 if (!newDrawFb) { 1778 /* create new framebuffer object */ 1779 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); 1780 if (!newDrawFb) { 1781 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); 1782 return; 1783 } 1784 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb); 1785 } 1786 newReadFb = newDrawFb; 1787 } 1788 else { 1789 /* Binding the window system framebuffer (which was originally set 1790 * with MakeCurrent). 1791 */ 1792 newDrawFb = ctx->WinSysDrawBuffer; 1793 newReadFb = ctx->WinSysReadBuffer; 1794 } 1795 1796 ASSERT(newDrawFb); 1797 ASSERT(newDrawFb != &DummyFramebuffer); 1798 1799 /* save pointers to current/old framebuffers */ 1800 oldDrawFb = ctx->DrawBuffer; 1801 oldReadFb = ctx->ReadBuffer; 1802 1803 /* check if really changing bindings */ 1804 if (oldDrawFb == newDrawFb) 1805 bindDrawBuf = GL_FALSE; 1806 if (oldReadFb == newReadFb) 1807 bindReadBuf = GL_FALSE; 1808 1809 /* 1810 * OK, now bind the new Draw/Read framebuffers, if they're changing. 1811 * 1812 * We also check if we're beginning and/or ending render-to-texture. 1813 * When a framebuffer with texture attachments is unbound, call 1814 * ctx->Driver.FinishRenderTexture(). 1815 * When a framebuffer with texture attachments is bound, call 1816 * ctx->Driver.RenderTexture(). 1817 * 1818 * Note that if the ReadBuffer has texture attachments we don't consider 1819 * that a render-to-texture case. 1820 */ 1821 if (bindReadBuf) { 1822 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1823 1824 /* check if old readbuffer was render-to-texture */ 1825 check_end_texture_render(ctx, oldReadFb); 1826 1827 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb); 1828 } 1829 1830 if (bindDrawBuf) { 1831 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1832 1833 /* check if old framebuffer had any texture attachments */ 1834 if (oldDrawFb) 1835 check_end_texture_render(ctx, oldDrawFb); 1836 1837 /* check if newly bound framebuffer has any texture attachments */ 1838 check_begin_texture_render(ctx, newDrawFb); 1839 1840 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb); 1841 } 1842 1843 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) { 1844 ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb); 1845 } 1846 } 1847 1848 1849 void GLAPIENTRY 1850 _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) 1851 { 1852 GLint i; 1853 GET_CURRENT_CONTEXT(ctx); 1854 1855 ASSERT_OUTSIDE_BEGIN_END(ctx); 1856 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1857 1858 for (i = 0; i < n; i++) { 1859 if (framebuffers[i] > 0) { 1860 struct gl_framebuffer *fb; 1861 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); 1862 if (fb) { 1863 ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); 1864 1865 /* check if deleting currently bound framebuffer object */ 1866 if (ctx->Extensions.EXT_framebuffer_blit) { 1867 /* separate draw/read binding points */ 1868 if (fb == ctx->DrawBuffer) { 1869 /* bind default */ 1870 ASSERT(fb->RefCount >= 2); 1871 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); 1872 } 1873 if (fb == ctx->ReadBuffer) { 1874 /* bind default */ 1875 ASSERT(fb->RefCount >= 2); 1876 _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); 1877 } 1878 } 1879 else { 1880 /* only one binding point for read/draw buffers */ 1881 if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) { 1882 /* bind default */ 1883 ASSERT(fb->RefCount >= 2); 1884 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 1885 } 1886 } 1887 1888 /* remove from hash table immediately, to free the ID */ 1889 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); 1890 1891 if (fb != &DummyFramebuffer) { 1892 /* But the object will not be freed until it's no longer 1893 * bound in any context. 1894 */ 1895 _mesa_reference_framebuffer(&fb, NULL); 1896 } 1897 } 1898 } 1899 } 1900 } 1901 1902 1903 void GLAPIENTRY 1904 _mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) 1905 { 1906 GET_CURRENT_CONTEXT(ctx); 1907 GLuint first; 1908 GLint i; 1909 1910 ASSERT_OUTSIDE_BEGIN_END(ctx); 1911 1912 if (n < 0) { 1913 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)"); 1914 return; 1915 } 1916 1917 if (!framebuffers) 1918 return; 1919 1920 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n); 1921 1922 for (i = 0; i < n; i++) { 1923 GLuint name = first + i; 1924 framebuffers[i] = name; 1925 /* insert dummy placeholder into hash table */ 1926 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1927 _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); 1928 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1929 } 1930 } 1931 1932 1933 1934 GLenum GLAPIENTRY 1935 _mesa_CheckFramebufferStatusEXT(GLenum target) 1936 { 1937 struct gl_framebuffer *buffer; 1938 GET_CURRENT_CONTEXT(ctx); 1939 1940 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 1941 1942 buffer = get_framebuffer_target(ctx, target); 1943 if (!buffer) { 1944 _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); 1945 return 0; 1946 } 1947 1948 if (_mesa_is_winsys_fbo(buffer)) { 1949 /* The window system / default framebuffer is always complete */ 1950 return GL_FRAMEBUFFER_COMPLETE_EXT; 1951 } 1952 1953 /* No need to flush here */ 1954 1955 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) { 1956 _mesa_test_framebuffer_completeness(ctx, buffer); 1957 } 1958 1959 return buffer->_Status; 1960 } 1961 1962 1963 /** 1964 * Replicate the src attachment point. Used by framebuffer_texture() when 1965 * the same texture is attached at GL_DEPTH_ATTACHMENT and 1966 * GL_STENCIL_ATTACHMENT. 1967 */ 1968 static void 1969 reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, 1970 gl_buffer_index dst, 1971 gl_buffer_index src) 1972 { 1973 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst]; 1974 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src]; 1975 1976 assert(src_att->Texture != NULL); 1977 assert(src_att->Renderbuffer != NULL); 1978 1979 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture); 1980 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer); 1981 dst_att->Type = src_att->Type; 1982 dst_att->Complete = src_att->Complete; 1983 dst_att->TextureLevel = src_att->TextureLevel; 1984 dst_att->Zoffset = src_att->Zoffset; 1985 } 1986 1987 1988 /** 1989 * Common code called by glFramebufferTexture1D/2D/3DEXT() and 1990 * glFramebufferTextureLayerEXT(). 1991 * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll 1992 * get textarget=0 in that case. 1993 */ 1994 static void 1995 framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, 1996 GLenum attachment, GLenum textarget, GLuint texture, 1997 GLint level, GLint zoffset) 1998 { 1999 struct gl_renderbuffer_attachment *att; 2000 struct gl_texture_object *texObj = NULL; 2001 struct gl_framebuffer *fb; 2002 GLenum maxLevelsTarget; 2003 2004 ASSERT_OUTSIDE_BEGIN_END(ctx); 2005 2006 fb = get_framebuffer_target(ctx, target); 2007 if (!fb) { 2008 _mesa_error(ctx, GL_INVALID_ENUM, 2009 "glFramebufferTexture%sEXT(target=0x%x)", caller, target); 2010 return; 2011 } 2012 2013 /* check framebuffer binding */ 2014 if (_mesa_is_winsys_fbo(fb)) { 2015 _mesa_error(ctx, GL_INVALID_OPERATION, 2016 "glFramebufferTexture%sEXT", caller); 2017 return; 2018 } 2019 2020 /* The textarget, level, and zoffset parameters are only validated if 2021 * texture is non-zero. 2022 */ 2023 if (texture) { 2024 GLboolean err = GL_TRUE; 2025 2026 texObj = _mesa_lookup_texture(ctx, texture); 2027 if (texObj != NULL) { 2028 if (textarget == 0) { 2029 /* If textarget == 0 it means we're being called by 2030 * glFramebufferTextureLayer() and textarget is not used. 2031 * The only legal texture types for that function are 3D and 2032 * 1D/2D arrays textures. 2033 */ 2034 err = (texObj->Target != GL_TEXTURE_3D) && 2035 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && 2036 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); 2037 } 2038 else { 2039 /* Make sure textarget is consistent with the texture's type */ 2040 err = (texObj->Target == GL_TEXTURE_CUBE_MAP) 2041 ? !_mesa_is_cube_face(textarget) 2042 : (texObj->Target != textarget); 2043 } 2044 } 2045 else { 2046 /* can't render to a non-existant texture */ 2047 _mesa_error(ctx, GL_INVALID_OPERATION, 2048 "glFramebufferTexture%sEXT(non existant texture)", 2049 caller); 2050 return; 2051 } 2052 2053 if (err) { 2054 _mesa_error(ctx, GL_INVALID_OPERATION, 2055 "glFramebufferTexture%sEXT(texture target mismatch)", 2056 caller); 2057 return; 2058 } 2059 2060 if (texObj->Target == GL_TEXTURE_3D) { 2061 const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 2062 if (zoffset < 0 || zoffset >= maxSize) { 2063 _mesa_error(ctx, GL_INVALID_VALUE, 2064 "glFramebufferTexture%sEXT(zoffset)", caller); 2065 return; 2066 } 2067 } 2068 else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || 2069 (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) { 2070 if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) { 2071 _mesa_error(ctx, GL_INVALID_VALUE, 2072 "glFramebufferTexture%sEXT(layer)", caller); 2073 return; 2074 } 2075 } 2076 2077 maxLevelsTarget = textarget ? textarget : texObj->Target; 2078 if ((level < 0) || 2079 (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) { 2080 _mesa_error(ctx, GL_INVALID_VALUE, 2081 "glFramebufferTexture%sEXT(level)", caller); 2082 return; 2083 } 2084 } 2085 2086 att = _mesa_get_attachment(ctx, fb, attachment); 2087 if (att == NULL) { 2088 _mesa_error(ctx, GL_INVALID_ENUM, 2089 "glFramebufferTexture%sEXT(attachment)", caller); 2090 return; 2091 } 2092 2093 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2094 2095 _glthread_LOCK_MUTEX(fb->Mutex); 2096 if (texObj) { 2097 if (attachment == GL_DEPTH_ATTACHMENT && 2098 texObj == fb->Attachment[BUFFER_STENCIL].Texture && 2099 level == fb->Attachment[BUFFER_STENCIL].TextureLevel && 2100 _mesa_tex_target_to_face(textarget) == 2101 fb->Attachment[BUFFER_STENCIL].CubeMapFace && 2102 zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) { 2103 /* The texture object is already attached to the stencil attachment 2104 * point. Don't create a new renderbuffer; just reuse the stencil 2105 * attachment's. This is required to prevent a GL error in 2106 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL). 2107 */ 2108 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, 2109 BUFFER_STENCIL); 2110 } else if (attachment == GL_STENCIL_ATTACHMENT && 2111 texObj == fb->Attachment[BUFFER_DEPTH].Texture && 2112 level == fb->Attachment[BUFFER_DEPTH].TextureLevel && 2113 _mesa_tex_target_to_face(textarget) == 2114 fb->Attachment[BUFFER_DEPTH].CubeMapFace && 2115 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) { 2116 /* As above, but with depth and stencil transposed. */ 2117 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, 2118 BUFFER_DEPTH); 2119 } else { 2120 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget, 2121 level, zoffset); 2122 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 2123 /* Above we created a new renderbuffer and attached it to the 2124 * depth attachment point. Now attach it to the stencil attachment 2125 * point too. 2126 */ 2127 assert(att == &fb->Attachment[BUFFER_DEPTH]); 2128 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL, 2129 BUFFER_DEPTH); 2130 } 2131 } 2132 2133 /* Set the render-to-texture flag. We'll check this flag in 2134 * glTexImage() and friends to determine if we need to revalidate 2135 * any FBOs that might be rendering into this texture. 2136 * This flag never gets cleared since it's non-trivial to determine 2137 * when all FBOs might be done rendering to this texture. That's OK 2138 * though since it's uncommon to render to a texture then repeatedly 2139 * call glTexImage() to change images in the texture. 2140 */ 2141 texObj->_RenderToTexture = GL_TRUE; 2142 } 2143 else { 2144 _mesa_remove_attachment(ctx, att); 2145 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 2146 assert(att == &fb->Attachment[BUFFER_DEPTH]); 2147 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); 2148 } 2149 } 2150 2151 invalidate_framebuffer(fb); 2152 2153 _glthread_UNLOCK_MUTEX(fb->Mutex); 2154 } 2155 2156 2157 2158 void GLAPIENTRY 2159 _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, 2160 GLenum textarget, GLuint texture, GLint level) 2161 { 2162 GET_CURRENT_CONTEXT(ctx); 2163 2164 if (texture != 0) { 2165 GLboolean error; 2166 2167 switch (textarget) { 2168 case GL_TEXTURE_1D: 2169 error = GL_FALSE; 2170 break; 2171 case GL_TEXTURE_1D_ARRAY: 2172 error = !ctx->Extensions.EXT_texture_array; 2173 break; 2174 default: 2175 error = GL_TRUE; 2176 } 2177 2178 if (error) { 2179 _mesa_error(ctx, GL_INVALID_OPERATION, 2180 "glFramebufferTexture1DEXT(textarget=%s)", 2181 _mesa_lookup_enum_by_nr(textarget)); 2182 return; 2183 } 2184 } 2185 2186 framebuffer_texture(ctx, "1D", target, attachment, textarget, texture, 2187 level, 0); 2188 } 2189 2190 2191 void GLAPIENTRY 2192 _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, 2193 GLenum textarget, GLuint texture, GLint level) 2194 { 2195 GET_CURRENT_CONTEXT(ctx); 2196 2197 if (texture != 0) { 2198 GLboolean error; 2199 2200 switch (textarget) { 2201 case GL_TEXTURE_2D: 2202 error = GL_FALSE; 2203 break; 2204 case GL_TEXTURE_RECTANGLE: 2205 error = _mesa_is_gles(ctx) 2206 || !ctx->Extensions.NV_texture_rectangle; 2207 break; 2208 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2209 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2210 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2211 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2212 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2213 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2214 error = !ctx->Extensions.ARB_texture_cube_map; 2215 break; 2216 case GL_TEXTURE_2D_ARRAY: 2217 error = (_mesa_is_gles(ctx) && ctx->Version < 30) 2218 || !ctx->Extensions.EXT_texture_array; 2219 break; 2220 default: 2221 error = GL_TRUE; 2222 } 2223 2224 if (error) { 2225 _mesa_error(ctx, GL_INVALID_OPERATION, 2226 "glFramebufferTexture2DEXT(textarget=%s)", 2227 _mesa_lookup_enum_by_nr(textarget)); 2228 return; 2229 } 2230 } 2231 2232 framebuffer_texture(ctx, "2D", target, attachment, textarget, texture, 2233 level, 0); 2234 } 2235 2236 2237 void GLAPIENTRY 2238 _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, 2239 GLenum textarget, GLuint texture, 2240 GLint level, GLint zoffset) 2241 { 2242 GET_CURRENT_CONTEXT(ctx); 2243 2244 if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { 2245 _mesa_error(ctx, GL_INVALID_OPERATION, 2246 "glFramebufferTexture3DEXT(textarget)"); 2247 return; 2248 } 2249 2250 framebuffer_texture(ctx, "3D", target, attachment, textarget, texture, 2251 level, zoffset); 2252 } 2253 2254 2255 void GLAPIENTRY 2256 _mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment, 2257 GLuint texture, GLint level, GLint layer) 2258 { 2259 GET_CURRENT_CONTEXT(ctx); 2260 2261 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, 2262 level, layer); 2263 } 2264 2265 2266 void GLAPIENTRY 2267 _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, 2268 GLenum renderbufferTarget, 2269 GLuint renderbuffer) 2270 { 2271 struct gl_renderbuffer_attachment *att; 2272 struct gl_framebuffer *fb; 2273 struct gl_renderbuffer *rb; 2274 GET_CURRENT_CONTEXT(ctx); 2275 2276 ASSERT_OUTSIDE_BEGIN_END(ctx); 2277 2278 fb = get_framebuffer_target(ctx, target); 2279 if (!fb) { 2280 _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); 2281 return; 2282 } 2283 2284 if (renderbufferTarget != GL_RENDERBUFFER_EXT) { 2285 _mesa_error(ctx, GL_INVALID_ENUM, 2286 "glFramebufferRenderbufferEXT(renderbufferTarget)"); 2287 return; 2288 } 2289 2290 if (_mesa_is_winsys_fbo(fb)) { 2291 /* Can't attach new renderbuffers to a window system framebuffer */ 2292 _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); 2293 return; 2294 } 2295 2296 att = _mesa_get_attachment(ctx, fb, attachment); 2297 if (att == NULL) { 2298 _mesa_error(ctx, GL_INVALID_ENUM, 2299 "glFramebufferRenderbufferEXT(invalid attachment %s)", 2300 _mesa_lookup_enum_by_nr(attachment)); 2301 return; 2302 } 2303 2304 if (renderbuffer) { 2305 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 2306 if (!rb) { 2307 _mesa_error(ctx, GL_INVALID_OPERATION, 2308 "glFramebufferRenderbufferEXT(non-existant" 2309 " renderbuffer %u)", renderbuffer); 2310 return; 2311 } 2312 else if (rb == &DummyRenderbuffer) { 2313 /* This is what NVIDIA does */ 2314 _mesa_error(ctx, GL_INVALID_VALUE, 2315 "glFramebufferRenderbufferEXT(renderbuffer %u)", 2316 renderbuffer); 2317 return; 2318 } 2319 } 2320 else { 2321 /* remove renderbuffer attachment */ 2322 rb = NULL; 2323 } 2324 2325 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT && 2326 rb && rb->Format != MESA_FORMAT_NONE) { 2327 /* make sure the renderbuffer is a depth/stencil format */ 2328 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); 2329 if (baseFormat != GL_DEPTH_STENCIL) { 2330 _mesa_error(ctx, GL_INVALID_OPERATION, 2331 "glFramebufferRenderbufferEXT(renderbuffer" 2332 " is not DEPTH_STENCIL format)"); 2333 return; 2334 } 2335 } 2336 2337 2338 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2339 2340 assert(ctx->Driver.FramebufferRenderbuffer); 2341 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); 2342 2343 /* Some subsequent GL commands may depend on the framebuffer's visual 2344 * after the binding is updated. Update visual info now. 2345 */ 2346 _mesa_update_framebuffer_visual(ctx, fb); 2347 } 2348 2349 2350 void GLAPIENTRY 2351 _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, 2352 GLenum pname, GLint *params) 2353 { 2354 const struct gl_renderbuffer_attachment *att; 2355 struct gl_framebuffer *buffer; 2356 GLenum err; 2357 GET_CURRENT_CONTEXT(ctx); 2358 2359 ASSERT_OUTSIDE_BEGIN_END(ctx); 2360 2361 /* The error differs in GL and GLES. */ 2362 err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM; 2363 2364 buffer = get_framebuffer_target(ctx, target); 2365 if (!buffer) { 2366 _mesa_error(ctx, GL_INVALID_ENUM, 2367 "glGetFramebufferAttachmentParameterivEXT(target)"); 2368 return; 2369 } 2370 2371 if (_mesa_is_winsys_fbo(buffer)) { 2372 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec 2373 * says: 2374 * 2375 * "If the framebuffer currently bound to target is zero, then 2376 * INVALID_OPERATION is generated." 2377 * 2378 * The EXT_framebuffer_object spec has the same wording, and the 2379 * OES_framebuffer_object spec refers to the EXT_framebuffer_object 2380 * spec. 2381 */ 2382 if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) { 2383 _mesa_error(ctx, GL_INVALID_OPERATION, 2384 "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); 2385 return; 2386 } 2387 /* the default / window-system FBO */ 2388 att = _mesa_get_fb0_attachment(ctx, buffer, attachment); 2389 } 2390 else { 2391 /* user-created framebuffer FBO */ 2392 att = _mesa_get_attachment(ctx, buffer, attachment); 2393 } 2394 2395 if (att == NULL) { 2396 _mesa_error(ctx, GL_INVALID_ENUM, 2397 "glGetFramebufferAttachmentParameterivEXT(attachment)"); 2398 return; 2399 } 2400 2401 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 2402 /* the depth and stencil attachments must point to the same buffer */ 2403 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt; 2404 depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT); 2405 stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); 2406 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) { 2407 _mesa_error(ctx, GL_INVALID_OPERATION, 2408 "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL" 2409 " attachments differ)"); 2410 return; 2411 } 2412 } 2413 2414 /* No need to flush here */ 2415 2416 switch (pname) { 2417 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: 2418 *params = _mesa_is_winsys_fbo(buffer) 2419 ? GL_FRAMEBUFFER_DEFAULT : att->Type; 2420 return; 2421 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: 2422 if (att->Type == GL_RENDERBUFFER_EXT) { 2423 *params = att->Renderbuffer->Name; 2424 } 2425 else if (att->Type == GL_TEXTURE) { 2426 *params = att->Texture->Name; 2427 } 2428 else { 2429 assert(att->Type == GL_NONE); 2430 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) { 2431 *params = 0; 2432 } else { 2433 goto invalid_pname_enum; 2434 } 2435 } 2436 return; 2437 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: 2438 if (att->Type == GL_TEXTURE) { 2439 *params = att->TextureLevel; 2440 } 2441 else if (att->Type == GL_NONE) { 2442 _mesa_error(ctx, err, 2443 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2444 } 2445 else { 2446 goto invalid_pname_enum; 2447 } 2448 return; 2449 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: 2450 if (att->Type == GL_TEXTURE) { 2451 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) { 2452 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace; 2453 } 2454 else { 2455 *params = 0; 2456 } 2457 } 2458 else if (att->Type == GL_NONE) { 2459 _mesa_error(ctx, err, 2460 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2461 } 2462 else { 2463 goto invalid_pname_enum; 2464 } 2465 return; 2466 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: 2467 if (ctx->API == API_OPENGLES) { 2468 goto invalid_pname_enum; 2469 } else if (att->Type == GL_NONE) { 2470 _mesa_error(ctx, err, 2471 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2472 } else if (att->Type == GL_TEXTURE) { 2473 if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) { 2474 *params = att->Zoffset; 2475 } 2476 else { 2477 *params = 0; 2478 } 2479 } 2480 else { 2481 goto invalid_pname_enum; 2482 } 2483 return; 2484 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: 2485 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) 2486 && !_mesa_is_gles3(ctx)) { 2487 goto invalid_pname_enum; 2488 } 2489 else if (att->Type == GL_NONE) { 2490 _mesa_error(ctx, err, 2491 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2492 } 2493 else { 2494 if (ctx->Extensions.EXT_framebuffer_sRGB) { 2495 *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); 2496 } 2497 else { 2498 /* According to ARB_framebuffer_sRGB, we should return LINEAR 2499 * if the sRGB conversion is unsupported. */ 2500 *params = GL_LINEAR; 2501 } 2502 } 2503 return; 2504 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: 2505 if ((ctx->API != API_OPENGL || !ctx->Extensions.ARB_framebuffer_object) 2506 && ctx->API != API_OPENGL_CORE 2507 && !_mesa_is_gles3(ctx)) { 2508 goto invalid_pname_enum; 2509 } 2510 else if (att->Type == GL_NONE) { 2511 _mesa_error(ctx, err, 2512 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2513 } 2514 else { 2515 gl_format format = att->Renderbuffer->Format; 2516 if (format == MESA_FORMAT_S8) { 2517 /* special cases */ 2518 *params = GL_INDEX; 2519 } 2520 else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) { 2521 /* depends on the attachment parameter */ 2522 if (attachment == GL_STENCIL_ATTACHMENT) { 2523 *params = GL_INDEX; 2524 } 2525 else { 2526 *params = GL_FLOAT; 2527 } 2528 } 2529 else { 2530 *params = _mesa_get_format_datatype(format); 2531 } 2532 } 2533 return; 2534 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: 2535 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: 2536 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: 2537 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: 2538 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: 2539 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: 2540 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) 2541 && !_mesa_is_gles3(ctx)) { 2542 goto invalid_pname_enum; 2543 } 2544 else if (att->Type == GL_NONE) { 2545 _mesa_error(ctx, err, 2546 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2547 } 2548 else if (att->Texture) { 2549 const struct gl_texture_image *texImage = 2550 _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target, 2551 att->TextureLevel); 2552 if (texImage) { 2553 *params = get_component_bits(pname, texImage->_BaseFormat, 2554 texImage->TexFormat); 2555 } 2556 else { 2557 *params = 0; 2558 } 2559 } 2560 else if (att->Renderbuffer) { 2561 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat, 2562 att->Renderbuffer->Format); 2563 } 2564 else { 2565 _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:" 2566 " invalid FBO attachment structure"); 2567 } 2568 return; 2569 default: 2570 goto invalid_pname_enum; 2571 } 2572 2573 return; 2574 2575 invalid_pname_enum: 2576 _mesa_error(ctx, GL_INVALID_ENUM, 2577 "glGetFramebufferAttachmentParameteriv(pname)"); 2578 return; 2579 } 2580 2581 2582 void GLAPIENTRY 2583 _mesa_GenerateMipmapEXT(GLenum target) 2584 { 2585 struct gl_texture_image *srcImage; 2586 struct gl_texture_object *texObj; 2587 GLboolean error; 2588 2589 GET_CURRENT_CONTEXT(ctx); 2590 2591 ASSERT_OUTSIDE_BEGIN_END(ctx); 2592 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2593 2594 switch (target) { 2595 case GL_TEXTURE_1D: 2596 error = _mesa_is_gles(ctx); 2597 break; 2598 case GL_TEXTURE_2D: 2599 error = GL_FALSE; 2600 break; 2601 case GL_TEXTURE_3D: 2602 error = ctx->API == API_OPENGLES; 2603 break; 2604 case GL_TEXTURE_CUBE_MAP: 2605 error = !ctx->Extensions.ARB_texture_cube_map; 2606 break; 2607 case GL_TEXTURE_1D_ARRAY: 2608 error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array; 2609 break; 2610 case GL_TEXTURE_2D_ARRAY: 2611 error = (_mesa_is_gles(ctx) && ctx->Version < 30) 2612 || !ctx->Extensions.EXT_texture_array; 2613 break; 2614 default: 2615 error = GL_TRUE; 2616 } 2617 2618 if (error) { 2619 _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)", 2620 _mesa_lookup_enum_by_nr(target)); 2621 return; 2622 } 2623 2624 texObj = _mesa_get_current_tex_object(ctx, target); 2625 2626 if (texObj->BaseLevel >= texObj->MaxLevel) { 2627 /* nothing to do */ 2628 return; 2629 } 2630 2631 if (texObj->Target == GL_TEXTURE_CUBE_MAP && 2632 !_mesa_cube_complete(texObj)) { 2633 _mesa_error(ctx, GL_INVALID_OPERATION, 2634 "glGenerateMipmap(incomplete cube map)"); 2635 return; 2636 } 2637 2638 _mesa_lock_texture(ctx, texObj); 2639 2640 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); 2641 if (!srcImage) { 2642 _mesa_unlock_texture(ctx, texObj); 2643 _mesa_error(ctx, GL_INVALID_OPERATION, 2644 "glGenerateMipmap(zero size base image)"); 2645 return; 2646 } 2647 2648 if (_mesa_is_enum_format_integer(srcImage->InternalFormat) || 2649 _mesa_is_depthstencil_format(srcImage->InternalFormat) || 2650 _mesa_is_stencil_format(srcImage->InternalFormat)) { 2651 _mesa_unlock_texture(ctx, texObj); 2652 _mesa_error(ctx, GL_INVALID_OPERATION, 2653 "glGenerateMipmap(invalid internal format)"); 2654 return; 2655 } 2656 2657 if (target == GL_TEXTURE_CUBE_MAP) { 2658 GLuint face; 2659 for (face = 0; face < 6; face++) 2660 ctx->Driver.GenerateMipmap(ctx, 2661 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, 2662 texObj); 2663 } 2664 else { 2665 ctx->Driver.GenerateMipmap(ctx, target, texObj); 2666 } 2667 _mesa_unlock_texture(ctx, texObj); 2668 } 2669 2670 2671 #if FEATURE_EXT_framebuffer_blit 2672 2673 static const struct gl_renderbuffer_attachment * 2674 find_attachment(const struct gl_framebuffer *fb, 2675 const struct gl_renderbuffer *rb) 2676 { 2677 GLuint i; 2678 for (i = 0; i < Elements(fb->Attachment); i++) { 2679 if (fb->Attachment[i].Renderbuffer == rb) 2680 return &fb->Attachment[i]; 2681 } 2682 return NULL; 2683 } 2684 2685 2686 /** 2687 * Helper function for checking if the datatypes of color buffers are 2688 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198: 2689 * 2690 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT 2691 * and any of the following conditions hold: 2692 * - The read buffer contains fixed-point or floating-point values and any 2693 * draw buffer contains neither fixed-point nor floating-point values. 2694 * - The read buffer contains unsigned integer values and any draw buffer 2695 * does not contain unsigned integer values. 2696 * - The read buffer contains signed integer values and any draw buffer 2697 * does not contain signed integer values." 2698 */ 2699 static GLboolean 2700 compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat) 2701 { 2702 GLenum srcType = _mesa_get_format_datatype(srcFormat); 2703 GLenum dstType = _mesa_get_format_datatype(dstFormat); 2704 2705 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) { 2706 assert(srcType == GL_UNSIGNED_NORMALIZED || 2707 srcType == GL_SIGNED_NORMALIZED || 2708 srcType == GL_FLOAT); 2709 /* Boil any of those types down to GL_FLOAT */ 2710 srcType = GL_FLOAT; 2711 } 2712 2713 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) { 2714 assert(dstType == GL_UNSIGNED_NORMALIZED || 2715 dstType == GL_SIGNED_NORMALIZED || 2716 dstType == GL_FLOAT); 2717 /* Boil any of those types down to GL_FLOAT */ 2718 dstType = GL_FLOAT; 2719 } 2720 2721 return srcType == dstType; 2722 } 2723 2724 2725 /** 2726 * Return the equivalent non-generic internal format. 2727 * This is useful for comparing whether two internal formats are semantically 2728 * equivalent. 2729 */ 2730 static GLenum 2731 get_nongeneric_internalformat(GLenum format) 2732 { 2733 switch (format) { 2734 /* GL 1.1 formats. */ 2735 case 4: 2736 case GL_RGBA: 2737 return GL_RGBA8; 2738 2739 case 3: 2740 case GL_RGB: 2741 return GL_RGB8; 2742 2743 case 2: 2744 case GL_LUMINANCE_ALPHA: 2745 return GL_LUMINANCE8_ALPHA8; 2746 2747 case 1: 2748 case GL_LUMINANCE: 2749 return GL_LUMINANCE8; 2750 2751 case GL_ALPHA: 2752 return GL_ALPHA8; 2753 2754 case GL_INTENSITY: 2755 return GL_INTENSITY8; 2756 2757 /* GL_ARB_texture_rg */ 2758 case GL_RED: 2759 return GL_R8; 2760 2761 case GL_RG: 2762 return GL_RG8; 2763 2764 /* GL_EXT_texture_sRGB */ 2765 case GL_SRGB: 2766 return GL_SRGB8; 2767 2768 case GL_SRGB_ALPHA: 2769 return GL_SRGB8_ALPHA8; 2770 2771 case GL_SLUMINANCE: 2772 return GL_SLUMINANCE8; 2773 2774 case GL_SLUMINANCE_ALPHA: 2775 return GL_SLUMINANCE8_ALPHA8; 2776 2777 /* GL_EXT_texture_snorm */ 2778 case GL_RGBA_SNORM: 2779 return GL_RGBA8_SNORM; 2780 2781 case GL_RGB_SNORM: 2782 return GL_RGB8_SNORM; 2783 2784 case GL_RG_SNORM: 2785 return GL_RG8_SNORM; 2786 2787 case GL_RED_SNORM: 2788 return GL_R8_SNORM; 2789 2790 case GL_LUMINANCE_ALPHA_SNORM: 2791 return GL_LUMINANCE8_ALPHA8_SNORM; 2792 2793 case GL_LUMINANCE_SNORM: 2794 return GL_LUMINANCE8_SNORM; 2795 2796 case GL_ALPHA_SNORM: 2797 return GL_ALPHA8_SNORM; 2798 2799 case GL_INTENSITY_SNORM: 2800 return GL_INTENSITY8_SNORM; 2801 2802 default: 2803 return format; 2804 } 2805 } 2806 2807 2808 static GLenum 2809 get_linear_internalformat(GLenum format) 2810 { 2811 switch (format) { 2812 case GL_SRGB: 2813 return GL_RGB; 2814 2815 case GL_SRGB_ALPHA: 2816 return GL_RGBA; 2817 2818 case GL_SRGB8: 2819 return GL_RGB8; 2820 2821 case GL_SRGB8_ALPHA8: 2822 return GL_RGBA8; 2823 2824 case GL_SLUMINANCE: 2825 return GL_LUMINANCE8; 2826 2827 case GL_SLUMINANCE_ALPHA: 2828 return GL_LUMINANCE8_ALPHA8; 2829 2830 default: 2831 return format; 2832 } 2833 } 2834 2835 2836 static GLboolean 2837 compatible_resolve_formats(const struct gl_renderbuffer *colorReadRb, 2838 const struct gl_renderbuffer *colorDrawRb) 2839 { 2840 GLenum readFormat, drawFormat; 2841 2842 /* The simple case where we know the backing Mesa formats are the same. 2843 */ 2844 if (_mesa_get_srgb_format_linear(colorReadRb->Format) == 2845 _mesa_get_srgb_format_linear(colorDrawRb->Format)) { 2846 return GL_TRUE; 2847 } 2848 2849 /* The Mesa formats are different, so we must check whether the internal 2850 * formats are compatible. 2851 * 2852 * Under some circumstances, the user may request e.g. two GL_RGBA8 2853 * textures and get two entirely different Mesa formats like RGBA8888 and 2854 * ARGB8888. Drivers behaving like that should be able to cope with 2855 * non-matching formats by themselves, because it's not the user's fault. 2856 * 2857 * Blits between linear and sRGB formats are also allowed. 2858 */ 2859 readFormat = get_nongeneric_internalformat(colorReadRb->InternalFormat); 2860 drawFormat = get_nongeneric_internalformat(colorDrawRb->InternalFormat); 2861 readFormat = get_linear_internalformat(readFormat); 2862 drawFormat = get_linear_internalformat(drawFormat); 2863 2864 if (readFormat == drawFormat) { 2865 return GL_TRUE; 2866 } 2867 2868 return GL_FALSE; 2869 } 2870 2871 2872 /** 2873 * Blit rectangular region, optionally from one framebuffer to another. 2874 * 2875 * Note, if the src buffer is multisampled and the dest is not, this is 2876 * when the samples must be resolved to a single color. 2877 */ 2878 void GLAPIENTRY 2879 _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 2880 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 2881 GLbitfield mask, GLenum filter) 2882 { 2883 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | 2884 GL_DEPTH_BUFFER_BIT | 2885 GL_STENCIL_BUFFER_BIT); 2886 const struct gl_framebuffer *readFb, *drawFb; 2887 const struct gl_renderbuffer *colorReadRb, *colorDrawRb; 2888 GET_CURRENT_CONTEXT(ctx); 2889 2890 ASSERT_OUTSIDE_BEGIN_END(ctx); 2891 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2892 2893 if (MESA_VERBOSE & VERBOSE_API) 2894 _mesa_debug(ctx, 2895 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", 2896 srcX0, srcY0, srcX1, srcY1, 2897 dstX0, dstY0, dstX1, dstY1, 2898 mask, _mesa_lookup_enum_by_nr(filter)); 2899 2900 if (ctx->NewState) { 2901 _mesa_update_state(ctx); 2902 } 2903 2904 readFb = ctx->ReadBuffer; 2905 drawFb = ctx->DrawBuffer; 2906 2907 if (!readFb || !drawFb) { 2908 /* This will normally never happen but someday we may want to 2909 * support MakeCurrent() with no drawables. 2910 */ 2911 return; 2912 } 2913 2914 /* check for complete framebuffers */ 2915 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || 2916 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 2917 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 2918 "glBlitFramebufferEXT(incomplete draw/read buffers)"); 2919 return; 2920 } 2921 2922 if (filter != GL_NEAREST && filter != GL_LINEAR) { 2923 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)"); 2924 return; 2925 } 2926 2927 if (mask & ~legalMaskBits) { 2928 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); 2929 return; 2930 } 2931 2932 /* depth/stencil must be blitted with nearest filtering */ 2933 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) 2934 && filter != GL_NEAREST) { 2935 _mesa_error(ctx, GL_INVALID_OPERATION, 2936 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); 2937 return; 2938 } 2939 2940 /* get color read/draw renderbuffers */ 2941 if (mask & GL_COLOR_BUFFER_BIT) { 2942 colorReadRb = readFb->_ColorReadBuffer; 2943 colorDrawRb = drawFb->_ColorDrawBuffers[0]; 2944 2945 /* From the EXT_framebuffer_object spec: 2946 * 2947 * "If a buffer is specified in <mask> and does not exist in both 2948 * the read and draw framebuffers, the corresponding bit is silently 2949 * ignored." 2950 */ 2951 if ((colorReadRb == NULL) || (colorDrawRb == NULL)) { 2952 colorReadRb = colorDrawRb = NULL; 2953 mask &= ~GL_COLOR_BUFFER_BIT; 2954 } 2955 else if (!compatible_color_datatypes(colorReadRb->Format, 2956 colorDrawRb->Format)) { 2957 _mesa_error(ctx, GL_INVALID_OPERATION, 2958 "glBlitFramebufferEXT(color buffer datatypes mismatch)"); 2959 return; 2960 } 2961 } 2962 else { 2963 colorReadRb = colorDrawRb = NULL; 2964 } 2965 2966 if (mask & GL_STENCIL_BUFFER_BIT) { 2967 struct gl_renderbuffer *readRb = 2968 readFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2969 struct gl_renderbuffer *drawRb = 2970 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2971 2972 /* From the EXT_framebuffer_object spec: 2973 * 2974 * "If a buffer is specified in <mask> and does not exist in both 2975 * the read and draw framebuffers, the corresponding bit is silently 2976 * ignored." 2977 */ 2978 if ((readRb == NULL) || (drawRb == NULL)) { 2979 mask &= ~GL_STENCIL_BUFFER_BIT; 2980 } 2981 else if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != 2982 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { 2983 /* There is no need to check the stencil datatype here, because 2984 * there is only one: GL_UNSIGNED_INT. 2985 */ 2986 _mesa_error(ctx, GL_INVALID_OPERATION, 2987 "glBlitFramebufferEXT(stencil buffer size mismatch)"); 2988 return; 2989 } 2990 } 2991 2992 if (mask & GL_DEPTH_BUFFER_BIT) { 2993 struct gl_renderbuffer *readRb = 2994 readFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2995 struct gl_renderbuffer *drawRb = 2996 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2997 2998 /* From the EXT_framebuffer_object spec: 2999 * 3000 * "If a buffer is specified in <mask> and does not exist in both 3001 * the read and draw framebuffers, the corresponding bit is silently 3002 * ignored." 3003 */ 3004 if ((readRb == NULL) || (drawRb == NULL)) { 3005 mask &= ~GL_DEPTH_BUFFER_BIT; 3006 } 3007 else if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != 3008 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || 3009 (_mesa_get_format_datatype(readRb->Format) != 3010 _mesa_get_format_datatype(drawRb->Format))) { 3011 _mesa_error(ctx, GL_INVALID_OPERATION, 3012 "glBlitFramebufferEXT(depth buffer format mismatch)"); 3013 return; 3014 } 3015 } 3016 3017 if (readFb->Visual.samples > 0 && 3018 drawFb->Visual.samples > 0 && 3019 readFb->Visual.samples != drawFb->Visual.samples) { 3020 _mesa_error(ctx, GL_INVALID_OPERATION, 3021 "glBlitFramebufferEXT(mismatched samples)"); 3022 return; 3023 } 3024 3025 /* extra checks for multisample copies... */ 3026 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { 3027 /* src and dest region sizes must be the same */ 3028 if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) || 3029 abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) { 3030 _mesa_error(ctx, GL_INVALID_OPERATION, 3031 "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); 3032 return; 3033 } 3034 3035 /* color formats must match */ 3036 if (colorReadRb && 3037 colorDrawRb && 3038 !compatible_resolve_formats(colorReadRb, colorDrawRb)) { 3039 _mesa_error(ctx, GL_INVALID_OPERATION, 3040 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); 3041 return; 3042 } 3043 } 3044 3045 if (filter == GL_LINEAR && (mask & GL_COLOR_BUFFER_BIT)) { 3046 /* 3.1 spec, page 199: 3047 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error 3048 * if filter is LINEAR and read buffer contains integer data." 3049 */ 3050 GLenum type = _mesa_get_format_datatype(colorReadRb->Format); 3051 if (type == GL_INT || type == GL_UNSIGNED_INT) { 3052 _mesa_error(ctx, GL_INVALID_OPERATION, 3053 "glBlitFramebufferEXT(integer color type)"); 3054 return; 3055 } 3056 } 3057 3058 if (!ctx->Extensions.EXT_framebuffer_blit) { 3059 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT"); 3060 return; 3061 } 3062 3063 /* Debug code */ 3064 if (DEBUG_BLIT) { 3065 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," 3066 " 0x%x, 0x%x)\n", 3067 srcX0, srcY0, srcX1, srcY1, 3068 dstX0, dstY0, dstX1, dstY1, 3069 mask, filter); 3070 if (colorReadRb) { 3071 const struct gl_renderbuffer_attachment *att; 3072 3073 att = find_attachment(readFb, colorReadRb); 3074 printf(" Src FBO %u RB %u (%dx%d) ", 3075 readFb->Name, colorReadRb->Name, 3076 colorReadRb->Width, colorReadRb->Height); 3077 if (att && att->Texture) { 3078 printf("Tex %u tgt 0x%x level %u face %u", 3079 att->Texture->Name, 3080 att->Texture->Target, 3081 att->TextureLevel, 3082 att->CubeMapFace); 3083 } 3084 printf("\n"); 3085 3086 att = find_attachment(drawFb, colorDrawRb); 3087 printf(" Dst FBO %u RB %u (%dx%d) ", 3088 drawFb->Name, colorDrawRb->Name, 3089 colorDrawRb->Width, colorDrawRb->Height); 3090 if (att && att->Texture) { 3091 printf("Tex %u tgt 0x%x level %u face %u", 3092 att->Texture->Name, 3093 att->Texture->Target, 3094 att->TextureLevel, 3095 att->CubeMapFace); 3096 } 3097 printf("\n"); 3098 } 3099 } 3100 3101 if (!mask) { 3102 return; 3103 } 3104 3105 ASSERT(ctx->Driver.BlitFramebuffer); 3106 ctx->Driver.BlitFramebuffer(ctx, 3107 srcX0, srcY0, srcX1, srcY1, 3108 dstX0, dstY0, dstX1, dstY1, 3109 mask, filter); 3110 } 3111 #endif /* FEATURE_EXT_framebuffer_blit */ 3112 3113 3114 #if FEATURE_ARB_geometry_shader4 3115 void GLAPIENTRY 3116 _mesa_FramebufferTextureARB(GLenum target, GLenum attachment, 3117 GLuint texture, GLint level) 3118 { 3119 GET_CURRENT_CONTEXT(ctx); 3120 _mesa_error(ctx, GL_INVALID_OPERATION, 3121 "glFramebufferTextureARB " 3122 "not implemented!"); 3123 } 3124 3125 3126 void GLAPIENTRY 3127 _mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, 3128 GLuint texture, GLint level, GLenum face) 3129 { 3130 GET_CURRENT_CONTEXT(ctx); 3131 _mesa_error(ctx, GL_INVALID_OPERATION, 3132 "glFramebufferTextureFaceARB " 3133 "not implemented!"); 3134 } 3135 #endif /* FEATURE_ARB_geometry_shader4 */ 3136 3137 static void 3138 invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, 3139 const GLenum *attachments, GLint x, GLint y, 3140 GLsizei width, GLsizei height, const char *name) 3141 { 3142 int i; 3143 struct gl_framebuffer *fb; 3144 GET_CURRENT_CONTEXT(ctx); 3145 3146 ASSERT_OUTSIDE_BEGIN_END(ctx); 3147 3148 fb = get_framebuffer_target(ctx, target); 3149 if (!fb) { 3150 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name); 3151 return; 3152 } 3153 3154 if (numAttachments < 0) { 3155 _mesa_error(ctx, GL_INVALID_VALUE, 3156 "%s(numAttachments < 0)", name); 3157 return; 3158 } 3159 3160 /* The GL_ARB_invalidate_subdata spec says: 3161 * 3162 * "If an attachment is specified that does not exist in the 3163 * framebuffer bound to <target>, it is ignored." 3164 * 3165 * It also says: 3166 * 3167 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than 3168 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error 3169 * INVALID_OPERATION is generated." 3170 * 3171 * No mention is made of GL_AUXi being out of range. Therefore, we allow 3172 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different 3173 * set of retrictions). 3174 */ 3175 for (i = 0; i < numAttachments; i++) { 3176 if (_mesa_is_winsys_fbo(fb)) { 3177 switch (attachments[i]) { 3178 case GL_ACCUM: 3179 case GL_AUX0: 3180 case GL_AUX1: 3181 case GL_AUX2: 3182 case GL_AUX3: 3183 /* Accumulation buffers and auxilary buffers were removed in 3184 * OpenGL 3.1, and they never existed in OpenGL ES. 3185 */ 3186 if (ctx->API != API_OPENGL) 3187 goto invalid_enum; 3188 break; 3189 case GL_COLOR: 3190 case GL_DEPTH: 3191 case GL_STENCIL: 3192 break; 3193 case GL_BACK_LEFT: 3194 case GL_BACK_RIGHT: 3195 case GL_FRONT_LEFT: 3196 case GL_FRONT_RIGHT: 3197 if (!_mesa_is_desktop_gl(ctx)) 3198 goto invalid_enum; 3199 break; 3200 default: 3201 goto invalid_enum; 3202 } 3203 } else { 3204 switch (attachments[i]) { 3205 case GL_DEPTH_ATTACHMENT: 3206 case GL_STENCIL_ATTACHMENT: 3207 break; 3208 case GL_COLOR_ATTACHMENT0: 3209 case GL_COLOR_ATTACHMENT1: 3210 case GL_COLOR_ATTACHMENT2: 3211 case GL_COLOR_ATTACHMENT3: 3212 case GL_COLOR_ATTACHMENT4: 3213 case GL_COLOR_ATTACHMENT5: 3214 case GL_COLOR_ATTACHMENT6: 3215 case GL_COLOR_ATTACHMENT7: 3216 case GL_COLOR_ATTACHMENT8: 3217 case GL_COLOR_ATTACHMENT9: 3218 case GL_COLOR_ATTACHMENT10: 3219 case GL_COLOR_ATTACHMENT11: 3220 case GL_COLOR_ATTACHMENT12: 3221 case GL_COLOR_ATTACHMENT13: 3222 case GL_COLOR_ATTACHMENT14: 3223 case GL_COLOR_ATTACHMENT15: { 3224 const int k = attachments[i] - GL_COLOR_ATTACHMENT0; 3225 if (k >= ctx->Const.MaxColorAttachments) { 3226 _mesa_error(ctx, GL_INVALID_OPERATION, 3227 "%s(attachment >= max. color attachments)", name); 3228 return; 3229 } 3230 } 3231 default: 3232 goto invalid_enum; 3233 } 3234 } 3235 } 3236 3237 /* We don't actually do anything for this yet. Just return after 3238 * validating the parameters and generating the required errors. 3239 */ 3240 return; 3241 3242 invalid_enum: 3243 _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name); 3244 return; 3245 } 3246 3247 void GLAPIENTRY 3248 _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, 3249 const GLenum *attachments, GLint x, GLint y, 3250 GLsizei width, GLsizei height) 3251 { 3252 invalidate_framebuffer_storage(target, numAttachments, attachments, 3253 x, y, width, height, 3254 "glInvalidateSubFramebuffer"); 3255 } 3256 3257 void GLAPIENTRY 3258 _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, 3259 const GLenum *attachments) 3260 { 3261 /* The GL_ARB_invalidate_subdata spec says: 3262 * 3263 * "The command 3264 * 3265 * void InvalidateFramebuffer(enum target, 3266 * sizei numAttachments, 3267 * const enum *attachments); 3268 * 3269 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>, 3270 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, 3271 * <MAX_VIEWPORT_DIMS[1]> respectively." 3272 */ 3273 invalidate_framebuffer_storage(target, numAttachments, attachments, 3274 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, 3275 "glInvalidateFramebuffer"); 3276 } 3277