fbobject.c revision f6b7157550205a0633b4c2cb49a807d581176e21
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 _mesa_error(ctx, GL_INVALID_OPERATION, 2568 "glGenerateMipmap(zero size base image)"); 2569 return; 2570 } 2571 2572 if (target == GL_TEXTURE_CUBE_MAP) { 2573 GLuint face; 2574 for (face = 0; face < 6; face++) 2575 ctx->Driver.GenerateMipmap(ctx, 2576 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, 2577 texObj); 2578 } 2579 else { 2580 ctx->Driver.GenerateMipmap(ctx, target, texObj); 2581 } 2582 _mesa_unlock_texture(ctx, texObj); 2583} 2584 2585 2586#if FEATURE_EXT_framebuffer_blit 2587 2588static const struct gl_renderbuffer_attachment * 2589find_attachment(const struct gl_framebuffer *fb, 2590 const struct gl_renderbuffer *rb) 2591{ 2592 GLuint i; 2593 for (i = 0; i < Elements(fb->Attachment); i++) { 2594 if (fb->Attachment[i].Renderbuffer == rb) 2595 return &fb->Attachment[i]; 2596 } 2597 return NULL; 2598} 2599 2600 2601/** 2602 * Helper function for checking if the datatypes of color buffers are 2603 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198: 2604 * 2605 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT 2606 * and any of the following conditions hold: 2607 * - The read buffer contains fixed-point or floating-point values and any 2608 * draw buffer contains neither fixed-point nor floating-point values. 2609 * - The read buffer contains unsigned integer values and any draw buffer 2610 * does not contain unsigned integer values. 2611 * - The read buffer contains signed integer values and any draw buffer 2612 * does not contain signed integer values." 2613 */ 2614static GLboolean 2615compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat) 2616{ 2617 GLenum srcType = _mesa_get_format_datatype(srcFormat); 2618 GLenum dstType = _mesa_get_format_datatype(dstFormat); 2619 2620 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) { 2621 assert(srcType == GL_UNSIGNED_NORMALIZED || 2622 srcType == GL_SIGNED_NORMALIZED || 2623 srcType == GL_FLOAT); 2624 /* Boil any of those types down to GL_FLOAT */ 2625 srcType = GL_FLOAT; 2626 } 2627 2628 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) { 2629 assert(dstType == GL_UNSIGNED_NORMALIZED || 2630 dstType == GL_SIGNED_NORMALIZED || 2631 dstType == GL_FLOAT); 2632 /* Boil any of those types down to GL_FLOAT */ 2633 dstType = GL_FLOAT; 2634 } 2635 2636 return srcType == dstType; 2637} 2638 2639 2640/** 2641 * Return the equivalent non-generic internal format. 2642 * This is useful for comparing whether two internal formats are semantically 2643 * equivalent. 2644 */ 2645static GLenum 2646get_nongeneric_internalformat(GLenum format) 2647{ 2648 switch (format) { 2649 /* GL 1.1 formats. */ 2650 case 4: 2651 case GL_RGBA: 2652 return GL_RGBA8; 2653 2654 case 3: 2655 case GL_RGB: 2656 return GL_RGB8; 2657 2658 case 2: 2659 case GL_LUMINANCE_ALPHA: 2660 return GL_LUMINANCE8_ALPHA8; 2661 2662 case 1: 2663 case GL_LUMINANCE: 2664 return GL_LUMINANCE8; 2665 2666 case GL_ALPHA: 2667 return GL_ALPHA8; 2668 2669 case GL_INTENSITY: 2670 return GL_INTENSITY8; 2671 2672 /* GL_ARB_texture_rg */ 2673 case GL_RED: 2674 return GL_R8; 2675 2676 case GL_RG: 2677 return GL_RG8; 2678 2679 /* GL_EXT_texture_sRGB */ 2680 case GL_SRGB: 2681 return GL_SRGB8; 2682 2683 case GL_SRGB_ALPHA: 2684 return GL_SRGB8_ALPHA8; 2685 2686 case GL_SLUMINANCE: 2687 return GL_SLUMINANCE8; 2688 2689 case GL_SLUMINANCE_ALPHA: 2690 return GL_SLUMINANCE8_ALPHA8; 2691 2692 /* GL_EXT_texture_snorm */ 2693 case GL_RGBA_SNORM: 2694 return GL_RGBA8_SNORM; 2695 2696 case GL_RGB_SNORM: 2697 return GL_RGB8_SNORM; 2698 2699 case GL_RG_SNORM: 2700 return GL_RG8_SNORM; 2701 2702 case GL_RED_SNORM: 2703 return GL_R8_SNORM; 2704 2705 case GL_LUMINANCE_ALPHA_SNORM: 2706 return GL_LUMINANCE8_ALPHA8_SNORM; 2707 2708 case GL_LUMINANCE_SNORM: 2709 return GL_LUMINANCE8_SNORM; 2710 2711 case GL_ALPHA_SNORM: 2712 return GL_ALPHA8_SNORM; 2713 2714 case GL_INTENSITY_SNORM: 2715 return GL_INTENSITY8_SNORM; 2716 2717 default: 2718 return format; 2719 } 2720} 2721 2722 2723static GLboolean 2724compatible_resolve_formats(const struct gl_renderbuffer *colorReadRb, 2725 const struct gl_renderbuffer *colorDrawRb) 2726{ 2727 /* The simple case where we know the backing formats are the same. 2728 */ 2729 if (colorReadRb->Format == colorDrawRb->Format) { 2730 return GL_TRUE; 2731 } 2732 2733 /* The Mesa formats are different, so we must check whether the internal 2734 * formats are compatible. 2735 * 2736 * Under some circumstances, the user may request e.g. two GL_RGBA8 2737 * textures and get two entirely different Mesa formats like RGBA8888 and 2738 * ARGB8888. Drivers behaving like that should be able to cope with 2739 * non-matching formats by themselves, because it's not the user's fault. 2740 */ 2741 if (get_nongeneric_internalformat(colorReadRb->InternalFormat) == 2742 get_nongeneric_internalformat(colorDrawRb->InternalFormat)) { 2743 return GL_TRUE; 2744 } 2745 2746 return GL_FALSE; 2747} 2748 2749 2750/** 2751 * Blit rectangular region, optionally from one framebuffer to another. 2752 * 2753 * Note, if the src buffer is multisampled and the dest is not, this is 2754 * when the samples must be resolved to a single color. 2755 */ 2756void GLAPIENTRY 2757_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 2758 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 2759 GLbitfield mask, GLenum filter) 2760{ 2761 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | 2762 GL_DEPTH_BUFFER_BIT | 2763 GL_STENCIL_BUFFER_BIT); 2764 const struct gl_framebuffer *readFb, *drawFb; 2765 const struct gl_renderbuffer *colorReadRb, *colorDrawRb; 2766 GET_CURRENT_CONTEXT(ctx); 2767 2768 ASSERT_OUTSIDE_BEGIN_END(ctx); 2769 FLUSH_VERTICES(ctx, _NEW_BUFFERS); 2770 2771 if (MESA_VERBOSE & VERBOSE_API) 2772 _mesa_debug(ctx, 2773 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", 2774 srcX0, srcY0, srcX1, srcY1, 2775 dstX0, dstY0, dstX1, dstY1, 2776 mask, _mesa_lookup_enum_by_nr(filter)); 2777 2778 if (ctx->NewState) { 2779 _mesa_update_state(ctx); 2780 } 2781 2782 readFb = ctx->ReadBuffer; 2783 drawFb = ctx->DrawBuffer; 2784 2785 if (!readFb || !drawFb) { 2786 /* This will normally never happen but someday we may want to 2787 * support MakeCurrent() with no drawables. 2788 */ 2789 return; 2790 } 2791 2792 /* check for complete framebuffers */ 2793 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || 2794 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 2795 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 2796 "glBlitFramebufferEXT(incomplete draw/read buffers)"); 2797 return; 2798 } 2799 2800 if (filter != GL_NEAREST && filter != GL_LINEAR) { 2801 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)"); 2802 return; 2803 } 2804 2805 if (mask & ~legalMaskBits) { 2806 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); 2807 return; 2808 } 2809 2810 /* depth/stencil must be blitted with nearest filtering */ 2811 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) 2812 && filter != GL_NEAREST) { 2813 _mesa_error(ctx, GL_INVALID_OPERATION, 2814 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); 2815 return; 2816 } 2817 2818 /* get color read/draw renderbuffers */ 2819 if (mask & GL_COLOR_BUFFER_BIT) { 2820 colorReadRb = readFb->_ColorReadBuffer; 2821 colorDrawRb = drawFb->_ColorDrawBuffers[0]; 2822 2823 /* From the EXT_framebuffer_object spec: 2824 * 2825 * "If a buffer is specified in <mask> and does not exist in both 2826 * the read and draw framebuffers, the corresponding bit is silently 2827 * ignored." 2828 */ 2829 if ((colorReadRb == NULL) || (colorDrawRb == NULL)) { 2830 colorReadRb = colorDrawRb = NULL; 2831 mask &= ~GL_COLOR_BUFFER_BIT; 2832 } 2833 else if (!compatible_color_datatypes(colorReadRb->Format, 2834 colorDrawRb->Format)) { 2835 _mesa_error(ctx, GL_INVALID_OPERATION, 2836 "glBlitFramebufferEXT(color buffer datatypes mismatch)"); 2837 return; 2838 } 2839 } 2840 else { 2841 colorReadRb = colorDrawRb = NULL; 2842 } 2843 2844 if (mask & GL_STENCIL_BUFFER_BIT) { 2845 struct gl_renderbuffer *readRb = 2846 readFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2847 struct gl_renderbuffer *drawRb = 2848 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; 2849 2850 /* From the EXT_framebuffer_object spec: 2851 * 2852 * "If a buffer is specified in <mask> and does not exist in both 2853 * the read and draw framebuffers, the corresponding bit is silently 2854 * ignored." 2855 */ 2856 if ((readRb == NULL) || (drawRb == NULL)) { 2857 mask &= ~GL_STENCIL_BUFFER_BIT; 2858 } 2859 else if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != 2860 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { 2861 /* There is no need to check the stencil datatype here, because 2862 * there is only one: GL_UNSIGNED_INT. 2863 */ 2864 _mesa_error(ctx, GL_INVALID_OPERATION, 2865 "glBlitFramebufferEXT(stencil buffer size mismatch)"); 2866 return; 2867 } 2868 } 2869 2870 if (mask & GL_DEPTH_BUFFER_BIT) { 2871 struct gl_renderbuffer *readRb = 2872 readFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2873 struct gl_renderbuffer *drawRb = 2874 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; 2875 2876 /* From the EXT_framebuffer_object spec: 2877 * 2878 * "If a buffer is specified in <mask> and does not exist in both 2879 * the read and draw framebuffers, the corresponding bit is silently 2880 * ignored." 2881 */ 2882 if ((readRb == NULL) || (drawRb == NULL)) { 2883 mask &= ~GL_DEPTH_BUFFER_BIT; 2884 } 2885 else if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != 2886 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || 2887 (_mesa_get_format_datatype(readRb->Format) != 2888 _mesa_get_format_datatype(drawRb->Format))) { 2889 _mesa_error(ctx, GL_INVALID_OPERATION, 2890 "glBlitFramebufferEXT(depth buffer format mismatch)"); 2891 return; 2892 } 2893 } 2894 2895 if (readFb->Visual.samples > 0 && 2896 drawFb->Visual.samples > 0 && 2897 readFb->Visual.samples != drawFb->Visual.samples) { 2898 _mesa_error(ctx, GL_INVALID_OPERATION, 2899 "glBlitFramebufferEXT(mismatched samples)"); 2900 return; 2901 } 2902 2903 /* extra checks for multisample copies... */ 2904 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { 2905 /* src and dest region sizes must be the same */ 2906 if (srcX1 - srcX0 != dstX1 - dstX0 || 2907 srcY1 - srcY0 != dstY1 - dstY0) { 2908 _mesa_error(ctx, GL_INVALID_OPERATION, 2909 "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); 2910 return; 2911 } 2912 2913 /* color formats must match */ 2914 if (colorReadRb && 2915 colorDrawRb && 2916 !compatible_resolve_formats(colorReadRb, colorDrawRb)) { 2917 _mesa_error(ctx, GL_INVALID_OPERATION, 2918 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); 2919 return; 2920 } 2921 } 2922 2923 if (filter == GL_LINEAR && (mask & GL_COLOR_BUFFER_BIT)) { 2924 /* 3.1 spec, page 199: 2925 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error 2926 * if filter is LINEAR and read buffer contains integer data." 2927 */ 2928 GLenum type = _mesa_get_format_datatype(colorReadRb->Format); 2929 if (type == GL_INT || type == GL_UNSIGNED_INT) { 2930 _mesa_error(ctx, GL_INVALID_OPERATION, 2931 "glBlitFramebufferEXT(integer color type)"); 2932 return; 2933 } 2934 } 2935 2936 if (!ctx->Extensions.EXT_framebuffer_blit) { 2937 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT"); 2938 return; 2939 } 2940 2941 /* Debug code */ 2942 if (DEBUG_BLIT) { 2943 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," 2944 " 0x%x, 0x%x)\n", 2945 srcX0, srcY0, srcX1, srcY1, 2946 dstX0, dstY0, dstX1, dstY1, 2947 mask, filter); 2948 if (colorReadRb) { 2949 const struct gl_renderbuffer_attachment *att; 2950 2951 att = find_attachment(readFb, colorReadRb); 2952 printf(" Src FBO %u RB %u (%dx%d) ", 2953 readFb->Name, colorReadRb->Name, 2954 colorReadRb->Width, colorReadRb->Height); 2955 if (att && att->Texture) { 2956 printf("Tex %u tgt 0x%x level %u face %u", 2957 att->Texture->Name, 2958 att->Texture->Target, 2959 att->TextureLevel, 2960 att->CubeMapFace); 2961 } 2962 printf("\n"); 2963 2964 att = find_attachment(drawFb, colorDrawRb); 2965 printf(" Dst FBO %u RB %u (%dx%d) ", 2966 drawFb->Name, colorDrawRb->Name, 2967 colorDrawRb->Width, colorDrawRb->Height); 2968 if (att && att->Texture) { 2969 printf("Tex %u tgt 0x%x level %u face %u", 2970 att->Texture->Name, 2971 att->Texture->Target, 2972 att->TextureLevel, 2973 att->CubeMapFace); 2974 } 2975 printf("\n"); 2976 } 2977 } 2978 2979 if (!mask) { 2980 return; 2981 } 2982 2983 ASSERT(ctx->Driver.BlitFramebuffer); 2984 ctx->Driver.BlitFramebuffer(ctx, 2985 srcX0, srcY0, srcX1, srcY1, 2986 dstX0, dstY0, dstX1, dstY1, 2987 mask, filter); 2988} 2989#endif /* FEATURE_EXT_framebuffer_blit */ 2990 2991 2992#if FEATURE_ARB_geometry_shader4 2993void GLAPIENTRY 2994_mesa_FramebufferTextureARB(GLenum target, GLenum attachment, 2995 GLuint texture, GLint level) 2996{ 2997 GET_CURRENT_CONTEXT(ctx); 2998 _mesa_error(ctx, GL_INVALID_OPERATION, 2999 "glFramebufferTextureARB " 3000 "not implemented!"); 3001} 3002 3003 3004void GLAPIENTRY 3005_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, 3006 GLuint texture, GLint level, GLenum face) 3007{ 3008 GET_CURRENT_CONTEXT(ctx); 3009 _mesa_error(ctx, GL_INVALID_OPERATION, 3010 "glFramebufferTextureFaceARB " 3011 "not implemented!"); 3012} 3013#endif /* FEATURE_ARB_geometry_shader4 */ 3014 3015static void 3016invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments, 3017 const GLenum *attachments, GLint x, GLint y, 3018 GLsizei width, GLsizei height, const char *name) 3019{ 3020 int i; 3021 struct gl_framebuffer *fb; 3022 GET_CURRENT_CONTEXT(ctx); 3023 3024 ASSERT_OUTSIDE_BEGIN_END(ctx); 3025 3026 fb = get_framebuffer_target(ctx, target); 3027 if (!fb) { 3028 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name); 3029 return; 3030 } 3031 3032 if (numAttachments < 0) { 3033 _mesa_error(ctx, GL_INVALID_VALUE, 3034 "%s(numAttachments < 0)", name); 3035 return; 3036 } 3037 3038 /* The GL_ARB_invalidate_subdata spec says: 3039 * 3040 * "If an attachment is specified that does not exist in the 3041 * framebuffer bound to <target>, it is ignored." 3042 * 3043 * It also says: 3044 * 3045 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than 3046 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error 3047 * INVALID_OPERATION is generated." 3048 * 3049 * No mention is made of GL_AUXi being out of range. Therefore, we allow 3050 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different 3051 * set of retrictions). 3052 */ 3053 for (i = 0; i < numAttachments; i++) { 3054 if (_mesa_is_winsys_fbo(fb)) { 3055 switch (attachments[i]) { 3056 case GL_ACCUM: 3057 case GL_AUX0: 3058 case GL_AUX1: 3059 case GL_AUX2: 3060 case GL_AUX3: 3061 /* Accumulation buffers and auxilary buffers were removed in 3062 * OpenGL 3.1, and they never existed in OpenGL ES. 3063 */ 3064 if (ctx->API != API_OPENGL) 3065 goto invalid_enum; 3066 break; 3067 case GL_COLOR: 3068 case GL_DEPTH: 3069 case GL_STENCIL: 3070 break; 3071 case GL_BACK_LEFT: 3072 case GL_BACK_RIGHT: 3073 case GL_FRONT_LEFT: 3074 case GL_FRONT_RIGHT: 3075 if (!_mesa_is_desktop_gl(ctx)) 3076 goto invalid_enum; 3077 break; 3078 default: 3079 goto invalid_enum; 3080 } 3081 } else { 3082 switch (attachments[i]) { 3083 case GL_DEPTH_ATTACHMENT: 3084 case GL_STENCIL_ATTACHMENT: 3085 break; 3086 case GL_COLOR_ATTACHMENT0: 3087 case GL_COLOR_ATTACHMENT1: 3088 case GL_COLOR_ATTACHMENT2: 3089 case GL_COLOR_ATTACHMENT3: 3090 case GL_COLOR_ATTACHMENT4: 3091 case GL_COLOR_ATTACHMENT5: 3092 case GL_COLOR_ATTACHMENT6: 3093 case GL_COLOR_ATTACHMENT7: 3094 case GL_COLOR_ATTACHMENT8: 3095 case GL_COLOR_ATTACHMENT9: 3096 case GL_COLOR_ATTACHMENT10: 3097 case GL_COLOR_ATTACHMENT11: 3098 case GL_COLOR_ATTACHMENT12: 3099 case GL_COLOR_ATTACHMENT13: 3100 case GL_COLOR_ATTACHMENT14: 3101 case GL_COLOR_ATTACHMENT15: { 3102 const int k = attachments[i] - GL_COLOR_ATTACHMENT0; 3103 if (k >= ctx->Const.MaxColorAttachments) { 3104 _mesa_error(ctx, GL_INVALID_OPERATION, 3105 "%s(attachment >= max. color attachments)", name); 3106 return; 3107 } 3108 } 3109 default: 3110 goto invalid_enum; 3111 } 3112 } 3113 } 3114 3115 /* We don't actually do anything for this yet. Just return after 3116 * validating the parameters and generating the required errors. 3117 */ 3118 return; 3119 3120invalid_enum: 3121 _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name); 3122 return; 3123} 3124 3125void GLAPIENTRY 3126_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, 3127 const GLenum *attachments, GLint x, GLint y, 3128 GLsizei width, GLsizei height) 3129{ 3130 invalidate_framebuffer_storage(target, numAttachments, attachments, 3131 x, y, width, height, 3132 "glInvalidateSubFramebuffer"); 3133} 3134 3135void GLAPIENTRY 3136_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments, 3137 const GLenum *attachments) 3138{ 3139 /* The GL_ARB_invalidate_subdata spec says: 3140 * 3141 * "The command 3142 * 3143 * void InvalidateFramebuffer(enum target, 3144 * sizei numAttachments, 3145 * const enum *attachments); 3146 * 3147 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>, 3148 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>, 3149 * <MAX_VIEWPORT_DIMS[1]> respectively." 3150 */ 3151 invalidate_framebuffer_storage(target, numAttachments, attachments, 3152 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT, 3153 "glInvalidateFramebuffer"); 3154} 3155