framebuffer.c revision 753af3a206e3976be9a0954578d866218fdbf30a
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5 4 * 5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26/** 27 * Functions for allocating/managing framebuffers and renderbuffers. 28 * Also, routines for reading/writing renderbuffer data as ubytes, 29 * ushorts, uints, etc. 30 */ 31 32 33#include "glheader.h" 34#include "imports.h" 35#include "context.h" 36#include "depthstencil.h" 37#include "mtypes.h" 38#include "fbobject.h" 39#include "framebuffer.h" 40#include "renderbuffer.h" 41 42 43 44/** 45 * Compute/set the _DepthMax field for the given framebuffer. 46 * This value depends on the Z buffer resolution. 47 */ 48static void 49compute_depth_max(struct gl_framebuffer *fb) 50{ 51 if (fb->Visual.depthBits == 0) { 52 /* Special case. Even if we don't have a depth buffer we need 53 * good values for DepthMax for Z vertex transformation purposes 54 * and for per-fragment fog computation. 55 */ 56 fb->_DepthMax = (1 << 16) - 1; 57 } 58 else if (fb->Visual.depthBits < 32) { 59 fb->_DepthMax = (1 << fb->Visual.depthBits) - 1; 60 } 61 else { 62 /* Special case since shift values greater than or equal to the 63 * number of bits in the left hand expression's type are undefined. 64 */ 65 fb->_DepthMax = 0xffffffff; 66 } 67 fb->_DepthMaxF = (GLfloat) fb->_DepthMax; 68 fb->_MRD = 1.0; /* Minimum resolvable depth value, for polygon offset */ 69} 70 71 72/** 73 * Create and initialize a gl_framebuffer object. 74 * This is intended for creating _window_system_ framebuffers, not generic 75 * framebuffer objects ala GL_EXT_framebuffer_object. 76 * 77 * \sa _mesa_new_framebuffer 78 */ 79struct gl_framebuffer * 80_mesa_create_framebuffer(const GLvisual *visual) 81{ 82 struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); 83 assert(visual); 84 if (fb) { 85 _mesa_initialize_framebuffer(fb, visual); 86 } 87 return fb; 88} 89 90 91/** 92 * Allocate a new gl_framebuffer object. 93 * This is the default function for ctx->Driver.NewFramebuffer(). 94 * This is for allocating user-created framebuffers, not window-system 95 * framebuffers! 96 * \sa _mesa_create_framebuffer 97 */ 98struct gl_framebuffer * 99_mesa_new_framebuffer(GLcontext *ctx, GLuint name) 100{ 101 struct gl_framebuffer *fb; 102 assert(name != 0); 103 fb = CALLOC_STRUCT(gl_framebuffer); 104 if (fb) { 105 fb->Name = name; 106 fb->RefCount = 1; 107 fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT; 108 fb->_ColorDrawBufferMask[0] = BUFFER_BIT_COLOR0; 109 fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; 110 fb->_ColorReadBufferIndex = BUFFER_COLOR0; 111 fb->Delete = _mesa_destroy_framebuffer; 112 } 113 return fb; 114} 115 116 117/** 118 * Initialize a gl_framebuffer object. Typically used to initialize 119 * window system-created framebuffers, not user-created framebuffers. 120 * \sa _mesa_create_framebuffer 121 */ 122void 123_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual) 124{ 125 assert(fb); 126 assert(visual); 127 128 _mesa_bzero(fb, sizeof(struct gl_framebuffer)); 129 130 /* save the visual */ 131 fb->Visual = *visual; 132 133 /* Init glRead/DrawBuffer state */ 134 if (visual->doubleBufferMode) { 135 fb->ColorDrawBuffer[0] = GL_BACK; 136 fb->_ColorDrawBufferMask[0] = BUFFER_BIT_BACK_LEFT; 137 fb->ColorReadBuffer = GL_BACK; 138 fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; 139 } 140 else { 141 fb->ColorDrawBuffer[0] = GL_FRONT; 142 fb->_ColorDrawBufferMask[0] = BUFFER_BIT_FRONT_LEFT; 143 fb->ColorReadBuffer = GL_FRONT; 144 fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; 145 } 146 147 fb->Delete = _mesa_destroy_framebuffer; 148 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; 149 150 compute_depth_max(fb); 151} 152 153 154/** 155 * Deallocate buffer and everything attached to it. 156 * Typically called via the gl_framebuffer->Delete() method. 157 */ 158void 159_mesa_destroy_framebuffer(struct gl_framebuffer *fb) 160{ 161 if (fb) { 162 _mesa_free_framebuffer_data(fb); 163 _mesa_free(fb); 164 } 165} 166 167 168/** 169 * Free all the data hanging off the given gl_framebuffer, but don't free 170 * the gl_framebuffer object itself. 171 */ 172void 173_mesa_free_framebuffer_data(struct gl_framebuffer *fb) 174{ 175 GLuint i; 176 177 assert(fb); 178 179 for (i = 0; i < BUFFER_COUNT; i++) { 180 struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 181 if (att->Renderbuffer) { 182 struct gl_renderbuffer *rb = att->Renderbuffer; 183 rb->RefCount--; 184 if (rb->RefCount == 0) { 185 rb->Delete(rb); 186 } 187 } 188 att->Type = GL_NONE; 189 att->Renderbuffer = NULL; 190 } 191 192 if (fb->_DepthBuffer) { 193 struct gl_renderbuffer *rb = fb->_DepthBuffer; 194 rb->RefCount--; 195 if (rb->RefCount <= 0) { 196 rb->Delete(rb); 197 } 198 fb->_DepthBuffer = NULL; 199 } 200 if (fb->_StencilBuffer) { 201 struct gl_renderbuffer *rb = fb->_StencilBuffer; 202 rb->RefCount--; 203 if (rb->RefCount <= 0) { 204 rb->Delete(rb); 205 } 206 fb->_StencilBuffer = NULL; 207 } 208} 209 210 211/** 212 * Resize the given framebuffer's renderbuffers to the new width and height. 213 * This should only be used for window-system framebuffers, not 214 * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object). 215 * This will typically be called via ctx->Driver.ResizeBuffers() or directly 216 * from a device driver. 217 * 218 * \note it's possible for ctx to be null since a window can be resized 219 * without a currently bound rendering context. 220 */ 221void 222_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb, 223 GLuint width, GLuint height) 224{ 225 GLuint i; 226 227 /* For window system framebuffers, Name is zero */ 228 assert(fb->Name == 0); 229 230 for (i = 0; i < BUFFER_COUNT; i++) { 231 struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 232 if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) { 233 struct gl_renderbuffer *rb = att->Renderbuffer; 234 /* only resize if size is changing */ 235 if (rb->Width != width || rb->Height != height) { 236 if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { 237 rb->Width = width; 238 rb->Height = height; 239 } 240 else { 241 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); 242 } 243 } 244 } 245 } 246 247 fb->Width = width; 248 fb->Height = height; 249 250 /* to update scissor / window bounds */ 251 if (ctx) 252 ctx->NewState |= _NEW_BUFFERS; 253} 254 255 256/** 257 * Examine all the framebuffer's renderbuffers to update the Width/Height 258 * fields of the framebuffer. If we have renderbuffers with different 259 * sizes, set the framebuffer's width and height to zero. 260 * Note: this is only intended for user-created framebuffers, not 261 * window-system framebuffes. 262 */ 263static void 264update_framebuffer_size(struct gl_framebuffer *fb) 265{ 266 GLboolean haveSize = GL_FALSE; 267 GLuint i; 268 269 /* user-created framebuffers only */ 270 assert(fb->Name); 271 272 for (i = 0; i < BUFFER_COUNT; i++) { 273 struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 274 const struct gl_renderbuffer *rb = att->Renderbuffer; 275 if (rb) { 276 if (haveSize) { 277 if (rb->Width != fb->Width && rb->Height != fb->Height) { 278 /* size mismatch! */ 279 fb->Width = 0; 280 fb->Height = 0; 281 return; 282 } 283 } 284 else { 285 fb->Width = rb->Width; 286 fb->Height = rb->Height; 287 haveSize = GL_TRUE; 288 } 289 } 290 } 291} 292 293 294/** 295 * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields. 296 * These values are computed from the buffer's width and height and 297 * the scissor box, if it's enabled. 298 * \param ctx the GL context. 299 */ 300void 301_mesa_update_draw_buffer_bounds(GLcontext *ctx) 302{ 303 struct gl_framebuffer *buffer = ctx->DrawBuffer; 304 305 if (buffer->Name) { 306 /* user-created framebuffer size depends on the renderbuffers */ 307 update_framebuffer_size(buffer); 308 } 309 310 buffer->_Xmin = 0; 311 buffer->_Ymin = 0; 312 buffer->_Xmax = buffer->Width; 313 buffer->_Ymax = buffer->Height; 314 315 if (ctx->Scissor.Enabled) { 316 if (ctx->Scissor.X > buffer->_Xmin) { 317 buffer->_Xmin = ctx->Scissor.X; 318 } 319 if (ctx->Scissor.Y > buffer->_Ymin) { 320 buffer->_Ymin = ctx->Scissor.Y; 321 } 322 if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) { 323 buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width; 324 } 325 if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) { 326 buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height; 327 } 328 /* finally, check for empty region */ 329 if (buffer->_Xmin > buffer->_Xmax) { 330 buffer->_Xmin = buffer->_Xmax; 331 } 332 if (buffer->_Ymin > buffer->_Ymax) { 333 buffer->_Ymin = buffer->_Ymax; 334 } 335 } 336 337 ASSERT(buffer->_Xmin <= buffer->_Xmax); 338 ASSERT(buffer->_Ymin <= buffer->_Ymax); 339} 340 341 342/** 343 * The glGet queries of the framebuffer red/green/blue size, stencil size, 344 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can 345 * change depending on the renderbuffer bindings. This function updates 346 * the given framebuffer's Visual from the current renderbuffer bindings. 347 * This is only intended for user-created framebuffers. 348 * 349 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal 350 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. 351 * The former one is used to convert floating point depth values into 352 * integer Z values. 353 */ 354void 355_mesa_update_framebuffer_visual(struct gl_framebuffer *fb) 356{ 357 GLuint i; 358 359 assert(fb->Name != 0); 360 361 _mesa_bzero(&fb->Visual, sizeof(fb->Visual)); 362 fb->Visual.rgbMode = GL_TRUE; /* assume this */ 363 364 /* find first RGB or CI renderbuffer */ 365 for (i = 0; i < BUFFER_COUNT; i++) { 366 if (fb->Attachment[i].Renderbuffer) { 367 const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 368 if (rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB) { 369 fb->Visual.redBits = rb->RedBits; 370 fb->Visual.greenBits = rb->GreenBits; 371 fb->Visual.blueBits = rb->BlueBits; 372 fb->Visual.alphaBits = rb->AlphaBits; 373 fb->Visual.rgbBits = fb->Visual.redBits 374 + fb->Visual.greenBits + fb->Visual.blueBits; 375 fb->Visual.floatMode = GL_FALSE; 376 break; 377 } 378 else if (rb->_BaseFormat == GL_COLOR_INDEX) { 379 fb->Visual.indexBits = rb->IndexBits; 380 fb->Visual.rgbMode = GL_FALSE; 381 break; 382 } 383 } 384 } 385 386 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { 387 fb->Visual.haveDepthBuffer = GL_TRUE; 388 fb->Visual.depthBits 389 = fb->Attachment[BUFFER_DEPTH].Renderbuffer->DepthBits; 390 } 391 392 if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { 393 fb->Visual.haveStencilBuffer = GL_TRUE; 394 fb->Visual.stencilBits 395 = fb->Attachment[BUFFER_STENCIL].Renderbuffer->StencilBits; 396 } 397 398 compute_depth_max(fb); 399} 400 401 402/** 403 * Helper function for _mesa_update_framebuffer(). 404 * Set the actual depth renderbuffer for the given framebuffer. 405 * Take care of reference counts, etc. 406 */ 407static void 408set_depth_renderbuffer(struct gl_framebuffer *fb, 409 struct gl_renderbuffer *rb) 410{ 411 if (fb->_DepthBuffer) { 412 fb->_DepthBuffer->RefCount--; 413 if (fb->_DepthBuffer->RefCount <= 0) { 414 fb->_DepthBuffer->Delete(fb->_DepthBuffer); 415 } 416 } 417 fb->_DepthBuffer = rb; 418 if (rb) 419 rb->RefCount++; 420} 421 422/** 423 * \sa set_depth_renderbuffer. 424 */ 425static void 426set_stencil_renderbuffer(struct gl_framebuffer *fb, 427 struct gl_renderbuffer *rb) 428{ 429 if (fb->_StencilBuffer) { 430 fb->_StencilBuffer->RefCount--; 431 if (fb->_StencilBuffer->RefCount <= 0) { 432 fb->_StencilBuffer->Delete(fb->_StencilBuffer); 433 } 434 } 435 fb->_StencilBuffer = rb; 436 if (rb) 437 rb->RefCount++; 438} 439 440 441/** 442 * Update state related to the current draw/read framebuffers. 443 * Specifically, update these framebuffer fields: 444 * _ColorDrawBuffers 445 * _NumColorDrawBuffers 446 * _ColorReadBuffer 447 * _DepthBuffer 448 * _StencilBuffer 449 * If the current framebuffer is user-created, make sure it's complete. 450 * The following functions can effect this state: glReadBuffer, 451 * glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT, 452 * glRenderbufferStorageEXT. 453 */ 454void 455_mesa_update_framebuffer(GLcontext *ctx) 456{ 457 struct gl_framebuffer *fb = ctx->DrawBuffer; 458 GLuint output; 459 460 /* Completeness only matters for user-created framebuffers */ 461 if (fb->Name != 0) { 462 _mesa_test_framebuffer_completeness(ctx, fb); 463 _mesa_update_framebuffer_visual(fb); 464 } 465 466 /* 467 * Update the list of color drawing renderbuffer pointers. 468 * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers 469 * writing colors. We need the inner loop here because 470 * glDrawBuffer(GL_FRONT_AND_BACK) can specify writing to two or four 471 * color buffers (for example). 472 */ 473 for (output = 0; output < ctx->Const.MaxDrawBuffers; output++) { 474 GLbitfield bufferMask = fb->_ColorDrawBufferMask[output]; 475 GLuint count = 0; 476 GLuint i; 477 for (i = 0; bufferMask && i < BUFFER_COUNT; i++) { 478 const GLuint bufferBit = 1 << i; 479 if (bufferBit & bufferMask) { 480 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 481 if (rb) { 482 fb->_ColorDrawBuffers[output][count] = rb; 483 count++; 484 } 485 else { 486 /*_mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");*/ 487 } 488 bufferMask &= ~bufferBit; 489 } 490 } 491 fb->_NumColorDrawBuffers[output] = count; 492 } 493 494 /* 495 * Update the color read renderbuffer pointer. 496 * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. 497 */ 498 if (fb->_ColorReadBufferIndex == -1) { 499 fb->_ColorReadBuffer = NULL; /* legal! */ 500 } 501 else { 502 ASSERT(fb->_ColorReadBufferIndex >= 0); 503 ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT); 504 fb->_ColorReadBuffer 505 = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; 506 } 507 508 /* 509 * Deal with GL_DEPTH_STENCIL renderbuffer(s) attached to the depth 510 * and/or stencil attachment points. If either of the DEPTH or STENCIL 511 * renderbuffer attachments are GL_DEPTH_STENCIL buffers, we need to set 512 * up depth/stencil renderbuffer wrappers. 513 */ 514 { 515 struct gl_renderbuffer *depthRb 516 = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 517 struct gl_renderbuffer *stencilRb 518 = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 519 520 if (depthRb && depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 521 /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */ 522 if (!fb->_DepthBuffer || fb->_DepthBuffer->Wrapped != depthRb) { 523 /* need to update wrapper */ 524 struct gl_renderbuffer *wrapper 525 = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); 526 set_depth_renderbuffer(fb, wrapper); 527 assert(fb->_DepthBuffer->Wrapped == depthRb); 528 } 529 } 530 else { 531 /* depthRb may be null */ 532 set_depth_renderbuffer(fb, depthRb); 533 } 534 535 if (stencilRb && stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 536 /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */ 537 if (!fb->_StencilBuffer || fb->_StencilBuffer->Wrapped != stencilRb) { 538 /* need to update wrapper */ 539 struct gl_renderbuffer *wrapper 540 = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); 541 set_stencil_renderbuffer(fb, wrapper); 542 assert(fb->_StencilBuffer->Wrapped == stencilRb); 543 } 544 } 545 else { 546 /* stencilRb may be null */ 547 set_stencil_renderbuffer(fb, stencilRb); 548 } 549 } 550 551 compute_depth_max(fb); 552} 553 554 555/** 556 * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels, 557 * glCopyTex[Sub]Image, etc. exists. 558 * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, 559 * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. 560 * \return GL_TRUE if buffer exists, GL_FALSE otherwise 561 */ 562GLboolean 563_mesa_source_buffer_exists(GLcontext *ctx, GLenum format) 564{ 565 const struct gl_renderbuffer_attachment *att 566 = ctx->ReadBuffer->Attachment; 567 568 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 569 return GL_FALSE; 570 } 571 572 switch (format) { 573 case GL_COLOR: 574 case GL_RED: 575 case GL_GREEN: 576 case GL_BLUE: 577 case GL_ALPHA: 578 case GL_LUMINANCE: 579 case GL_LUMINANCE_ALPHA: 580 case GL_INTENSITY: 581 case GL_RGB: 582 case GL_BGR: 583 case GL_RGBA: 584 case GL_BGRA: 585 case GL_ABGR_EXT: 586 case GL_COLOR_INDEX: 587 if (ctx->ReadBuffer->_ColorReadBuffer == NULL) { 588 return GL_FALSE; 589 } 590 break; 591 case GL_DEPTH: 592 case GL_DEPTH_COMPONENT: 593 if (!att[BUFFER_DEPTH].Renderbuffer) { 594 return GL_FALSE; 595 } 596 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 597 break; 598 case GL_STENCIL: 599 case GL_STENCIL_INDEX: 600 if (!att[BUFFER_STENCIL].Renderbuffer) { 601 return GL_FALSE; 602 } 603 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 604 break; 605 case GL_DEPTH_STENCIL_EXT: 606 if (!att[BUFFER_DEPTH].Renderbuffer || 607 !att[BUFFER_STENCIL].Renderbuffer) { 608 return GL_FALSE; 609 } 610 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 611 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 612 break; 613 default: 614 _mesa_problem(ctx, 615 "Unexpected format 0x%x in _mesa_source_buffer_exists", 616 format); 617 return GL_FALSE; 618 } 619 620 /* OK */ 621 return GL_TRUE; 622} 623 624 625/** 626 * As above, but for drawing operations. 627 * XXX code do some code merging w/ above function. 628 */ 629GLboolean 630_mesa_dest_buffer_exists(GLcontext *ctx, GLenum format) 631{ 632 const struct gl_renderbuffer_attachment *att 633 = ctx->ReadBuffer->Attachment; 634 635 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 636 return GL_FALSE; 637 } 638 639 switch (format) { 640 case GL_COLOR: 641 case GL_RED: 642 case GL_GREEN: 643 case GL_BLUE: 644 case GL_ALPHA: 645 case GL_LUMINANCE: 646 case GL_LUMINANCE_ALPHA: 647 case GL_INTENSITY: 648 case GL_RGB: 649 case GL_BGR: 650 case GL_RGBA: 651 case GL_BGRA: 652 case GL_ABGR_EXT: 653 case GL_COLOR_INDEX: 654 /* nothing special */ 655 break; 656 case GL_DEPTH: 657 case GL_DEPTH_COMPONENT: 658 if (!att[BUFFER_DEPTH].Renderbuffer) { 659 return GL_FALSE; 660 } 661 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 662 break; 663 case GL_STENCIL: 664 case GL_STENCIL_INDEX: 665 if (!att[BUFFER_STENCIL].Renderbuffer) { 666 return GL_FALSE; 667 } 668 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 669 break; 670 case GL_DEPTH_STENCIL_EXT: 671 if (!att[BUFFER_DEPTH].Renderbuffer || 672 !att[BUFFER_STENCIL].Renderbuffer) { 673 return GL_FALSE; 674 } 675 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 676 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 677 break; 678 default: 679 _mesa_problem(ctx, 680 "Unexpected format 0x%x in _mesa_source_buffer_exists", 681 format); 682 return GL_FALSE; 683 } 684 685 /* OK */ 686 return GL_TRUE; 687} 688