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