Merge branch 'master' into autoconf2
[mesa.git] / src / mesa / drivers / dri / intel / intel_depthstencil.c
1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * 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
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.
25 *
26 **************************************************************************/
27
28 #include "glheader.h"
29 #include "imports.h"
30 #include "context.h"
31 #include "depthstencil.h"
32 #include "fbobject.h"
33 #include "framebuffer.h"
34 #include "hash.h"
35 #include "mtypes.h"
36 #include "renderbuffer.h"
37
38 #include "intel_context.h"
39 #include "intel_fbo.h"
40 #include "intel_depthstencil.h"
41 #include "intel_regions.h"
42
43
44 /**
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).
48 *
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).
52 *
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.
56 *
57 * This code manages all that.
58 *
59 * 1. Depth renderbuffers are always allocated in hardware as 32bpp
60 * GL_DEPTH24_STENCIL8 buffers.
61 *
62 * 2. Stencil renderbuffers are initially allocated in software as 8bpp
63 * GL_STENCIL_INDEX8 buffers.
64 *
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).
68 *
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.
73 *
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.
77 *
78 * 6. We also undo the pairing when we find a change in buffer bindings.
79 *
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.
82 *
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.
86 *
87 */
88
89
90
91 static void
92 map_regions(GLcontext * ctx,
93 struct intel_renderbuffer *depthRb,
94 struct intel_renderbuffer *stencilRb)
95 {
96 struct intel_context *intel = intel_context(ctx);
97 if (depthRb && depthRb->region) {
98 intel_region_map(intel, depthRb->region);
99 depthRb->pfMap = depthRb->region->map;
100 depthRb->pfPitch = depthRb->region->pitch;
101 }
102 if (stencilRb && stencilRb->region) {
103 intel_region_map(intel, stencilRb->region);
104 stencilRb->pfMap = stencilRb->region->map;
105 stencilRb->pfPitch = stencilRb->region->pitch;
106 }
107 }
108
109 static void
110 unmap_regions(GLcontext * ctx,
111 struct intel_renderbuffer *depthRb,
112 struct intel_renderbuffer *stencilRb)
113 {
114 struct intel_context *intel = intel_context(ctx);
115 if (depthRb && depthRb->region) {
116 intel_region_unmap(intel, depthRb->region);
117 depthRb->pfMap = NULL;
118 depthRb->pfPitch = 0;
119 }
120 if (stencilRb && stencilRb->region) {
121 intel_region_unmap(intel, stencilRb->region);
122 stencilRb->pfMap = NULL;
123 stencilRb->pfPitch = 0;
124 }
125 }
126
127
128
129 /**
130 * Undo the pairing/interleaving between depth and stencil buffers.
131 * irb should be a depth/stencil or stencil renderbuffer.
132 */
133 void
134 intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb)
135 {
136 if (irb->PairedStencil) {
137 /* irb is a depth/stencil buffer */
138 struct gl_renderbuffer *stencilRb;
139 struct intel_renderbuffer *stencilIrb;
140
141 ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
142
143 stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil);
144 stencilIrb = intel_renderbuffer(stencilRb);
145 if (stencilIrb) {
146 /* need to extract stencil values from the depth buffer */
147 ASSERT(stencilIrb->PairedDepth == irb->Base.Name);
148 map_regions(ctx, irb, stencilIrb);
149 _mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base);
150 unmap_regions(ctx, irb, stencilIrb);
151 stencilIrb->PairedDepth = 0;
152 }
153 irb->PairedStencil = 0;
154 }
155 else if (irb->PairedDepth) {
156 /* irb is a stencil buffer */
157 struct gl_renderbuffer *depthRb;
158 struct intel_renderbuffer *depthIrb;
159
160 ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
161 irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
162
163 depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth);
164 depthIrb = intel_renderbuffer(depthRb);
165 if (depthIrb) {
166 /* need to extract stencil values from the depth buffer */
167 ASSERT(depthIrb->PairedStencil == irb->Base.Name);
168 map_regions(ctx, depthIrb, irb);
169 _mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base);
170 unmap_regions(ctx, depthIrb, irb);
171 depthIrb->PairedStencil = 0;
172 }
173 irb->PairedDepth = 0;
174 }
175 else {
176 _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing");
177 }
178
179 ASSERT(irb->PairedStencil == 0);
180 ASSERT(irb->PairedDepth == 0);
181 }
182
183
184 /**
185 * Examine the depth and stencil renderbuffers which are attached to the
186 * framebuffer. If both depth and stencil are attached, make sure that the
187 * renderbuffers are 'paired' (combined). If only depth or only stencil is
188 * attached, undo any previous pairing.
189 *
190 * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments
191 * change, for example).
192 */
193 void
194 intel_validate_paired_depth_stencil(GLcontext * ctx,
195 struct gl_framebuffer *fb)
196 {
197 struct intel_renderbuffer *depthRb, *stencilRb;
198
199 depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
200 stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
201
202 if (depthRb && stencilRb) {
203 if (depthRb == stencilRb) {
204 /* Using a user-created combined depth/stencil buffer.
205 * Nothing to do.
206 */
207 ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT);
208 ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
209 }
210 else {
211 /* Separate depth/stencil buffers, need to interleave now */
212 ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT);
213 ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX);
214 /* may need to interleave depth/stencil now */
215 if (depthRb->PairedStencil == stencilRb->Base.Name) {
216 /* OK, the depth and stencil buffers are already interleaved */
217 ASSERT(stencilRb->PairedDepth == depthRb->Base.Name);
218 }
219 else {
220 /* need to setup new pairing/interleaving */
221 if (depthRb->PairedStencil) {
222 intel_unpair_depth_stencil(ctx, depthRb);
223 }
224 if (stencilRb->PairedDepth) {
225 intel_unpair_depth_stencil(ctx, stencilRb);
226 }
227
228 ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
229 ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
230 stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
231
232 /* establish new pairing: interleave stencil into depth buffer */
233 map_regions(ctx, depthRb, stencilRb);
234 _mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base);
235 unmap_regions(ctx, depthRb, stencilRb);
236 depthRb->PairedStencil = stencilRb->Base.Name;
237 stencilRb->PairedDepth = depthRb->Base.Name;
238 }
239
240 }
241 }
242 else if (depthRb) {
243 /* Depth buffer but no stencil buffer.
244 * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
245 */
246 /* can't assert this until storage is allocated:
247 ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
248 */
249 /* intel_undo any previous pairing */
250 if (depthRb->PairedStencil) {
251 intel_unpair_depth_stencil(ctx, depthRb);
252 }
253 }
254 else if (stencilRb) {
255 /* Stencil buffer but no depth buffer.
256 * Since h/w doesn't typically support just 8bpp stencil w/out Z,
257 * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
258 */
259 /* undo any previous pairing */
260 if (stencilRb->PairedDepth) {
261 intel_unpair_depth_stencil(ctx, stencilRb);
262 }
263 if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
264 /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */
265 _mesa_promote_stencil(ctx, &stencilRb->Base);
266 ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
267 }
268 }
269
270 /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */
271 _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
272 if (depthRb && depthRb->PairedStencil)
273 _mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH);
274 else
275 _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
276
277
278 /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
279 * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer
280 * if present.
281 */
282 }