Code reorganization: move files into their places.
[mesa.git] / src / gallium / drivers / softpipe / sp_quad_depth_test.c
1 /**************************************************************************
2 *
3 * Copyright 2007 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 /**
29 * \brief Quad depth testing
30 */
31
32 #include "pipe/p_defines.h"
33 #include "pipe/p_util.h"
34 #include "sp_context.h"
35 #include "sp_headers.h"
36 #include "sp_surface.h"
37 #include "sp_quad.h"
38 #include "sp_tile_cache.h"
39
40
41 /**
42 * Do depth testing for a quad.
43 * Not static since it's used by the stencil code.
44 */
45
46 /*
47 * To increase efficiency, we should probably have multiple versions
48 * of this function that are specifically for Z16, Z32 and FP Z buffers.
49 * Try to effectively do that with codegen...
50 */
51
52 void
53 sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
54 {
55 struct softpipe_context *softpipe = qs->softpipe;
56 struct pipe_surface *ps = softpipe->framebuffer.zsbuf;
57 const enum pipe_format format = ps->format;
58 unsigned bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */
59 unsigned qzzzz[QUAD_SIZE]; /**< Z values from the quad */
60 unsigned zmask = 0;
61 unsigned j;
62 struct softpipe_cached_tile *tile
63 = sp_get_cached_tile(softpipe, softpipe->zsbuf_cache, quad->x0, quad->y0);
64
65 assert(ps); /* shouldn't get here if there's no zbuffer */
66
67 /*
68 * Convert quad's float depth values to int depth values (qzzzz).
69 * If the Z buffer stores integer values, we _have_ to do the depth
70 * compares with integers (not floats). Otherwise, the float->int->float
71 * conversion of Z values (which isn't an identity function) will cause
72 * Z-fighting errors.
73 *
74 * Also, get the zbuffer values (bzzzz) from the cached tile.
75 */
76 switch (format) {
77 case PIPE_FORMAT_Z16_UNORM:
78 {
79 float scale = 65535.0;
80
81 for (j = 0; j < QUAD_SIZE; j++) {
82 qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
83 }
84
85 for (j = 0; j < QUAD_SIZE; j++) {
86 int x = quad->x0 % TILE_SIZE + (j & 1);
87 int y = quad->y0 % TILE_SIZE + (j >> 1);
88 bzzzz[j] = tile->data.depth16[y][x];
89 }
90 }
91 break;
92 case PIPE_FORMAT_Z32_UNORM:
93 {
94 double scale = (double) (uint) ~0UL;
95
96 for (j = 0; j < QUAD_SIZE; j++) {
97 qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
98 }
99
100 for (j = 0; j < QUAD_SIZE; j++) {
101 int x = quad->x0 % TILE_SIZE + (j & 1);
102 int y = quad->y0 % TILE_SIZE + (j >> 1);
103 bzzzz[j] = tile->data.depth32[y][x];
104 }
105 }
106 break;
107 case PIPE_FORMAT_S8Z24_UNORM:
108 {
109 float scale = (float) ((1 << 24) - 1);
110
111 for (j = 0; j < QUAD_SIZE; j++) {
112 qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
113 }
114
115 for (j = 0; j < QUAD_SIZE; j++) {
116 int x = quad->x0 % TILE_SIZE + (j & 1);
117 int y = quad->y0 % TILE_SIZE + (j >> 1);
118 bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
119 }
120 }
121 break;
122 case PIPE_FORMAT_Z24S8_UNORM:
123 {
124 float scale = (float) ((1 << 24) - 1);
125
126 for (j = 0; j < QUAD_SIZE; j++) {
127 qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
128 }
129
130 for (j = 0; j < QUAD_SIZE; j++) {
131 int x = quad->x0 % TILE_SIZE + (j & 1);
132 int y = quad->y0 % TILE_SIZE + (j >> 1);
133 bzzzz[j] = tile->data.depth32[y][x] >> 8;
134 }
135 }
136 break;
137 default:
138 assert(0);
139 }
140
141 switch (softpipe->depth_stencil->depth.func) {
142 case PIPE_FUNC_NEVER:
143 /* zmask = 0 */
144 break;
145 case PIPE_FUNC_LESS:
146 /* Note this is pretty much a single sse or cell instruction.
147 * Like this: quad->mask &= (quad->outputs.depth < zzzz);
148 */
149 for (j = 0; j < QUAD_SIZE; j++) {
150 if (qzzzz[j] < bzzzz[j])
151 zmask |= 1 << j;
152 }
153 break;
154 case PIPE_FUNC_EQUAL:
155 for (j = 0; j < QUAD_SIZE; j++) {
156 if (qzzzz[j] == bzzzz[j])
157 zmask |= 1 << j;
158 }
159 break;
160 case PIPE_FUNC_LEQUAL:
161 for (j = 0; j < QUAD_SIZE; j++) {
162 if (qzzzz[j] <= bzzzz[j])
163 zmask |= (1 << j);
164 }
165 break;
166 case PIPE_FUNC_GREATER:
167 for (j = 0; j < QUAD_SIZE; j++) {
168 if (qzzzz[j] > bzzzz[j])
169 zmask |= (1 << j);
170 }
171 break;
172 case PIPE_FUNC_NOTEQUAL:
173 for (j = 0; j < QUAD_SIZE; j++) {
174 if (qzzzz[j] != bzzzz[j])
175 zmask |= (1 << j);
176 }
177 break;
178 case PIPE_FUNC_GEQUAL:
179 for (j = 0; j < QUAD_SIZE; j++) {
180 if (qzzzz[j] >= bzzzz[j])
181 zmask |= (1 << j);
182 }
183 break;
184 case PIPE_FUNC_ALWAYS:
185 zmask = MASK_ALL;
186 break;
187 default:
188 abort();
189 }
190
191 quad->mask &= zmask;
192
193 if (softpipe->depth_stencil->depth.writemask) {
194
195 /* This is also efficient with sse / spe instructions:
196 */
197 for (j = 0; j < QUAD_SIZE; j++) {
198 if (quad->mask & (1 << j)) {
199 bzzzz[j] = qzzzz[j];
200 }
201 }
202
203 /* put updated Z values back into cached tile */
204 switch (format) {
205 case PIPE_FORMAT_Z16_UNORM:
206 for (j = 0; j < QUAD_SIZE; j++) {
207 int x = quad->x0 % TILE_SIZE + (j & 1);
208 int y = quad->y0 % TILE_SIZE + (j >> 1);
209 tile->data.depth16[y][x] = (ushort) bzzzz[j];
210 }
211 break;
212 case PIPE_FORMAT_Z32_UNORM:
213 for (j = 0; j < QUAD_SIZE; j++) {
214 int x = quad->x0 % TILE_SIZE + (j & 1);
215 int y = quad->y0 % TILE_SIZE + (j >> 1);
216 tile->data.depth32[y][x] = bzzzz[j];
217 }
218 break;
219 case PIPE_FORMAT_S8Z24_UNORM:
220 for (j = 0; j < QUAD_SIZE; j++) {
221 int x = quad->x0 % TILE_SIZE + (j & 1);
222 int y = quad->y0 % TILE_SIZE + (j >> 1);
223 uint s8z24 = tile->data.depth32[y][x];
224 s8z24 = (s8z24 & 0xff000000) | bzzzz[j];
225 tile->data.depth32[y][x] = s8z24;
226 }
227 break;
228 case PIPE_FORMAT_Z24S8_UNORM:
229 for (j = 0; j < QUAD_SIZE; j++) {
230 int x = quad->x0 % TILE_SIZE + (j & 1);
231 int y = quad->y0 % TILE_SIZE + (j >> 1);
232 uint z24s8 = tile->data.depth32[y][x];
233 z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 24);
234 tile->data.depth32[y][x] = z24s8;
235 }
236 break;
237 default:
238 assert(0);
239 }
240 }
241 }
242
243
244 static void
245 depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
246 {
247 sp_depth_test_quad(qs, quad);
248
249 if (quad->mask)
250 qs->next->run(qs->next, quad);
251 }
252
253
254 static void depth_test_begin(struct quad_stage *qs)
255 {
256 qs->next->begin(qs->next);
257 }
258
259
260 static void depth_test_destroy(struct quad_stage *qs)
261 {
262 FREE( qs );
263 }
264
265
266 struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe )
267 {
268 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
269
270 stage->softpipe = softpipe;
271 stage->begin = depth_test_begin;
272 stage->run = depth_test_quad;
273 stage->destroy = depth_test_destroy;
274
275 return stage;
276 }