1 /**************************************************************************
3 * Copyright 2007 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 **************************************************************************/
29 * \brief Quad depth testing
32 #include "pipe/p_defines.h"
33 #include "util/u_memory.h"
34 #include "sp_context.h"
35 #include "sp_headers.h"
36 #include "sp_surface.h"
38 #include "sp_tile_cache.h"
42 * Do depth testing for a quad.
43 * Not static since it's used by the stencil code.
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...
53 sp_depth_test_quad(struct quad_stage
*qs
, struct quad_header
*quad
)
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 */
62 struct softpipe_cached_tile
*tile
63 = sp_get_cached_tile(softpipe
, softpipe
->zsbuf_cache
, quad
->input
.x0
, quad
->input
.y0
);
65 assert(ps
); /* shouldn't get here if there's no zbuffer */
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
74 * Also, get the zbuffer values (bzzzz) from the cached tile.
77 case PIPE_FORMAT_Z16_UNORM
:
79 float scale
= 65535.0;
81 for (j
= 0; j
< QUAD_SIZE
; j
++) {
82 qzzzz
[j
] = (unsigned) (quad
->output
.depth
[j
] * scale
);
85 for (j
= 0; j
< QUAD_SIZE
; j
++) {
86 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
87 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
88 bzzzz
[j
] = tile
->data
.depth16
[y
][x
];
92 case PIPE_FORMAT_Z32_UNORM
:
94 double scale
= (double) (uint
) ~0UL;
96 for (j
= 0; j
< QUAD_SIZE
; j
++) {
97 qzzzz
[j
] = (unsigned) (quad
->output
.depth
[j
] * scale
);
100 for (j
= 0; j
< QUAD_SIZE
; j
++) {
101 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
102 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
103 bzzzz
[j
] = tile
->data
.depth32
[y
][x
];
107 case PIPE_FORMAT_X8Z24_UNORM
:
109 case PIPE_FORMAT_S8Z24_UNORM
:
111 float scale
= (float) ((1 << 24) - 1);
113 for (j
= 0; j
< QUAD_SIZE
; j
++) {
114 qzzzz
[j
] = (unsigned) (quad
->output
.depth
[j
] * scale
);
117 for (j
= 0; j
< QUAD_SIZE
; j
++) {
118 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
119 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
120 bzzzz
[j
] = tile
->data
.depth32
[y
][x
] & 0xffffff;
124 case PIPE_FORMAT_Z24X8_UNORM
:
126 case PIPE_FORMAT_Z24S8_UNORM
:
128 float scale
= (float) ((1 << 24) - 1);
130 for (j
= 0; j
< QUAD_SIZE
; j
++) {
131 qzzzz
[j
] = (unsigned) (quad
->output
.depth
[j
] * scale
);
134 for (j
= 0; j
< QUAD_SIZE
; j
++) {
135 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
136 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
137 bzzzz
[j
] = tile
->data
.depth32
[y
][x
] >> 8;
145 switch (softpipe
->depth_stencil
->depth
.func
) {
146 case PIPE_FUNC_NEVER
:
150 /* Note this is pretty much a single sse or cell instruction.
151 * Like this: quad->mask &= (quad->outputs.depth < zzzz);
153 for (j
= 0; j
< QUAD_SIZE
; j
++) {
154 if (qzzzz
[j
] < bzzzz
[j
])
158 case PIPE_FUNC_EQUAL
:
159 for (j
= 0; j
< QUAD_SIZE
; j
++) {
160 if (qzzzz
[j
] == bzzzz
[j
])
164 case PIPE_FUNC_LEQUAL
:
165 for (j
= 0; j
< QUAD_SIZE
; j
++) {
166 if (qzzzz
[j
] <= bzzzz
[j
])
170 case PIPE_FUNC_GREATER
:
171 for (j
= 0; j
< QUAD_SIZE
; j
++) {
172 if (qzzzz
[j
] > bzzzz
[j
])
176 case PIPE_FUNC_NOTEQUAL
:
177 for (j
= 0; j
< QUAD_SIZE
; j
++) {
178 if (qzzzz
[j
] != bzzzz
[j
])
182 case PIPE_FUNC_GEQUAL
:
183 for (j
= 0; j
< QUAD_SIZE
; j
++) {
184 if (qzzzz
[j
] >= bzzzz
[j
])
188 case PIPE_FUNC_ALWAYS
:
195 quad
->inout
.mask
&= zmask
;
197 if (softpipe
->depth_stencil
->depth
.writemask
) {
199 /* This is also efficient with sse / spe instructions:
201 for (j
= 0; j
< QUAD_SIZE
; j
++) {
202 if (quad
->inout
.mask
& (1 << j
)) {
207 /* put updated Z values back into cached tile */
209 case PIPE_FORMAT_Z16_UNORM
:
210 for (j
= 0; j
< QUAD_SIZE
; j
++) {
211 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
212 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
213 tile
->data
.depth16
[y
][x
] = (ushort
) bzzzz
[j
];
216 case PIPE_FORMAT_X8Z24_UNORM
:
218 /* (yes, this falls through to a different case than above) */
219 case PIPE_FORMAT_Z32_UNORM
:
220 for (j
= 0; j
< QUAD_SIZE
; j
++) {
221 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
222 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
223 tile
->data
.depth32
[y
][x
] = bzzzz
[j
];
226 case PIPE_FORMAT_S8Z24_UNORM
:
227 for (j
= 0; j
< QUAD_SIZE
; j
++) {
228 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
229 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
230 uint s8z24
= tile
->data
.depth32
[y
][x
];
231 s8z24
= (s8z24
& 0xff000000) | bzzzz
[j
];
232 tile
->data
.depth32
[y
][x
] = s8z24
;
235 case PIPE_FORMAT_Z24S8_UNORM
:
236 for (j
= 0; j
< QUAD_SIZE
; j
++) {
237 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
238 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
239 uint z24s8
= tile
->data
.depth32
[y
][x
];
240 z24s8
= (z24s8
& 0xff) | (bzzzz
[j
] << 8);
241 tile
->data
.depth32
[y
][x
] = z24s8
;
244 case PIPE_FORMAT_Z24X8_UNORM
:
245 for (j
= 0; j
< QUAD_SIZE
; j
++) {
246 int x
= quad
->input
.x0
% TILE_SIZE
+ (j
& 1);
247 int y
= quad
->input
.y0
% TILE_SIZE
+ (j
>> 1);
248 tile
->data
.depth32
[y
][x
] = bzzzz
[j
] << 8;
259 depth_test_quad(struct quad_stage
*qs
, struct quad_header
*quad
)
261 sp_depth_test_quad(qs
, quad
);
263 if (quad
->inout
.mask
)
264 qs
->next
->run(qs
->next
, quad
);
268 static void depth_test_begin(struct quad_stage
*qs
)
270 qs
->next
->begin(qs
->next
);
274 static void depth_test_destroy(struct quad_stage
*qs
)
280 struct quad_stage
*sp_quad_depth_test_stage( struct softpipe_context
*softpipe
)
282 struct quad_stage
*stage
= CALLOC_STRUCT(quad_stage
);
284 stage
->softpipe
= softpipe
;
285 stage
->begin
= depth_test_begin
;
286 stage
->run
= depth_test_quad
;
287 stage
->destroy
= depth_test_destroy
;