fbobject.c revision 342be8aa88819446220bba680d8e0b628078156f
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 */ 71static struct gl_framebuffer DummyFramebuffer; 72static struct gl_renderbuffer DummyRenderbuffer; 73 74/* We bind this framebuffer when applications pass a NULL 75 * drawable/surface in make current. */ 76static struct gl_framebuffer IncompleteFramebuffer; 77 78 79static void 80delete_dummy_renderbuffer(struct gl_renderbuffer *rb) 81{ 82 /* no op */ 83} 84 85static void 86delete_dummy_framebuffer(struct gl_framebuffer *fb) 87{ 88 /* no op */ 89} 90 91 92void 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 103struct gl_framebuffer * 104_mesa_get_incomplete_framebuffer(void) 105{ 106 return &IncompleteFramebuffer; 107} 108 109/** 110 * Helper routine for getting a gl_renderbuffer. 111 */ 112struct 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 */ 129struct 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 */ 148static void 149invalidate_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 */ 162static struct gl_framebuffer * 163get_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 */ 188struct 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 */ 241static 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 */ 301void 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 */ 328void 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 */ 369void 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 */ 387void 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 */ 424void 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 */ 459static void 460att_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 */ 471static void 472fbo_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 */ 483GLboolean 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 */ 507static GLboolean 508is_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 */ 526static void 527test_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 */ 675void 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 numImages = 0; 689 fb->Width = 0; 690 fb->Height = 0; 691 692 /* Start at -2 to more easily loop over all attachment points. 693 * -2: depth buffer 694 * -1: stencil buffer 695 * >=0: color buffer 696 */ 697 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { 698 struct gl_renderbuffer_attachment *att; 699 GLenum f; 700 gl_format attFormat; 701 702 /* 703 * XXX for ARB_fbo, only check color buffers that are named by 704 * GL_READ_BUFFER and GL_DRAW_BUFFERi. 705 */ 706 707 /* check for attachment completeness 708 */ 709 if (i == -2) { 710 att = &fb->Attachment[BUFFER_DEPTH]; 711 test_attachment_completeness(ctx, GL_DEPTH, att); 712 if (!att->Complete) { 713 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; 714 fbo_incomplete("depth attachment incomplete", -1); 715 return; 716 } 717 } 718 else if (i == -1) { 719 att = &fb->Attachment[BUFFER_STENCIL]; 720 test_attachment_completeness(ctx, GL_STENCIL, att); 721 if (!att->Complete) { 722 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; 723 fbo_incomplete("stencil attachment incomplete", -1); 724 return; 725 } 726 } 727 else { 728 att = &fb->Attachment[BUFFER_COLOR0 + i]; 729 test_attachment_completeness(ctx, GL_COLOR, att); 730 if (!att->Complete) { 731 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; 732 fbo_incomplete("color attachment incomplete", i); 733 return; 734 } 735 } 736 737 /* get width, height, format of the renderbuffer/texture 738 */ 739 if (att->Type == GL_TEXTURE) { 740 const struct gl_texture_image *texImg = 741 _mesa_get_attachment_teximage(att); 742 minWidth = MIN2(minWidth, texImg->Width); 743 maxWidth = MAX2(maxWidth, texImg->Width); 744 minHeight = MIN2(minHeight, texImg->Height); 745 maxHeight = MAX2(maxHeight, texImg->Height); 746 f = texImg->_BaseFormat; 747 attFormat = texImg->TexFormat; 748 numImages++; 749 if (!_mesa_is_legal_color_format(ctx, f) && 750 !is_legal_depth_format(ctx, f)) { 751 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; 752 fbo_incomplete("texture attachment incomplete", -1); 753 return; 754 } 755 } 756 else if (att->Type == GL_RENDERBUFFER_EXT) { 757 minWidth = MIN2(minWidth, att->Renderbuffer->Width); 758 maxWidth = MAX2(minWidth, att->Renderbuffer->Width); 759 minHeight = MIN2(minHeight, att->Renderbuffer->Height); 760 maxHeight = MAX2(minHeight, att->Renderbuffer->Height); 761 f = att->Renderbuffer->InternalFormat; 762 attFormat = att->Renderbuffer->Format; 763 numImages++; 764 } 765 else { 766 assert(att->Type == GL_NONE); 767 continue; 768 } 769 770 if (att->Renderbuffer && numSamples < 0) { 771 /* first buffer */ 772 numSamples = att->Renderbuffer->NumSamples; 773 } 774 775 /* check if integer color */ 776 fb->_IntegerColor = _mesa_is_format_integer_color(attFormat); 777 778 /* Error-check width, height, format, samples 779 */ 780 if (numImages == 1) { 781 /* save format, num samples */ 782 if (i >= 0) { 783 intFormat = f; 784 } 785 } 786 else { 787 if (!ctx->Extensions.ARB_framebuffer_object) { 788 /* check that width, height, format are same */ 789 if (minWidth != maxWidth || minHeight != maxHeight) { 790 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; 791 fbo_incomplete("width or height mismatch", -1); 792 return; 793 } 794 /* check that all color buffers are the same format */ 795 if (intFormat != GL_NONE && f != intFormat) { 796 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; 797 fbo_incomplete("format mismatch", -1); 798 return; 799 } 800 } 801 if (att->Renderbuffer && 802 att->Renderbuffer->NumSamples != numSamples) { 803 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE; 804 fbo_incomplete("inconsistant number of samples", i); 805 return; 806 } 807 } 808 809 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported) 810 */ 811 if (att->Type == GL_RENDERBUFFER && 812 att->Renderbuffer->Format == MESA_FORMAT_NONE) { 813 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; 814 fbo_incomplete("unsupported renderbuffer format", i); 815 return; 816 } 817 } 818 819#if FEATURE_GL 820 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) { 821 /* Check that all DrawBuffers are present */ 822 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { 823 if (fb->ColorDrawBuffer[j] != GL_NONE) { 824 const struct gl_renderbuffer_attachment *att 825 = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); 826 assert(att); 827 if (att->Type == GL_NONE) { 828 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; 829 fbo_incomplete("missing drawbuffer", j); 830 return; 831 } 832 } 833 } 834 835 /* Check that the ReadBuffer is present */ 836 if (fb->ColorReadBuffer != GL_NONE) { 837 const struct gl_renderbuffer_attachment *att 838 = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer); 839 assert(att); 840 if (att->Type == GL_NONE) { 841 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; 842 fbo_incomplete("missing readbuffer", -1); 843 return; 844 } 845 } 846 } 847#else 848 (void) j; 849#endif 850 851 if (numImages == 0) { 852 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; 853 fbo_incomplete("no attachments", -1); 854 return; 855 } 856 857 /* Provisionally set status = COMPLETE ... */ 858 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; 859 860 /* ... but the driver may say the FB is incomplete. 861 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED 862 * if anything. 863 */ 864 if (ctx->Driver.ValidateFramebuffer) { 865 ctx->Driver.ValidateFramebuffer(ctx, fb); 866 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 867 fbo_incomplete("driver marked FBO as incomplete", -1); 868 } 869 } 870 871 if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) { 872 /* 873 * Note that if ARB_framebuffer_object is supported and the attached 874 * renderbuffers/textures are different sizes, the framebuffer 875 * width/height will be set to the smallest width/height. 876 */ 877 fb->Width = minWidth; 878 fb->Height = minHeight; 879 880 /* finally, update the visual info for the framebuffer */ 881 _mesa_update_framebuffer_visual(ctx, fb); 882 } 883} 884 885 886GLboolean GLAPIENTRY 887_mesa_IsRenderbufferEXT(GLuint renderbuffer) 888{ 889 GET_CURRENT_CONTEXT(ctx); 890 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 891 if (renderbuffer) { 892 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 893 if (rb != NULL && rb != &DummyRenderbuffer) 894 return GL_TRUE; 895 } 896 return GL_FALSE; 897} 898 899 900void GLAPIENTRY 901_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) 902{ 903 struct gl_renderbuffer *newRb; 904 GET_CURRENT_CONTEXT(ctx); 905 906 ASSERT_OUTSIDE_BEGIN_END(ctx); 907 908 if (target != GL_RENDERBUFFER_EXT) { 909 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)"); 910 return; 911 } 912 913 /* No need to flush here since the render buffer binding has no 914 * effect on rendering state. 915 */ 916 917 if (renderbuffer) { 918 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 919 if (newRb == &DummyRenderbuffer) { 920 /* ID was reserved, but no real renderbuffer object made yet */ 921 newRb = NULL; 922 } 923 else if (!newRb && ctx->Extensions.ARB_framebuffer_object) { 924 /* All RB IDs must be Gen'd */ 925 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)"); 926 return; 927 } 928 929 if (!newRb) { 930 /* create new renderbuffer object */ 931 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); 932 if (!newRb) { 933 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); 934 return; 935 } 936 ASSERT(newRb->AllocStorage); 937 _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); 938 newRb->RefCount = 1; /* referenced by hash table */ 939 } 940 } 941 else { 942 newRb = NULL; 943 } 944 945 ASSERT(newRb != &DummyRenderbuffer); 946 947 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb); 948} 949 950 951/** 952 * If the given renderbuffer is anywhere attached to the framebuffer, detach 953 * the renderbuffer. 954 * This is used when a renderbuffer object is deleted. 955 * The spec calls for unbinding. 956 */ 957static void 958detach_renderbuffer(struct gl_context *ctx, 959 struct gl_framebuffer *fb, 960 struct gl_renderbuffer *rb) 961{ 962 GLuint i; 963 for (i = 0; i < BUFFER_COUNT; i++) { 964 if (fb->Attachment[i].Renderbuffer == rb) { 965 _mesa_remove_attachment(ctx, &fb->Attachment[i]); 966 } 967 } 968 invalidate_framebuffer(fb); 969} 970 971 972void GLAPIENTRY 973_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) 974{ 975 GLint i; 976 GET_CURRENT_CONTEXT(ctx); 977 978 ASSERT_OUTSIDE_BEGIN_END(ctx); 979 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 980 981 for (i = 0; i < n; i++) { 982 if (renderbuffers[i] > 0) { 983 struct gl_renderbuffer *rb; 984 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); 985 if (rb) { 986 /* check if deleting currently bound renderbuffer object */ 987 if (rb == ctx->CurrentRenderbuffer) { 988 /* bind default */ 989 ASSERT(rb->RefCount >= 2); 990 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); 991 } 992 993 if (_mesa_is_user_fbo(ctx->DrawBuffer)) { 994 detach_renderbuffer(ctx, ctx->DrawBuffer, rb); 995 } 996 if (_mesa_is_user_fbo(ctx->ReadBuffer) 997 && ctx->ReadBuffer != ctx->DrawBuffer) { 998 detach_renderbuffer(ctx, ctx->ReadBuffer, rb); 999 } 1000 1001 /* Remove from hash table immediately, to free the ID. 1002 * But the object will not be freed until it's no longer 1003 * referenced anywhere else. 1004 */ 1005 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); 1006 1007 if (rb != &DummyRenderbuffer) { 1008 /* no longer referenced by hash table */ 1009 _mesa_reference_renderbuffer(&rb, NULL); 1010 } 1011 } 1012 } 1013 } 1014} 1015 1016 1017void GLAPIENTRY 1018_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) 1019{ 1020 GET_CURRENT_CONTEXT(ctx); 1021 GLuint first; 1022 GLint i; 1023 1024 ASSERT_OUTSIDE_BEGIN_END(ctx); 1025 1026 if (n < 0) { 1027 _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); 1028 return; 1029 } 1030 1031 if (!renderbuffers) 1032 return; 1033 1034 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); 1035 1036 for (i = 0; i < n; i++) { 1037 GLuint name = first + i; 1038 renderbuffers[i] = name; 1039 /* insert dummy placeholder into hash table */ 1040 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1041 _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); 1042 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1043 } 1044} 1045 1046 1047/** 1048 * Given an internal format token for a render buffer, return the 1049 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, 1050 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE, 1051 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc). 1052 * 1053 * This is similar to _mesa_base_tex_format() but the set of valid 1054 * internal formats is different. 1055 * 1056 * Note that even if a format is determined to be legal here, validation 1057 * of the FBO may fail if the format is not supported by the driver/GPU. 1058 * 1059 * \param internalFormat as passed to glRenderbufferStorage() 1060 * \return the base internal format, or 0 if internalFormat is illegal 1061 */ 1062GLenum 1063_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) 1064{ 1065 /* 1066 * Notes: some formats such as alpha, luminance, etc. were added 1067 * with GL_ARB_framebuffer_object. 1068 */ 1069 switch (internalFormat) { 1070 case GL_ALPHA: 1071 case GL_ALPHA4: 1072 case GL_ALPHA8: 1073 case GL_ALPHA12: 1074 case GL_ALPHA16: 1075 return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; 1076 case GL_LUMINANCE: 1077 case GL_LUMINANCE4: 1078 case GL_LUMINANCE8: 1079 case GL_LUMINANCE12: 1080 case GL_LUMINANCE16: 1081 return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; 1082 case GL_LUMINANCE_ALPHA: 1083 case GL_LUMINANCE4_ALPHA4: 1084 case GL_LUMINANCE6_ALPHA2: 1085 case GL_LUMINANCE8_ALPHA8: 1086 case GL_LUMINANCE12_ALPHA4: 1087 case GL_LUMINANCE12_ALPHA12: 1088 case GL_LUMINANCE16_ALPHA16: 1089 return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; 1090 case GL_INTENSITY: 1091 case GL_INTENSITY4: 1092 case GL_INTENSITY8: 1093 case GL_INTENSITY12: 1094 case GL_INTENSITY16: 1095 return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; 1096 case GL_RGB: 1097 case GL_R3_G3_B2: 1098 case GL_RGB4: 1099 case GL_RGB5: 1100 case GL_RGB8: 1101 case GL_RGB10: 1102 case GL_RGB12: 1103 case GL_RGB16: 1104 case GL_SRGB8_EXT: 1105 return GL_RGB; 1106 case GL_RGBA: 1107 case GL_RGBA2: 1108 case GL_RGBA4: 1109 case GL_RGB5_A1: 1110 case GL_RGBA8: 1111 case GL_RGB10_A2: 1112 case GL_RGBA12: 1113 case GL_RGBA16: 1114 case GL_SRGB8_ALPHA8_EXT: 1115 return GL_RGBA; 1116 case GL_STENCIL_INDEX: 1117 case GL_STENCIL_INDEX1_EXT: 1118 case GL_STENCIL_INDEX4_EXT: 1119 case GL_STENCIL_INDEX8_EXT: 1120 case GL_STENCIL_INDEX16_EXT: 1121 return GL_STENCIL_INDEX; 1122 case GL_DEPTH_COMPONENT: 1123 case GL_DEPTH_COMPONENT16: 1124 case GL_DEPTH_COMPONENT24: 1125 case GL_DEPTH_COMPONENT32: 1126 return GL_DEPTH_COMPONENT; 1127 case GL_DEPTH_STENCIL_EXT: 1128 case GL_DEPTH24_STENCIL8_EXT: 1129 if (ctx->Extensions.EXT_packed_depth_stencil) 1130 return GL_DEPTH_STENCIL_EXT; 1131 else 1132 return 0; 1133 case GL_DEPTH_COMPONENT32F: 1134 if (ctx->Extensions.ARB_depth_buffer_float) 1135 return GL_DEPTH_COMPONENT; 1136 else 1137 return 0; 1138 case GL_DEPTH32F_STENCIL8: 1139 if (ctx->Extensions.ARB_depth_buffer_float) 1140 return GL_DEPTH_STENCIL; 1141 else 1142 return 0; 1143 case GL_RED: 1144 case GL_R8: 1145 case GL_R16: 1146 return ctx->Extensions.ARB_texture_rg ? GL_RED : 0; 1147 case GL_RG: 1148 case GL_RG8: 1149 case GL_RG16: 1150 return ctx->Extensions.ARB_texture_rg ? GL_RG : 0; 1151 /* signed normalized texture formats */ 1152 case GL_RED_SNORM: 1153 case GL_R8_SNORM: 1154 case GL_R16_SNORM: 1155 return ctx->Extensions.EXT_texture_snorm ? GL_RED : 0; 1156 case GL_RG_SNORM: 1157 case GL_RG8_SNORM: 1158 case GL_RG16_SNORM: 1159 return ctx->Extensions.EXT_texture_snorm ? GL_RG : 0; 1160 case GL_RGB_SNORM: 1161 case GL_RGB8_SNORM: 1162 case GL_RGB16_SNORM: 1163 return ctx->Extensions.EXT_texture_snorm ? GL_RGB : 0; 1164 case GL_RGBA_SNORM: 1165 case GL_RGBA8_SNORM: 1166 case GL_RGBA16_SNORM: 1167 return ctx->Extensions.EXT_texture_snorm ? GL_RGBA : 0; 1168 case GL_ALPHA_SNORM: 1169 case GL_ALPHA8_SNORM: 1170 case GL_ALPHA16_SNORM: 1171 return ctx->Extensions.EXT_texture_snorm && 1172 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; 1173 case GL_LUMINANCE_SNORM: 1174 case GL_LUMINANCE8_SNORM: 1175 case GL_LUMINANCE16_SNORM: 1176 return ctx->Extensions.EXT_texture_snorm && 1177 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; 1178 case GL_LUMINANCE_ALPHA_SNORM: 1179 case GL_LUMINANCE8_ALPHA8_SNORM: 1180 case GL_LUMINANCE16_ALPHA16_SNORM: 1181 return ctx->Extensions.EXT_texture_snorm && 1182 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; 1183 case GL_INTENSITY_SNORM: 1184 case GL_INTENSITY8_SNORM: 1185 case GL_INTENSITY16_SNORM: 1186 return ctx->Extensions.EXT_texture_snorm && 1187 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; 1188 case GL_R16F: 1189 case GL_R32F: 1190 return ctx->Extensions.ARB_texture_rg && 1191 ctx->Extensions.ARB_texture_float ? GL_RED : 0; 1192 case GL_RG16F: 1193 case GL_RG32F: 1194 return ctx->Extensions.ARB_texture_rg && 1195 ctx->Extensions.ARB_texture_float ? GL_RG : 0; 1196 case GL_RGB16F: 1197 case GL_RGB32F: 1198 return ctx->Extensions.ARB_texture_float ? GL_RGB : 0; 1199 case GL_RGBA16F: 1200 case GL_RGBA32F: 1201 return ctx->Extensions.ARB_texture_float ? GL_RGBA : 0; 1202 case GL_ALPHA16F_ARB: 1203 case GL_ALPHA32F_ARB: 1204 return ctx->Extensions.ARB_texture_float && 1205 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; 1206 case GL_LUMINANCE16F_ARB: 1207 case GL_LUMINANCE32F_ARB: 1208 return ctx->Extensions.ARB_texture_float && 1209 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; 1210 case GL_LUMINANCE_ALPHA16F_ARB: 1211 case GL_LUMINANCE_ALPHA32F_ARB: 1212 return ctx->Extensions.ARB_texture_float && 1213 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; 1214 case GL_INTENSITY16F_ARB: 1215 case GL_INTENSITY32F_ARB: 1216 return ctx->Extensions.ARB_texture_float && 1217 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; 1218 case GL_RGB9_E5: 1219 return ctx->Extensions.EXT_texture_shared_exponent ? GL_RGB : 0; 1220 case GL_R11F_G11F_B10F: 1221 return ctx->Extensions.EXT_packed_float ? GL_RGB : 0; 1222 1223 case GL_RGBA8UI_EXT: 1224 case GL_RGBA16UI_EXT: 1225 case GL_RGBA32UI_EXT: 1226 case GL_RGBA8I_EXT: 1227 case GL_RGBA16I_EXT: 1228 case GL_RGBA32I_EXT: 1229 return ctx->Version >= 30 || 1230 ctx->Extensions.EXT_texture_integer ? GL_RGBA : 0; 1231 1232 case GL_RGB8UI_EXT: 1233 case GL_RGB16UI_EXT: 1234 case GL_RGB32UI_EXT: 1235 case GL_RGB8I_EXT: 1236 case GL_RGB16I_EXT: 1237 case GL_RGB32I_EXT: 1238 return ctx->Version >= 30 || 1239 ctx->Extensions.EXT_texture_integer ? GL_RGB : 0; 1240 1241 case GL_R8UI: 1242 case GL_R8I: 1243 case GL_R16UI: 1244 case GL_R16I: 1245 case GL_R32UI: 1246 case GL_R32I: 1247 return ctx->Version >= 30 || 1248 (ctx->Extensions.ARB_texture_rg && 1249 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0; 1250 1251 case GL_RG8UI: 1252 case GL_RG8I: 1253 case GL_RG16UI: 1254 case GL_RG16I: 1255 case GL_RG32UI: 1256 case GL_RG32I: 1257 return ctx->Version >= 30 || 1258 (ctx->Extensions.ARB_texture_rg && 1259 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0; 1260 1261 case GL_INTENSITY8I_EXT: 1262 case GL_INTENSITY8UI_EXT: 1263 case GL_INTENSITY16I_EXT: 1264 case GL_INTENSITY16UI_EXT: 1265 case GL_INTENSITY32I_EXT: 1266 case GL_INTENSITY32UI_EXT: 1267 return ctx->Extensions.EXT_texture_integer && 1268 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; 1269 1270 case GL_LUMINANCE8I_EXT: 1271 case GL_LUMINANCE8UI_EXT: 1272 case GL_LUMINANCE16I_EXT: 1273 case GL_LUMINANCE16UI_EXT: 1274 case GL_LUMINANCE32I_EXT: 1275 case GL_LUMINANCE32UI_EXT: 1276 return ctx->Extensions.EXT_texture_integer && 1277 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; 1278 1279 case GL_LUMINANCE_ALPHA8I_EXT: 1280 case GL_LUMINANCE_ALPHA8UI_EXT: 1281 case GL_LUMINANCE_ALPHA16I_EXT: 1282 case GL_LUMINANCE_ALPHA16UI_EXT: 1283 case GL_LUMINANCE_ALPHA32I_EXT: 1284 case GL_LUMINANCE_ALPHA32UI_EXT: 1285 return ctx->Extensions.EXT_texture_integer && 1286 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; 1287 1288 case GL_ALPHA8I_EXT: 1289 case GL_ALPHA8UI_EXT: 1290 case GL_ALPHA16I_EXT: 1291 case GL_ALPHA16UI_EXT: 1292 case GL_ALPHA32I_EXT: 1293 case GL_ALPHA32UI_EXT: 1294 return ctx->Extensions.EXT_texture_integer && 1295 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; 1296 1297 case GL_RGB10_A2UI: 1298 return ctx->Extensions.ARB_texture_rgb10_a2ui ? GL_RGBA : 0; 1299 1300 case GL_RGB565: 1301 return ctx->Extensions.ARB_ES2_compatibility ? GL_RGB : 0; 1302 default: 1303 return 0; 1304 } 1305} 1306 1307 1308/** 1309 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk(). 1310 */ 1311static void 1312invalidate_rb(GLuint key, void *data, void *userData) 1313{ 1314 struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 1315 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData; 1316 1317 /* If this is a user-created FBO */ 1318 if (_mesa_is_user_fbo(fb)) { 1319 GLuint i; 1320 for (i = 0; i < BUFFER_COUNT; i++) { 1321 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 1322 if (att->Type == GL_RENDERBUFFER && 1323 att->Renderbuffer == rb) { 1324 /* Mark fb status as indeterminate to force re-validation */ 1325 fb->_Status = 0; 1326 return; 1327 } 1328 } 1329 } 1330} 1331 1332 1333/** sentinal value, see below */ 1334#define NO_SAMPLES 1000 1335 1336 1337/** 1338 * Helper function used by _mesa_RenderbufferStorageEXT() and 1339 * _mesa_RenderbufferStorageMultisample(). 1340 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT(). 1341 */ 1342static void 1343renderbuffer_storage(GLenum target, GLenum internalFormat, 1344 GLsizei width, GLsizei height, GLsizei samples) 1345{ 1346 const char *func = samples == NO_SAMPLES ? 1347 "glRenderbufferStorage" : "RenderbufferStorageMultisample"; 1348 struct gl_renderbuffer *rb; 1349 GLenum baseFormat; 1350 GET_CURRENT_CONTEXT(ctx); 1351 1352 ASSERT_OUTSIDE_BEGIN_END(ctx); 1353 1354 if (target != GL_RENDERBUFFER_EXT) { 1355 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); 1356 return; 1357 } 1358 1359 baseFormat = _mesa_base_fbo_format(ctx, internalFormat); 1360 if (baseFormat == 0) { 1361 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func); 1362 return; 1363 } 1364 1365 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { 1366 _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); 1367 return; 1368 } 1369 1370 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) { 1371 _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func); 1372 return; 1373 } 1374 1375 if (samples == NO_SAMPLES) { 1376 /* NumSamples == 0 indicates non-multisampling */ 1377 samples = 0; 1378 } 1379 else if (samples > (GLsizei) ctx->Const.MaxSamples) { 1380 /* note: driver may choose to use more samples than what's requested */ 1381 _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func); 1382 return; 1383 } 1384 1385 rb = ctx->CurrentRenderbuffer; 1386 if (!rb) { 1387 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); 1388 return; 1389 } 1390 1391 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1392 1393 if (rb->InternalFormat == internalFormat && 1394 rb->Width == (GLuint) width && 1395 rb->Height == (GLuint) height && 1396 rb->NumSamples == samples) { 1397 /* no change in allocation needed */ 1398 return; 1399 } 1400 1401 /* These MUST get set by the AllocStorage func */ 1402 rb->Format = MESA_FORMAT_NONE; 1403 rb->NumSamples = samples; 1404 1405 /* Now allocate the storage */ 1406 ASSERT(rb->AllocStorage); 1407 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { 1408 /* No error - check/set fields now */ 1409 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */ 1410 assert(rb->Width == (GLuint) width); 1411 assert(rb->Height == (GLuint) height); 1412 rb->InternalFormat = internalFormat; 1413 rb->_BaseFormat = baseFormat; 1414 assert(rb->_BaseFormat != 0); 1415 } 1416 else { 1417 /* Probably ran out of memory - clear the fields */ 1418 rb->Width = 0; 1419 rb->Height = 0; 1420 rb->Format = MESA_FORMAT_NONE; 1421 rb->InternalFormat = GL_NONE; 1422 rb->_BaseFormat = GL_NONE; 1423 rb->NumSamples = 0; 1424 } 1425 1426 /* Invalidate the framebuffers the renderbuffer is attached in. */ 1427 if (rb->AttachedAnytime) { 1428 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb); 1429 } 1430} 1431 1432 1433#if FEATURE_OES_EGL_image 1434void GLAPIENTRY 1435_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) 1436{ 1437 struct gl_renderbuffer *rb; 1438 GET_CURRENT_CONTEXT(ctx); 1439 ASSERT_OUTSIDE_BEGIN_END(ctx); 1440 1441 if (!ctx->Extensions.OES_EGL_image) { 1442 _mesa_error(ctx, GL_INVALID_OPERATION, 1443 "glEGLImageTargetRenderbufferStorageOES(unsupported)"); 1444 return; 1445 } 1446 1447 if (target != GL_RENDERBUFFER) { 1448 _mesa_error(ctx, GL_INVALID_ENUM, 1449 "EGLImageTargetRenderbufferStorageOES"); 1450 return; 1451 } 1452 1453 rb = ctx->CurrentRenderbuffer; 1454 if (!rb) { 1455 _mesa_error(ctx, GL_INVALID_OPERATION, 1456 "EGLImageTargetRenderbufferStorageOES"); 1457 return; 1458 } 1459 1460 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1461 1462 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image); 1463} 1464#endif 1465 1466 1467/** 1468 * Helper function for _mesa_GetRenderbufferParameterivEXT() and 1469 * _mesa_GetFramebufferAttachmentParameterivEXT() 1470 * We have to be careful to respect the base format. For example, if a 1471 * renderbuffer/texture was created with internalFormat=GL_RGB but the 1472 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE 1473 * we need to return zero. 1474 */ 1475static GLint 1476get_component_bits(GLenum pname, GLenum baseFormat, gl_format format) 1477{ 1478 if (_mesa_base_format_has_channel(baseFormat, pname)) 1479 return _mesa_get_format_bits(format, pname); 1480 else 1481 return 0; 1482} 1483 1484 1485 1486void GLAPIENTRY 1487_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, 1488 GLsizei width, GLsizei height) 1489{ 1490 /* GL_ARB_fbo says calling this function is equivalent to calling 1491 * glRenderbufferStorageMultisample() with samples=0. We pass in 1492 * a token value here just for error reporting purposes. 1493 */ 1494 renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES); 1495} 1496 1497 1498void GLAPIENTRY 1499_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, 1500 GLenum internalFormat, 1501 GLsizei width, GLsizei height) 1502{ 1503 renderbuffer_storage(target, internalFormat, width, height, samples); 1504} 1505 1506 1507/** 1508 * OpenGL ES version of glRenderBufferStorage. 1509 */ 1510void GLAPIENTRY 1511_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, 1512 GLsizei width, GLsizei height) 1513{ 1514 switch (internalFormat) { 1515 case GL_RGB565: 1516 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */ 1517 /* choose a closest format */ 1518 internalFormat = GL_RGB5; 1519 break; 1520 default: 1521 break; 1522 } 1523 1524 renderbuffer_storage(target, internalFormat, width, height, 0); 1525} 1526 1527 1528void GLAPIENTRY 1529_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) 1530{ 1531 struct gl_renderbuffer *rb; 1532 GET_CURRENT_CONTEXT(ctx); 1533 1534 ASSERT_OUTSIDE_BEGIN_END(ctx); 1535 1536 if (target != GL_RENDERBUFFER_EXT) { 1537 _mesa_error(ctx, GL_INVALID_ENUM, 1538 "glGetRenderbufferParameterivEXT(target)"); 1539 return; 1540 } 1541 1542 rb = ctx->CurrentRenderbuffer; 1543 if (!rb) { 1544 _mesa_error(ctx, GL_INVALID_OPERATION, 1545 "glGetRenderbufferParameterivEXT"); 1546 return; 1547 } 1548 1549 /* No need to flush here since we're just quering state which is 1550 * not effected by rendering. 1551 */ 1552 1553 switch (pname) { 1554 case GL_RENDERBUFFER_WIDTH_EXT: 1555 *params = rb->Width; 1556 return; 1557 case GL_RENDERBUFFER_HEIGHT_EXT: 1558 *params = rb->Height; 1559 return; 1560 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT: 1561 *params = rb->InternalFormat; 1562 return; 1563 case GL_RENDERBUFFER_RED_SIZE_EXT: 1564 case GL_RENDERBUFFER_GREEN_SIZE_EXT: 1565 case GL_RENDERBUFFER_BLUE_SIZE_EXT: 1566 case GL_RENDERBUFFER_ALPHA_SIZE_EXT: 1567 case GL_RENDERBUFFER_DEPTH_SIZE_EXT: 1568 case GL_RENDERBUFFER_STENCIL_SIZE_EXT: 1569 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format); 1570 break; 1571 case GL_RENDERBUFFER_SAMPLES: 1572 if (ctx->Extensions.ARB_framebuffer_object) { 1573 *params = rb->NumSamples; 1574 break; 1575 } 1576 /* fallthrough */ 1577 default: 1578 _mesa_error(ctx, GL_INVALID_ENUM, 1579 "glGetRenderbufferParameterivEXT(target)"); 1580 return; 1581 } 1582} 1583 1584 1585GLboolean GLAPIENTRY 1586_mesa_IsFramebufferEXT(GLuint framebuffer) 1587{ 1588 GET_CURRENT_CONTEXT(ctx); 1589 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1590 if (framebuffer) { 1591 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer); 1592 if (rb != NULL && rb != &DummyFramebuffer) 1593 return GL_TRUE; 1594 } 1595 return GL_FALSE; 1596} 1597 1598 1599/** 1600 * Check if any of the attachments of the given framebuffer are textures 1601 * (render to texture). Call ctx->Driver.RenderTexture() for such 1602 * attachments. 1603 */ 1604static void 1605check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) 1606{ 1607 GLuint i; 1608 ASSERT(ctx->Driver.RenderTexture); 1609 1610 if (_mesa_is_winsys_fbo(fb)) 1611 return; /* can't render to texture with winsys framebuffers */ 1612 1613 for (i = 0; i < BUFFER_COUNT; i++) { 1614 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 1615 if (att->Texture && _mesa_get_attachment_teximage(att)) { 1616 ctx->Driver.RenderTexture(ctx, fb, att); 1617 } 1618 } 1619} 1620 1621 1622/** 1623 * Examine all the framebuffer's attachments to see if any are textures. 1624 * If so, call ctx->Driver.FinishRenderTexture() for each texture to 1625 * notify the device driver that the texture image may have changed. 1626 */ 1627static void 1628check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) 1629{ 1630 if (_mesa_is_winsys_fbo(fb)) 1631 return; /* can't render to texture with winsys framebuffers */ 1632 1633 if (ctx->Driver.FinishRenderTexture) { 1634 GLuint i; 1635 for (i = 0; i < BUFFER_COUNT; i++) { 1636 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 1637 if (att->Texture && att->Renderbuffer) { 1638 ctx->Driver.FinishRenderTexture(ctx, att); 1639 } 1640 } 1641 } 1642} 1643 1644 1645void GLAPIENTRY 1646_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) 1647{ 1648 struct gl_framebuffer *newDrawFb, *newReadFb; 1649 struct gl_framebuffer *oldDrawFb, *oldReadFb; 1650 GLboolean bindReadBuf, bindDrawBuf; 1651 GET_CURRENT_CONTEXT(ctx); 1652 1653#ifdef DEBUG 1654 if (ctx->Extensions.ARB_framebuffer_object) { 1655 ASSERT(ctx->Extensions.EXT_framebuffer_object); 1656 ASSERT(ctx->Extensions.EXT_framebuffer_blit); 1657 } 1658#endif 1659 1660 ASSERT_OUTSIDE_BEGIN_END(ctx); 1661 1662 if (!ctx->Extensions.EXT_framebuffer_object) { 1663 _mesa_error(ctx, GL_INVALID_OPERATION, 1664 "glBindFramebufferEXT(unsupported)"); 1665 return; 1666 } 1667 1668 switch (target) { 1669#if FEATURE_EXT_framebuffer_blit 1670 case GL_DRAW_FRAMEBUFFER_EXT: 1671 if (!ctx->Extensions.EXT_framebuffer_blit) { 1672 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); 1673 return; 1674 } 1675 bindDrawBuf = GL_TRUE; 1676 bindReadBuf = GL_FALSE; 1677 break; 1678 case GL_READ_FRAMEBUFFER_EXT: 1679 if (!ctx->Extensions.EXT_framebuffer_blit) { 1680 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); 1681 return; 1682 } 1683 bindDrawBuf = GL_FALSE; 1684 bindReadBuf = GL_TRUE; 1685 break; 1686#endif 1687 case GL_FRAMEBUFFER_EXT: 1688 bindDrawBuf = GL_TRUE; 1689 bindReadBuf = GL_TRUE; 1690 break; 1691 default: 1692 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); 1693 return; 1694 } 1695 1696 if (framebuffer) { 1697 /* Binding a user-created framebuffer object */ 1698 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer); 1699 if (newDrawFb == &DummyFramebuffer) { 1700 /* ID was reserved, but no real framebuffer object made yet */ 1701 newDrawFb = NULL; 1702 } 1703 else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) { 1704 /* All FBO IDs must be Gen'd */ 1705 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)"); 1706 return; 1707 } 1708 1709 if (!newDrawFb) { 1710 /* create new framebuffer object */ 1711 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); 1712 if (!newDrawFb) { 1713 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); 1714 return; 1715 } 1716 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb); 1717 } 1718 newReadFb = newDrawFb; 1719 } 1720 else { 1721 /* Binding the window system framebuffer (which was originally set 1722 * with MakeCurrent). 1723 */ 1724 newDrawFb = ctx->WinSysDrawBuffer; 1725 newReadFb = ctx->WinSysReadBuffer; 1726 } 1727 1728 ASSERT(newDrawFb); 1729 ASSERT(newDrawFb != &DummyFramebuffer); 1730 1731 /* save pointers to current/old framebuffers */ 1732 oldDrawFb = ctx->DrawBuffer; 1733 oldReadFb = ctx->ReadBuffer; 1734 1735 /* check if really changing bindings */ 1736 if (oldDrawFb == newDrawFb) 1737 bindDrawBuf = GL_FALSE; 1738 if (oldReadFb == newReadFb) 1739 bindReadBuf = GL_FALSE; 1740 1741 /* 1742 * OK, now bind the new Draw/Read framebuffers, if they're changing. 1743 * 1744 * We also check if we're beginning and/or ending render-to-texture. 1745 * When a framebuffer with texture attachments is unbound, call 1746 * ctx->Driver.FinishRenderTexture(). 1747 * When a framebuffer with texture attachments is bound, call 1748 * ctx->Driver.RenderTexture(). 1749 * 1750 * Note that if the ReadBuffer has texture attachments we don't consider 1751 * that a render-to-texture case. 1752 */ 1753 if (bindReadBuf) { 1754 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1755 1756 /* check if old readbuffer was render-to-texture */ 1757 check_end_texture_render(ctx, oldReadFb); 1758 1759 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb); 1760 } 1761 1762 if (bindDrawBuf) { 1763 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1764 1765 /* check if old framebuffer had any texture attachments */ 1766 if (oldDrawFb) 1767 check_end_texture_render(ctx, oldDrawFb); 1768 1769 /* check if newly bound framebuffer has any texture attachments */ 1770 check_begin_texture_render(ctx, newDrawFb); 1771 1772 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb); 1773 } 1774 1775 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) { 1776 ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb); 1777 } 1778} 1779 1780 1781void GLAPIENTRY 1782_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) 1783{ 1784 GLint i; 1785 GET_CURRENT_CONTEXT(ctx); 1786 1787 ASSERT_OUTSIDE_BEGIN_END(ctx); 1788 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 1789 1790 for (i = 0; i < n; i++) { 1791 if (framebuffers[i] > 0) { 1792 struct gl_framebuffer *fb; 1793 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); 1794 if (fb) { 1795 ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); 1796 1797 /* check if deleting currently bound framebuffer object */ 1798 if (ctx->Extensions.EXT_framebuffer_blit) { 1799 /* separate draw/read binding points */ 1800 if (fb == ctx->DrawBuffer) { 1801 /* bind default */ 1802 ASSERT(fb->RefCount >= 2); 1803 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); 1804 } 1805 if (fb == ctx->ReadBuffer) { 1806 /* bind default */ 1807 ASSERT(fb->RefCount >= 2); 1808 _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); 1809 } 1810 } 1811 else { 1812 /* only one binding point for read/draw buffers */ 1813 if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) { 1814 /* bind default */ 1815 ASSERT(fb->RefCount >= 2); 1816 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 1817 } 1818 } 1819 1820 /* remove from hash table immediately, to free the ID */ 1821 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); 1822 1823 if (fb != &DummyFramebuffer) { 1824 /* But the object will not be freed until it's no longer 1825 * bound in any context. 1826 */ 1827 _mesa_reference_framebuffer(&fb, NULL); 1828 } 1829 } 1830 } 1831 } 1832} 1833 1834 1835void GLAPIENTRY 1836_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) 1837{ 1838 GET_CURRENT_CONTEXT(ctx); 1839 GLuint first; 1840 GLint i; 1841 1842 ASSERT_OUTSIDE_BEGIN_END(ctx); 1843 1844 if (n < 0) { 1845 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)"); 1846 return; 1847 } 1848 1849 if (!framebuffers) 1850 return; 1851 1852 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n); 1853 1854 for (i = 0; i < n; i++) { 1855 GLuint name = first + i; 1856 framebuffers[i] = name; 1857 /* insert dummy placeholder into hash table */ 1858 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 1859 _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); 1860 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 1861 } 1862} 1863 1864 1865 1866GLenum GLAPIENTRY 1867_mesa_CheckFramebufferStatusEXT(GLenum target) 1868{ 1869 struct gl_framebuffer *buffer; 1870 GET_CURRENT_CONTEXT(ctx); 1871 1872 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 1873 1874 buffer = get_framebuffer_target(ctx, target); 1875 if (!buffer) { 1876 _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); 1877 return 0; 1878 } 1879 1880 if (_mesa_is_winsys_fbo(buffer)) { 1881 /* The window system / default framebuffer is always complete */ 1882 return GL_FRAMEBUFFER_COMPLETE_EXT; 1883 } 1884 1885 /* No need to flush here */ 1886 1887 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) { 1888 _mesa_test_framebuffer_completeness(ctx, buffer); 1889 } 1890 1891 return buffer->_Status; 1892} 1893 1894 1895/** 1896 * Replicate the src attachment point. Used by framebuffer_texture() when 1897 * the same texture is attached at GL_DEPTH_ATTACHMENT and 1898 * GL_STENCIL_ATTACHMENT. 1899 */ 1900static void 1901reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb, 1902 gl_buffer_index dst, 1903 gl_buffer_index src) 1904{ 1905 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst]; 1906 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src]; 1907 1908 assert(src_att->Texture != NULL); 1909 assert(src_att->Renderbuffer != NULL); 1910 1911 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture); 1912 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer); 1913 dst_att->Type = src_att->Type; 1914 dst_att->Complete = src_att->Complete; 1915 dst_att->TextureLevel = src_att->TextureLevel; 1916 dst_att->Zoffset = src_att->Zoffset; 1917} 1918 1919 1920/** 1921 * Common code called by glFramebufferTexture1D/2D/3DEXT() and 1922 * glFramebufferTextureLayerEXT(). 1923 * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll 1924 * get textarget=0 in that case. 1925 */ 1926static void 1927framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, 1928 GLenum attachment, GLenum textarget, GLuint texture, 1929 GLint level, GLint zoffset) 1930{ 1931 struct gl_renderbuffer_attachment *att; 1932 struct gl_texture_object *texObj = NULL; 1933 struct gl_framebuffer *fb; 1934 GLenum maxLevelsTarget; 1935 1936 ASSERT_OUTSIDE_BEGIN_END(ctx); 1937 1938 fb = get_framebuffer_target(ctx, target); 1939 if (!fb) { 1940 _mesa_error(ctx, GL_INVALID_ENUM, 1941 "glFramebufferTexture%sEXT(target=0x%x)", caller, target); 1942 return; 1943 } 1944 1945 /* check framebuffer binding */ 1946 if (_mesa_is_winsys_fbo(fb)) { 1947 _mesa_error(ctx, GL_INVALID_OPERATION, 1948 "glFramebufferTexture%sEXT", caller); 1949 return; 1950 } 1951 1952 /* The textarget, level, and zoffset parameters are only validated if 1953 * texture is non-zero. 1954 */ 1955 if (texture) { 1956 GLboolean err = GL_TRUE; 1957 1958 texObj = _mesa_lookup_texture(ctx, texture); 1959 if (texObj != NULL) { 1960 if (textarget == 0) { 1961 /* If textarget == 0 it means we're being called by 1962 * glFramebufferTextureLayer() and textarget is not used. 1963 * The only legal texture types for that function are 3D and 1964 * 1D/2D arrays textures. 1965 */ 1966 err = (texObj->Target != GL_TEXTURE_3D) && 1967 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && 1968 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); 1969 } 1970 else { 1971 /* Make sure textarget is consistent with the texture's type */ 1972 err = (texObj->Target == GL_TEXTURE_CUBE_MAP) 1973 ? !_mesa_is_cube_face(textarget) 1974 : (texObj->Target != textarget); 1975 } 1976 } 1977 else { 1978 /* can't render to a non-existant texture */ 1979 _mesa_error(ctx, GL_INVALID_OPERATION, 1980 "glFramebufferTexture%sEXT(non existant texture)", 1981 caller); 1982 return; 1983 } 1984 1985 if (err) { 1986 _mesa_error(ctx, GL_INVALID_OPERATION, 1987 "glFramebufferTexture%sEXT(texture target mismatch)", 1988 caller); 1989 return; 1990 } 1991 1992 if (texObj->Target == GL_TEXTURE_3D) { 1993 const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 1994 if (zoffset < 0 || zoffset >= maxSize) { 1995 _mesa_error(ctx, GL_INVALID_VALUE, 1996 "glFramebufferTexture%sEXT(zoffset)", caller); 1997 return; 1998 } 1999 } 2000 else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || 2001 (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) { 2002 if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) { 2003 _mesa_error(ctx, GL_INVALID_VALUE, 2004 "glFramebufferTexture%sEXT(layer)", caller); 2005 return; 2006 } 2007 } 2008 2009 maxLevelsTarget = textarget ? textarget : texObj->Target; 2010 if ((level < 0) || 2011 (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) { 2012 _mesa_error(ctx, GL_INVALID_VALUE, 2013 "glFramebufferTexture%sEXT(level)", caller); 2014 return; 2015 } 2016 } 2017 2018 att = _mesa_get_attachment(ctx, fb, attachment); 2019 if (att == NULL) { 2020 _mesa_error(ctx, GL_INVALID_ENUM, 2021 "glFramebufferTexture%sEXT(attachment)", caller); 2022 return; 2023 } 2024 2025 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2026 2027 _glthread_LOCK_MUTEX(fb->Mutex); 2028 if (texObj) { 2029 if (attachment == GL_DEPTH_ATTACHMENT && 2030 texObj == fb->Attachment[BUFFER_STENCIL].Texture && 2031 level == fb->Attachment[BUFFER_STENCIL].TextureLevel && 2032 _mesa_tex_target_to_face(textarget) == 2033 fb->Attachment[BUFFER_STENCIL].CubeMapFace && 2034 zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) { 2035 /* The texture object is already attached to the stencil attachment 2036 * point. Don't create a new renderbuffer; just reuse the stencil 2037 * attachment's. This is required to prevent a GL error in 2038 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL). 2039 */ 2040 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH, 2041 BUFFER_STENCIL); 2042 } else if (attachment == GL_STENCIL_ATTACHMENT && 2043 texObj == fb->Attachment[BUFFER_DEPTH].Texture && 2044 level == fb->Attachment[BUFFER_DEPTH].TextureLevel && 2045 _mesa_tex_target_to_face(textarget) == 2046 fb->Attachment[BUFFER_DEPTH].CubeMapFace && 2047 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) { 2048 /* As above, but with depth and stencil transposed. */ 2049 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL, 2050 BUFFER_DEPTH); 2051 } else { 2052 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget, 2053 level, zoffset); 2054 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 2055 /* Above we created a new renderbuffer and attached it to the 2056 * depth attachment point. Now attach it to the stencil attachment 2057 * point too. 2058 */ 2059 assert(att == &fb->Attachment[BUFFER_DEPTH]); 2060 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL, 2061 BUFFER_DEPTH); 2062 } 2063 } 2064 2065 /* Set the render-to-texture flag. We'll check this flag in 2066 * glTexImage() and friends to determine if we need to revalidate 2067 * any FBOs that might be rendering into this texture. 2068 * This flag never gets cleared since it's non-trivial to determine 2069 * when all FBOs might be done rendering to this texture. That's OK 2070 * though since it's uncommon to render to a texture then repeatedly 2071 * call glTexImage() to change images in the texture. 2072 */ 2073 texObj->_RenderToTexture = GL_TRUE; 2074 } 2075 else { 2076 _mesa_remove_attachment(ctx, att); 2077 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 2078 assert(att == &fb->Attachment[BUFFER_DEPTH]); 2079 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]); 2080 } 2081 } 2082 2083 invalidate_framebuffer(fb); 2084 2085 _glthread_UNLOCK_MUTEX(fb->Mutex); 2086} 2087 2088 2089 2090void GLAPIENTRY 2091_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, 2092 GLenum textarget, GLuint texture, GLint level) 2093{ 2094 GET_CURRENT_CONTEXT(ctx); 2095 2096 if (texture != 0) { 2097 GLboolean error; 2098 2099 switch (textarget) { 2100 case GL_TEXTURE_1D: 2101 error = GL_FALSE; 2102 break; 2103 case GL_TEXTURE_1D_ARRAY: 2104 error = !ctx->Extensions.EXT_texture_array; 2105 break; 2106 default: 2107 error = GL_TRUE; 2108 } 2109 2110 if (error) { 2111 _mesa_error(ctx, GL_INVALID_OPERATION, 2112 "glFramebufferTexture1DEXT(textarget=%s)", 2113 _mesa_lookup_enum_by_nr(textarget)); 2114 return; 2115 } 2116 } 2117 2118 framebuffer_texture(ctx, "1D", target, attachment, textarget, texture, 2119 level, 0); 2120} 2121 2122 2123void GLAPIENTRY 2124_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, 2125 GLenum textarget, GLuint texture, GLint level) 2126{ 2127 GET_CURRENT_CONTEXT(ctx); 2128 2129 if (texture != 0) { 2130 GLboolean error; 2131 2132 switch (textarget) { 2133 case GL_TEXTURE_2D: 2134 error = GL_FALSE; 2135 break; 2136 case GL_TEXTURE_RECTANGLE: 2137 error = !ctx->Extensions.NV_texture_rectangle; 2138 break; 2139 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2140 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2141 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2142 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2143 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2144 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2145 error = !ctx->Extensions.ARB_texture_cube_map; 2146 break; 2147 case GL_TEXTURE_2D_ARRAY: 2148 error = !ctx->Extensions.EXT_texture_array; 2149 break; 2150 default: 2151 error = GL_TRUE; 2152 } 2153 2154 if (error) { 2155 _mesa_error(ctx, GL_INVALID_OPERATION, 2156 "glFramebufferTexture2DEXT(textarget=%s)", 2157 _mesa_lookup_enum_by_nr(textarget)); 2158 return; 2159 } 2160 } 2161 2162 framebuffer_texture(ctx, "2D", target, attachment, textarget, texture, 2163 level, 0); 2164} 2165 2166 2167void GLAPIENTRY 2168_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, 2169 GLenum textarget, GLuint texture, 2170 GLint level, GLint zoffset) 2171{ 2172 GET_CURRENT_CONTEXT(ctx); 2173 2174 if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { 2175 _mesa_error(ctx, GL_INVALID_OPERATION, 2176 "glFramebufferTexture3DEXT(textarget)"); 2177 return; 2178 } 2179 2180 framebuffer_texture(ctx, "3D", target, attachment, textarget, texture, 2181 level, zoffset); 2182} 2183 2184 2185void GLAPIENTRY 2186_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment, 2187 GLuint texture, GLint level, GLint layer) 2188{ 2189 GET_CURRENT_CONTEXT(ctx); 2190 2191 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, 2192 level, layer); 2193} 2194 2195 2196void GLAPIENTRY 2197_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, 2198 GLenum renderbufferTarget, 2199 GLuint renderbuffer) 2200{ 2201 struct gl_renderbuffer_attachment *att; 2202 struct gl_framebuffer *fb; 2203 struct gl_renderbuffer *rb; 2204 GET_CURRENT_CONTEXT(ctx); 2205 2206 ASSERT_OUTSIDE_BEGIN_END(ctx); 2207 2208 fb = get_framebuffer_target(ctx, target); 2209 if (!fb) { 2210 _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); 2211 return; 2212 } 2213 2214 if (renderbufferTarget != GL_RENDERBUFFER_EXT) { 2215 _mesa_error(ctx, GL_INVALID_ENUM, 2216 "glFramebufferRenderbufferEXT(renderbufferTarget)"); 2217 return; 2218 } 2219 2220 if (_mesa_is_winsys_fbo(fb)) { 2221 /* Can't attach new renderbuffers to a window system framebuffer */ 2222 _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); 2223 return; 2224 } 2225 2226 att = _mesa_get_attachment(ctx, fb, attachment); 2227 if (att == NULL) { 2228 _mesa_error(ctx, GL_INVALID_ENUM, 2229 "glFramebufferRenderbufferEXT(invalid attachment %s)", 2230 _mesa_lookup_enum_by_nr(attachment)); 2231 return; 2232 } 2233 2234 if (renderbuffer) { 2235 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 2236 if (!rb) { 2237 _mesa_error(ctx, GL_INVALID_OPERATION, 2238 "glFramebufferRenderbufferEXT(non-existant" 2239 " renderbuffer %u)", renderbuffer); 2240 return; 2241 } 2242 else if (rb == &DummyRenderbuffer) { 2243 /* This is what NVIDIA does */ 2244 _mesa_error(ctx, GL_INVALID_VALUE, 2245 "glFramebufferRenderbufferEXT(renderbuffer %u)", 2246 renderbuffer); 2247 return; 2248 } 2249 } 2250 else { 2251 /* remove renderbuffer attachment */ 2252 rb = NULL; 2253 } 2254 2255 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT && 2256 rb && rb->Format != MESA_FORMAT_NONE) { 2257 /* make sure the renderbuffer is a depth/stencil format */ 2258 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); 2259 if (baseFormat != GL_DEPTH_STENCIL) { 2260 _mesa_error(ctx, GL_INVALID_OPERATION, 2261 "glFramebufferRenderbufferEXT(renderbuffer" 2262 " is not DEPTH_STENCIL format)"); 2263 return; 2264 } 2265 } 2266 2267 2268 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2269 2270 assert(ctx->Driver.FramebufferRenderbuffer); 2271 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); 2272 2273 /* Some subsequent GL commands may depend on the framebuffer's visual 2274 * after the binding is updated. Update visual info now. 2275 */ 2276 _mesa_update_framebuffer_visual(ctx, fb); 2277} 2278 2279 2280void GLAPIENTRY 2281_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, 2282 GLenum pname, GLint *params) 2283{ 2284 const struct gl_renderbuffer_attachment *att; 2285 struct gl_framebuffer *buffer; 2286 GLenum err; 2287 GET_CURRENT_CONTEXT(ctx); 2288 2289 ASSERT_OUTSIDE_BEGIN_END(ctx); 2290 2291 /* The error differs in GL and GLES. */ 2292 err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM; 2293 2294 buffer = get_framebuffer_target(ctx, target); 2295 if (!buffer) { 2296 _mesa_error(ctx, GL_INVALID_ENUM, 2297 "glGetFramebufferAttachmentParameterivEXT(target)"); 2298 return; 2299 } 2300 2301 if (_mesa_is_winsys_fbo(buffer)) { 2302 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec 2303 * says: 2304 * 2305 * "If the framebuffer currently bound to target is zero, then 2306 * INVALID_OPERATION is generated." 2307 * 2308 * The EXT_framebuffer_object spec has the same wording, and the 2309 * OES_framebuffer_object spec refers to the EXT_framebuffer_object 2310 * spec. 2311 */ 2312 if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) { 2313 _mesa_error(ctx, GL_INVALID_OPERATION, 2314 "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); 2315 return; 2316 } 2317 /* the default / window-system FBO */ 2318 att = _mesa_get_fb0_attachment(ctx, buffer, attachment); 2319 } 2320 else { 2321 /* user-created framebuffer FBO */ 2322 att = _mesa_get_attachment(ctx, buffer, attachment); 2323 } 2324 2325 if (att == NULL) { 2326 _mesa_error(ctx, GL_INVALID_ENUM, 2327 "glGetFramebufferAttachmentParameterivEXT(attachment)"); 2328 return; 2329 } 2330 2331 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 2332 /* the depth and stencil attachments must point to the same buffer */ 2333 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt; 2334 depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT); 2335 stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); 2336 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) { 2337 _mesa_error(ctx, GL_INVALID_OPERATION, 2338 "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL" 2339 " attachments differ)"); 2340 return; 2341 } 2342 } 2343 2344 /* No need to flush here */ 2345 2346 switch (pname) { 2347 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: 2348 *params = _mesa_is_winsys_fbo(buffer) 2349 ? GL_FRAMEBUFFER_DEFAULT : att->Type; 2350 return; 2351 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: 2352 if (att->Type == GL_RENDERBUFFER_EXT) { 2353 *params = att->Renderbuffer->Name; 2354 } 2355 else if (att->Type == GL_TEXTURE) { 2356 *params = att->Texture->Name; 2357 } 2358 else { 2359 assert(att->Type == GL_NONE); 2360 if (_mesa_is_desktop_gl(ctx)) { 2361 *params = 0; 2362 } else { 2363 _mesa_error(ctx, GL_INVALID_ENUM, 2364 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2365 } 2366 } 2367 return; 2368 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: 2369 if (att->Type == GL_TEXTURE) { 2370 *params = att->TextureLevel; 2371 } 2372 else if (att->Type == GL_NONE) { 2373 _mesa_error(ctx, err, 2374 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2375 } 2376 else { 2377 _mesa_error(ctx, GL_INVALID_ENUM, 2378 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2379 } 2380 return; 2381 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: 2382 if (att->Type == GL_TEXTURE) { 2383 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) { 2384 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace; 2385 } 2386 else { 2387 *params = 0; 2388 } 2389 } 2390 else if (att->Type == GL_NONE) { 2391 _mesa_error(ctx, err, 2392 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2393 } 2394 else { 2395 _mesa_error(ctx, GL_INVALID_ENUM, 2396 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2397 } 2398 return; 2399 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: 2400 if (att->Type == GL_TEXTURE) { 2401 if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) { 2402 *params = att->Zoffset; 2403 } 2404 else { 2405 *params = 0; 2406 } 2407 } 2408 else if (att->Type == GL_NONE) { 2409 _mesa_error(ctx, err, 2410 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2411 } 2412 else { 2413 _mesa_error(ctx, GL_INVALID_ENUM, 2414 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2415 } 2416 return; 2417 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: 2418 if (!ctx->Extensions.ARB_framebuffer_object) { 2419 _mesa_error(ctx, GL_INVALID_ENUM, 2420 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2421 } 2422 else if (att->Type == GL_NONE) { 2423 _mesa_error(ctx, err, 2424 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2425 } 2426 else { 2427 if (ctx->Extensions.EXT_framebuffer_sRGB) { 2428 *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); 2429 } 2430 else { 2431 /* According to ARB_framebuffer_sRGB, we should return LINEAR 2432 * if the sRGB conversion is unsupported. */ 2433 *params = GL_LINEAR; 2434 } 2435 } 2436 return; 2437 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: 2438 if (!ctx->Extensions.ARB_framebuffer_object) { 2439 _mesa_error(ctx, GL_INVALID_ENUM, 2440 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2441 return; 2442 } 2443 else if (att->Type == GL_NONE) { 2444 _mesa_error(ctx, err, 2445 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2446 } 2447 else { 2448 gl_format format = att->Renderbuffer->Format; 2449 if (format == MESA_FORMAT_S8) { 2450 /* special cases */ 2451 *params = GL_INDEX; 2452 } 2453 else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) { 2454 /* depends on the attachment parameter */ 2455 if (attachment == GL_STENCIL_ATTACHMENT) { 2456 *params = GL_INDEX; 2457 } 2458 else { 2459 *params = GL_FLOAT; 2460 } 2461 } 2462 else { 2463 *params = _mesa_get_format_datatype(format); 2464 } 2465 } 2466 return; 2467 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: 2468 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: 2469 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: 2470 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: 2471 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: 2472 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: 2473 if (!ctx->Extensions.ARB_framebuffer_object) { 2474 _mesa_error(ctx, GL_INVALID_ENUM, 2475 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2476 } 2477 else if (att->Type == GL_NONE) { 2478 _mesa_error(ctx, err, 2479 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2480 } 2481 else if (att->Texture) { 2482 const struct gl_texture_image *texImage = 2483 _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target, 2484 att->TextureLevel); 2485 if (texImage) { 2486 *params = get_component_bits(pname, texImage->_BaseFormat, 2487 texImage->TexFormat); 2488 } 2489 else { 2490 *params = 0; 2491 } 2492 } 2493 else if (att->Renderbuffer) { 2494 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat, 2495 att->Renderbuffer->Format); 2496 } 2497 else { 2498 _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:" 2499 " invalid FBO attachment structure"); 2500 } 2501 return; 2502 default: 2503 _mesa_error(ctx, GL_INVALID_ENUM, 2504 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2505 return; 2506 } 2507} 2508 2509 2510void GLAPIENTRY 2511_mesa_GenerateMipmapEXT(GLenum target) 2512{ 2513 struct gl_texture_image *srcImage; 2514 struct gl_texture_object *texObj; 2515 GLboolean error; 2516 2517 GET_CURRENT_CONTEXT(ctx); 2518 2519 ASSERT_OUTSIDE_BEGIN_END(ctx); 2520 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2521 2522 switch (target) { 2523 case GL_TEXTURE_1D: 2524 case GL_TEXTURE_2D: 2525 case GL_TEXTURE_3D: 2526 error = GL_FALSE; 2527 break; 2528 case GL_TEXTURE_CUBE_MAP: 2529 error = !ctx->Extensions.ARB_texture_cube_map; 2530 break; 2531 case GL_TEXTURE_1D_ARRAY: 2532 case GL_TEXTURE_2D_ARRAY: 2533 error = !ctx->Extensions.EXT_texture_array; 2534 break; 2535 default: 2536 error = GL_TRUE; 2537 } 2538 2539 if (error) { 2540 _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)", 2541 _mesa_lookup_enum_by_nr(target)); 2542 return; 2543 } 2544 2545 texObj = _mesa_get_current_tex_object(ctx, target); 2546 2547 if (texObj->BaseLevel >= texObj->MaxLevel) { 2548 /* nothing to do */ 2549 return; 2550 } 2551 2552 if (texObj->Target == GL_TEXTURE_CUBE_MAP && 2553 !_mesa_cube_complete(texObj)) { 2554 _mesa_error(ctx, GL_INVALID_OPERATION, 2555 "glGenerateMipmap(incomplete cube map)"); 2556 return; 2557 } 2558 2559 _mesa_lock_texture(ctx, texObj); 2560 2561 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); 2562 if (!srcImage) { 2563 _mesa_unlock_texture(ctx, texObj); 2564 return; 2565 } 2566 2567 if (target == GL_TEXTURE_CUBE_MAP) { 2568 GLuint face; 2569 for (face = 0; face < 6; face++) 2570 ctx->Driver.GenerateMipmap(ctx, 2571 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, 2572 texObj); 2573 } 2574 else { 2575 ctx->Driver.GenerateMipmap(ctx, target, texObj); 2576 } 2577 _mesa_unlock_texture(ctx, texObj); 2578} 2579 2580 2581#if FEATURE_EXT_framebuffer_blit 2582 2583static const struct gl_renderbuffer_attachment * 2584find_attachment(const struct gl_framebuffer *fb, 2585 const struct gl_renderbuffer *rb) 2586{ 2587 GLuint i; 2588 for (i = 0; i < Elements(fb->Attachment); i++) { 2589 if (fb->Attachment[i].Renderbuffer == rb) 2590 return &fb->Attachment[i]; 2591 } 2592 return NULL; 2593} 2594 2595 2596/** 2597 * Helper function for checking if the datatypes of color buffers are 2598 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198: 2599 * 2600 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT 2601 * and any of the following conditions hold: 2602 * - The read buffer contains fixed-point or floating-point values and any 2603 * draw buffer contains neither fixed-point nor floating-point values. 2604 * - The read buffer contains unsigned integer values and any draw buffer 2605 * does not contain unsigned integer values. 2606 * - The read buffer contains signed integer values and any draw buffer 2607 * does not contain signed integer values." 2608 */ 2609static GLboolean 2610compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat) 2611{ 2612 GLenum srcType = _mesa_get_format_datatype(srcFormat); 2613 GLenum dstType = _mesa_get_format_datatype(dstFormat); 2614 2615 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) { 2616 assert(srcType == GL_UNSIGNED_NORMALIZED || 2617 srcType == GL_SIGNED_NORMALIZED || 2618 srcType == GL_FLOAT); 2619 /* Boil any of those types down to GL_FLOAT */ 2620 srcType = GL_FLOAT; 2621 } 2622 2623 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) { 2624 assert(dstType == GL_UNSIGNED_NORMALIZED || 2625 dstType == GL_SIGNED_NORMALIZED || 2626 dstType == GL_FLOAT); 2627 /* Boil any of those types down to GL_FLOAT */ 2628 dstType = GL_FLOAT; 2629 } 2630 2631 return srcType == dstType; 2632} 2633 2634 2635/** 2636 * Return the equivalent non-generic internal format. 2637 * This is useful for comparing whether two internal formats are semantically 2638 * equivalent. 2639 */ 2640static GLenum 2641get_nongeneric_internalformat(GLenum format) 2642{ 2643 switch (format) { 2644 /* GL 1.1 formats. */ 2645 case 4: 2646 case GL_RGBA: 2647 return GL_RGBA8; 2648 2649 case 3: 2650 case GL_RGB: 2651 return GL_RGB8; 2652 2653 case 2: 2654 case GL_LUMINANCE_ALPHA: 2655 return GL_LUMINANCE8_ALPHA8; 2656 2657 case 1: 2658 case GL_LUMINANCE: 2659 return GL_LUMINANCE8; 2660 2661 case GL_ALPHA: 2662 return GL_ALPHA8; 2663 2664 case GL_INTENSITY: 2665 return GL_INTENSITY8; 2666 2667 /* GL_ARB_texture_rg */ 2668 case GL_RED: 2669 return GL_R8; 2670 2671 case GL_RG: 2672 return GL_RG8; 2673 2674 /* GL_EXT_texture_sRGB */ 2675 case GL_SRGB: 2676 return GL_SRGB8; 2677 2678 case GL_SRGB_ALPHA: 2679 return GL_SRGB8_ALPHA8; 2680 2681 case GL_SLUMINANCE: 2682 return GL_SLUMINANCE8; 2683 2684 case GL_SLUMINANCE_ALPHA: 2685 return GL_SLUMINANCE8_ALPHA8; 2686 2687 /* GL_EXT_texture_snorm */ 2688 case GL_RGBA_SNORM: 2689 return GL_RGBA8_SNORM; 2690 2691 case GL_RGB_SNORM: 2692 return GL_RGB8_SNORM; 2693 2694 case GL_RG_SNORM: 2695 return GL_RG8_SNORM; 2696 2697 case GL_RED_SNORM: 2698 return GL_R8_SNORM; 2699 2700 case GL_LUMINANCE_ALPHA_SNORM: 2701 return GL_LUMINANCE8_ALPHA8_SNORM; 2702 2703 case GL_LUMINANCE_SNORM: 2704 return GL_LUMINANCE8_SNORM; 2705 2706 case GL_ALPHA_SNORM: 2707 return GL_ALPHA8_SNORM; 2708 2709 case GL_INTENSITY_SNORM: 2710 return GL_INTENSITY8_SNORM; 2711 2712 default: 2713 return format; 2714 } 2715} 2716 2717 2718static GLboolean 2719compatible_resolve_formats(const struct gl_renderbuffer *colorReadRb, 2720 const struct gl_renderbuffer *colorDrawRb) 2721{ 2722 /* The simple case where we know the backing formats are the same. 2723 */ 2724 if (colorReadRb->Format == colorDrawRb->Format) { 2725 return GL_TRUE; 2726 } 2727 2728 /* The Mesa formats are different, so we must check whether the internal 2729 * formats are compatible. 2730 * 2731 * Under some circumstances, the user may request e.g. two GL_RGBA8 2732 * textures and get two entirely different Mesa formats like RGBA8888 and 2733 * ARGB8888. Drivers behaving like that should be able to cope with 2734 * non-matching formats by themselves, because it's not the user's fault. 2735 */ 2736 if (get_nongeneric_internalformat(colorReadRb->InternalFormat) == 2737 get_nongeneric_internalformat(colorDrawRb->InternalFormat)) { 2738 return GL_TRUE; 2739 } 2740 2741 return GL_FALSE; 2742} 2743 2744 2745/** 2746 * Blit rectangular region, optionally from one framebuffer to another. 2747 * 2748 * Note, if the src buffer is multisampled and the dest is not, this is 2749 * when the samples must be resolved to a single color. 2750 */ 2751void GLAPIENTRY 2752_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 2753 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 2754 GLbitfield mask, GLenum filter) 2755{ 2756 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | 2757 GL_DEPTH_BUFFER_BIT | 2758 GL_STENCIL_BUFFER_BIT); 2759 const struct gl_framebuffer *readFb, *drawFb; 2760 const struct gl_renderbuffer *colorReadRb, *colorDrawRb; 2761 GET_CURRENT_CONTEXT(ctx); 2762 2763 ASSERT_OUTSIDE_BEGIN_END(ctx); 2764 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2765 2766 if (MESA_VERBOSE & VERBOSE_API) 2767 _mesa_debug(ctx, 2768 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", 2769 srcX0, srcY0, srcX1, srcY1, 2770 dstX0, dstY0, dstX1, dstY1, 2771 mask, _mesa_lookup_enum_by_nr(filter)); 2772 2773 if (ctx->NewState) { 2774 _mesa_update_state(ctx); 2775 } 2776 2777 readFb = ctx->ReadBuffer; 2778 drawFb = ctx->DrawBuffer; 2779 2780 if (!readFb || !drawFb) { 2781 /* This will normally never happen but someday we may want to 2782 * support MakeCurrent() with no drawables. 2783 */ 2784 return; 2785 } 2786 2787 /* check for complete framebuffers */ 2788 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || 2789 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 2790 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 2791 "glBlitFramebufferEXT(incomplete draw/read buffers)"); 2792 return; 2793 } 2794 2795 if (filter != GL_NEAREST && filter != GL_LINEAR) { 2796 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)"); 2797 return; 2798 } 2799 2800 if (mask & ~legalMaskBits) { 2801 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); 2802 return; 2803 } 2804 2805 /* depth/stencil must be blitted with nearest filtering */ 2806 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) 2807 && filter != GL_NEAREST) { 2808 _mesa_error(ctx, GL_INVALID_OPERATION, 2809 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); 2810 return; 2811 } 2812 2813 /* get color read/draw renderbuffers */ 2814 if (mask & GL_COLOR_BUFFER_BIT) { 2815 colorReadRb = readFb->_ColorReadBuffer; 2816 colorDrawRb = drawFb->_ColorDrawBuffers[0]; 2817 2818 /* From the EXT_framebuffer_object spec: 2819 * 2820 * "If a buffer is specified in <mask> and does not exist in both 2821 * the read and draw framebuffers, the corresponding bit is silently 2822 * ignored." 2823 */ 2824 if ((colorReadRb == NULL) || (colorDrawRb == NULL)) { 2825 colorReadRb = colorDrawRb = NULL; 2826 mask &= ~GL_COLOR_BUFFER_BIT; 2827 } 2828 else if (!compatible_color_datatypes(colorReadRb->Format, 2829 colorDrawRb->Format)) { 2830 _mesa_error(ctx, GL_INVALID_OPERATION, 2831 "glBlitFramebufferEXT(color buffer datatypes mismatch)"); 2832 return; 2833 } 2834 } 2835 else { 2836 colorReadRb = colorDrawRb = NULL; 2837 } 2838 2839 if (mask & GL_STENCIL_BUFFER_BIT) { 2840 struct gl_renderbuffer *readRb = 2841 readFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2842 struct gl_renderbuffer *drawRb = 2843 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2844 2845 /* From the EXT_framebuffer_object spec: 2846 * 2847 * "If a buffer is specified in <mask> and does not exist in both 2848 * the read and draw framebuffers, the corresponding bit is silently 2849 * ignored." 2850 */ 2851 if ((readRb == NULL) || (drawRb == NULL)) { 2852 mask &= ~GL_STENCIL_BUFFER_BIT; 2853 } 2854 else if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != 2855 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { 2856 /* There is no need to check the stencil datatype here, because 2857 * there is only one: GL_UNSIGNED_INT. 2858 */ 2859 _mesa_error(ctx, GL_INVALID_OPERATION, 2860 "glBlitFramebufferEXT(stencil buffer size mismatch)"); 2861 return; 2862 } 2863 } 2864 2865 if (mask & GL_DEPTH_BUFFER_BIT) { 2866 struct gl_renderbuffer *readRb = 2867 readFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2868 struct gl_renderbuffer *drawRb = 2869 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2870 2871 /* From the EXT_framebuffer_object spec: 2872 * 2873 * "If a buffer is specified in <mask> and does not exist in both 2874 * the read and draw framebuffers, the corresponding bit is silently 2875 * ignored." 2876 */ 2877 if ((readRb == NULL) || (drawRb == NULL)) { 2878 mask &= ~GL_DEPTH_BUFFER_BIT; 2879 } 2880 else if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != 2881 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || 2882 (_mesa_get_format_datatype(readRb->Format) != 2883 _mesa_get_format_datatype(drawRb->Format))) { 2884 _mesa_error(ctx, GL_INVALID_OPERATION, 2885 "glBlitFramebufferEXT(depth buffer format mismatch)"); 2886 return; 2887 } 2888 } 2889 2890 if (readFb->Visual.samples > 0 && 2891 drawFb->Visual.samples > 0 && 2892 readFb->Visual.samples != drawFb->Visual.samples) { 2893 _mesa_error(ctx, GL_INVALID_OPERATION, 2894 "glBlitFramebufferEXT(mismatched samples)"); 2895 return; 2896 } 2897 2898 /* extra checks for multisample copies... */ 2899 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { 2900 /* src and dest region sizes must be the same */ 2901 if (srcX1 - srcX0 != dstX1 - dstX0 || 2902 srcY1 - srcY0 != dstY1 - dstY0) { 2903 _mesa_error(ctx, GL_INVALID_OPERATION, 2904 "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); 2905 return; 2906 } 2907 2908 /* color formats must match */ 2909 if (colorReadRb && 2910 colorDrawRb && 2911 !compatible_resolve_formats(colorReadRb, colorDrawRb)) { 2912 _mesa_error(ctx, GL_INVALID_OPERATION, 2913 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); 2914 return; 2915 } 2916 } 2917 2918 if (filter == GL_LINEAR && (mask & GL_COLOR_BUFFER_BIT)) { 2919 /* 3.1 spec, page 199: 2920 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error 2921 * if filter is LINEAR and read buffer contains integer data." 2922 */ 2923 GLenum type = _mesa_get_format_datatype(colorReadRb->Format); 2924 if (type == GL_INT || type == GL_UNSIGNED_INT) { 2925 _mesa_error(ctx, GL_INVALID_OPERATION, 2926 "glBlitFramebufferEXT(integer color type)"); 2927 return; 2928 } 2929 } 2930 2931 if (!ctx->Extensions.EXT_framebuffer_blit) { 2932 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT"); 2933 return; 2934 } 2935 2936 /* Debug code */ 2937 if (DEBUG_BLIT) { 2938 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," 2939 " 0x%x, 0x%x)\n", 2940 srcX0, srcY0, srcX1, srcY1, 2941 dstX0, dstY0, dstX1, dstY1, 2942 mask, filter); 2943 if (colorReadRb) { 2944 const struct gl_renderbuffer_attachment *att; 2945 2946 att = find_attachment(readFb, colorReadRb); 2947 printf(" Src FBO %u RB %u (%dx%d) ", 2948 readFb->Name, colorReadRb->Name, 2949 colorReadRb->Width, colorReadRb->Height); 2950 if (att && att->Texture) { 2951 printf("Tex %u tgt 0x%x level %u face %u", 2952 att->Texture->Name, 2953 att->Texture->Target, 2954 att->TextureLevel, 2955 att->CubeMapFace); 2956 } 2957 printf("\n"); 2958 2959 att = find_attachment(drawFb, colorDrawRb); 2960 printf(" Dst FBO %u RB %u (%dx%d) ", 2961 drawFb->Name, colorDrawRb->Name, 2962 colorDrawRb->Width, colorDrawRb->Height); 2963 if (att && att->Texture) { 2964 printf("Tex %u tgt 0x%x level %u face %u", 2965 att->Texture->Name, 2966 att->Texture->Target, 2967 att->TextureLevel, 2968 att->CubeMapFace); 2969 } 2970 printf("\n"); 2971 } 2972 } 2973 2974 if (!mask) { 2975 return; 2976 } 2977 2978 ASSERT(ctx->Driver.BlitFramebuffer); 2979 ctx->Driver.BlitFramebuffer(ctx, 2980 srcX0, srcY0, srcX1, srcY1, 2981 dstX0, dstY0, dstX1, dstY1, 2982 mask, filter); 2983} 2984#endif /* FEATURE_EXT_framebuffer_blit */ 2985 2986 2987#if FEATURE_ARB_geometry_shader4 2988void GLAPIENTRY 2989_mesa_FramebufferTextureARB(GLenum target, GLenum attachment, 2990 GLuint texture, GLint level) 2991{ 2992 GET_CURRENT_CONTEXT(ctx); 2993 _mesa_error(ctx, GL_INVALID_OPERATION, 2994 "glFramebufferTextureARB " 2995 "not implemented!"); 2996} 2997 2998 2999void GLAPIENTRY 3000_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, 3001 GLuint texture, GLint level, GLenum face) 3002{ 3003 GET_CURRENT_CONTEXT(ctx); 3004 _mesa_error(ctx, GL_INVALID_OPERATION, 3005 "glFramebufferTextureFaceARB " 3006 "not implemented!"); 3007} 3008#endif /* FEATURE_ARB_geometry_shader4 */ 3009 3010static void 3011invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, 3012 const GLenum *attachments, GLint x, GLint y, 3013 GLsizei width, GLsizei height, const char *name) 3014{ 3015 int i; 3016 struct gl_framebuffer *fb; 3017 GET_CURRENT_CONTEXT(ctx); 3018 3019 ASSERT_OUTSIDE_BEGIN_END(ctx); 3020 3021 fb = get_framebuffer_target(ctx, target); 3022 if (!fb) { 3023 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name); 3024 return; 3025 } 3026 3027 if (numAttachments < 0) { 3028 _mesa_error(ctx, GL_INVALID_VALUE, 3029 "%s(numAttachments < 0)", name); 3030 return; 3031 } 3032 3033 /* The GL_ARB_invalidate_subdata spec says: 3034 * 3035 * "If an attachment is specified that does not exist in the 3036 * framebuffer bound to <target>, it is ignored." 3037 * 3038 * It also says: 3039 * 3040 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than 3041 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error 3042 * INVALID_OPERATION is generated." 3043 * 3044 * No mention is made of GL_AUXi being out of range. Therefore, we allow 3045 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different 3046 * set of retrictions). 3047 */ 3048 for (i = 0; i < numAttachments; i++) { 3049 if (_mesa_is_winsys_fbo(fb)) { 3050 switch (attachments[i]) { 3051 case GL_ACCUM: 3052 case GL_AUX0: 3053 case GL_AUX1: 3054 case GL_AUX2: 3055 case GL_AUX3: 3056 /* Accumulation buffers and auxilary buffers were removed in 3057 * OpenGL 3.1, and they never existed in OpenGL ES. 3058 */ 3059 if (ctx->API != API_OPENGL) 3060 goto invalid_enum; 3061 break; 3062 case GL_COLOR: 3063 case GL_DEPTH: 3064 case GL_STENCIL: 3065 break; 3066 case GL_BACK_LEFT: 3067 case GL_BACK_RIGHT: 3068 case GL_FRONT_LEFT: 3069 case GL_FRONT_RIGHT: 3070 if (!_mesa_is_desktop_gl(ctx)) 3071 goto invalid_enum; 3072 break; 3073 default: 3074 goto invalid_enum; 3075 } 3076 } else { 3077 switch (attachments[i]) { 3078 case GL_DEPTH_ATTACHMENT: 3079 case GL_STENCIL_ATTACHMENT: 3080 break; 3081 case GL_COLOR_ATTACHMENT0: 3082 case GL_COLOR_ATTACHMENT1: 3083 case GL_COLOR_ATTACHMENT2: 3084 case GL_COLOR_ATTACHMENT3: 3085 case GL_COLOR_ATTACHMENT4: 3086 case GL_COLOR_ATTACHMENT5: 3087 case GL_COLOR_ATTACHMENT6: 3088 case GL_COLOR_ATTACHMENT7: 3089 case GL_COLOR_ATTACHMENT8: 3090 case GL_COLOR_ATTACHMENT9: 3091 case GL_COLOR_ATTACHMENT10: 3092 case GL_COLOR_ATTACHMENT11: 3093 case GL_COLOR_ATTACHMENT12: 3094 case GL_COLOR_ATTACHMENT13: 3095 case GL_COLOR_ATTACHMENT14: 3096 case GL_COLOR_ATTACHMENT15: { 3097 const int k = attachments[i] - GL_COLOR_ATTACHMENT0; 3098 if (k >= ctx->Const.MaxColorAttachments) { 3099 _mesa_error(ctx, GL_INVALID_OPERATION, 3100 "%s(attachment >= max. color attachments)", name); 3101 return; 3102 } 3103 } 3104 default: 3105 goto invalid_enum; 3106 } 3107 } 3108 } 3109 3110 /* We don't actually do anything for this yet. Just return after 3111 * validating the parameters and generating the required errors. 3112 */ 3113 return; 3114 3115invalid_enum: 3116 _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name); 3117 return; 3118} 3119 3120void GLAPIENTRY 3121_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, 3122 const GLenum *attachments, GLint x, GLint y, 3123 GLsizei width, GLsizei height) 3124{ 3125 invalidate_framebuffer_storage(target, numAttachments, attachments, 3126 x, y, width, height, 3127 "glInvalidateSubFramebuffer"); 3128} 3129 3130void GLAPIENTRY 3131_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, 3132 const GLenum *attachments) 3133{ 3134 /* The GL_ARB_invalidate_subdata spec says: 3135 * 3136 * "The command 3137 * 3138 * void InvalidateFramebuffer(enum target, 3139 * sizei numAttachments, 3140 * const enum *attachments); 3141 * 3142 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>, 3143 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, 3144 * <MAX_VIEWPORT_DIMS[1]> respectively." 3145 */ 3146 invalidate_framebuffer_storage(target, numAttachments, attachments, 3147 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, 3148 "glInvalidateFramebuffer"); 3149} 3150