1 /**************************************************************************
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
31 #include "depthstencil.h"
33 #include "framebuffer.h"
36 #include "renderbuffer.h"
38 #include "intel_context.h"
39 #include "intel_fbo.h"
40 #include "intel_depthstencil.h"
41 #include "intel_regions.h"
42 #include "intel_span.h"
45 * The GL_EXT_framebuffer_object allows the user to create their own
46 * framebuffer objects consisting of color renderbuffers (0 or more),
47 * depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1).
49 * The spec considers depth and stencil renderbuffers to be totally independent
50 * buffers. In reality, most graphics hardware today uses a combined
51 * depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil).
53 * This causes difficulty because the user may create some number of depth
54 * renderbuffers and some number of stencil renderbuffers and bind them
55 * together in framebuffers in any combination.
57 * This code manages all that.
59 * 1. Depth renderbuffers are always allocated in hardware as 32bpp
60 * GL_DEPTH24_STENCIL8 buffers.
62 * 2. Stencil renderbuffers are initially allocated in software as 8bpp
63 * GL_STENCIL_INDEX8 buffers.
65 * 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth
66 * fields (respectively) to indicate if the buffer's currently paired
67 * with another stencil or depth buffer (respectively).
69 * 4. When a depth and stencil buffer are initially both attached to the
70 * current framebuffer, we merge the stencil buffer values into the
71 * depth buffer (really a depth+stencil buffer). The then hardware uses
72 * the combined buffer.
74 * 5. Whenever a depth or stencil buffer is reallocated (with
75 * glRenderbufferStorage) we undo the pairing and copy the stencil values
76 * from the combined depth/stencil buffer back to the stencil-only buffer.
78 * 6. We also undo the pairing when we find a change in buffer bindings.
80 * 7. If a framebuffer is only using a depth renderbuffer (no stencil), we
81 * just use the combined depth/stencil buffer and ignore the stencil values.
83 * 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have
84 * to promote the 8bpp software stencil buffer to a 32bpp hardware
85 * depth+stencil buffer.
90 * Undo the pairing/interleaving between depth and stencil buffers.
91 * irb should be a depth/stencil or stencil renderbuffer.
94 intel_unpair_depth_stencil(GLcontext
*ctx
, struct intel_renderbuffer
*irb
)
96 struct intel_context
*intel
= intel_context(ctx
);
97 struct gl_renderbuffer
*rb
= &irb
->Base
;
99 if (irb
->PairedStencil
) {
100 /* irb is a depth/stencil buffer */
101 struct gl_renderbuffer
*stencilRb
;
102 struct intel_renderbuffer
*stencilIrb
;
104 ASSERT(rb
->_ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
106 stencilRb
= _mesa_lookup_renderbuffer(ctx
, irb
->PairedStencil
);
107 stencilIrb
= intel_renderbuffer(stencilRb
);
109 /* need to extract stencil values from the depth buffer */
110 ASSERT(stencilIrb
->PairedDepth
== rb
->Name
);
111 intel_renderbuffer_map(intel
, rb
);
112 intel_renderbuffer_map(intel
, stencilRb
);
113 _mesa_extract_stencil(ctx
, rb
, stencilRb
);
114 intel_renderbuffer_unmap(intel
, stencilRb
);
115 intel_renderbuffer_unmap(intel
, rb
);
116 stencilIrb
->PairedDepth
= 0;
118 irb
->PairedStencil
= 0;
120 else if (irb
->PairedDepth
) {
121 /* irb is a stencil buffer */
122 struct gl_renderbuffer
*depthRb
;
123 struct intel_renderbuffer
*depthIrb
;
125 ASSERT(rb
->_ActualFormat
== GL_STENCIL_INDEX8_EXT
||
126 rb
->_ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
128 depthRb
= _mesa_lookup_renderbuffer(ctx
, irb
->PairedDepth
);
129 depthIrb
= intel_renderbuffer(depthRb
);
131 /* need to extract stencil values from the depth buffer */
132 ASSERT(depthIrb
->PairedStencil
== rb
->Name
);
133 intel_renderbuffer_map(intel
, rb
);
134 intel_renderbuffer_map(intel
, depthRb
);
135 _mesa_extract_stencil(ctx
, depthRb
, rb
);
136 intel_renderbuffer_unmap(intel
, depthRb
);
137 intel_renderbuffer_unmap(intel
, rb
);
138 depthIrb
->PairedStencil
= 0;
140 irb
->PairedDepth
= 0;
143 _mesa_problem(ctx
, "Problem in undo_depth_stencil_pairing");
146 ASSERT(irb
->PairedStencil
== 0);
147 ASSERT(irb
->PairedDepth
== 0);
152 * Examine the depth and stencil renderbuffers which are attached to the
153 * framebuffer. If both depth and stencil are attached, make sure that the
154 * renderbuffers are 'paired' (combined). If only depth or only stencil is
155 * attached, undo any previous pairing.
157 * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments
158 * change, for example).
161 intel_validate_paired_depth_stencil(GLcontext
* ctx
,
162 struct gl_framebuffer
*fb
)
164 struct intel_context
*intel
= intel_context(ctx
);
165 struct intel_renderbuffer
*depthRb
, *stencilRb
;
167 depthRb
= intel_get_renderbuffer(fb
, BUFFER_DEPTH
);
168 stencilRb
= intel_get_renderbuffer(fb
, BUFFER_STENCIL
);
170 if (depthRb
&& stencilRb
) {
171 if (depthRb
== stencilRb
) {
172 /* Using a user-created combined depth/stencil buffer.
175 ASSERT(depthRb
->Base
._BaseFormat
== GL_DEPTH_STENCIL_EXT
);
176 ASSERT(depthRb
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
179 /* Separate depth/stencil buffers, need to interleave now */
180 ASSERT(depthRb
->Base
._BaseFormat
== GL_DEPTH_COMPONENT
);
181 ASSERT(stencilRb
->Base
._BaseFormat
== GL_STENCIL_INDEX
);
182 /* may need to interleave depth/stencil now */
183 if (depthRb
->PairedStencil
== stencilRb
->Base
.Name
) {
184 /* OK, the depth and stencil buffers are already interleaved */
185 ASSERT(stencilRb
->PairedDepth
== depthRb
->Base
.Name
);
188 /* need to setup new pairing/interleaving */
189 if (depthRb
->PairedStencil
) {
190 intel_unpair_depth_stencil(ctx
, depthRb
);
192 if (stencilRb
->PairedDepth
) {
193 intel_unpair_depth_stencil(ctx
, stencilRb
);
196 ASSERT(depthRb
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
197 ASSERT(stencilRb
->Base
._ActualFormat
== GL_STENCIL_INDEX8_EXT
||
198 stencilRb
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
200 /* establish new pairing: interleave stencil into depth buffer */
201 intel_renderbuffer_map(intel
, &depthRb
->Base
);
202 intel_renderbuffer_map(intel
, &stencilRb
->Base
);
203 _mesa_insert_stencil(ctx
, &depthRb
->Base
, &stencilRb
->Base
);
204 intel_renderbuffer_unmap(intel
, &stencilRb
->Base
);
205 intel_renderbuffer_unmap(intel
, &depthRb
->Base
);
206 depthRb
->PairedStencil
= stencilRb
->Base
.Name
;
207 stencilRb
->PairedDepth
= depthRb
->Base
.Name
;
213 /* Depth buffer but no stencil buffer.
214 * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
216 /* can't assert this until storage is allocated:
217 ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
219 /* intel_undo any previous pairing */
220 if (depthRb
->PairedStencil
) {
221 intel_unpair_depth_stencil(ctx
, depthRb
);
224 else if (stencilRb
) {
225 /* Stencil buffer but no depth buffer.
226 * Since h/w doesn't typically support just 8bpp stencil w/out Z,
227 * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
229 /* undo any previous pairing */
230 if (stencilRb
->PairedDepth
) {
231 intel_unpair_depth_stencil(ctx
, stencilRb
);
233 if (stencilRb
->Base
._ActualFormat
== GL_STENCIL_INDEX8_EXT
) {
234 /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */
235 _mesa_promote_stencil(ctx
, &stencilRb
->Base
);
236 ASSERT(stencilRb
->Base
._ActualFormat
== GL_DEPTH24_STENCIL8_EXT
);
240 /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */
241 _mesa_update_depth_buffer(ctx
, fb
, BUFFER_DEPTH
);
242 if (depthRb
&& depthRb
->PairedStencil
)
243 _mesa_update_stencil_buffer(ctx
, fb
, BUFFER_DEPTH
);
245 _mesa_update_stencil_buffer(ctx
, fb
, BUFFER_STENCIL
);
248 /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
249 * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer