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