Go to the source code of this file.
Defines | |
#define | STENCIL_MAX 0xff |
Quad stencil testing. | |
Functions | |
static unsigned | do_stencil_test (const ubyte stencilVals[QUAD_SIZE], unsigned func, unsigned ref, unsigned valMask) |
Do the basic stencil test (compare stencil buffer values against the reference value. | |
static void | apply_stencil_op (ubyte stencilVals[QUAD_SIZE], unsigned mask, unsigned op, ubyte ref, ubyte wrtMask) |
Apply the stencil operator to stencil values. | |
static void | stencil_test_quad (struct quad_stage *qs, struct quad_header *quad) |
Do stencil (and depth) testing. | |
static void | stencil_begin (struct quad_stage *qs) |
static void | stencil_destroy (struct quad_stage *qs) |
struct quad_stage * | sp_quad_stencil_test_stage (struct softpipe_context *softpipe) |
#define STENCIL_MAX 0xff |
static void apply_stencil_op | ( | ubyte | stencilVals[QUAD_SIZE], | |
unsigned | mask, | |||
unsigned | op, | |||
ubyte | ref, | |||
ubyte | wrtMask | |||
) | [static] |
Apply the stencil operator to stencil values.
stencilVals | the stencil buffer values (read and written) | |
mask | indicates which pixels to update | |
op | the stencil operator (PIPE_STENCIL_OP_x) | |
ref | the stencil reference value | |
wrtMask | writemask controlling which bits are changed in the stencil values |
Definition at line 108 of file sp_quad_stencil.c.
References assert, PIPE_STENCIL_OP_DECR, PIPE_STENCIL_OP_DECR_WRAP, PIPE_STENCIL_OP_INCR, PIPE_STENCIL_OP_INCR_WRAP, PIPE_STENCIL_OP_INVERT, PIPE_STENCIL_OP_KEEP, PIPE_STENCIL_OP_REPLACE, PIPE_STENCIL_OP_ZERO, and STENCIL_MAX.
00110 { 00111 unsigned j; 00112 ubyte newstencil[QUAD_SIZE]; 00113 00114 for (j = 0; j < QUAD_SIZE; j++) { 00115 newstencil[j] = stencilVals[j]; 00116 } 00117 00118 switch (op) { 00119 case PIPE_STENCIL_OP_KEEP: 00120 /* no-op */ 00121 break; 00122 case PIPE_STENCIL_OP_ZERO: 00123 for (j = 0; j < QUAD_SIZE; j++) { 00124 if (mask & (1 << j)) { 00125 newstencil[j] = 0; 00126 } 00127 } 00128 break; 00129 case PIPE_STENCIL_OP_REPLACE: 00130 for (j = 0; j < QUAD_SIZE; j++) { 00131 if (mask & (1 << j)) { 00132 newstencil[j] = ref; 00133 } 00134 } 00135 break; 00136 case PIPE_STENCIL_OP_INCR: 00137 for (j = 0; j < QUAD_SIZE; j++) { 00138 if (mask & (1 << j)) { 00139 if (stencilVals[j] < STENCIL_MAX) { 00140 newstencil[j] = stencilVals[j] + 1; 00141 } 00142 } 00143 } 00144 break; 00145 case PIPE_STENCIL_OP_DECR: 00146 for (j = 0; j < QUAD_SIZE; j++) { 00147 if (mask & (1 << j)) { 00148 if (stencilVals[j] > 0) { 00149 newstencil[j] = stencilVals[j] - 1; 00150 } 00151 } 00152 } 00153 break; 00154 case PIPE_STENCIL_OP_INCR_WRAP: 00155 for (j = 0; j < QUAD_SIZE; j++) { 00156 if (mask & (1 << j)) { 00157 newstencil[j] = stencilVals[j] + 1; 00158 } 00159 } 00160 break; 00161 case PIPE_STENCIL_OP_DECR_WRAP: 00162 for (j = 0; j < QUAD_SIZE; j++) { 00163 if (mask & (1 << j)) { 00164 newstencil[j] = stencilVals[j] - 1; 00165 } 00166 } 00167 break; 00168 case PIPE_STENCIL_OP_INVERT: 00169 for (j = 0; j < QUAD_SIZE; j++) { 00170 if (mask & (1 << j)) { 00171 newstencil[j] = ~stencilVals[j]; 00172 } 00173 } 00174 break; 00175 default: 00176 assert(0); 00177 } 00178 00179 /* 00180 * update the stencil values 00181 */ 00182 if (wrtMask != STENCIL_MAX) { 00183 /* apply bit-wise stencil buffer writemask */ 00184 for (j = 0; j < QUAD_SIZE; j++) { 00185 stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]); 00186 } 00187 } 00188 else { 00189 for (j = 0; j < QUAD_SIZE; j++) { 00190 stencilVals[j] = newstencil[j]; 00191 } 00192 } 00193 }
static unsigned do_stencil_test | ( | const ubyte | stencilVals[QUAD_SIZE], | |
unsigned | func, | |||
unsigned | ref, | |||
unsigned | valMask | |||
) | [static] |
Do the basic stencil test (compare stencil buffer values against the reference value.
stencilVals | the stencil values from the stencil buffer | |
func | the stencil func (PIPE_FUNC_x) | |
ref | the stencil reference value | |
valMask | the stencil value mask indicating which bits of the stencil values and ref value are to be used. |
Definition at line 32 of file sp_quad_stencil.c.
References assert, MASK_ALL, PIPE_FUNC_ALWAYS, PIPE_FUNC_EQUAL, PIPE_FUNC_GEQUAL, PIPE_FUNC_GREATER, PIPE_FUNC_LEQUAL, PIPE_FUNC_LESS, PIPE_FUNC_NEVER, and PIPE_FUNC_NOTEQUAL.
00034 { 00035 unsigned passMask = 0x0; 00036 unsigned j; 00037 00038 ref &= valMask; 00039 00040 switch (func) { 00041 case PIPE_FUNC_NEVER: 00042 /* passMask = 0x0 */ 00043 break; 00044 case PIPE_FUNC_LESS: 00045 for (j = 0; j < QUAD_SIZE; j++) { 00046 if (ref < (stencilVals[j] & valMask)) { 00047 passMask |= (1 << j); 00048 } 00049 } 00050 break; 00051 case PIPE_FUNC_EQUAL: 00052 for (j = 0; j < QUAD_SIZE; j++) { 00053 if (ref == (stencilVals[j] & valMask)) { 00054 passMask |= (1 << j); 00055 } 00056 } 00057 break; 00058 case PIPE_FUNC_LEQUAL: 00059 for (j = 0; j < QUAD_SIZE; j++) { 00060 if (ref <= (stencilVals[j] & valMask)) { 00061 passMask |= (1 << j); 00062 } 00063 } 00064 break; 00065 case PIPE_FUNC_GREATER: 00066 for (j = 0; j < QUAD_SIZE; j++) { 00067 if (ref > (stencilVals[j] & valMask)) { 00068 passMask |= (1 << j); 00069 } 00070 } 00071 break; 00072 case PIPE_FUNC_NOTEQUAL: 00073 for (j = 0; j < QUAD_SIZE; j++) { 00074 if (ref != (stencilVals[j] & valMask)) { 00075 passMask |= (1 << j); 00076 } 00077 } 00078 break; 00079 case PIPE_FUNC_GEQUAL: 00080 for (j = 0; j < QUAD_SIZE; j++) { 00081 if (ref >= (stencilVals[j] & valMask)) { 00082 passMask |= (1 << j); 00083 } 00084 } 00085 break; 00086 case PIPE_FUNC_ALWAYS: 00087 passMask = MASK_ALL; 00088 break; 00089 default: 00090 assert(0); 00091 } 00092 00093 return passMask; 00094 }
struct quad_stage* sp_quad_stencil_test_stage | ( | struct softpipe_context * | softpipe | ) | [read] |
Definition at line 342 of file sp_quad_stencil.c.
References quad_stage::begin, CALLOC_STRUCT, quad_stage::destroy, quad_stage::run, quad_stage::softpipe, stencil_begin(), stencil_destroy(), and stencil_test_quad().
00343 { 00344 struct quad_stage *stage = CALLOC_STRUCT(quad_stage); 00345 00346 stage->softpipe = softpipe; 00347 stage->begin = stencil_begin; 00348 stage->run = stencil_test_quad; 00349 stage->destroy = stencil_destroy; 00350 00351 return stage; 00352 }
static void stencil_begin | ( | struct quad_stage * | qs | ) | [static] |
Definition at line 330 of file sp_quad_stencil.c.
References quad_stage::begin, and quad_stage::next.
static void stencil_destroy | ( | struct quad_stage * | qs | ) | [static] |
Definition at line 336 of file sp_quad_stencil.c.
References FREE.
00337 { 00338 FREE( qs ); 00339 }
static void stencil_test_quad | ( | struct quad_stage * | qs, | |
struct quad_header * | quad | |||
) | [static] |
Do stencil (and depth) testing.
Stenciling depends on the outcome of depth testing.
Definition at line 201 of file sp_quad_stencil.c.
References apply_stencil_op(), assert, softpipe_cached_tile::data, pipe_depth_stencil_alpha_state::depth, softpipe_cached_tile::depth32, softpipe_context::depth_stencil, do_stencil_test(), pipe_depth_state::enabled, pipe_stencil_state::enabled, softpipe_cached_tile::face, quad_header_input::facing, pipe_stencil_state::fail_op, pipe_surface::format, softpipe_context::framebuffer, pipe_stencil_state::func, quad_header::inout, quad_header::input, quad_header_inout::mask, quad_stage::next, PIPE_FORMAT_S8_UNORM, PIPE_FORMAT_S8Z24_UNORM, PIPE_FORMAT_Z24S8_UNORM, PIPE_STENCIL_OP_KEEP, QUAD_SIZE, pipe_stencil_state::ref_value, quad_stage::run, quad_stage::softpipe, sp_depth_test_quad(), sp_get_cached_tile(), pipe_depth_stencil_alpha_state::stencil, softpipe_cached_tile::stencil8, TILE_SIZE, pipe_stencil_state::value_mask, pipe_stencil_state::write_mask, softpipe_cached_tile::x, quad_header_input::x0, softpipe_cached_tile::y, quad_header_input::y0, pipe_stencil_state::zfail_op, pipe_stencil_state::zpass_op, pipe_framebuffer_state::zsbuf, and softpipe_context::zsbuf_cache.
00202 { 00203 struct softpipe_context *softpipe = qs->softpipe; 00204 struct pipe_surface *ps = softpipe->framebuffer.zsbuf; 00205 unsigned func, zFailOp, zPassOp, failOp; 00206 ubyte ref, wrtMask, valMask; 00207 ubyte stencilVals[QUAD_SIZE]; 00208 struct softpipe_cached_tile *tile 00209 = sp_get_cached_tile(softpipe, softpipe->zsbuf_cache, quad->input.x0, quad->input.y0); 00210 uint j; 00211 uint face = quad->input.facing; 00212 00213 if (!softpipe->depth_stencil->stencil[1].enabled) { 00214 /* single-sided stencil test, use front (face=0) state */ 00215 face = 0; 00216 } 00217 00218 /* choose front or back face function, operator, etc */ 00219 /* XXX we could do these initializations once per primitive */ 00220 func = softpipe->depth_stencil->stencil[face].func; 00221 failOp = softpipe->depth_stencil->stencil[face].fail_op; 00222 zFailOp = softpipe->depth_stencil->stencil[face].zfail_op; 00223 zPassOp = softpipe->depth_stencil->stencil[face].zpass_op; 00224 ref = softpipe->depth_stencil->stencil[face].ref_value; 00225 wrtMask = softpipe->depth_stencil->stencil[face].write_mask; 00226 valMask = softpipe->depth_stencil->stencil[face].value_mask; 00227 00228 assert(ps); /* shouldn't get here if there's no stencil buffer */ 00229 00230 /* get stencil values from cached tile */ 00231 switch (ps->format) { 00232 case PIPE_FORMAT_S8Z24_UNORM: 00233 for (j = 0; j < QUAD_SIZE; j++) { 00234 int x = quad->input.x0 % TILE_SIZE + (j & 1); 00235 int y = quad->input.y0 % TILE_SIZE + (j >> 1); 00236 stencilVals[j] = tile->data.depth32[y][x] >> 24; 00237 } 00238 break; 00239 case PIPE_FORMAT_Z24S8_UNORM: 00240 for (j = 0; j < QUAD_SIZE; j++) { 00241 int x = quad->input.x0 % TILE_SIZE + (j & 1); 00242 int y = quad->input.y0 % TILE_SIZE + (j >> 1); 00243 stencilVals[j] = tile->data.depth32[y][x] & 0xff; 00244 } 00245 break; 00246 case PIPE_FORMAT_S8_UNORM: 00247 for (j = 0; j < QUAD_SIZE; j++) { 00248 int x = quad->input.x0 % TILE_SIZE + (j & 1); 00249 int y = quad->input.y0 % TILE_SIZE + (j >> 1); 00250 stencilVals[j] = tile->data.stencil8[y][x]; 00251 } 00252 break; 00253 default: 00254 assert(0); 00255 } 00256 00257 /* do the stencil test first */ 00258 { 00259 unsigned passMask, failMask; 00260 passMask = do_stencil_test(stencilVals, func, ref, valMask); 00261 failMask = quad->inout.mask & ~passMask; 00262 quad->inout.mask &= passMask; 00263 00264 if (failOp != PIPE_STENCIL_OP_KEEP) { 00265 apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask); 00266 } 00267 } 00268 00269 if (quad->inout.mask) { 00270 /* now the pixels that passed the stencil test are depth tested */ 00271 if (softpipe->depth_stencil->depth.enabled) { 00272 const unsigned origMask = quad->inout.mask; 00273 00274 sp_depth_test_quad(qs, quad); /* quad->mask is updated */ 00275 00276 /* update stencil buffer values according to z pass/fail result */ 00277 if (zFailOp != PIPE_STENCIL_OP_KEEP) { 00278 const unsigned failMask = origMask & ~quad->inout.mask; 00279 apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask); 00280 } 00281 00282 if (zPassOp != PIPE_STENCIL_OP_KEEP) { 00283 const unsigned passMask = origMask & quad->inout.mask; 00284 apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask); 00285 } 00286 } 00287 else { 00288 /* no depth test, apply Zpass operator to stencil buffer values */ 00289 apply_stencil_op(stencilVals, quad->inout.mask, zPassOp, ref, wrtMask); 00290 } 00291 00292 } 00293 00294 /* put new stencil values into cached tile */ 00295 switch (ps->format) { 00296 case PIPE_FORMAT_S8Z24_UNORM: 00297 for (j = 0; j < QUAD_SIZE; j++) { 00298 int x = quad->input.x0 % TILE_SIZE + (j & 1); 00299 int y = quad->input.y0 % TILE_SIZE + (j >> 1); 00300 uint s8z24 = tile->data.depth32[y][x]; 00301 s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff); 00302 tile->data.depth32[y][x] = s8z24; 00303 } 00304 break; 00305 case PIPE_FORMAT_Z24S8_UNORM: 00306 for (j = 0; j < QUAD_SIZE; j++) { 00307 int x = quad->input.x0 % TILE_SIZE + (j & 1); 00308 int y = quad->input.y0 % TILE_SIZE + (j >> 1); 00309 uint z24s8 = tile->data.depth32[y][x]; 00310 z24s8 = (z24s8 & 0xffffff00) | stencilVals[j]; 00311 tile->data.depth32[y][x] = z24s8; 00312 } 00313 break; 00314 case PIPE_FORMAT_S8_UNORM: 00315 for (j = 0; j < QUAD_SIZE; j++) { 00316 int x = quad->input.x0 % TILE_SIZE + (j & 1); 00317 int y = quad->input.y0 % TILE_SIZE + (j >> 1); 00318 tile->data.stencil8[y][x] = stencilVals[j]; 00319 } 00320 break; 00321 default: 00322 assert(0); 00323 } 00324 00325 if (quad->inout.mask) 00326 qs->next->run(qs->next, quad); 00327 }