fbobject.c revision e06d6168cb4367728fac68264757a700932c2f73
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 = !ctx->Extensions.NV_texture_rectangle; 2141 break; 2142 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2143 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2144 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2145 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2146 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2147 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2148 error = !ctx->Extensions.ARB_texture_cube_map; 2149 break; 2150 case GL_TEXTURE_2D_ARRAY: 2151 error = !ctx->Extensions.EXT_texture_array; 2152 break; 2153 default: 2154 error = GL_TRUE; 2155 } 2156 2157 if (error) { 2158 _mesa_error(ctx, GL_INVALID_OPERATION, 2159 "glFramebufferTexture2DEXT(textarget=%s)", 2160 _mesa_lookup_enum_by_nr(textarget)); 2161 return; 2162 } 2163 } 2164 2165 framebuffer_texture(ctx, "2D", target, attachment, textarget, texture, 2166 level, 0); 2167} 2168 2169 2170void GLAPIENTRY 2171_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, 2172 GLenum textarget, GLuint texture, 2173 GLint level, GLint zoffset) 2174{ 2175 GET_CURRENT_CONTEXT(ctx); 2176 2177 if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { 2178 _mesa_error(ctx, GL_INVALID_OPERATION, 2179 "glFramebufferTexture3DEXT(textarget)"); 2180 return; 2181 } 2182 2183 framebuffer_texture(ctx, "3D", target, attachment, textarget, texture, 2184 level, zoffset); 2185} 2186 2187 2188void GLAPIENTRY 2189_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment, 2190 GLuint texture, GLint level, GLint layer) 2191{ 2192 GET_CURRENT_CONTEXT(ctx); 2193 2194 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, 2195 level, layer); 2196} 2197 2198 2199void GLAPIENTRY 2200_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, 2201 GLenum renderbufferTarget, 2202 GLuint renderbuffer) 2203{ 2204 struct gl_renderbuffer_attachment *att; 2205 struct gl_framebuffer *fb; 2206 struct gl_renderbuffer *rb; 2207 GET_CURRENT_CONTEXT(ctx); 2208 2209 ASSERT_OUTSIDE_BEGIN_END(ctx); 2210 2211 fb = get_framebuffer_target(ctx, target); 2212 if (!fb) { 2213 _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); 2214 return; 2215 } 2216 2217 if (renderbufferTarget != GL_RENDERBUFFER_EXT) { 2218 _mesa_error(ctx, GL_INVALID_ENUM, 2219 "glFramebufferRenderbufferEXT(renderbufferTarget)"); 2220 return; 2221 } 2222 2223 if (_mesa_is_winsys_fbo(fb)) { 2224 /* Can't attach new renderbuffers to a window system framebuffer */ 2225 _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); 2226 return; 2227 } 2228 2229 att = _mesa_get_attachment(ctx, fb, attachment); 2230 if (att == NULL) { 2231 _mesa_error(ctx, GL_INVALID_ENUM, 2232 "glFramebufferRenderbufferEXT(invalid attachment %s)", 2233 _mesa_lookup_enum_by_nr(attachment)); 2234 return; 2235 } 2236 2237 if (renderbuffer) { 2238 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); 2239 if (!rb) { 2240 _mesa_error(ctx, GL_INVALID_OPERATION, 2241 "glFramebufferRenderbufferEXT(non-existant" 2242 " renderbuffer %u)", renderbuffer); 2243 return; 2244 } 2245 else if (rb == &DummyRenderbuffer) { 2246 /* This is what NVIDIA does */ 2247 _mesa_error(ctx, GL_INVALID_VALUE, 2248 "glFramebufferRenderbufferEXT(renderbuffer %u)", 2249 renderbuffer); 2250 return; 2251 } 2252 } 2253 else { 2254 /* remove renderbuffer attachment */ 2255 rb = NULL; 2256 } 2257 2258 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT && 2259 rb && rb->Format != MESA_FORMAT_NONE) { 2260 /* make sure the renderbuffer is a depth/stencil format */ 2261 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); 2262 if (baseFormat != GL_DEPTH_STENCIL) { 2263 _mesa_error(ctx, GL_INVALID_OPERATION, 2264 "glFramebufferRenderbufferEXT(renderbuffer" 2265 " is not DEPTH_STENCIL format)"); 2266 return; 2267 } 2268 } 2269 2270 2271 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2272 2273 assert(ctx->Driver.FramebufferRenderbuffer); 2274 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); 2275 2276 /* Some subsequent GL commands may depend on the framebuffer's visual 2277 * after the binding is updated. Update visual info now. 2278 */ 2279 _mesa_update_framebuffer_visual(ctx, fb); 2280} 2281 2282 2283void GLAPIENTRY 2284_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, 2285 GLenum pname, GLint *params) 2286{ 2287 const struct gl_renderbuffer_attachment *att; 2288 struct gl_framebuffer *buffer; 2289 GLenum err; 2290 GET_CURRENT_CONTEXT(ctx); 2291 2292 ASSERT_OUTSIDE_BEGIN_END(ctx); 2293 2294 /* The error differs in GL and GLES. */ 2295 err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM; 2296 2297 buffer = get_framebuffer_target(ctx, target); 2298 if (!buffer) { 2299 _mesa_error(ctx, GL_INVALID_ENUM, 2300 "glGetFramebufferAttachmentParameterivEXT(target)"); 2301 return; 2302 } 2303 2304 if (_mesa_is_winsys_fbo(buffer)) { 2305 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec 2306 * says: 2307 * 2308 * "If the framebuffer currently bound to target is zero, then 2309 * INVALID_OPERATION is generated." 2310 * 2311 * The EXT_framebuffer_object spec has the same wording, and the 2312 * OES_framebuffer_object spec refers to the EXT_framebuffer_object 2313 * spec. 2314 */ 2315 if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) { 2316 _mesa_error(ctx, GL_INVALID_OPERATION, 2317 "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); 2318 return; 2319 } 2320 /* the default / window-system FBO */ 2321 att = _mesa_get_fb0_attachment(ctx, buffer, attachment); 2322 } 2323 else { 2324 /* user-created framebuffer FBO */ 2325 att = _mesa_get_attachment(ctx, buffer, attachment); 2326 } 2327 2328 if (att == NULL) { 2329 _mesa_error(ctx, GL_INVALID_ENUM, 2330 "glGetFramebufferAttachmentParameterivEXT(attachment)"); 2331 return; 2332 } 2333 2334 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { 2335 /* the depth and stencil attachments must point to the same buffer */ 2336 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt; 2337 depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT); 2338 stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); 2339 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) { 2340 _mesa_error(ctx, GL_INVALID_OPERATION, 2341 "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL" 2342 " attachments differ)"); 2343 return; 2344 } 2345 } 2346 2347 /* No need to flush here */ 2348 2349 switch (pname) { 2350 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: 2351 *params = _mesa_is_winsys_fbo(buffer) 2352 ? GL_FRAMEBUFFER_DEFAULT : att->Type; 2353 return; 2354 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: 2355 if (att->Type == GL_RENDERBUFFER_EXT) { 2356 *params = att->Renderbuffer->Name; 2357 } 2358 else if (att->Type == GL_TEXTURE) { 2359 *params = att->Texture->Name; 2360 } 2361 else { 2362 assert(att->Type == GL_NONE); 2363 if (_mesa_is_desktop_gl(ctx)) { 2364 *params = 0; 2365 } else { 2366 _mesa_error(ctx, GL_INVALID_ENUM, 2367 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2368 } 2369 } 2370 return; 2371 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: 2372 if (att->Type == GL_TEXTURE) { 2373 *params = att->TextureLevel; 2374 } 2375 else if (att->Type == GL_NONE) { 2376 _mesa_error(ctx, err, 2377 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2378 } 2379 else { 2380 _mesa_error(ctx, GL_INVALID_ENUM, 2381 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2382 } 2383 return; 2384 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: 2385 if (att->Type == GL_TEXTURE) { 2386 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) { 2387 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace; 2388 } 2389 else { 2390 *params = 0; 2391 } 2392 } 2393 else if (att->Type == GL_NONE) { 2394 _mesa_error(ctx, err, 2395 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2396 } 2397 else { 2398 _mesa_error(ctx, GL_INVALID_ENUM, 2399 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2400 } 2401 return; 2402 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: 2403 if (att->Type == GL_TEXTURE) { 2404 if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) { 2405 *params = att->Zoffset; 2406 } 2407 else { 2408 *params = 0; 2409 } 2410 } 2411 else if (att->Type == GL_NONE) { 2412 _mesa_error(ctx, err, 2413 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2414 } 2415 else { 2416 _mesa_error(ctx, GL_INVALID_ENUM, 2417 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2418 } 2419 return; 2420 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: 2421 if (!ctx->Extensions.ARB_framebuffer_object) { 2422 _mesa_error(ctx, GL_INVALID_ENUM, 2423 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2424 } 2425 else if (att->Type == GL_NONE) { 2426 _mesa_error(ctx, err, 2427 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2428 } 2429 else { 2430 if (ctx->Extensions.EXT_framebuffer_sRGB) { 2431 *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); 2432 } 2433 else { 2434 /* According to ARB_framebuffer_sRGB, we should return LINEAR 2435 * if the sRGB conversion is unsupported. */ 2436 *params = GL_LINEAR; 2437 } 2438 } 2439 return; 2440 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: 2441 if (!ctx->Extensions.ARB_framebuffer_object) { 2442 _mesa_error(ctx, GL_INVALID_ENUM, 2443 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2444 return; 2445 } 2446 else if (att->Type == GL_NONE) { 2447 _mesa_error(ctx, err, 2448 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2449 } 2450 else { 2451 gl_format format = att->Renderbuffer->Format; 2452 if (format == MESA_FORMAT_S8) { 2453 /* special cases */ 2454 *params = GL_INDEX; 2455 } 2456 else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) { 2457 /* depends on the attachment parameter */ 2458 if (attachment == GL_STENCIL_ATTACHMENT) { 2459 *params = GL_INDEX; 2460 } 2461 else { 2462 *params = GL_FLOAT; 2463 } 2464 } 2465 else { 2466 *params = _mesa_get_format_datatype(format); 2467 } 2468 } 2469 return; 2470 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: 2471 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: 2472 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: 2473 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: 2474 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: 2475 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: 2476 if (!ctx->Extensions.ARB_framebuffer_object) { 2477 _mesa_error(ctx, GL_INVALID_ENUM, 2478 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2479 } 2480 else if (att->Type == GL_NONE) { 2481 _mesa_error(ctx, err, 2482 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2483 } 2484 else if (att->Texture) { 2485 const struct gl_texture_image *texImage = 2486 _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target, 2487 att->TextureLevel); 2488 if (texImage) { 2489 *params = get_component_bits(pname, texImage->_BaseFormat, 2490 texImage->TexFormat); 2491 } 2492 else { 2493 *params = 0; 2494 } 2495 } 2496 else if (att->Renderbuffer) { 2497 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat, 2498 att->Renderbuffer->Format); 2499 } 2500 else { 2501 _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:" 2502 " invalid FBO attachment structure"); 2503 } 2504 return; 2505 default: 2506 _mesa_error(ctx, GL_INVALID_ENUM, 2507 "glGetFramebufferAttachmentParameterivEXT(pname)"); 2508 return; 2509 } 2510} 2511 2512 2513void GLAPIENTRY 2514_mesa_GenerateMipmapEXT(GLenum target) 2515{ 2516 struct gl_texture_image *srcImage; 2517 struct gl_texture_object *texObj; 2518 GLboolean error; 2519 2520 GET_CURRENT_CONTEXT(ctx); 2521 2522 ASSERT_OUTSIDE_BEGIN_END(ctx); 2523 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2524 2525 switch (target) { 2526 case GL_TEXTURE_1D: 2527 case GL_TEXTURE_2D: 2528 case GL_TEXTURE_3D: 2529 error = GL_FALSE; 2530 break; 2531 case GL_TEXTURE_CUBE_MAP: 2532 error = !ctx->Extensions.ARB_texture_cube_map; 2533 break; 2534 case GL_TEXTURE_1D_ARRAY: 2535 case GL_TEXTURE_2D_ARRAY: 2536 error = !ctx->Extensions.EXT_texture_array; 2537 break; 2538 default: 2539 error = GL_TRUE; 2540 } 2541 2542 if (error) { 2543 _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)", 2544 _mesa_lookup_enum_by_nr(target)); 2545 return; 2546 } 2547 2548 texObj = _mesa_get_current_tex_object(ctx, target); 2549 2550 if (texObj->BaseLevel >= texObj->MaxLevel) { 2551 /* nothing to do */ 2552 return; 2553 } 2554 2555 if (texObj->Target == GL_TEXTURE_CUBE_MAP && 2556 !_mesa_cube_complete(texObj)) { 2557 _mesa_error(ctx, GL_INVALID_OPERATION, 2558 "glGenerateMipmap(incomplete cube map)"); 2559 return; 2560 } 2561 2562 _mesa_lock_texture(ctx, texObj); 2563 2564 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); 2565 if (!srcImage) { 2566 _mesa_unlock_texture(ctx, texObj); 2567 return; 2568 } 2569 2570 if (target == GL_TEXTURE_CUBE_MAP) { 2571 GLuint face; 2572 for (face = 0; face < 6; face++) 2573 ctx->Driver.GenerateMipmap(ctx, 2574 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, 2575 texObj); 2576 } 2577 else { 2578 ctx->Driver.GenerateMipmap(ctx, target, texObj); 2579 } 2580 _mesa_unlock_texture(ctx, texObj); 2581} 2582 2583 2584#if FEATURE_EXT_framebuffer_blit 2585 2586static const struct gl_renderbuffer_attachment * 2587find_attachment(const struct gl_framebuffer *fb, 2588 const struct gl_renderbuffer *rb) 2589{ 2590 GLuint i; 2591 for (i = 0; i < Elements(fb->Attachment); i++) { 2592 if (fb->Attachment[i].Renderbuffer == rb) 2593 return &fb->Attachment[i]; 2594 } 2595 return NULL; 2596} 2597 2598 2599/** 2600 * Helper function for checking if the datatypes of color buffers are 2601 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198: 2602 * 2603 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT 2604 * and any of the following conditions hold: 2605 * - The read buffer contains fixed-point or floating-point values and any 2606 * draw buffer contains neither fixed-point nor floating-point values. 2607 * - The read buffer contains unsigned integer values and any draw buffer 2608 * does not contain unsigned integer values. 2609 * - The read buffer contains signed integer values and any draw buffer 2610 * does not contain signed integer values." 2611 */ 2612static GLboolean 2613compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat) 2614{ 2615 GLenum srcType = _mesa_get_format_datatype(srcFormat); 2616 GLenum dstType = _mesa_get_format_datatype(dstFormat); 2617 2618 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) { 2619 assert(srcType == GL_UNSIGNED_NORMALIZED || 2620 srcType == GL_SIGNED_NORMALIZED || 2621 srcType == GL_FLOAT); 2622 /* Boil any of those types down to GL_FLOAT */ 2623 srcType = GL_FLOAT; 2624 } 2625 2626 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) { 2627 assert(dstType == GL_UNSIGNED_NORMALIZED || 2628 dstType == GL_SIGNED_NORMALIZED || 2629 dstType == GL_FLOAT); 2630 /* Boil any of those types down to GL_FLOAT */ 2631 dstType = GL_FLOAT; 2632 } 2633 2634 return srcType == dstType; 2635} 2636 2637 2638/** 2639 * Return the equivalent non-generic internal format. 2640 * This is useful for comparing whether two internal formats are semantically 2641 * equivalent. 2642 */ 2643static GLenum 2644get_nongeneric_internalformat(GLenum format) 2645{ 2646 switch (format) { 2647 /* GL 1.1 formats. */ 2648 case 4: 2649 case GL_RGBA: 2650 return GL_RGBA8; 2651 2652 case 3: 2653 case GL_RGB: 2654 return GL_RGB8; 2655 2656 case 2: 2657 case GL_LUMINANCE_ALPHA: 2658 return GL_LUMINANCE8_ALPHA8; 2659 2660 case 1: 2661 case GL_LUMINANCE: 2662 return GL_LUMINANCE8; 2663 2664 case GL_ALPHA: 2665 return GL_ALPHA8; 2666 2667 case GL_INTENSITY: 2668 return GL_INTENSITY8; 2669 2670 /* GL_ARB_texture_rg */ 2671 case GL_RED: 2672 return GL_R8; 2673 2674 case GL_RG: 2675 return GL_RG8; 2676 2677 /* GL_EXT_texture_sRGB */ 2678 case GL_SRGB: 2679 return GL_SRGB8; 2680 2681 case GL_SRGB_ALPHA: 2682 return GL_SRGB8_ALPHA8; 2683 2684 case GL_SLUMINANCE: 2685 return GL_SLUMINANCE8; 2686 2687 case GL_SLUMINANCE_ALPHA: 2688 return GL_SLUMINANCE8_ALPHA8; 2689 2690 /* GL_EXT_texture_snorm */ 2691 case GL_RGBA_SNORM: 2692 return GL_RGBA8_SNORM; 2693 2694 case GL_RGB_SNORM: 2695 return GL_RGB8_SNORM; 2696 2697 case GL_RG_SNORM: 2698 return GL_RG8_SNORM; 2699 2700 case GL_RED_SNORM: 2701 return GL_R8_SNORM; 2702 2703 case GL_LUMINANCE_ALPHA_SNORM: 2704 return GL_LUMINANCE8_ALPHA8_SNORM; 2705 2706 case GL_LUMINANCE_SNORM: 2707 return GL_LUMINANCE8_SNORM; 2708 2709 case GL_ALPHA_SNORM: 2710 return GL_ALPHA8_SNORM; 2711 2712 case GL_INTENSITY_SNORM: 2713 return GL_INTENSITY8_SNORM; 2714 2715 default: 2716 return format; 2717 } 2718} 2719 2720 2721static GLboolean 2722compatible_resolve_formats(const struct gl_renderbuffer *colorReadRb, 2723 const struct gl_renderbuffer *colorDrawRb) 2724{ 2725 /* The simple case where we know the backing formats are the same. 2726 */ 2727 if (colorReadRb->Format == colorDrawRb->Format) { 2728 return GL_TRUE; 2729 } 2730 2731 /* The Mesa formats are different, so we must check whether the internal 2732 * formats are compatible. 2733 * 2734 * Under some circumstances, the user may request e.g. two GL_RGBA8 2735 * textures and get two entirely different Mesa formats like RGBA8888 and 2736 * ARGB8888. Drivers behaving like that should be able to cope with 2737 * non-matching formats by themselves, because it's not the user's fault. 2738 */ 2739 if (get_nongeneric_internalformat(colorReadRb->InternalFormat) == 2740 get_nongeneric_internalformat(colorDrawRb->InternalFormat)) { 2741 return GL_TRUE; 2742 } 2743 2744 return GL_FALSE; 2745} 2746 2747 2748/** 2749 * Blit rectangular region, optionally from one framebuffer to another. 2750 * 2751 * Note, if the src buffer is multisampled and the dest is not, this is 2752 * when the samples must be resolved to a single color. 2753 */ 2754void GLAPIENTRY 2755_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 2756 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 2757 GLbitfield mask, GLenum filter) 2758{ 2759 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | 2760 GL_DEPTH_BUFFER_BIT | 2761 GL_STENCIL_BUFFER_BIT); 2762 const struct gl_framebuffer *readFb, *drawFb; 2763 const struct gl_renderbuffer *colorReadRb, *colorDrawRb; 2764 GET_CURRENT_CONTEXT(ctx); 2765 2766 ASSERT_OUTSIDE_BEGIN_END(ctx); 2767 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2768 2769 if (MESA_VERBOSE & VERBOSE_API) 2770 _mesa_debug(ctx, 2771 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", 2772 srcX0, srcY0, srcX1, srcY1, 2773 dstX0, dstY0, dstX1, dstY1, 2774 mask, _mesa_lookup_enum_by_nr(filter)); 2775 2776 if (ctx->NewState) { 2777 _mesa_update_state(ctx); 2778 } 2779 2780 readFb = ctx->ReadBuffer; 2781 drawFb = ctx->DrawBuffer; 2782 2783 if (!readFb || !drawFb) { 2784 /* This will normally never happen but someday we may want to 2785 * support MakeCurrent() with no drawables. 2786 */ 2787 return; 2788 } 2789 2790 /* check for complete framebuffers */ 2791 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || 2792 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 2793 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 2794 "glBlitFramebufferEXT(incomplete draw/read buffers)"); 2795 return; 2796 } 2797 2798 if (filter != GL_NEAREST && filter != GL_LINEAR) { 2799 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)"); 2800 return; 2801 } 2802 2803 if (mask & ~legalMaskBits) { 2804 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); 2805 return; 2806 } 2807 2808 /* depth/stencil must be blitted with nearest filtering */ 2809 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) 2810 && filter != GL_NEAREST) { 2811 _mesa_error(ctx, GL_INVALID_OPERATION, 2812 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); 2813 return; 2814 } 2815 2816 /* get color read/draw renderbuffers */ 2817 if (mask & GL_COLOR_BUFFER_BIT) { 2818 colorReadRb = readFb->_ColorReadBuffer; 2819 colorDrawRb = drawFb->_ColorDrawBuffers[0]; 2820 2821 /* From the EXT_framebuffer_object spec: 2822 * 2823 * "If a buffer is specified in <mask> and does not exist in both 2824 * the read and draw framebuffers, the corresponding bit is silently 2825 * ignored." 2826 */ 2827 if ((colorReadRb == NULL) || (colorDrawRb == NULL)) { 2828 colorReadRb = colorDrawRb = NULL; 2829 mask &= ~GL_COLOR_BUFFER_BIT; 2830 } 2831 else if (!compatible_color_datatypes(colorReadRb->Format, 2832 colorDrawRb->Format)) { 2833 _mesa_error(ctx, GL_INVALID_OPERATION, 2834 "glBlitFramebufferEXT(color buffer datatypes mismatch)"); 2835 return; 2836 } 2837 } 2838 else { 2839 colorReadRb = colorDrawRb = NULL; 2840 } 2841 2842 if (mask & GL_STENCIL_BUFFER_BIT) { 2843 struct gl_renderbuffer *readRb = 2844 readFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2845 struct gl_renderbuffer *drawRb = 2846 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2847 2848 /* From the EXT_framebuffer_object spec: 2849 * 2850 * "If a buffer is specified in <mask> and does not exist in both 2851 * the read and draw framebuffers, the corresponding bit is silently 2852 * ignored." 2853 */ 2854 if ((readRb == NULL) || (drawRb == NULL)) { 2855 mask &= ~GL_STENCIL_BUFFER_BIT; 2856 } 2857 else if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != 2858 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { 2859 /* There is no need to check the stencil datatype here, because 2860 * there is only one: GL_UNSIGNED_INT. 2861 */ 2862 _mesa_error(ctx, GL_INVALID_OPERATION, 2863 "glBlitFramebufferEXT(stencil buffer size mismatch)"); 2864 return; 2865 } 2866 } 2867 2868 if (mask & GL_DEPTH_BUFFER_BIT) { 2869 struct gl_renderbuffer *readRb = 2870 readFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2871 struct gl_renderbuffer *drawRb = 2872 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2873 2874 /* From the EXT_framebuffer_object spec: 2875 * 2876 * "If a buffer is specified in <mask> and does not exist in both 2877 * the read and draw framebuffers, the corresponding bit is silently 2878 * ignored." 2879 */ 2880 if ((readRb == NULL) || (drawRb == NULL)) { 2881 mask &= ~GL_DEPTH_BUFFER_BIT; 2882 } 2883 else if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != 2884 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || 2885 (_mesa_get_format_datatype(readRb->Format) != 2886 _mesa_get_format_datatype(drawRb->Format))) { 2887 _mesa_error(ctx, GL_INVALID_OPERATION, 2888 "glBlitFramebufferEXT(depth buffer format mismatch)"); 2889 return; 2890 } 2891 } 2892 2893 if (readFb->Visual.samples > 0 && 2894 drawFb->Visual.samples > 0 && 2895 readFb->Visual.samples != drawFb->Visual.samples) { 2896 _mesa_error(ctx, GL_INVALID_OPERATION, 2897 "glBlitFramebufferEXT(mismatched samples)"); 2898 return; 2899 } 2900 2901 /* extra checks for multisample copies... */ 2902 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { 2903 /* src and dest region sizes must be the same */ 2904 if (srcX1 - srcX0 != dstX1 - dstX0 || 2905 srcY1 - srcY0 != dstY1 - dstY0) { 2906 _mesa_error(ctx, GL_INVALID_OPERATION, 2907 "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); 2908 return; 2909 } 2910 2911 /* color formats must match */ 2912 if (colorReadRb && 2913 colorDrawRb && 2914 !compatible_resolve_formats(colorReadRb, colorDrawRb)) { 2915 _mesa_error(ctx, GL_INVALID_OPERATION, 2916 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); 2917 return; 2918 } 2919 } 2920 2921 if (filter == GL_LINEAR && (mask & GL_COLOR_BUFFER_BIT)) { 2922 /* 3.1 spec, page 199: 2923 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error 2924 * if filter is LINEAR and read buffer contains integer data." 2925 */ 2926 GLenum type = _mesa_get_format_datatype(colorReadRb->Format); 2927 if (type == GL_INT || type == GL_UNSIGNED_INT) { 2928 _mesa_error(ctx, GL_INVALID_OPERATION, 2929 "glBlitFramebufferEXT(integer color type)"); 2930 return; 2931 } 2932 } 2933 2934 if (!ctx->Extensions.EXT_framebuffer_blit) { 2935 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT"); 2936 return; 2937 } 2938 2939 /* Debug code */ 2940 if (DEBUG_BLIT) { 2941 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," 2942 " 0x%x, 0x%x)\n", 2943 srcX0, srcY0, srcX1, srcY1, 2944 dstX0, dstY0, dstX1, dstY1, 2945 mask, filter); 2946 if (colorReadRb) { 2947 const struct gl_renderbuffer_attachment *att; 2948 2949 att = find_attachment(readFb, colorReadRb); 2950 printf(" Src FBO %u RB %u (%dx%d) ", 2951 readFb->Name, colorReadRb->Name, 2952 colorReadRb->Width, colorReadRb->Height); 2953 if (att && att->Texture) { 2954 printf("Tex %u tgt 0x%x level %u face %u", 2955 att->Texture->Name, 2956 att->Texture->Target, 2957 att->TextureLevel, 2958 att->CubeMapFace); 2959 } 2960 printf("\n"); 2961 2962 att = find_attachment(drawFb, colorDrawRb); 2963 printf(" Dst FBO %u RB %u (%dx%d) ", 2964 drawFb->Name, colorDrawRb->Name, 2965 colorDrawRb->Width, colorDrawRb->Height); 2966 if (att && att->Texture) { 2967 printf("Tex %u tgt 0x%x level %u face %u", 2968 att->Texture->Name, 2969 att->Texture->Target, 2970 att->TextureLevel, 2971 att->CubeMapFace); 2972 } 2973 printf("\n"); 2974 } 2975 } 2976 2977 if (!mask) { 2978 return; 2979 } 2980 2981 ASSERT(ctx->Driver.BlitFramebuffer); 2982 ctx->Driver.BlitFramebuffer(ctx, 2983 srcX0, srcY0, srcX1, srcY1, 2984 dstX0, dstY0, dstX1, dstY1, 2985 mask, filter); 2986} 2987#endif /* FEATURE_EXT_framebuffer_blit */ 2988 2989 2990#if FEATURE_ARB_geometry_shader4 2991void GLAPIENTRY 2992_mesa_FramebufferTextureARB(GLenum target, GLenum attachment, 2993 GLuint texture, GLint level) 2994{ 2995 GET_CURRENT_CONTEXT(ctx); 2996 _mesa_error(ctx, GL_INVALID_OPERATION, 2997 "glFramebufferTextureARB " 2998 "not implemented!"); 2999} 3000 3001 3002void GLAPIENTRY 3003_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, 3004 GLuint texture, GLint level, GLenum face) 3005{ 3006 GET_CURRENT_CONTEXT(ctx); 3007 _mesa_error(ctx, GL_INVALID_OPERATION, 3008 "glFramebufferTextureFaceARB " 3009 "not implemented!"); 3010} 3011#endif /* FEATURE_ARB_geometry_shader4 */ 3012 3013static void 3014invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, 3015 const GLenum *attachments, GLint x, GLint y, 3016 GLsizei width, GLsizei height, const char *name) 3017{ 3018 int i; 3019 struct gl_framebuffer *fb; 3020 GET_CURRENT_CONTEXT(ctx); 3021 3022 ASSERT_OUTSIDE_BEGIN_END(ctx); 3023 3024 fb = get_framebuffer_target(ctx, target); 3025 if (!fb) { 3026 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name); 3027 return; 3028 } 3029 3030 if (numAttachments < 0) { 3031 _mesa_error(ctx, GL_INVALID_VALUE, 3032 "%s(numAttachments < 0)", name); 3033 return; 3034 } 3035 3036 /* The GL_ARB_invalidate_subdata spec says: 3037 * 3038 * "If an attachment is specified that does not exist in the 3039 * framebuffer bound to <target>, it is ignored." 3040 * 3041 * It also says: 3042 * 3043 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than 3044 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error 3045 * INVALID_OPERATION is generated." 3046 * 3047 * No mention is made of GL_AUXi being out of range. Therefore, we allow 3048 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different 3049 * set of retrictions). 3050 */ 3051 for (i = 0; i < numAttachments; i++) { 3052 if (_mesa_is_winsys_fbo(fb)) { 3053 switch (attachments[i]) { 3054 case GL_ACCUM: 3055 case GL_AUX0: 3056 case GL_AUX1: 3057 case GL_AUX2: 3058 case GL_AUX3: 3059 /* Accumulation buffers and auxilary buffers were removed in 3060 * OpenGL 3.1, and they never existed in OpenGL ES. 3061 */ 3062 if (ctx->API != API_OPENGL) 3063 goto invalid_enum; 3064 break; 3065 case GL_COLOR: 3066 case GL_DEPTH: 3067 case GL_STENCIL: 3068 break; 3069 case GL_BACK_LEFT: 3070 case GL_BACK_RIGHT: 3071 case GL_FRONT_LEFT: 3072 case GL_FRONT_RIGHT: 3073 if (!_mesa_is_desktop_gl(ctx)) 3074 goto invalid_enum; 3075 break; 3076 default: 3077 goto invalid_enum; 3078 } 3079 } else { 3080 switch (attachments[i]) { 3081 case GL_DEPTH_ATTACHMENT: 3082 case GL_STENCIL_ATTACHMENT: 3083 break; 3084 case GL_COLOR_ATTACHMENT0: 3085 case GL_COLOR_ATTACHMENT1: 3086 case GL_COLOR_ATTACHMENT2: 3087 case GL_COLOR_ATTACHMENT3: 3088 case GL_COLOR_ATTACHMENT4: 3089 case GL_COLOR_ATTACHMENT5: 3090 case GL_COLOR_ATTACHMENT6: 3091 case GL_COLOR_ATTACHMENT7: 3092 case GL_COLOR_ATTACHMENT8: 3093 case GL_COLOR_ATTACHMENT9: 3094 case GL_COLOR_ATTACHMENT10: 3095 case GL_COLOR_ATTACHMENT11: 3096 case GL_COLOR_ATTACHMENT12: 3097 case GL_COLOR_ATTACHMENT13: 3098 case GL_COLOR_ATTACHMENT14: 3099 case GL_COLOR_ATTACHMENT15: { 3100 const int k = attachments[i] - GL_COLOR_ATTACHMENT0; 3101 if (k >= ctx->Const.MaxColorAttachments) { 3102 _mesa_error(ctx, GL_INVALID_OPERATION, 3103 "%s(attachment >= max. color attachments)", name); 3104 return; 3105 } 3106 } 3107 default: 3108 goto invalid_enum; 3109 } 3110 } 3111 } 3112 3113 /* We don't actually do anything for this yet. Just return after 3114 * validating the parameters and generating the required errors. 3115 */ 3116 return; 3117 3118invalid_enum: 3119 _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name); 3120 return; 3121} 3122 3123void GLAPIENTRY 3124_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, 3125 const GLenum *attachments, GLint x, GLint y, 3126 GLsizei width, GLsizei height) 3127{ 3128 invalidate_framebuffer_storage(target, numAttachments, attachments, 3129 x, y, width, height, 3130 "glInvalidateSubFramebuffer"); 3131} 3132 3133void GLAPIENTRY 3134_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, 3135 const GLenum *attachments) 3136{ 3137 /* The GL_ARB_invalidate_subdata spec says: 3138 * 3139 * "The command 3140 * 3141 * void InvalidateFramebuffer(enum target, 3142 * sizei numAttachments, 3143 * const enum *attachments); 3144 * 3145 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>, 3146 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, 3147 * <MAX_VIEWPORT_DIMS[1]> respectively." 3148 */ 3149 invalidate_framebuffer_storage(target, numAttachments, attachments, 3150 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, 3151 "glInvalidateFramebuffer"); 3152} 3153