Go to the source code of this file.
Defines | |
#define | FRAC(f) ((f) - util_ifloor(f)) |
Texture sampling. | |
#define | LERP(T, A, B) ( (A) + (T) * ((B) - (A)) ) |
Linear interpolation macro. | |
#define | REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B)) |
If A is a signed integer, A % B doesn't give the right value for A < 0 (in terms of texture repeat). | |
Functions | |
static float | lerp_2d (float a, float b, float v00, float v10, float v01, float v11) |
Do 2D/biliner interpolation of float values. | |
static int | nearest_texcoord (unsigned wrapMode, float s, unsigned size) |
Apply texture coord wrapping mode and return integer texture index. | |
static void | linear_texcoord (unsigned wrapMode, float s, unsigned size, int *i0, int *i1, float *a) |
Used to compute texel locations for linear sampling. | |
static int | nearest_texcoord_unnorm (unsigned wrapMode, float s, unsigned size) |
For RECT textures / unnormalized texcoords Only a subset of wrap modes supported. | |
static void | linear_texcoord_unnorm (unsigned wrapMode, float s, unsigned size, int *i0, int *i1, float *a) |
For RECT textures / unnormalized texcoords. | |
static unsigned | choose_cube_face (float rx, float ry, float rz, float *newS, float *newT) |
static float | compute_lambda (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias) |
Examine the quad's texture coordinates to compute the partial derivatives w.r.t X and Y, then compute lambda (level of detail). | |
static void | choose_mipmap_levels (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, unsigned *level0, unsigned *level1, float *levelBlend, unsigned *imgFilter) |
Do several things here: 1. | |
static void | get_texel (struct tgsi_sampler *sampler, unsigned face, unsigned level, int x, int y, int z, float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j) |
Get a texel from a texture, using the texture tile cache. | |
static void | shadow_compare (uint compare_func, float rgba[NUM_CHANNELS][QUAD_SIZE], const float p[QUAD_SIZE], uint j) |
Compare texcoord 'p' (aka R) against texture value 'rgba[0]' When we sampled the depth texture, the depth value was put into all RGBA channels. | |
static void | sp_get_samples_2d_common (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE], const unsigned faces[4]) |
Common code for sampling 1D/2D/cube textures. | |
static void | sp_get_samples_1d (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE]) |
static void | sp_get_samples_2d (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE]) |
static void | sp_get_samples_3d (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE]) |
static void | sp_get_samples_cube (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE]) |
static void | sp_get_samples_rect (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE]) |
void | sp_get_samples (struct tgsi_sampler *sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE]) |
Called via tgsi_sampler::get_samples() Use the sampler's state setting to get a filtered RGBA value from the sampler's texture. |
#define FRAC | ( | f | ) | ((f) - util_ifloor(f)) |
#define LERP | ( | T, | |||
A, | |||||
B | ) | ( (A) + (T) * ((B) - (A)) ) |
#define REMAINDER | ( | A, | |||
B | ) | ((unsigned) (A) % (unsigned) (B)) |
If A is a signed integer, A % B doesn't give the right value for A < 0 (in terms of texture repeat).
Just casting to unsigned fixes that.
Definition at line 85 of file sp_tex_sample.c.
static unsigned choose_cube_face | ( | float | rx, | |
float | ry, | |||
float | rz, | |||
float * | newS, | |||
float * | newT | |||
) | [static] |
Definition at line 392 of file sp_tex_sample.c.
References PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_POS_Y, and PIPE_TEX_FACE_POS_Z.
00393 { 00394 /* 00395 major axis 00396 direction target sc tc ma 00397 ---------- ------------------------------- --- --- --- 00398 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx 00399 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx 00400 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry 00401 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry 00402 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz 00403 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz 00404 */ 00405 const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); 00406 unsigned face; 00407 float sc, tc, ma; 00408 00409 if (arx > ary && arx > arz) { 00410 if (rx >= 0.0F) { 00411 face = PIPE_TEX_FACE_POS_X; 00412 sc = -rz; 00413 tc = -ry; 00414 ma = arx; 00415 } 00416 else { 00417 face = PIPE_TEX_FACE_NEG_X; 00418 sc = rz; 00419 tc = -ry; 00420 ma = arx; 00421 } 00422 } 00423 else if (ary > arx && ary > arz) { 00424 if (ry >= 0.0F) { 00425 face = PIPE_TEX_FACE_POS_Y; 00426 sc = rx; 00427 tc = rz; 00428 ma = ary; 00429 } 00430 else { 00431 face = PIPE_TEX_FACE_NEG_Y; 00432 sc = rx; 00433 tc = -rz; 00434 ma = ary; 00435 } 00436 } 00437 else { 00438 if (rz > 0.0F) { 00439 face = PIPE_TEX_FACE_POS_Z; 00440 sc = rx; 00441 tc = -ry; 00442 ma = arz; 00443 } 00444 else { 00445 face = PIPE_TEX_FACE_NEG_Z; 00446 sc = -rx; 00447 tc = -ry; 00448 ma = arz; 00449 } 00450 } 00451 00452 *newS = ( sc / ma + 1.0F ) * 0.5F; 00453 *newT = ( tc / ma + 1.0F ) * 0.5F; 00454 00455 return face; 00456 }
static void choose_mipmap_levels | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
unsigned * | level0, | |||
unsigned * | level1, | |||
float * | levelBlend, | |||
unsigned * | imgFilter | |||
) | [static] |
Do several things here: 1.
Compute lambda from the texcoords, if needed 2. Determine if we're minifying or magnifying 3. If minifying, choose mipmap levels 4. Return image filter to use within mipmap images
Definition at line 519 of file sp_tex_sample.c.
References CLAMP, compute_lambda(), FRAC, pipe_texture::last_level, pipe_sampler_state::mag_img_filter, pipe_sampler_state::min_img_filter, pipe_sampler_state::min_lod, pipe_sampler_state::min_mip_filter, PIPE_TEX_MIPFILTER_NEAREST, PIPE_TEX_MIPFILTER_NONE, tgsi_sampler::state, and tgsi_sampler::texture.
00526 { 00527 if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 00528 /* no mipmap selection needed */ 00529 *level0 = *level1 = CLAMP((int) sampler->state->min_lod, 00530 0, (int) sampler->texture->last_level); 00531 00532 if (sampler->state->min_img_filter != sampler->state->mag_img_filter) { 00533 /* non-mipmapped texture, but still need to determine if doing 00534 * minification or magnification. 00535 */ 00536 float lambda = compute_lambda(sampler, s, t, p, lodbias); 00537 if (lambda <= 0.0) { 00538 *imgFilter = sampler->state->mag_img_filter; 00539 } 00540 else { 00541 *imgFilter = sampler->state->min_img_filter; 00542 } 00543 } 00544 else { 00545 *imgFilter = sampler->state->mag_img_filter; 00546 } 00547 } 00548 else { 00549 float lambda; 00550 00551 if (1) 00552 /* fragment shader */ 00553 lambda = compute_lambda(sampler, s, t, p, lodbias); 00554 else 00555 /* vertex shader */ 00556 lambda = lodbias; /* not really a bias, but absolute LOD */ 00557 00558 if (lambda <= 0.0) { /* XXX threshold depends on the filter */ 00559 /* magnifying */ 00560 *imgFilter = sampler->state->mag_img_filter; 00561 *level0 = *level1 = 0; 00562 } 00563 else { 00564 /* minifying */ 00565 *imgFilter = sampler->state->min_img_filter; 00566 00567 /* choose mipmap level(s) and compute the blend factor between them */ 00568 if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { 00569 /* Nearest mipmap level */ 00570 const int lvl = (int) (lambda + 0.5); 00571 *level0 = 00572 *level1 = CLAMP(lvl, 0, (int) sampler->texture->last_level); 00573 } 00574 else { 00575 /* Linear interpolation between mipmap levels */ 00576 const int lvl = (int) lambda; 00577 *level0 = CLAMP(lvl, 0, (int) sampler->texture->last_level); 00578 *level1 = CLAMP(lvl + 1, 0, (int) sampler->texture->last_level); 00579 *levelBlend = FRAC(lambda); /* blending weight between levels */ 00580 } 00581 } 00582 } 00583 }
static float compute_lambda | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias | |||
) | [static] |
Examine the quad's texture coordinates to compute the partial derivatives w.r.t X and Y, then compute lambda (level of detail).
This is only done for fragment shaders, not vertex shaders.
Definition at line 466 of file sp_tex_sample.c.
References assert, CLAMP, pipe_texture::depth, pipe_texture::height, pipe_sampler_state::lod_bias, max(), MAX2, pipe_sampler_state::max_lod, pipe_sampler_state::min_lod, pipe_sampler_state::normalized_coords, QUAD_BOTTOM_LEFT, QUAD_BOTTOM_RIGHT, QUAD_TOP_LEFT, tgsi_sampler::state, tgsi_sampler::texture, util_fast_log2(), and pipe_texture::width.
00471 { 00472 float rho, lambda; 00473 00474 assert(sampler->state->normalized_coords); 00475 00476 assert(s); 00477 { 00478 float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]; 00479 float dsdy = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]; 00480 dsdx = fabsf(dsdx); 00481 dsdy = fabsf(dsdy); 00482 rho = MAX2(dsdx, dsdy) * sampler->texture->width[0]; 00483 } 00484 if (t) { 00485 float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]; 00486 float dtdy = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]; 00487 float max; 00488 dtdx = fabsf(dtdx); 00489 dtdy = fabsf(dtdy); 00490 max = MAX2(dtdx, dtdy) * sampler->texture->height[0]; 00491 rho = MAX2(rho, max); 00492 } 00493 if (p) { 00494 float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]; 00495 float dpdy = p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]; 00496 float max; 00497 dpdx = fabsf(dpdx); 00498 dpdy = fabsf(dpdy); 00499 max = MAX2(dpdx, dpdy) * sampler->texture->depth[0]; 00500 rho = MAX2(rho, max); 00501 } 00502 00503 lambda = util_fast_log2(rho); 00504 lambda += lodbias + sampler->state->lod_bias; 00505 lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod); 00506 00507 return lambda; 00508 }
static void get_texel | ( | struct tgsi_sampler * | sampler, | |
unsigned | face, | |||
unsigned | level, | |||
int | x, | |||
int | y, | |||
int | z, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE], | |||
unsigned | j | |||
) | [static] |
Get a texel from a texture, using the texture tile cache.
face | the cube face in 0..5 | |
level | the mipmap level | |
x | the x coord of texel within 2D image | |
y | the y coord of texel within 2D image | |
z | which slice of a 3D texture | |
rgba | the quad to put the texel/color into | |
j | which element of the rgba quad to write to |
Definition at line 601 of file sp_tex_sample.c.
References pipe_sampler_state::border_color, tgsi_sampler::cache, softpipe_cached_tile::color, softpipe_cached_tile::data, debug_printf(), pipe_texture::depth, pipe_texture::format, pipe_texture::height, pf_name(), tgsi_sampler::pipe, sp_get_cached_tile_tex(), tgsi_sampler::state, tgsi_sampler::texture, TILE_SIZE, and pipe_texture::width.
00604 { 00605 if (x < 0 || x >= (int) sampler->texture->width[level] || 00606 y < 0 || y >= (int) sampler->texture->height[level] || 00607 z < 0 || z >= (int) sampler->texture->depth[level]) { 00608 rgba[0][j] = sampler->state->border_color[0]; 00609 rgba[1][j] = sampler->state->border_color[1]; 00610 rgba[2][j] = sampler->state->border_color[2]; 00611 rgba[3][j] = sampler->state->border_color[3]; 00612 } 00613 else { 00614 const int tx = x % TILE_SIZE; 00615 const int ty = y % TILE_SIZE; 00616 const struct softpipe_cached_tile *tile 00617 = sp_get_cached_tile_tex(sampler->pipe, sampler->cache, 00618 x, y, z, face, level); 00619 rgba[0][j] = tile->data.color[ty][tx][0]; 00620 rgba[1][j] = tile->data.color[ty][tx][1]; 00621 rgba[2][j] = tile->data.color[ty][tx][2]; 00622 rgba[3][j] = tile->data.color[ty][tx][3]; 00623 if (0) 00624 { 00625 debug_printf("Get texel %f %f %f %f from %s\n", 00626 rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j], 00627 pf_name(sampler->texture->format)); 00628 } 00629 } 00630 }
static float lerp_2d | ( | float | a, | |
float | b, | |||
float | v00, | |||
float | v10, | |||
float | v01, | |||
float | v11 | |||
) | [static] |
Do 2D/biliner interpolation of float values.
v00, v10, v01 and v11 are typically four texture samples in a square/box. a and b are the horizontal and vertical interpolants. It's important that this function is inlined when compiled with optimization! If we find that's not true on some systems, convert to a macro.
Definition at line 72 of file sp_tex_sample.c.
References LERP.
00074 { 00075 const float temp0 = LERP(a, v00, v10); 00076 const float temp1 = LERP(a, v01, v11); 00077 return LERP(b, temp0, temp1); 00078 }
static void linear_texcoord | ( | unsigned | wrapMode, | |
float | s, | |||
unsigned | size, | |||
int * | i0, | |||
int * | i1, | |||
float * | a | |||
) | [static] |
Used to compute texel locations for linear sampling.
wrapMode | PIPE_TEX_WRAP_x | |
s | the texcoord | |
size | the texture image size | |
i0 | returns first texture index | |
i1 | returns second texture index (usually *i0 + 1) | |
a | returns blend factor/weight between texture indexes |
Definition at line 222 of file sp_tex_sample.c.
References assert, FRAC, max(), min(), PIPE_TEX_WRAP_CLAMP, PIPE_TEX_WRAP_CLAMP_TO_BORDER, PIPE_TEX_WRAP_CLAMP_TO_EDGE, PIPE_TEX_WRAP_MIRROR_CLAMP, PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER, PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE, PIPE_TEX_WRAP_MIRROR_REPEAT, PIPE_TEX_WRAP_REPEAT, REMAINDER, and util_ifloor().
00224 { 00225 float u; 00226 switch (wrapMode) { 00227 case PIPE_TEX_WRAP_REPEAT: 00228 u = s * size - 0.5F; 00229 *i0 = REMAINDER(util_ifloor(u), size); 00230 *i1 = REMAINDER(*i0 + 1, size); 00231 break; 00232 case PIPE_TEX_WRAP_CLAMP: 00233 if (s <= 0.0F) 00234 u = 0.0F; 00235 else if (s >= 1.0F) 00236 u = (float) size; 00237 else 00238 u = s * size; 00239 u -= 0.5F; 00240 *i0 = util_ifloor(u); 00241 *i1 = *i0 + 1; 00242 break; 00243 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 00244 if (s <= 0.0F) 00245 u = 0.0F; 00246 else if (s >= 1.0F) 00247 u = (float) size; 00248 else 00249 u = s * size; 00250 u -= 0.5F; 00251 *i0 = util_ifloor(u); 00252 *i1 = *i0 + 1; 00253 if (*i0 < 0) 00254 *i0 = 0; 00255 if (*i1 >= (int) size) 00256 *i1 = size - 1; 00257 break; 00258 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 00259 { 00260 const float min = -1.0F / (2.0F * size); 00261 const float max = 1.0F - min; 00262 if (s <= min) 00263 u = min * size; 00264 else if (s >= max) 00265 u = max * size; 00266 else 00267 u = s * size; 00268 u -= 0.5F; 00269 *i0 = util_ifloor(u); 00270 *i1 = *i0 + 1; 00271 } 00272 break; 00273 case PIPE_TEX_WRAP_MIRROR_REPEAT: 00274 { 00275 const int flr = util_ifloor(s); 00276 if (flr & 1) 00277 u = 1.0F - (s - (float) flr); 00278 else 00279 u = s - (float) flr; 00280 u = (u * size) - 0.5F; 00281 *i0 = util_ifloor(u); 00282 *i1 = *i0 + 1; 00283 if (*i0 < 0) 00284 *i0 = 0; 00285 if (*i1 >= (int) size) 00286 *i1 = size - 1; 00287 } 00288 break; 00289 case PIPE_TEX_WRAP_MIRROR_CLAMP: 00290 u = fabsf(s); 00291 if (u >= 1.0F) 00292 u = (float) size; 00293 else 00294 u *= size; 00295 u -= 0.5F; 00296 *i0 = util_ifloor(u); 00297 *i1 = *i0 + 1; 00298 break; 00299 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 00300 u = fabsf(s); 00301 if (u >= 1.0F) 00302 u = (float) size; 00303 else 00304 u *= size; 00305 u -= 0.5F; 00306 *i0 = util_ifloor(u); 00307 *i1 = *i0 + 1; 00308 if (*i0 < 0) 00309 *i0 = 0; 00310 if (*i1 >= (int) size) 00311 *i1 = size - 1; 00312 break; 00313 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 00314 { 00315 const float min = -1.0F / (2.0F * size); 00316 const float max = 1.0F - min; 00317 u = fabsf(s); 00318 if (u <= min) 00319 u = min * size; 00320 else if (u >= max) 00321 u = max * size; 00322 else 00323 u *= size; 00324 u -= 0.5F; 00325 *i0 = util_ifloor(u); 00326 *i1 = *i0 + 1; 00327 } 00328 break; 00329 default: 00330 assert(0); 00331 } 00332 *a = FRAC(u); 00333 }
static void linear_texcoord_unnorm | ( | unsigned | wrapMode, | |
float | s, | |||
unsigned | size, | |||
int * | i0, | |||
int * | i1, | |||
float * | a | |||
) | [static] |
For RECT textures / unnormalized texcoords.
Only a subset of wrap modes supported.
Definition at line 364 of file sp_tex_sample.c.
References assert, CLAMP, FRAC, PIPE_TEX_WRAP_CLAMP, PIPE_TEX_WRAP_CLAMP_TO_BORDER, PIPE_TEX_WRAP_CLAMP_TO_EDGE, and util_ifloor().
00366 { 00367 switch (wrapMode) { 00368 case PIPE_TEX_WRAP_CLAMP: 00369 /* Not exactly what the spec says, but it matches NVIDIA output */ 00370 s = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f); 00371 *i0 = util_ifloor(s); 00372 *i1 = *i0 + 1; 00373 break; 00374 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 00375 /* fall-through */ 00376 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 00377 s = CLAMP(s, 0.5F, (float) size - 0.5F); 00378 s -= 0.5F; 00379 *i0 = util_ifloor(s); 00380 *i1 = *i0 + 1; 00381 if (*i1 > (int) size - 1) 00382 *i1 = size - 1; 00383 break; 00384 default: 00385 assert(0); 00386 } 00387 *a = FRAC(s); 00388 }
static int nearest_texcoord | ( | unsigned | wrapMode, | |
float | s, | |||
unsigned | size | |||
) | [static] |
Apply texture coord wrapping mode and return integer texture index.
wrapMode | PIPE_TEX_WRAP_x | |
s | the texcoord | |
size | the texture image size |
Definition at line 96 of file sp_tex_sample.c.
References assert, max(), min(), PIPE_TEX_WRAP_CLAMP, PIPE_TEX_WRAP_CLAMP_TO_BORDER, PIPE_TEX_WRAP_CLAMP_TO_EDGE, PIPE_TEX_WRAP_MIRROR_CLAMP, PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER, PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE, PIPE_TEX_WRAP_MIRROR_REPEAT, PIPE_TEX_WRAP_REPEAT, REMAINDER, and util_ifloor().
00097 { 00098 int i; 00099 switch (wrapMode) { 00100 case PIPE_TEX_WRAP_REPEAT: 00101 /* s limited to [0,1) */ 00102 /* i limited to [0,size-1] */ 00103 i = util_ifloor(s * size); 00104 i = REMAINDER(i, size); 00105 return i; 00106 case PIPE_TEX_WRAP_CLAMP: 00107 /* s limited to [0,1] */ 00108 /* i limited to [0,size-1] */ 00109 if (s <= 0.0F) 00110 i = 0; 00111 else if (s >= 1.0F) 00112 i = size - 1; 00113 else 00114 i = util_ifloor(s * size); 00115 return i; 00116 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 00117 { 00118 /* s limited to [min,max] */ 00119 /* i limited to [0, size-1] */ 00120 const float min = 1.0F / (2.0F * size); 00121 const float max = 1.0F - min; 00122 if (s < min) 00123 i = 0; 00124 else if (s > max) 00125 i = size - 1; 00126 else 00127 i = util_ifloor(s * size); 00128 } 00129 return i; 00130 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 00131 { 00132 /* s limited to [min,max] */ 00133 /* i limited to [-1, size] */ 00134 const float min = -1.0F / (2.0F * size); 00135 const float max = 1.0F - min; 00136 if (s <= min) 00137 i = -1; 00138 else if (s >= max) 00139 i = size; 00140 else 00141 i = util_ifloor(s * size); 00142 } 00143 return i; 00144 case PIPE_TEX_WRAP_MIRROR_REPEAT: 00145 { 00146 const float min = 1.0F / (2.0F * size); 00147 const float max = 1.0F - min; 00148 const int flr = util_ifloor(s); 00149 float u; 00150 if (flr & 1) 00151 u = 1.0F - (s - (float) flr); 00152 else 00153 u = s - (float) flr; 00154 if (u < min) 00155 i = 0; 00156 else if (u > max) 00157 i = size - 1; 00158 else 00159 i = util_ifloor(u * size); 00160 } 00161 return i; 00162 case PIPE_TEX_WRAP_MIRROR_CLAMP: 00163 { 00164 /* s limited to [0,1] */ 00165 /* i limited to [0,size-1] */ 00166 const float u = fabsf(s); 00167 if (u <= 0.0F) 00168 i = 0; 00169 else if (u >= 1.0F) 00170 i = size - 1; 00171 else 00172 i = util_ifloor(u * size); 00173 } 00174 return i; 00175 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 00176 { 00177 /* s limited to [min,max] */ 00178 /* i limited to [0, size-1] */ 00179 const float min = 1.0F / (2.0F * size); 00180 const float max = 1.0F - min; 00181 const float u = fabsf(s); 00182 if (u < min) 00183 i = 0; 00184 else if (u > max) 00185 i = size - 1; 00186 else 00187 i = util_ifloor(u * size); 00188 } 00189 return i; 00190 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 00191 { 00192 /* s limited to [min,max] */ 00193 /* i limited to [0, size-1] */ 00194 const float min = -1.0F / (2.0F * size); 00195 const float max = 1.0F - min; 00196 const float u = fabsf(s); 00197 if (u < min) 00198 i = -1; 00199 else if (u > max) 00200 i = size; 00201 else 00202 i = util_ifloor(u * size); 00203 } 00204 return i; 00205 default: 00206 assert(0); 00207 return 0; 00208 } 00209 }
static int nearest_texcoord_unnorm | ( | unsigned | wrapMode, | |
float | s, | |||
unsigned | size | |||
) | [static] |
For RECT textures / unnormalized texcoords Only a subset of wrap modes supported.
Definition at line 341 of file sp_tex_sample.c.
References assert, CLAMP, PIPE_TEX_WRAP_CLAMP, PIPE_TEX_WRAP_CLAMP_TO_BORDER, PIPE_TEX_WRAP_CLAMP_TO_EDGE, and util_ifloor().
00342 { 00343 int i; 00344 switch (wrapMode) { 00345 case PIPE_TEX_WRAP_CLAMP: 00346 i = util_ifloor(s); 00347 return CLAMP(i, 0, (int) size-1); 00348 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 00349 /* fall-through */ 00350 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 00351 return util_ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) ); 00352 default: 00353 assert(0); 00354 return 0; 00355 } 00356 }
static void shadow_compare | ( | uint | compare_func, | |
float | rgba[NUM_CHANNELS][QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
uint | j | |||
) | [static] |
Compare texcoord 'p' (aka R) against texture value 'rgba[0]' When we sampled the depth texture, the depth value was put into all RGBA channels.
We look at the red channel here.
Definition at line 639 of file sp_tex_sample.c.
References assert, 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.
00643 { 00644 int k; 00645 switch (compare_func) { 00646 case PIPE_FUNC_LESS: 00647 k = p[j] < rgba[0][j]; 00648 break; 00649 case PIPE_FUNC_LEQUAL: 00650 k = p[j] <= rgba[0][j]; 00651 break; 00652 case PIPE_FUNC_GREATER: 00653 k = p[j] > rgba[0][j]; 00654 break; 00655 case PIPE_FUNC_GEQUAL: 00656 k = p[j] >= rgba[0][j]; 00657 break; 00658 case PIPE_FUNC_EQUAL: 00659 k = p[j] == rgba[0][j]; 00660 break; 00661 case PIPE_FUNC_NOTEQUAL: 00662 k = p[j] != rgba[0][j]; 00663 break; 00664 case PIPE_FUNC_ALWAYS: 00665 k = 1; 00666 break; 00667 case PIPE_FUNC_NEVER: 00668 k = 0; 00669 break; 00670 default: 00671 k = 0; 00672 assert(0); 00673 break; 00674 } 00675 00676 rgba[0][j] = rgba[1][j] = rgba[2][j] = (float) k; 00677 }
void sp_get_samples | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE] | |||
) |
Called via tgsi_sampler::get_samples() Use the sampler's state setting to get a filtered RGBA value from the sampler's texture.
XXX we can implement many versions of this function, each tightly coded for a specific combination of sampler state (nearest + repeat), (bilinear mipmap + clamp), etc.
The update_samplers() function in st_atom_sampler.c could create a new tgsi_sampler object for each state combo it finds....
Definition at line 1039 of file sp_tex_sample.c.
References assert, pipe_sampler_state::normalized_coords, PIPE_TEXTURE_1D, PIPE_TEXTURE_2D, PIPE_TEXTURE_3D, PIPE_TEXTURE_CUBE, sp_get_samples_1d(), sp_get_samples_2d(), sp_get_samples_3d(), sp_get_samples_cube(), sp_get_samples_rect(), tgsi_sampler::state, pipe_texture::target, and tgsi_sampler::texture.
01045 { 01046 if (!sampler->texture) 01047 return; 01048 01049 switch (sampler->texture->target) { 01050 case PIPE_TEXTURE_1D: 01051 assert(sampler->state->normalized_coords); 01052 sp_get_samples_1d(sampler, s, t, p, lodbias, rgba); 01053 break; 01054 case PIPE_TEXTURE_2D: 01055 if (sampler->state->normalized_coords) 01056 sp_get_samples_2d(sampler, s, t, p, lodbias, rgba); 01057 else 01058 sp_get_samples_rect(sampler, s, t, p, lodbias, rgba); 01059 break; 01060 case PIPE_TEXTURE_3D: 01061 assert(sampler->state->normalized_coords); 01062 sp_get_samples_3d(sampler, s, t, p, lodbias, rgba); 01063 break; 01064 case PIPE_TEXTURE_CUBE: 01065 assert(sampler->state->normalized_coords); 01066 sp_get_samples_cube(sampler, s, t, p, lodbias, rgba); 01067 break; 01068 default: 01069 assert(0); 01070 } 01071 01072 #if 0 /* DEBUG */ 01073 { 01074 int i; 01075 printf("Sampled at %f, %f, %f:\n", s[0], t[0], p[0]); 01076 for (i = 0; i < 4; i++) { 01077 printf("Frag %d: %f %f %f %f\n", i, 01078 rgba[0][i], 01079 rgba[1][i], 01080 rgba[2][i], 01081 rgba[3][i]); 01082 } 01083 } 01084 #endif 01085 }
static void sp_get_samples_1d | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE] | |||
) | [static] |
Definition at line 793 of file sp_tex_sample.c.
References sp_get_samples_2d_common().
00799 { 00800 static const unsigned faces[4] = {0, 0, 0, 0}; 00801 static const float tzero[4] = {0, 0, 0, 0}; 00802 sp_get_samples_2d_common(sampler, s, tzero, NULL, lodbias, rgba, faces); 00803 }
static void sp_get_samples_2d | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE] | |||
) | [static] |
Definition at line 807 of file sp_tex_sample.c.
References sp_get_samples_2d_common().
00813 { 00814 static const unsigned faces[4] = {0, 0, 0, 0}; 00815 sp_get_samples_2d_common(sampler, s, t, p, lodbias, rgba, faces); 00816 }
static void sp_get_samples_2d_common | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE], | |||
const unsigned | faces[4] | |||
) | [static] |
Common code for sampling 1D/2D/cube textures.
Could probably extend for 3D...
Definition at line 685 of file sp_tex_sample.c.
References assert, choose_mipmap_levels(), pipe_sampler_state::compare_func, pipe_sampler_state::compare_mode, get_texel(), pipe_texture::height, LERP, lerp_2d(), linear_texcoord(), nearest_texcoord(), pipe_sampler_state::normalized_coords, NUM_CHANNELS, PIPE_TEX_COMPARE_R_TO_TEXTURE, PIPE_TEX_FILTER_ANISO, PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST, shadow_compare(), tgsi_sampler::state, tgsi_sampler::texture, pipe_texture::width, pipe_sampler_state::wrap_s, pipe_sampler_state::wrap_t, softpipe_cached_tile::x, and softpipe_cached_tile::y.
00692 { 00693 const uint compare_func = sampler->state->compare_func; 00694 unsigned level0, level1, j, imgFilter; 00695 int width, height; 00696 float levelBlend; 00697 00698 choose_mipmap_levels(sampler, s, t, p, lodbias, 00699 &level0, &level1, &levelBlend, &imgFilter); 00700 00701 assert(sampler->state->normalized_coords); 00702 00703 width = sampler->texture->width[level0]; 00704 height = sampler->texture->height[level0]; 00705 00706 assert(width > 0); 00707 00708 switch (imgFilter) { 00709 case PIPE_TEX_FILTER_NEAREST: 00710 for (j = 0; j < QUAD_SIZE; j++) { 00711 int x = nearest_texcoord(sampler->state->wrap_s, s[j], width); 00712 int y = nearest_texcoord(sampler->state->wrap_t, t[j], height); 00713 get_texel(sampler, faces[j], level0, x, y, 0, rgba, j); 00714 if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 00715 shadow_compare(compare_func, rgba, p, j); 00716 } 00717 00718 if (level0 != level1) { 00719 /* get texels from second mipmap level and blend */ 00720 float rgba2[4][4]; 00721 unsigned c; 00722 x = x / 2; 00723 y = y / 2; 00724 get_texel(sampler, faces[j], level1, x, y, 0, rgba2, j); 00725 if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 00726 shadow_compare(compare_func, rgba2, p, j); 00727 } 00728 00729 for (c = 0; c < NUM_CHANNELS; c++) { 00730 rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]); 00731 } 00732 } 00733 } 00734 break; 00735 case PIPE_TEX_FILTER_LINEAR: 00736 case PIPE_TEX_FILTER_ANISO: 00737 for (j = 0; j < QUAD_SIZE; j++) { 00738 float tx[4][4], a, b; 00739 int x0, y0, x1, y1, c; 00740 linear_texcoord(sampler->state->wrap_s, s[j], width, &x0, &x1, &a); 00741 linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &b); 00742 get_texel(sampler, faces[j], level0, x0, y0, 0, tx, 0); 00743 get_texel(sampler, faces[j], level0, x1, y0, 0, tx, 1); 00744 get_texel(sampler, faces[j], level0, x0, y1, 0, tx, 2); 00745 get_texel(sampler, faces[j], level0, x1, y1, 0, tx, 3); 00746 if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 00747 shadow_compare(compare_func, tx, p, 0); 00748 shadow_compare(compare_func, tx, p, 1); 00749 shadow_compare(compare_func, tx, p, 2); 00750 shadow_compare(compare_func, tx, p, 3); 00751 } 00752 00753 for (c = 0; c < 4; c++) { 00754 rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 00755 } 00756 00757 if (level0 != level1) { 00758 /* get texels from second mipmap level and blend */ 00759 float rgba2[4][4]; 00760 x0 = x0 / 2; 00761 y0 = y0 / 2; 00762 x1 = x1 / 2; 00763 y1 = y1 / 2; 00764 get_texel(sampler, faces[j], level1, x0, y0, 0, tx, 0); 00765 get_texel(sampler, faces[j], level1, x1, y0, 0, tx, 1); 00766 get_texel(sampler, faces[j], level1, x0, y1, 0, tx, 2); 00767 get_texel(sampler, faces[j], level1, x1, y1, 0, tx, 3); 00768 if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 00769 shadow_compare(compare_func, tx, p, 0); 00770 shadow_compare(compare_func, tx, p, 1); 00771 shadow_compare(compare_func, tx, p, 2); 00772 shadow_compare(compare_func, tx, p, 3); 00773 } 00774 00775 for (c = 0; c < 4; c++) { 00776 rgba2[c][j] = lerp_2d(a, b, 00777 tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 00778 } 00779 00780 for (c = 0; c < NUM_CHANNELS; c++) { 00781 rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]); 00782 } 00783 } 00784 } 00785 break; 00786 default: 00787 assert(0); 00788 } 00789 }
static void sp_get_samples_3d | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE] | |||
) | [static] |
Definition at line 820 of file sp_tex_sample.c.
References assert, choose_mipmap_levels(), pipe_texture::depth, softpipe_cached_tile::face, get_texel(), pipe_texture::height, LERP, lerp_2d(), linear_texcoord(), nearest_texcoord(), pipe_sampler_state::normalized_coords, NUM_CHANNELS, PIPE_TEX_FILTER_ANISO, PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST, tgsi_sampler::state, tgsi_sampler::texture, pipe_texture::width, pipe_sampler_state::wrap_r, pipe_sampler_state::wrap_s, pipe_sampler_state::wrap_t, softpipe_cached_tile::x, softpipe_cached_tile::y, and softpipe_cached_tile::z.
00826 { 00827 /* get/map pipe_surfaces corresponding to 3D tex slices */ 00828 unsigned level0, level1, j, imgFilter; 00829 int width, height, depth; 00830 float levelBlend; 00831 const uint face = 0; 00832 00833 choose_mipmap_levels(sampler, s, t, p, lodbias, 00834 &level0, &level1, &levelBlend, &imgFilter); 00835 00836 assert(sampler->state->normalized_coords); 00837 00838 width = sampler->texture->width[level0]; 00839 height = sampler->texture->height[level0]; 00840 depth = sampler->texture->depth[level0]; 00841 00842 assert(width > 0); 00843 assert(height > 0); 00844 assert(depth > 0); 00845 00846 switch (imgFilter) { 00847 case PIPE_TEX_FILTER_NEAREST: 00848 for (j = 0; j < QUAD_SIZE; j++) { 00849 int x = nearest_texcoord(sampler->state->wrap_s, s[j], width); 00850 int y = nearest_texcoord(sampler->state->wrap_t, t[j], height); 00851 int z = nearest_texcoord(sampler->state->wrap_r, p[j], depth); 00852 get_texel(sampler, face, level0, x, y, z, rgba, j); 00853 00854 if (level0 != level1) { 00855 /* get texels from second mipmap level and blend */ 00856 float rgba2[4][4]; 00857 unsigned c; 00858 x /= 2; 00859 y /= 2; 00860 z /= 2; 00861 get_texel(sampler, face, level1, x, y, z, rgba2, j); 00862 for (c = 0; c < NUM_CHANNELS; c++) { 00863 rgba[c][j] = LERP(levelBlend, rgba2[c][j], rgba[c][j]); 00864 } 00865 } 00866 } 00867 break; 00868 case PIPE_TEX_FILTER_LINEAR: 00869 case PIPE_TEX_FILTER_ANISO: 00870 for (j = 0; j < QUAD_SIZE; j++) { 00871 float texel0[4][4], texel1[4][4]; 00872 float xw, yw, zw; /* interpolation weights */ 00873 int x0, x1, y0, y1, z0, z1, c; 00874 linear_texcoord(sampler->state->wrap_s, s[j], width, &x0, &x1, &xw); 00875 linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &yw); 00876 linear_texcoord(sampler->state->wrap_r, p[j], depth, &z0, &z1, &zw); 00877 get_texel(sampler, face, level0, x0, y0, z0, texel0, 0); 00878 get_texel(sampler, face, level0, x1, y0, z0, texel0, 1); 00879 get_texel(sampler, face, level0, x0, y1, z0, texel0, 2); 00880 get_texel(sampler, face, level0, x1, y1, z0, texel0, 3); 00881 get_texel(sampler, face, level0, x0, y0, z1, texel1, 0); 00882 get_texel(sampler, face, level0, x1, y0, z1, texel1, 1); 00883 get_texel(sampler, face, level0, x0, y1, z1, texel1, 2); 00884 get_texel(sampler, face, level0, x1, y1, z1, texel1, 3); 00885 00886 /* 3D lerp */ 00887 for (c = 0; c < 4; c++) { 00888 float ctemp0[4][4], ctemp1[4][4]; 00889 ctemp0[c][j] = lerp_2d(xw, yw, 00890 texel0[c][0], texel0[c][1], 00891 texel0[c][2], texel0[c][3]); 00892 ctemp1[c][j] = lerp_2d(xw, yw, 00893 texel1[c][0], texel1[c][1], 00894 texel1[c][2], texel1[c][3]); 00895 rgba[c][j] = LERP(zw, ctemp0[c][j], ctemp1[c][j]); 00896 } 00897 00898 if (level0 != level1) { 00899 /* get texels from second mipmap level and blend */ 00900 float rgba2[4][4]; 00901 x0 /= 2; 00902 y0 /= 2; 00903 z0 /= 2; 00904 x1 /= 2; 00905 y1 /= 2; 00906 z1 /= 2; 00907 get_texel(sampler, face, level1, x0, y0, z0, texel0, 0); 00908 get_texel(sampler, face, level1, x1, y0, z0, texel0, 1); 00909 get_texel(sampler, face, level1, x0, y1, z0, texel0, 2); 00910 get_texel(sampler, face, level1, x1, y1, z0, texel0, 3); 00911 get_texel(sampler, face, level1, x0, y0, z1, texel1, 0); 00912 get_texel(sampler, face, level1, x1, y0, z1, texel1, 1); 00913 get_texel(sampler, face, level1, x0, y1, z1, texel1, 2); 00914 get_texel(sampler, face, level1, x1, y1, z1, texel1, 3); 00915 00916 /* 3D lerp */ 00917 for (c = 0; c < 4; c++) { 00918 float ctemp0[4][4], ctemp1[4][4]; 00919 ctemp0[c][j] = lerp_2d(xw, yw, 00920 texel0[c][0], texel0[c][1], 00921 texel0[c][2], texel0[c][3]); 00922 ctemp1[c][j] = lerp_2d(xw, yw, 00923 texel1[c][0], texel1[c][1], 00924 texel1[c][2], texel1[c][3]); 00925 rgba2[c][j] = LERP(zw, ctemp0[c][j], ctemp1[c][j]); 00926 } 00927 00928 /* blend mipmap levels */ 00929 for (c = 0; c < NUM_CHANNELS; c++) { 00930 rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]); 00931 } 00932 } 00933 } 00934 break; 00935 default: 00936 assert(0); 00937 } 00938 }
static void sp_get_samples_cube | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE] | |||
) | [static] |
Definition at line 942 of file sp_tex_sample.c.
References choose_cube_face(), and sp_get_samples_2d_common().
00948 { 00949 unsigned faces[QUAD_SIZE], j; 00950 float ssss[4], tttt[4]; 00951 for (j = 0; j < QUAD_SIZE; j++) { 00952 faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j); 00953 } 00954 sp_get_samples_2d_common(sampler, ssss, tttt, NULL, lodbias, rgba, faces); 00955 }
static void sp_get_samples_rect | ( | struct tgsi_sampler * | sampler, | |
const float | s[QUAD_SIZE], | |||
const float | t[QUAD_SIZE], | |||
const float | p[QUAD_SIZE], | |||
float | lodbias, | |||
float | rgba[NUM_CHANNELS][QUAD_SIZE] | |||
) | [static] |
Definition at line 959 of file sp_tex_sample.c.
References assert, choose_mipmap_levels(), pipe_sampler_state::compare_func, pipe_sampler_state::compare_mode, softpipe_cached_tile::face, get_texel(), pipe_texture::height, lerp_2d(), linear_texcoord_unnorm(), nearest_texcoord_unnorm(), PIPE_TEX_COMPARE_R_TO_TEXTURE, PIPE_TEX_FILTER_ANISO, PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST, shadow_compare(), tgsi_sampler::state, tgsi_sampler::texture, pipe_texture::width, pipe_sampler_state::wrap_s, pipe_sampler_state::wrap_t, softpipe_cached_tile::x, and softpipe_cached_tile::y.
00965 { 00966 //sp_get_samples_2d_common(sampler, s, t, p, lodbias, rgba, faces); 00967 static const uint face = 0; 00968 const uint compare_func = sampler->state->compare_func; 00969 unsigned level0, level1, j, imgFilter; 00970 int width, height; 00971 float levelBlend; 00972 00973 choose_mipmap_levels(sampler, s, t, p, lodbias, 00974 &level0, &level1, &levelBlend, &imgFilter); 00975 00976 /* texture RECTS cannot be mipmapped */ 00977 assert(level0 == level1); 00978 00979 width = sampler->texture->width[level0]; 00980 height = sampler->texture->height[level0]; 00981 00982 assert(width > 0); 00983 00984 switch (imgFilter) { 00985 case PIPE_TEX_FILTER_NEAREST: 00986 for (j = 0; j < QUAD_SIZE; j++) { 00987 int x = nearest_texcoord_unnorm(sampler->state->wrap_s, s[j], width); 00988 int y = nearest_texcoord_unnorm(sampler->state->wrap_t, t[j], height); 00989 get_texel(sampler, face, level0, x, y, 0, rgba, j); 00990 if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 00991 shadow_compare(compare_func, rgba, p, j); 00992 } 00993 } 00994 break; 00995 case PIPE_TEX_FILTER_LINEAR: 00996 case PIPE_TEX_FILTER_ANISO: 00997 for (j = 0; j < QUAD_SIZE; j++) { 00998 float tx[4][4], a, b; 00999 int x0, y0, x1, y1, c; 01000 linear_texcoord_unnorm(sampler->state->wrap_s, s[j], width, &x0, &x1, &a); 01001 linear_texcoord_unnorm(sampler->state->wrap_t, t[j], height, &y0, &y1, &b); 01002 get_texel(sampler, face, level0, x0, y0, 0, tx, 0); 01003 get_texel(sampler, face, level0, x1, y0, 0, tx, 1); 01004 get_texel(sampler, face, level0, x0, y1, 0, tx, 2); 01005 get_texel(sampler, face, level0, x1, y1, 0, tx, 3); 01006 if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 01007 shadow_compare(compare_func, tx, p, 0); 01008 shadow_compare(compare_func, tx, p, 1); 01009 shadow_compare(compare_func, tx, p, 2); 01010 shadow_compare(compare_func, tx, p, 3); 01011 } 01012 01013 for (c = 0; c < 4; c++) { 01014 rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 01015 } 01016 } 01017 break; 01018 default: 01019 assert(0); 01020 } 01021 }