include surface.offset in address calculations
[mesa.git] / src / mesa / pipe / softpipe / sp_quad_depth_test.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \brief Quad depth testing
27 */
28
29 #include "main/glheader.h"
30 #include "main/imports.h"
31 #include "pipe/p_defines.h"
32 #include "sp_context.h"
33 #include "sp_headers.h"
34 #include "sp_surface.h"
35 #include "sp_quad.h"
36
37
38 /**
39 * Do depth testing for a quad.
40 * Not static since it's used by the stencil code.
41 */
42 void
43 sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
44 {
45 struct softpipe_context *softpipe = qs->softpipe;
46 struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf);
47 GLuint bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */
48 GLuint qzzzz[QUAD_SIZE]; /**< Z values from the quad */
49 GLuint zmask = 0;
50 GLuint j;
51 GLfloat scale;
52
53 assert(sps); /* shouldn't get here if there's no zbuffer */
54
55 /*
56 * To increase efficiency, we should probably have multiple versions
57 * of this function that are specifically for Z16, Z32 and FP Z buffers.
58 * Try to effectively do that with codegen...
59 */
60 if (sps->surface.format == PIPE_FORMAT_U_Z16)
61 scale = 65535.0;
62 else if (sps->surface.format == PIPE_FORMAT_S8_Z24)
63 scale = (float) ((1 << 24) - 1);
64 else
65 assert(0); /* XXX fix this someday */
66
67 /*
68 * Convert quad's float depth values to int depth values.
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 for (j = 0; j < QUAD_SIZE; j++) {
75 qzzzz[j] = (GLuint) (quad->outputs.depth[j] * scale);
76 }
77
78 /* get zquad from zbuffer */
79 sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz);
80
81 switch (softpipe->depth_test.func) {
82 case PIPE_FUNC_NEVER:
83 /* zmask = 0 */
84 break;
85 case PIPE_FUNC_LESS:
86 /* Note this is pretty much a single sse or cell instruction.
87 * Like this: quad->mask &= (quad->outputs.depth < zzzz);
88 */
89 for (j = 0; j < QUAD_SIZE; j++) {
90 if (qzzzz[j] < bzzzz[j])
91 zmask |= 1 << j;
92 }
93 break;
94 case PIPE_FUNC_EQUAL:
95 for (j = 0; j < QUAD_SIZE; j++) {
96 if (qzzzz[j] == bzzzz[j])
97 zmask |= 1 << j;
98 }
99 break;
100 case PIPE_FUNC_LEQUAL:
101 for (j = 0; j < QUAD_SIZE; j++) {
102 if (qzzzz[j] <= bzzzz[j])
103 zmask |= (1 << j);
104 }
105 break;
106 case PIPE_FUNC_GREATER:
107 for (j = 0; j < QUAD_SIZE; j++) {
108 if (qzzzz[j] > bzzzz[j])
109 zmask |= (1 << j);
110 }
111 break;
112 case PIPE_FUNC_NOTEQUAL:
113 for (j = 0; j < QUAD_SIZE; j++) {
114 if (qzzzz[j] != bzzzz[j])
115 zmask |= (1 << j);
116 }
117 break;
118 case PIPE_FUNC_GEQUAL:
119 for (j = 0; j < QUAD_SIZE; j++) {
120 if (qzzzz[j] >= bzzzz[j])
121 zmask |= (1 << j);
122 }
123 break;
124 case PIPE_FUNC_ALWAYS:
125 zmask = MASK_ALL;
126 break;
127 default:
128 abort();
129 }
130
131 quad->mask &= zmask;
132
133 if (softpipe->depth_test.writemask) {
134
135 /* This is also efficient with sse / spe instructions:
136 */
137 for (j = 0; j < QUAD_SIZE; j++) {
138 if (quad->mask & (1 << j)) {
139 bzzzz[j] = qzzzz[j];
140 }
141 }
142
143 /* write updated zquad to zbuffer */
144 sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz);
145 }
146 }
147
148
149 static void
150 depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
151 {
152 sp_depth_test_quad(qs, quad);
153
154 if (quad->mask)
155 qs->next->run(qs->next, quad);
156 }
157
158
159 static void depth_test_begin(struct quad_stage *qs)
160 {
161 if (qs->next)
162 qs->next->begin(qs->next);
163 }
164
165
166 struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe )
167 {
168 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
169
170 stage->softpipe = softpipe;
171 stage->begin = depth_test_begin;
172 stage->run = depth_test_quad;
173
174 return stage;
175 }