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 "pipe/p_util.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
->x0
, quad
->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
->outputs
.depth
[j
] * scale
);
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
];
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
->outputs
.depth
[j
] * scale
);
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
];
107 case PIPE_FORMAT_S8Z24_UNORM
:
109 float scale
= (float) ((1 << 24) - 1);
111 for (j
= 0; j
< QUAD_SIZE
; j
++) {
112 qzzzz
[j
] = (unsigned) (quad
->outputs
.depth
[j
] * scale
);
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;
122 case PIPE_FORMAT_Z24S8_UNORM
:
124 float scale
= (float) ((1 << 24) - 1);
126 for (j
= 0; j
< QUAD_SIZE
; j
++) {
127 qzzzz
[j
] = (unsigned) (quad
->outputs
.depth
[j
] * scale
);
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;
141 switch (softpipe
->depth_stencil
->depth
.func
) {
142 case PIPE_FUNC_NEVER
:
146 /* Note this is pretty much a single sse or cell instruction.
147 * Like this: quad->mask &= (quad->outputs.depth < zzzz);
149 for (j
= 0; j
< QUAD_SIZE
; j
++) {
150 if (qzzzz
[j
] < bzzzz
[j
])
154 case PIPE_FUNC_EQUAL
:
155 for (j
= 0; j
< QUAD_SIZE
; j
++) {
156 if (qzzzz
[j
] == bzzzz
[j
])
160 case PIPE_FUNC_LEQUAL
:
161 for (j
= 0; j
< QUAD_SIZE
; j
++) {
162 if (qzzzz
[j
] <= bzzzz
[j
])
166 case PIPE_FUNC_GREATER
:
167 for (j
= 0; j
< QUAD_SIZE
; j
++) {
168 if (qzzzz
[j
] > bzzzz
[j
])
172 case PIPE_FUNC_NOTEQUAL
:
173 for (j
= 0; j
< QUAD_SIZE
; j
++) {
174 if (qzzzz
[j
] != bzzzz
[j
])
178 case PIPE_FUNC_GEQUAL
:
179 for (j
= 0; j
< QUAD_SIZE
; j
++) {
180 if (qzzzz
[j
] >= bzzzz
[j
])
184 case PIPE_FUNC_ALWAYS
:
193 if (softpipe
->depth_stencil
->depth
.writemask
) {
195 /* This is also efficient with sse / spe instructions:
197 for (j
= 0; j
< QUAD_SIZE
; j
++) {
198 if (quad
->mask
& (1 << j
)) {
203 /* put updated Z values back into cached tile */
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
];
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
];
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
;
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
;
245 depth_test_quad(struct quad_stage
*qs
, struct quad_header
*quad
)
247 sp_depth_test_quad(qs
, quad
);
250 qs
->next
->run(qs
->next
, quad
);
254 static void depth_test_begin(struct quad_stage
*qs
)
256 qs
->next
->begin(qs
->next
);
260 static void depth_test_destroy(struct quad_stage
*qs
)
266 struct quad_stage
*sp_quad_depth_test_stage( struct softpipe_context
*softpipe
)
268 struct quad_stage
*stage
= CALLOC_STRUCT(quad_stage
);
270 stage
->softpipe
= softpipe
;
271 stage
->begin
= depth_test_begin
;
272 stage
->run
= depth_test_quad
;
273 stage
->destroy
= depth_test_destroy
;