OSDN Git Service

i965: new integrated graphics chipset support
[android-x86/external-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 }