2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * Functions for allocating/managing framebuffers and renderbuffers.
28 * Also, routines for reading/writing renderbuffer data as ubytes,
29 * ushorts, uints, etc.
36 #include "depthstencil.h"
39 #include "framebuffer.h"
40 #include "renderbuffer.h"
45 * Compute/set the _DepthMax field for the given framebuffer.
46 * This value depends on the Z buffer resolution.
49 compute_depth_max(struct gl_framebuffer
*fb
)
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.
56 fb
->_DepthMax
= (1 << 16) - 1;
58 else if (fb
->Visual
.depthBits
< 32) {
59 fb
->_DepthMax
= (1 << fb
->Visual
.depthBits
) - 1;
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.
65 fb
->_DepthMax
= 0xffffffff;
67 fb
->_DepthMaxF
= (GLfloat
) fb
->_DepthMax
;
68 fb
->_MRD
= 1.0; /* Minimum resolvable depth value, for polygon offset */
73 * Set the framebuffer's _DepthBuffer field, taking care of
74 * reference counts, etc.
77 set_depth_renderbuffer(struct gl_framebuffer
*fb
,
78 struct gl_renderbuffer
*rb
)
80 if (fb
->_DepthBuffer
) {
81 _mesa_unreference_renderbuffer(&fb
->_DepthBuffer
);
83 fb
->_DepthBuffer
= rb
;
91 * Set the framebuffer's _StencilBuffer field, taking care of
92 * reference counts, etc.
95 set_stencil_renderbuffer(struct gl_framebuffer
*fb
,
96 struct gl_renderbuffer
*rb
)
98 if (fb
->_StencilBuffer
) {
99 _mesa_unreference_renderbuffer(&fb
->_StencilBuffer
);
101 fb
->_StencilBuffer
= rb
;
109 * Create and initialize a gl_framebuffer object.
110 * This is intended for creating _window_system_ framebuffers, not generic
111 * framebuffer objects ala GL_EXT_framebuffer_object.
113 * \sa _mesa_new_framebuffer
115 struct gl_framebuffer
*
116 _mesa_create_framebuffer(const GLvisual
*visual
)
118 struct gl_framebuffer
*fb
= CALLOC_STRUCT(gl_framebuffer
);
121 _mesa_initialize_framebuffer(fb
, visual
);
128 * Allocate a new gl_framebuffer object.
129 * This is the default function for ctx->Driver.NewFramebuffer().
130 * This is for allocating user-created framebuffers, not window-system
132 * \sa _mesa_create_framebuffer
134 struct gl_framebuffer
*
135 _mesa_new_framebuffer(GLcontext
*ctx
, GLuint name
)
137 struct gl_framebuffer
*fb
;
140 fb
= CALLOC_STRUCT(gl_framebuffer
);
144 fb
->ColorDrawBuffer
[0] = GL_COLOR_ATTACHMENT0_EXT
;
145 fb
->_ColorDrawBufferMask
[0] = BUFFER_BIT_COLOR0
;
146 fb
->ColorReadBuffer
= GL_COLOR_ATTACHMENT0_EXT
;
147 fb
->_ColorReadBufferIndex
= BUFFER_COLOR0
;
148 fb
->Delete
= _mesa_destroy_framebuffer
;
155 * Initialize a gl_framebuffer object. Typically used to initialize
156 * window system-created framebuffers, not user-created framebuffers.
157 * \sa _mesa_create_framebuffer
160 _mesa_initialize_framebuffer(struct gl_framebuffer
*fb
, const GLvisual
*visual
)
165 _mesa_bzero(fb
, sizeof(struct gl_framebuffer
));
167 _glthread_INIT_MUTEX(fb
->Mutex
);
171 /* save the visual */
172 fb
->Visual
= *visual
;
174 /* Init glRead/DrawBuffer state */
175 if (visual
->doubleBufferMode
) {
176 fb
->ColorDrawBuffer
[0] = GL_BACK
;
177 fb
->_ColorDrawBufferMask
[0] = BUFFER_BIT_BACK_LEFT
;
178 fb
->ColorReadBuffer
= GL_BACK
;
179 fb
->_ColorReadBufferIndex
= BUFFER_BACK_LEFT
;
182 fb
->ColorDrawBuffer
[0] = GL_FRONT
;
183 fb
->_ColorDrawBufferMask
[0] = BUFFER_BIT_FRONT_LEFT
;
184 fb
->ColorReadBuffer
= GL_FRONT
;
185 fb
->_ColorReadBufferIndex
= BUFFER_FRONT_LEFT
;
188 fb
->Delete
= _mesa_destroy_framebuffer
;
189 fb
->_Status
= GL_FRAMEBUFFER_COMPLETE_EXT
;
191 compute_depth_max(fb
);
196 * Deallocate buffer and everything attached to it.
197 * Typically called via the gl_framebuffer->Delete() method.
200 _mesa_destroy_framebuffer(struct gl_framebuffer
*fb
)
203 _mesa_free_framebuffer_data(fb
);
210 * Free all the data hanging off the given gl_framebuffer, but don't free
211 * the gl_framebuffer object itself.
214 _mesa_free_framebuffer_data(struct gl_framebuffer
*fb
)
219 assert(fb
->RefCount
== 0);
221 _glthread_DESTROY_MUTEX(fb
->Mutex
);
223 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
224 struct gl_renderbuffer_attachment
*att
= &fb
->Attachment
[i
];
225 if (att
->Renderbuffer
) {
226 _mesa_unreference_renderbuffer(&att
->Renderbuffer
);
229 /* render to texture */
230 att
->Texture
->RefCount
--;
231 if (att
->Texture
->RefCount
== 0) {
232 GET_CURRENT_CONTEXT(ctx
);
234 ctx
->Driver
.DeleteTexture(ctx
, att
->Texture
);
242 /* unbind depth/stencil to decr ref counts */
243 set_depth_renderbuffer(fb
, NULL
);
244 set_stencil_renderbuffer(fb
, NULL
);
249 * Set *ptr to point to fb, with refcounting and locking.
252 _mesa_reference_framebuffer(struct gl_framebuffer
**ptr
,
253 struct gl_framebuffer
*fb
)
258 _glthread_LOCK_MUTEX(fb
->Mutex
);
260 _glthread_UNLOCK_MUTEX(fb
->Mutex
);
266 * Undo/remove a reference to a framebuffer object.
267 * Decrement the framebuffer object's reference count and delete it when
268 * the refcount hits zero.
269 * Note: we pass the address of a pointer and set it to NULL.
272 _mesa_unreference_framebuffer(struct gl_framebuffer
**fb
)
276 GLboolean deleteFlag
= GL_FALSE
;
278 _glthread_LOCK_MUTEX((*fb
)->Mutex
);
279 ASSERT((*fb
)->RefCount
> 0);
281 deleteFlag
= ((*fb
)->RefCount
== 0);
282 _glthread_UNLOCK_MUTEX((*fb
)->Mutex
);
295 * Resize the given framebuffer's renderbuffers to the new width and height.
296 * This should only be used for window-system framebuffers, not
297 * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object).
298 * This will typically be called via ctx->Driver.ResizeBuffers() or directly
299 * from a device driver.
301 * \note it's possible for ctx to be null since a window can be resized
302 * without a currently bound rendering context.
305 _mesa_resize_framebuffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
,
306 GLuint width
, GLuint height
)
310 /* XXX I think we could check if the size is not changing
314 /* For window system framebuffers, Name is zero */
315 assert(fb
->Name
== 0);
317 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
318 struct gl_renderbuffer_attachment
*att
= &fb
->Attachment
[i
];
319 if (att
->Type
== GL_RENDERBUFFER_EXT
&& att
->Renderbuffer
) {
320 struct gl_renderbuffer
*rb
= att
->Renderbuffer
;
321 /* only resize if size is changing */
322 if (rb
->Width
!= width
|| rb
->Height
!= height
) {
323 /* could just as well pass rb->_ActualFormat here */
324 if (rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
)) {
325 ASSERT(rb
->Width
== width
);
326 ASSERT(rb
->Height
== height
);
329 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Resizing framebuffer");
336 if (fb
->_DepthBuffer
) {
337 struct gl_renderbuffer
*rb
= fb
->_DepthBuffer
;
338 if (rb
->Width
!= width
|| rb
->Height
!= height
) {
339 if (!rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
)) {
340 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Resizing framebuffer");
345 if (fb
->_StencilBuffer
) {
346 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
347 if (rb
->Width
!= width
|| rb
->Height
!= height
) {
348 if (!rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
)) {
349 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Resizing framebuffer");
358 /* update scissor / window bounds */
359 _mesa_update_draw_buffer_bounds(ctx
);
360 /* Signal new buffer state so that swrast will update its clipping
361 * info (the CLIP_BIT flag).
363 ctx
->NewState
|= _NEW_BUFFERS
;
369 * Examine all the framebuffer's renderbuffers to update the Width/Height
370 * fields of the framebuffer. If we have renderbuffers with different
371 * sizes, set the framebuffer's width and height to zero.
372 * Note: this is only intended for user-created framebuffers, not
373 * window-system framebuffes.
376 update_framebuffer_size(struct gl_framebuffer
*fb
)
378 GLboolean haveSize
= GL_FALSE
;
381 /* user-created framebuffers only */
384 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
385 struct gl_renderbuffer_attachment
*att
= &fb
->Attachment
[i
];
386 const struct gl_renderbuffer
*rb
= att
->Renderbuffer
;
389 if (rb
->Width
!= fb
->Width
&& rb
->Height
!= fb
->Height
) {
397 fb
->Width
= rb
->Width
;
398 fb
->Height
= rb
->Height
;
407 * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields.
408 * These values are computed from the buffer's width and height and
409 * the scissor box, if it's enabled.
410 * \param ctx the GL context.
413 _mesa_update_draw_buffer_bounds(GLcontext
*ctx
)
415 struct gl_framebuffer
*buffer
= ctx
->DrawBuffer
;
421 /* user-created framebuffer size depends on the renderbuffers */
422 update_framebuffer_size(buffer
);
427 buffer
->_Xmax
= buffer
->Width
;
428 buffer
->_Ymax
= buffer
->Height
;
430 if (ctx
->Scissor
.Enabled
) {
431 if (ctx
->Scissor
.X
> buffer
->_Xmin
) {
432 buffer
->_Xmin
= ctx
->Scissor
.X
;
434 if (ctx
->Scissor
.Y
> buffer
->_Ymin
) {
435 buffer
->_Ymin
= ctx
->Scissor
.Y
;
437 if (ctx
->Scissor
.X
+ ctx
->Scissor
.Width
< buffer
->_Xmax
) {
438 buffer
->_Xmax
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
;
440 if (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
< buffer
->_Ymax
) {
441 buffer
->_Ymax
= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
;
443 /* finally, check for empty region */
444 if (buffer
->_Xmin
> buffer
->_Xmax
) {
445 buffer
->_Xmin
= buffer
->_Xmax
;
447 if (buffer
->_Ymin
> buffer
->_Ymax
) {
448 buffer
->_Ymin
= buffer
->_Ymax
;
452 ASSERT(buffer
->_Xmin
<= buffer
->_Xmax
);
453 ASSERT(buffer
->_Ymin
<= buffer
->_Ymax
);
458 * The glGet queries of the framebuffer red/green/blue size, stencil size,
459 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can
460 * change depending on the renderbuffer bindings. This function updates
461 * the given framebuffer's Visual from the current renderbuffer bindings.
463 * This may apply to user-created framebuffers or window system framebuffers.
465 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
466 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
467 * The former one is used to convert floating point depth values into
471 _mesa_update_framebuffer_visual(struct gl_framebuffer
*fb
)
475 _mesa_bzero(&fb
->Visual
, sizeof(fb
->Visual
));
476 fb
->Visual
.rgbMode
= GL_TRUE
; /* assume this */
478 #if 0 /* this _might_ be needed */
479 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
480 /* leave visual fields zero'd */
485 /* find first RGB or CI renderbuffer */
486 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
487 if (fb
->Attachment
[i
].Renderbuffer
) {
488 const struct gl_renderbuffer
*rb
= fb
->Attachment
[i
].Renderbuffer
;
489 if (rb
->_BaseFormat
== GL_RGBA
|| rb
->_BaseFormat
== GL_RGB
) {
490 fb
->Visual
.redBits
= rb
->RedBits
;
491 fb
->Visual
.greenBits
= rb
->GreenBits
;
492 fb
->Visual
.blueBits
= rb
->BlueBits
;
493 fb
->Visual
.alphaBits
= rb
->AlphaBits
;
494 fb
->Visual
.rgbBits
= fb
->Visual
.redBits
495 + fb
->Visual
.greenBits
+ fb
->Visual
.blueBits
;
496 fb
->Visual
.floatMode
= GL_FALSE
;
499 else if (rb
->_BaseFormat
== GL_COLOR_INDEX
) {
500 fb
->Visual
.indexBits
= rb
->IndexBits
;
501 fb
->Visual
.rgbMode
= GL_FALSE
;
507 if (fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
) {
508 fb
->Visual
.haveDepthBuffer
= GL_TRUE
;
510 = fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
->DepthBits
;
513 if (fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
) {
514 fb
->Visual
.haveStencilBuffer
= GL_TRUE
;
515 fb
->Visual
.stencilBits
516 = fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
->StencilBits
;
519 if (fb
->Attachment
[BUFFER_ACCUM
].Renderbuffer
) {
520 fb
->Visual
.haveAccumBuffer
= GL_TRUE
;
521 fb
->Visual
.accumRedBits
522 = fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
->RedBits
;
523 fb
->Visual
.accumGreenBits
524 = fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
->GreenBits
;
525 fb
->Visual
.accumBlueBits
526 = fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
->BlueBits
;
527 fb
->Visual
.accumAlphaBits
528 = fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
->AlphaBits
;
531 compute_depth_max(fb
);
536 * Update the framebuffer's _DepthBuffer field using the renderbuffer
537 * found at the given attachment index.
539 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
540 * create and install a depth wrapper/adaptor.
542 * \param fb the framebuffer whose _DepthBuffer field to update
543 * \param attIndex indicates the renderbuffer to possibly wrap
546 _mesa_update_depth_buffer(GLcontext
*ctx
,
547 struct gl_framebuffer
*fb
,
550 struct gl_renderbuffer
*depthRb
;
552 /* only one possiblity for now */
553 ASSERT(attIndex
== BUFFER_DEPTH
);
555 depthRb
= fb
->Attachment
[attIndex
].Renderbuffer
;
557 if (depthRb
&& depthRb
->_ActualFormat
== GL_DEPTH24_STENCIL8_EXT
) {
558 /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
559 if (!fb
->_DepthBuffer
560 || fb
->_DepthBuffer
->Wrapped
!= depthRb
561 || fb
->_DepthBuffer
->_BaseFormat
!= GL_DEPTH_COMPONENT
) {
562 /* need to update wrapper */
563 struct gl_renderbuffer
*wrapper
564 = _mesa_new_z24_renderbuffer_wrapper(ctx
, depthRb
);
565 set_depth_renderbuffer(fb
, wrapper
);
566 ASSERT(fb
->_DepthBuffer
->Wrapped
== depthRb
);
570 /* depthRb may be null */
571 set_depth_renderbuffer(fb
, depthRb
);
577 * Update the framebuffer's _StencilBuffer field using the renderbuffer
578 * found at the given attachment index.
580 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
581 * create and install a stencil wrapper/adaptor.
583 * \param fb the framebuffer whose _StencilBuffer field to update
584 * \param attIndex indicates the renderbuffer to possibly wrap
587 _mesa_update_stencil_buffer(GLcontext
*ctx
,
588 struct gl_framebuffer
*fb
,
591 struct gl_renderbuffer
*stencilRb
;
593 ASSERT(attIndex
== BUFFER_DEPTH
||
594 attIndex
== BUFFER_STENCIL
);
596 stencilRb
= fb
->Attachment
[attIndex
].Renderbuffer
;
598 if (stencilRb
&& stencilRb
->_ActualFormat
== GL_DEPTH24_STENCIL8_EXT
) {
599 /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
600 if (!fb
->_StencilBuffer
601 || fb
->_StencilBuffer
->Wrapped
!= stencilRb
602 || fb
->_StencilBuffer
->_BaseFormat
!= GL_STENCIL_INDEX
) {
603 /* need to update wrapper */
604 struct gl_renderbuffer
*wrapper
605 = _mesa_new_s8_renderbuffer_wrapper(ctx
, stencilRb
);
606 set_stencil_renderbuffer(fb
, wrapper
);
607 ASSERT(fb
->_StencilBuffer
->Wrapped
== stencilRb
);
611 /* stencilRb may be null */
612 set_stencil_renderbuffer(fb
, stencilRb
);
618 * Update the list of color drawing renderbuffer pointers.
619 * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers
623 update_color_draw_buffers(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
628 * Fragment programs can write to multiple colorbuffers with
629 * the GL_ARB_draw_buffers extension.
631 for (output
= 0; output
< ctx
->Const
.MaxDrawBuffers
; output
++) {
632 GLbitfield bufferMask
= fb
->_ColorDrawBufferMask
[output
];
635 if (!fb
->DeletePending
) {
636 /* We need the inner loop here because glDrawBuffer(GL_FRONT_AND_BACK)
637 * can specify writing to two or four color buffers (for example).
639 for (i
= 0; bufferMask
&& i
< BUFFER_COUNT
; i
++) {
640 const GLuint bufferBit
= 1 << i
;
641 if (bufferBit
& bufferMask
) {
642 struct gl_renderbuffer
*rb
= fb
->Attachment
[i
].Renderbuffer
;
644 fb
->_ColorDrawBuffers
[output
][count
] = rb
;
649 _mesa_warning(ctx, "DrawBuffer names a missing buffer!\n");
652 bufferMask
&= ~bufferBit
;
656 fb
->_NumColorDrawBuffers
[output
] = count
;
662 * Update the color read renderbuffer pointer.
663 * Unlike the DrawBuffer, we can only read from one (or zero) color buffers.
666 update_color_read_buffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
669 if (fb
->_ColorReadBufferIndex
== -1 || fb
->DeletePending
) {
670 fb
->_ColorReadBuffer
= NULL
; /* legal! */
673 ASSERT(fb
->_ColorReadBufferIndex
>= 0);
674 ASSERT(fb
->_ColorReadBufferIndex
< BUFFER_COUNT
);
676 = fb
->Attachment
[fb
->_ColorReadBufferIndex
].Renderbuffer
;
682 * Update state related to the current draw/read framebuffers.
683 * Specifically, update these framebuffer fields:
685 * _NumColorDrawBuffers
689 * If the current framebuffer is user-created, make sure it's complete.
690 * The following functions can effect this state: glReadBuffer,
691 * glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT,
692 * glRenderbufferStorageEXT.
695 _mesa_update_framebuffer(GLcontext
*ctx
)
697 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
699 /* Completeness only matters for user-created framebuffers */
701 _mesa_test_framebuffer_completeness(ctx
, fb
);
702 _mesa_update_framebuffer_visual(fb
);
705 update_color_draw_buffers(ctx
, fb
);
706 update_color_read_buffer(ctx
, fb
);
707 _mesa_update_depth_buffer(ctx
, fb
, BUFFER_DEPTH
);
708 _mesa_update_stencil_buffer(ctx
, fb
, BUFFER_STENCIL
);
710 compute_depth_max(fb
);
715 * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
716 * glCopyTex[Sub]Image, etc. exists.
717 * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
718 * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
719 * \return GL_TRUE if buffer exists, GL_FALSE otherwise
722 _mesa_source_buffer_exists(GLcontext
*ctx
, GLenum format
)
724 const struct gl_renderbuffer_attachment
*att
725 = ctx
->ReadBuffer
->Attachment
;
727 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
738 case GL_LUMINANCE_ALPHA
:
746 if (ctx
->ReadBuffer
->_ColorReadBuffer
== NULL
) {
749 /* XXX enable this post 6.5 release:
750 ASSERT(ctx->ReadBuffer->_ColorReadBuffer->RedBits > 0 ||
751 ctx->ReadBuffer->_ColorReadBuffer->IndexBits > 0);
755 case GL_DEPTH_COMPONENT
:
756 if (!att
[BUFFER_DEPTH
].Renderbuffer
) {
759 ASSERT(att
[BUFFER_DEPTH
].Renderbuffer
->DepthBits
> 0);
762 case GL_STENCIL_INDEX
:
763 if (!att
[BUFFER_STENCIL
].Renderbuffer
) {
766 ASSERT(att
[BUFFER_STENCIL
].Renderbuffer
->StencilBits
> 0);
768 case GL_DEPTH_STENCIL_EXT
:
769 if (!att
[BUFFER_DEPTH
].Renderbuffer
||
770 !att
[BUFFER_STENCIL
].Renderbuffer
) {
773 ASSERT(att
[BUFFER_DEPTH
].Renderbuffer
->DepthBits
> 0);
774 ASSERT(att
[BUFFER_STENCIL
].Renderbuffer
->StencilBits
> 0);
778 "Unexpected format 0x%x in _mesa_source_buffer_exists",
789 * As above, but for drawing operations.
790 * XXX code do some code merging w/ above function.
793 _mesa_dest_buffer_exists(GLcontext
*ctx
, GLenum format
)
795 const struct gl_renderbuffer_attachment
*att
796 = ctx
->ReadBuffer
->Attachment
;
798 if (ctx
->DrawBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
809 case GL_LUMINANCE_ALPHA
:
817 /* nothing special */
818 /* Could assert that colorbuffer has RedBits > 0 */
821 case GL_DEPTH_COMPONENT
:
822 if (!att
[BUFFER_DEPTH
].Renderbuffer
) {
825 ASSERT(att
[BUFFER_DEPTH
].Renderbuffer
->DepthBits
> 0);
828 case GL_STENCIL_INDEX
:
829 if (!att
[BUFFER_STENCIL
].Renderbuffer
) {
832 ASSERT(att
[BUFFER_STENCIL
].Renderbuffer
->StencilBits
> 0);
834 case GL_DEPTH_STENCIL_EXT
:
835 if (!att
[BUFFER_DEPTH
].Renderbuffer
||
836 !att
[BUFFER_STENCIL
].Renderbuffer
) {
839 ASSERT(att
[BUFFER_DEPTH
].Renderbuffer
->DepthBits
> 0);
840 ASSERT(att
[BUFFER_STENCIL
].Renderbuffer
->StencilBits
> 0);
844 "Unexpected format 0x%x in _mesa_source_buffer_exists",