00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 #include "sp_context.h"
00036 #include "sp_headers.h"
00037 #include "sp_surface.h"
00038 #include "sp_tex_sample.h"
00039 #include "sp_tile_cache.h"
00040 #include "pipe/p_context.h"
00041 #include "pipe/p_defines.h"
00042 #include "tgsi/tgsi_exec.h"
00043 #include "util/u_math.h"
00044 #include "util/u_memory.h"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #define FRAC(f) ((f) - util_ifloor(f))
00055
00056
00060 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
00061
00062
00071 static INLINE float
00072 lerp_2d(float a, float b,
00073 float v00, float v10, float v01, float v11)
00074 {
00075 const float temp0 = LERP(a, v00, v10);
00076 const float temp1 = LERP(a, v01, v11);
00077 return LERP(b, temp0, temp1);
00078 }
00079
00080
00085 #define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
00086
00087
00095 static INLINE int
00096 nearest_texcoord(unsigned wrapMode, float s, unsigned size)
00097 {
00098 int i;
00099 switch (wrapMode) {
00100 case PIPE_TEX_WRAP_REPEAT:
00101
00102
00103 i = util_ifloor(s * size);
00104 i = REMAINDER(i, size);
00105 return i;
00106 case PIPE_TEX_WRAP_CLAMP:
00107
00108
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
00119
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
00133
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
00165
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
00178
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
00193
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 }
00210
00211
00221 static INLINE void
00222 linear_texcoord(unsigned wrapMode, float s, unsigned size,
00223 int *i0, int *i1, float *a)
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 }
00334
00335
00340 static INLINE int
00341 nearest_texcoord_unnorm(unsigned wrapMode, float s, unsigned size)
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
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 }
00357
00358
00363 static INLINE void
00364 linear_texcoord_unnorm(unsigned wrapMode, float s, unsigned size,
00365 int *i0, int *i1, float *a)
00366 {
00367 switch (wrapMode) {
00368 case PIPE_TEX_WRAP_CLAMP:
00369
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
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 }
00389
00390
00391 static unsigned
00392 choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)
00393 {
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
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 }
00457
00458
00465 static float
00466 compute_lambda(struct tgsi_sampler *sampler,
00467 const float s[QUAD_SIZE],
00468 const float t[QUAD_SIZE],
00469 const float p[QUAD_SIZE],
00470 float lodbias)
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 }
00509
00510
00518 static void
00519 choose_mipmap_levels(struct tgsi_sampler *sampler,
00520 const float s[QUAD_SIZE],
00521 const float t[QUAD_SIZE],
00522 const float p[QUAD_SIZE],
00523 float lodbias,
00524 unsigned *level0, unsigned *level1, float *levelBlend,
00525 unsigned *imgFilter)
00526 {
00527 if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
00528
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
00534
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
00553 lambda = compute_lambda(sampler, s, t, p, lodbias);
00554 else
00555
00556 lambda = lodbias;
00557
00558 if (lambda <= 0.0) {
00559
00560 *imgFilter = sampler->state->mag_img_filter;
00561 *level0 = *level1 = 0;
00562 }
00563 else {
00564
00565 *imgFilter = sampler->state->min_img_filter;
00566
00567
00568 if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
00569
00570 const int lvl = (int) (lambda + 0.5);
00571 *level0 =
00572 *level1 = CLAMP(lvl, 0, (int) sampler->texture->last_level);
00573 }
00574 else {
00575
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);
00580 }
00581 }
00582 }
00583 }
00584
00585
00600 static void
00601 get_texel(struct tgsi_sampler *sampler,
00602 unsigned face, unsigned level, int x, int y, int z,
00603 float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
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 }
00631
00632
00638 static INLINE void
00639 shadow_compare(uint compare_func,
00640 float rgba[NUM_CHANNELS][QUAD_SIZE],
00641 const float p[QUAD_SIZE],
00642 uint j)
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 }
00678
00679
00684 static void
00685 sp_get_samples_2d_common(struct tgsi_sampler *sampler,
00686 const float s[QUAD_SIZE],
00687 const float t[QUAD_SIZE],
00688 const float p[QUAD_SIZE],
00689 float lodbias,
00690 float rgba[NUM_CHANNELS][QUAD_SIZE],
00691 const unsigned faces[4])
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
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
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 }
00790
00791
00792 static void
00793 sp_get_samples_1d(struct tgsi_sampler *sampler,
00794 const float s[QUAD_SIZE],
00795 const float t[QUAD_SIZE],
00796 const float p[QUAD_SIZE],
00797 float lodbias,
00798 float rgba[NUM_CHANNELS][QUAD_SIZE])
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 }
00804
00805
00806 static void
00807 sp_get_samples_2d(struct tgsi_sampler *sampler,
00808 const float s[QUAD_SIZE],
00809 const float t[QUAD_SIZE],
00810 const float p[QUAD_SIZE],
00811 float lodbias,
00812 float rgba[NUM_CHANNELS][QUAD_SIZE])
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 }
00817
00818
00819 static void
00820 sp_get_samples_3d(struct tgsi_sampler *sampler,
00821 const float s[QUAD_SIZE],
00822 const float t[QUAD_SIZE],
00823 const float p[QUAD_SIZE],
00824 float lodbias,
00825 float rgba[NUM_CHANNELS][QUAD_SIZE])
00826 {
00827
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
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;
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
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
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
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
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 }
00939
00940
00941 static void
00942 sp_get_samples_cube(struct tgsi_sampler *sampler,
00943 const float s[QUAD_SIZE],
00944 const float t[QUAD_SIZE],
00945 const float p[QUAD_SIZE],
00946 float lodbias,
00947 float rgba[NUM_CHANNELS][QUAD_SIZE])
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 }
00956
00957
00958 static void
00959 sp_get_samples_rect(struct tgsi_sampler *sampler,
00960 const float s[QUAD_SIZE],
00961 const float t[QUAD_SIZE],
00962 const float p[QUAD_SIZE],
00963 float lodbias,
00964 float rgba[NUM_CHANNELS][QUAD_SIZE])
00965 {
00966
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
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 }
01022
01023
01024
01025
01038 void
01039 sp_get_samples(struct tgsi_sampler *sampler,
01040 const float s[QUAD_SIZE],
01041 const float t[QUAD_SIZE],
01042 const float p[QUAD_SIZE],
01043 float lodbias,
01044 float rgba[NUM_CHANNELS][QUAD_SIZE])
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
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 }
01086