sp_tex_sample.c revision d204659c8c725c02212ad4a49275c7447f2d02a6
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * Copyright 2008 VMware, Inc. 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 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29/** 30 * Texture sampling 31 * 32 * Authors: 33 * Brian Paul 34 * Keith Whitwell 35 */ 36 37#include "pipe/p_context.h" 38#include "pipe/p_defines.h" 39#include "pipe/p_shader_tokens.h" 40#include "util/u_math.h" 41#include "util/u_memory.h" 42#include "sp_quad.h" /* only for #define QUAD_* tokens */ 43#include "sp_tex_sample.h" 44#include "sp_tile_cache.h" 45 46 47 48/* 49 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes 50 * see 1-pixel bands of improperly weighted linear-filtered textures. 51 * The tests/texwrap.c demo is a good test. 52 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0. 53 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x). 54 */ 55#define FRAC(f) ((f) - util_ifloor(f)) 56 57 58/** 59 * Linear interpolation macro 60 */ 61static INLINE float 62lerp(float a, float v0, float v1) 63{ 64 return v0 + a * (v1 - v0); 65} 66 67 68/** 69 * Do 2D/biliner interpolation of float values. 70 * v00, v10, v01 and v11 are typically four texture samples in a square/box. 71 * a and b are the horizontal and vertical interpolants. 72 * It's important that this function is inlined when compiled with 73 * optimization! If we find that's not true on some systems, convert 74 * to a macro. 75 */ 76static INLINE float 77lerp_2d(float a, float b, 78 float v00, float v10, float v01, float v11) 79{ 80 const float temp0 = lerp(a, v00, v10); 81 const float temp1 = lerp(a, v01, v11); 82 return lerp(b, temp0, temp1); 83} 84 85 86/** 87 * As above, but 3D interpolation of 8 values. 88 */ 89static INLINE float 90lerp_3d(float a, float b, float c, 91 float v000, float v100, float v010, float v110, 92 float v001, float v101, float v011, float v111) 93{ 94 const float temp0 = lerp_2d(a, b, v000, v100, v010, v110); 95 const float temp1 = lerp_2d(a, b, v001, v101, v011, v111); 96 return lerp(c, temp0, temp1); 97} 98 99 100 101/** 102 * If A is a signed integer, A % B doesn't give the right value for A < 0 103 * (in terms of texture repeat). Just casting to unsigned fixes that. 104 */ 105#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B)) 106 107 108/** 109 * Apply texture coord wrapping mode and return integer texture indexes 110 * for a vector of four texcoords (S or T or P). 111 * \param wrapMode PIPE_TEX_WRAP_x 112 * \param s the incoming texcoords 113 * \param size the texture image size 114 * \param icoord returns the integer texcoords 115 * \return integer texture index 116 */ 117static void 118wrap_nearest_repeat(const float s[4], unsigned size, 119 int icoord[4]) 120{ 121 uint ch; 122 123 /* s limited to [0,1) */ 124 /* i limited to [0,size-1] */ 125 for (ch = 0; ch < 4; ch++) { 126 int i = util_ifloor(s[ch] * size); 127 icoord[ch] = REMAINDER(i, size); 128 } 129} 130 131 132static void 133wrap_nearest_clamp(const float s[4], unsigned size, 134 int icoord[4]) 135{ 136 uint ch; 137 /* s limited to [0,1] */ 138 /* i limited to [0,size-1] */ 139 for (ch = 0; ch < 4; ch++) { 140 if (s[ch] <= 0.0F) 141 icoord[ch] = 0; 142 else if (s[ch] >= 1.0F) 143 icoord[ch] = size - 1; 144 else 145 icoord[ch] = util_ifloor(s[ch] * size); 146 } 147} 148 149 150static void 151wrap_nearest_clamp_to_edge(const float s[4], unsigned size, 152 int icoord[4]) 153{ 154 uint ch; 155 /* s limited to [min,max] */ 156 /* i limited to [0, size-1] */ 157 const float min = 1.0F / (2.0F * size); 158 const float max = 1.0F - min; 159 for (ch = 0; ch < 4; ch++) { 160 if (s[ch] < min) 161 icoord[ch] = 0; 162 else if (s[ch] > max) 163 icoord[ch] = size - 1; 164 else 165 icoord[ch] = util_ifloor(s[ch] * size); 166 } 167} 168 169 170static void 171wrap_nearest_clamp_to_border(const float s[4], unsigned size, 172 int icoord[4]) 173{ 174 uint ch; 175 /* s limited to [min,max] */ 176 /* i limited to [-1, size] */ 177 const float min = -1.0F / (2.0F * size); 178 const float max = 1.0F - min; 179 for (ch = 0; ch < 4; ch++) { 180 if (s[ch] <= min) 181 icoord[ch] = -1; 182 else if (s[ch] >= max) 183 icoord[ch] = size; 184 else 185 icoord[ch] = util_ifloor(s[ch] * size); 186 } 187} 188 189static void 190wrap_nearest_mirror_repeat(const float s[4], unsigned size, 191 int icoord[4]) 192{ 193 uint ch; 194 const float min = 1.0F / (2.0F * size); 195 const float max = 1.0F - min; 196 for (ch = 0; ch < 4; ch++) { 197 const int flr = util_ifloor(s[ch]); 198 float u; 199 if (flr & 1) 200 u = 1.0F - (s[ch] - (float) flr); 201 else 202 u = s[ch] - (float) flr; 203 if (u < min) 204 icoord[ch] = 0; 205 else if (u > max) 206 icoord[ch] = size - 1; 207 else 208 icoord[ch] = util_ifloor(u * size); 209 } 210} 211 212static void 213wrap_nearest_mirror_clamp(const float s[4], unsigned size, 214 int icoord[4]) 215{ 216 uint ch; 217 for (ch = 0; ch < 4; ch++) { 218 /* s limited to [0,1] */ 219 /* i limited to [0,size-1] */ 220 const float u = fabsf(s[ch]); 221 if (u <= 0.0F) 222 icoord[ch] = 0; 223 else if (u >= 1.0F) 224 icoord[ch] = size - 1; 225 else 226 icoord[ch] = util_ifloor(u * size); 227 } 228} 229 230static void 231wrap_nearest_mirror_clamp_to_edge(const float s[4], unsigned size, 232 int icoord[4]) 233{ 234 uint ch; 235 /* s limited to [min,max] */ 236 /* i limited to [0, size-1] */ 237 const float min = 1.0F / (2.0F * size); 238 const float max = 1.0F - min; 239 for (ch = 0; ch < 4; ch++) { 240 const float u = fabsf(s[ch]); 241 if (u < min) 242 icoord[ch] = 0; 243 else if (u > max) 244 icoord[ch] = size - 1; 245 else 246 icoord[ch] = util_ifloor(u * size); 247 } 248} 249 250 251static void 252wrap_nearest_mirror_clamp_to_border(const float s[4], unsigned size, 253 int icoord[4]) 254{ 255 uint ch; 256 /* s limited to [min,max] */ 257 /* i limited to [0, size-1] */ 258 const float min = -1.0F / (2.0F * size); 259 const float max = 1.0F - min; 260 for (ch = 0; ch < 4; ch++) { 261 const float u = fabsf(s[ch]); 262 if (u < min) 263 icoord[ch] = -1; 264 else if (u > max) 265 icoord[ch] = size; 266 else 267 icoord[ch] = util_ifloor(u * size); 268 } 269} 270 271 272/** 273 * Used to compute texel locations for linear sampling for four texcoords. 274 * \param wrapMode PIPE_TEX_WRAP_x 275 * \param s the texcoords 276 * \param size the texture image size 277 * \param icoord0 returns first texture indexes 278 * \param icoord1 returns second texture indexes (usually icoord0 + 1) 279 * \param w returns blend factor/weight between texture indexes 280 * \param icoord returns the computed integer texture coords 281 */ 282static void 283wrap_linear_repeat(const float s[4], unsigned size, 284 int icoord0[4], int icoord1[4], float w[4]) 285{ 286 uint ch; 287 288 for (ch = 0; ch < 4; ch++) { 289 float u = s[ch] * size - 0.5F; 290 icoord0[ch] = REMAINDER(util_ifloor(u), size); 291 icoord1[ch] = REMAINDER(icoord0[ch] + 1, size); 292 w[ch] = FRAC(u); 293 } 294} 295 296static void 297wrap_linear_clamp(const float s[4], unsigned size, 298 int icoord0[4], int icoord1[4], float w[4]) 299{ 300 uint ch; 301 for (ch = 0; ch < 4; ch++) { 302 float u = CLAMP(s[ch], 0.0F, 1.0F); 303 u = u * size - 0.5f; 304 icoord0[ch] = util_ifloor(u); 305 icoord1[ch] = icoord0[ch] + 1; 306 w[ch] = FRAC(u); 307 } 308} 309 310static void 311wrap_linear_clamp_to_edge(const float s[4], unsigned size, 312 int icoord0[4], int icoord1[4], float w[4]) 313{ 314 uint ch; 315 for (ch = 0; ch < 4; ch++) { 316 float u = CLAMP(s[ch], 0.0F, 1.0F); 317 u = u * size - 0.5f; 318 icoord0[ch] = util_ifloor(u); 319 icoord1[ch] = icoord0[ch] + 1; 320 if (icoord0[ch] < 0) 321 icoord0[ch] = 0; 322 if (icoord1[ch] >= (int) size) 323 icoord1[ch] = size - 1; 324 w[ch] = FRAC(u); 325 } 326} 327 328static void 329wrap_linear_clamp_to_border(const float s[4], unsigned size, 330 int icoord0[4], int icoord1[4], float w[4]) 331{ 332 const float min = -1.0F / (2.0F * size); 333 const float max = 1.0F - min; 334 uint ch; 335 for (ch = 0; ch < 4; ch++) { 336 float u = CLAMP(s[ch], min, max); 337 u = u * size - 0.5f; 338 icoord0[ch] = util_ifloor(u); 339 icoord1[ch] = icoord0[ch] + 1; 340 w[ch] = FRAC(u); 341 } 342} 343 344 345static void 346wrap_linear_mirror_repeat(const float s[4], unsigned size, 347 int icoord0[4], int icoord1[4], float w[4]) 348{ 349 uint ch; 350 for (ch = 0; ch < 4; ch++) { 351 const int flr = util_ifloor(s[ch]); 352 float u; 353 if (flr & 1) 354 u = 1.0F - (s[ch] - (float) flr); 355 else 356 u = s[ch] - (float) flr; 357 u = u * size - 0.5F; 358 icoord0[ch] = util_ifloor(u); 359 icoord1[ch] = icoord0[ch] + 1; 360 if (icoord0[ch] < 0) 361 icoord0[ch] = 0; 362 if (icoord1[ch] >= (int) size) 363 icoord1[ch] = size - 1; 364 w[ch] = FRAC(u); 365 } 366} 367 368static void 369wrap_linear_mirror_clamp(const float s[4], unsigned size, 370 int icoord0[4], int icoord1[4], float w[4]) 371{ 372 uint ch; 373 for (ch = 0; ch < 4; ch++) { 374 float u = fabsf(s[ch]); 375 if (u >= 1.0F) 376 u = (float) size; 377 else 378 u *= size; 379 u -= 0.5F; 380 icoord0[ch] = util_ifloor(u); 381 icoord1[ch] = icoord0[ch] + 1; 382 w[ch] = FRAC(u); 383 } 384} 385 386static void 387wrap_linear_mirror_clamp_to_edge(const float s[4], unsigned size, 388 int icoord0[4], int icoord1[4], float w[4]) 389{ 390 uint ch; 391 for (ch = 0; ch < 4; ch++) { 392 float u = fabsf(s[ch]); 393 if (u >= 1.0F) 394 u = (float) size; 395 else 396 u *= size; 397 u -= 0.5F; 398 icoord0[ch] = util_ifloor(u); 399 icoord1[ch] = icoord0[ch] + 1; 400 if (icoord0[ch] < 0) 401 icoord0[ch] = 0; 402 if (icoord1[ch] >= (int) size) 403 icoord1[ch] = size - 1; 404 w[ch] = FRAC(u); 405 } 406} 407 408static void 409wrap_linear_mirror_clamp_to_border(const float s[4], unsigned size, 410 int icoord0[4], int icoord1[4], float w[4]) 411{ 412 const float min = -1.0F / (2.0F * size); 413 const float max = 1.0F - min; 414 uint ch; 415 for (ch = 0; ch < 4; ch++) { 416 float u = fabsf(s[ch]); 417 if (u <= min) 418 u = min * size; 419 else if (u >= max) 420 u = max * size; 421 else 422 u *= size; 423 u -= 0.5F; 424 icoord0[ch] = util_ifloor(u); 425 icoord1[ch] = icoord0[ch] + 1; 426 w[ch] = FRAC(u); 427 } 428} 429 430 431/** 432 * For RECT textures / unnormalized texcoords 433 * Only a subset of wrap modes supported. 434 */ 435static void 436wrap_nearest_unorm_clamp(const float s[4], unsigned size, 437 int icoord[4]) 438{ 439 uint ch; 440 for (ch = 0; ch < 4; ch++) { 441 int i = util_ifloor(s[ch]); 442 icoord[ch]= CLAMP(i, 0, (int) size-1); 443 } 444} 445 446/* Handles clamp_to_edge and clamp_to_border: 447 */ 448static void 449wrap_nearest_unorm_clamp_to_border(const float s[4], unsigned size, 450 int icoord[4]) 451{ 452 uint ch; 453 for (ch = 0; ch < 4; ch++) { 454 icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) ); 455 } 456} 457 458 459/** 460 * For RECT textures / unnormalized texcoords. 461 * Only a subset of wrap modes supported. 462 */ 463static void 464wrap_linear_unorm_clamp(const float s[4], unsigned size, 465 int icoord0[4], int icoord1[4], float w[4]) 466{ 467 uint ch; 468 for (ch = 0; ch < 4; ch++) { 469 /* Not exactly what the spec says, but it matches NVIDIA output */ 470 float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f); 471 icoord0[ch] = util_ifloor(u); 472 icoord1[ch] = icoord0[ch] + 1; 473 w[ch] = FRAC(u); 474 } 475} 476 477static void 478wrap_linear_unorm_clamp_to_border( const float s[4], unsigned size, 479 int icoord0[4], int icoord1[4], float w[4]) 480{ 481 uint ch; 482 for (ch = 0; ch < 4; ch++) { 483 float u = CLAMP(s[ch], 0.5F, (float) size - 0.5F); 484 u -= 0.5F; 485 icoord0[ch] = util_ifloor(u); 486 icoord1[ch] = icoord0[ch] + 1; 487 if (icoord1[ch] > (int) size - 1) 488 icoord1[ch] = size - 1; 489 w[ch] = FRAC(u); 490 } 491} 492 493 494 495 496 497/** 498 * Examine the quad's texture coordinates to compute the partial 499 * derivatives w.r.t X and Y, then compute lambda (level of detail). 500 */ 501static float 502compute_lambda_1d(const struct sp_sampler_varient *samp, 503 const float s[QUAD_SIZE], 504 const float t[QUAD_SIZE], 505 const float p[QUAD_SIZE], 506 float lodbias) 507{ 508 const struct pipe_texture *texture = samp->texture; 509 const struct pipe_sampler_state *sampler = samp->sampler; 510 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); 511 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); 512 float rho = MAX2(dsdx, dsdy) * texture->width[0]; 513 float lambda; 514 515 lambda = util_fast_log2(rho); 516 lambda += lodbias + sampler->lod_bias; 517 lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod); 518 519 return lambda; 520} 521 522static float 523compute_lambda_2d(const struct sp_sampler_varient *samp, 524 const float s[QUAD_SIZE], 525 const float t[QUAD_SIZE], 526 const float p[QUAD_SIZE], 527 float lodbias) 528{ 529 const struct pipe_texture *texture = samp->texture; 530 const struct pipe_sampler_state *sampler = samp->sampler; 531 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); 532 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); 533 float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); 534 float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]); 535 float maxx = MAX2(dsdx, dsdy) * texture->width[0]; 536 float maxy = MAX2(dtdx, dtdy) * texture->height[0]; 537 float rho = MAX2(maxx, maxy); 538 float lambda; 539 540 lambda = util_fast_log2(rho); 541 lambda += lodbias + sampler->lod_bias; 542 lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod); 543 544 return lambda; 545} 546 547 548static float 549compute_lambda_3d(const struct sp_sampler_varient *samp, 550 const float s[QUAD_SIZE], 551 const float t[QUAD_SIZE], 552 const float p[QUAD_SIZE], 553 float lodbias) 554{ 555 const struct pipe_texture *texture = samp->texture; 556 const struct pipe_sampler_state *sampler = samp->sampler; 557 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); 558 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); 559 float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); 560 float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]); 561 float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]); 562 float dpdy = fabsf(p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]); 563 float maxx = MAX2(dsdx, dsdy) * texture->width[0]; 564 float maxy = MAX2(dtdx, dtdy) * texture->height[0]; 565 float maxz = MAX2(dpdx, dpdy) * texture->depth[0]; 566 float rho, lambda; 567 568 rho = MAX2(maxx, maxy); 569 rho = MAX2(rho, maxz); 570 571 lambda = util_fast_log2(rho); 572 lambda += lodbias + sampler->lod_bias; 573 lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod); 574 575 return lambda; 576} 577 578 579 580static float 581compute_lambda_vert(const struct sp_sampler_varient *samp, 582 const float s[QUAD_SIZE], 583 const float t[QUAD_SIZE], 584 const float p[QUAD_SIZE], 585 float lodbias) 586{ 587 return lodbias; 588} 589 590 591 592/** 593 * Get a texel from a texture, using the texture tile cache. 594 * 595 * \param face the cube face in 0..5 596 * \param level the mipmap level 597 * \param x the x coord of texel within 2D image 598 * \param y the y coord of texel within 2D image 599 * \param z which slice of a 3D texture 600 * \param rgba the quad to put the texel/color into 601 * \param j which element of the rgba quad to write to 602 * 603 * XXX maybe move this into sp_tile_cache.c and merge with the 604 * sp_get_cached_tile_tex() function. Also, get 4 texels instead of 1... 605 */ 606static INLINE void 607get_texel_quad_2d(const struct tgsi_sampler *tgsi_sampler, 608 unsigned face, unsigned level, int x, int y, 609 const float *out[4]) 610{ 611 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 612 613 const struct softpipe_cached_tile *tile 614 = sp_get_cached_tile_tex(samp->cache, 615 tile_address(x, y, 0, face, level)); 616 617 y %= TILE_SIZE; 618 x %= TILE_SIZE; 619 620 out[0] = &tile->data.color[y ][x ][0]; 621 out[1] = &tile->data.color[y ][x+1][0]; 622 out[2] = &tile->data.color[y+1][x ][0]; 623 out[3] = &tile->data.color[y+1][x+1][0]; 624} 625 626static INLINE const float * 627get_texel_2d_ptr(const struct tgsi_sampler *tgsi_sampler, 628 unsigned face, unsigned level, int x, int y) 629{ 630 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 631 632 const struct softpipe_cached_tile *tile 633 = sp_get_cached_tile_tex(samp->cache, 634 tile_address(x, y, 0, face, level)); 635 636 y %= TILE_SIZE; 637 x %= TILE_SIZE; 638 639 return &tile->data.color[y][x][0]; 640} 641 642 643static INLINE void 644get_texel_quad_2d_mt(const struct tgsi_sampler *tgsi_sampler, 645 unsigned face, unsigned level, 646 int x0, int y0, 647 int x1, int y1, 648 const float *out[4]) 649{ 650 unsigned i; 651 652 for (i = 0; i < 4; i++) { 653 unsigned tx = (i & 1) ? x1 : x0; 654 unsigned ty = (i >> 1) ? y1 : y0; 655 656 out[i] = get_texel_2d_ptr( tgsi_sampler, face, level, tx, ty ); 657 } 658} 659 660static INLINE void 661get_texel(const struct tgsi_sampler *tgsi_sampler, 662 unsigned face, unsigned level, int x, int y, int z, 663 float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j) 664{ 665 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 666 const struct pipe_texture *texture = samp->texture; 667 const struct pipe_sampler_state *sampler = samp->sampler; 668 669 if (x < 0 || x >= (int) texture->width[level] || 670 y < 0 || y >= (int) texture->height[level] || 671 z < 0 || z >= (int) texture->depth[level]) { 672 rgba[0][j] = sampler->border_color[0]; 673 rgba[1][j] = sampler->border_color[1]; 674 rgba[2][j] = sampler->border_color[2]; 675 rgba[3][j] = sampler->border_color[3]; 676 } 677 else { 678 const unsigned tx = x % TILE_SIZE; 679 const unsigned ty = y % TILE_SIZE; 680 const struct softpipe_cached_tile *tile; 681 682 tile = sp_get_cached_tile_tex(samp->cache, 683 tile_address(x, y, z, face, level)); 684 685 rgba[0][j] = tile->data.color[ty][tx][0]; 686 rgba[1][j] = tile->data.color[ty][tx][1]; 687 rgba[2][j] = tile->data.color[ty][tx][2]; 688 rgba[3][j] = tile->data.color[ty][tx][3]; 689 if (0) 690 { 691 debug_printf("Get texel %f %f %f %f from %s\n", 692 rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j], 693 pf_name(texture->format)); 694 } 695 } 696} 697 698 699 700 701 702static INLINE void 703img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler, 704 const float s[QUAD_SIZE], 705 const float t[QUAD_SIZE], 706 const float p[QUAD_SIZE], 707 float lodbias, 708 float rgba[NUM_CHANNELS][QUAD_SIZE]) 709{ 710 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 711 unsigned j; 712 unsigned level = samp->level; 713 unsigned xpot = 1 << (samp->xpot - level); 714 unsigned ypot = 1 << (samp->ypot - level); 715 unsigned xmax = (xpot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, xpot) - 1; */ 716 unsigned ymax = (ypot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, ypot) - 1; */ 717 718 for (j = 0; j < QUAD_SIZE; j++) { 719 int c; 720 721 float u = s[j] * xpot - 0.5F; 722 float v = t[j] * ypot - 0.5F; 723 724 int uflr = util_ifloor(u); 725 int vflr = util_ifloor(v); 726 727 float xw = u - (float)uflr; 728 float yw = v - (float)vflr; 729 730 int x0 = uflr & (xpot - 1); 731 int y0 = vflr & (ypot - 1); 732 733 const float *tx[4]; 734 735 736 /* Can we fetch all four at once: 737 */ 738 if (x0 < xmax && y0 < ymax) 739 { 740 get_texel_quad_2d(tgsi_sampler, 0, level, x0, y0, tx); 741 } 742 else 743 { 744 unsigned x1 = (x0 + 1) & (xpot - 1); 745 unsigned y1 = (y0 + 1) & (ypot - 1); 746 get_texel_quad_2d_mt(tgsi_sampler, 0, level, 747 x0, y0, x1, y1, tx); 748 } 749 750 751 /* interpolate R, G, B, A */ 752 for (c = 0; c < 4; c++) { 753 rgba[c][j] = lerp_2d(xw, yw, 754 tx[0][c], tx[1][c], 755 tx[2][c], tx[3][c]); 756 } 757 } 758} 759 760 761static INLINE void 762img_filter_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler, 763 const float s[QUAD_SIZE], 764 const float t[QUAD_SIZE], 765 const float p[QUAD_SIZE], 766 float lodbias, 767 float rgba[NUM_CHANNELS][QUAD_SIZE]) 768{ 769 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 770 unsigned j; 771 unsigned level = samp->level; 772 unsigned xpot = 1 << (samp->xpot - level); 773 unsigned ypot = 1 << (samp->ypot - level); 774 775 for (j = 0; j < QUAD_SIZE; j++) { 776 int c; 777 778 float u = s[j] * xpot; 779 float v = t[j] * ypot; 780 781 int uflr = util_ifloor(u); 782 int vflr = util_ifloor(v); 783 784 int x0 = uflr & (xpot - 1); 785 int y0 = vflr & (ypot - 1); 786 787 const float *out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0); 788 789 for (c = 0; c < 4; c++) { 790 rgba[c][j] = out[c]; 791 } 792 } 793} 794 795 796static INLINE void 797img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler, 798 const float s[QUAD_SIZE], 799 const float t[QUAD_SIZE], 800 const float p[QUAD_SIZE], 801 float lodbias, 802 float rgba[NUM_CHANNELS][QUAD_SIZE]) 803{ 804 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 805 unsigned j; 806 unsigned level = samp->level; 807 unsigned xpot = 1 << (samp->xpot - level); 808 unsigned ypot = 1 << (samp->ypot - level); 809 810 for (j = 0; j < QUAD_SIZE; j++) { 811 int c; 812 813 float u = s[j] * xpot; 814 float v = t[j] * ypot; 815 816 int x0, y0; 817 const float *out; 818 819 x0 = util_ifloor(u); 820 if (x0 < 0) 821 x0 = 0; 822 else if (x0 > xpot - 1) 823 x0 = xpot - 1; 824 825 y0 = util_ifloor(v); 826 if (y0 < 0) 827 y0 = 0; 828 else if (y0 > ypot - 1) 829 y0 = ypot - 1; 830 831 out = get_texel_2d_ptr(tgsi_sampler, 0, level, x0, y0); 832 833 for (c = 0; c < 4; c++) { 834 rgba[c][j] = out[c]; 835 } 836 } 837} 838 839static void 840img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler, 841 const float s[QUAD_SIZE], 842 const float t[QUAD_SIZE], 843 const float p[QUAD_SIZE], 844 float lodbias, 845 float rgba[NUM_CHANNELS][QUAD_SIZE]) 846{ 847 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 848 const struct pipe_texture *texture = samp->texture; 849 unsigned level0, j; 850 int width; 851 int x[4]; 852 853 level0 = samp->level; 854 width = texture->width[level0]; 855 856 assert(width > 0); 857 858 samp->nearest_texcoord_s(s, width, x); 859 860 for (j = 0; j < QUAD_SIZE; j++) { 861 get_texel(tgsi_sampler, 0, level0, x[j], 0, 0, rgba, j); 862 } 863} 864 865 866static void 867img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, 868 const float s[QUAD_SIZE], 869 const float t[QUAD_SIZE], 870 const float p[QUAD_SIZE], 871 float lodbias, 872 float rgba[NUM_CHANNELS][QUAD_SIZE]) 873{ 874 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 875 const struct pipe_texture *texture = samp->texture; 876 const unsigned *faces = samp->faces; /* zero when not cube-mapping */ 877 unsigned level0, j; 878 int width, height; 879 int x[4], y[4]; 880 881 level0 = samp->level; 882 width = texture->width[level0]; 883 height = texture->height[level0]; 884 885 assert(width > 0); 886 887 samp->nearest_texcoord_s(s, width, x); 888 samp->nearest_texcoord_t(t, height, y); 889 890 for (j = 0; j < QUAD_SIZE; j++) { 891 get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j); 892 } 893} 894 895 896static void 897img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler, 898 const float s[QUAD_SIZE], 899 const float t[QUAD_SIZE], 900 const float p[QUAD_SIZE], 901 float lodbias, 902 float rgba[NUM_CHANNELS][QUAD_SIZE]) 903{ 904 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 905 const struct pipe_texture *texture = samp->texture; 906 unsigned level0, j; 907 int width, height, depth; 908 int x[4], y[4], z[4]; 909 910 level0 = samp->level; 911 width = texture->width[level0]; 912 height = texture->height[level0]; 913 depth = texture->depth[level0]; 914 915 assert(width > 0); 916 assert(height > 0); 917 assert(depth > 0); 918 919 samp->nearest_texcoord_s(s, width, x); 920 samp->nearest_texcoord_t(t, height, y); 921 samp->nearest_texcoord_p(p, depth, z); 922 923 for (j = 0; j < QUAD_SIZE; j++) { 924 get_texel(tgsi_sampler, 0, level0, x[j], y[j], z[j], rgba, j); 925 } 926} 927 928 929static void 930img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler, 931 const float s[QUAD_SIZE], 932 const float t[QUAD_SIZE], 933 const float p[QUAD_SIZE], 934 float lodbias, 935 float rgba[NUM_CHANNELS][QUAD_SIZE]) 936{ 937 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 938 const struct pipe_texture *texture = samp->texture; 939 unsigned level0, j; 940 int width; 941 int x0[4], x1[4]; 942 float xw[4]; /* weights */ 943 944 945 level0 = samp->level; 946 width = texture->width[level0]; 947 948 assert(width > 0); 949 950 samp->linear_texcoord_s(s, width, x0, x1, xw); 951 952 953 for (j = 0; j < QUAD_SIZE; j++) { 954 float tx[4][4]; /* texels */ 955 int c; 956 get_texel(tgsi_sampler, 0, level0, x0[j], 0, 0, tx, 0); 957 get_texel(tgsi_sampler, 0, level0, x1[j], 0, 0, tx, 1); 958 959 /* interpolate R, G, B, A */ 960 for (c = 0; c < 4; c++) { 961 rgba[c][j] = lerp(xw[j], tx[c][0], tx[c][1]); 962 } 963 } 964} 965 966static void 967img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, 968 const float s[QUAD_SIZE], 969 const float t[QUAD_SIZE], 970 const float p[QUAD_SIZE], 971 float lodbias, 972 float rgba[NUM_CHANNELS][QUAD_SIZE]) 973{ 974 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 975 const struct pipe_texture *texture = samp->texture; 976 const unsigned *faces = samp->faces; /* zero when not cube-mapping */ 977 unsigned level0, j; 978 int width, height; 979 int x0[4], y0[4], x1[4], y1[4]; 980 float xw[4], yw[4]; /* weights */ 981 982 983 level0 = samp->level; 984 width = texture->width[level0]; 985 height = texture->height[level0]; 986 987 assert(width > 0); 988 989 samp->linear_texcoord_s(s, width, x0, x1, xw); 990 samp->linear_texcoord_t(t, height, y0, y1, yw); 991 992 for (j = 0; j < QUAD_SIZE; j++) { 993 float tx[4][4]; /* texels */ 994 int c; 995 get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0); 996 get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1); 997 get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2); 998 get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3); 999 1000 /* interpolate R, G, B, A */ 1001 for (c = 0; c < 4; c++) { 1002 rgba[c][j] = lerp_2d(xw[j], yw[j], 1003 tx[c][0], tx[c][1], 1004 tx[c][2], tx[c][3]); 1005 } 1006 } 1007} 1008 1009 1010static void 1011img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler, 1012 const float s[QUAD_SIZE], 1013 const float t[QUAD_SIZE], 1014 const float p[QUAD_SIZE], 1015 float lodbias, 1016 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1017{ 1018 const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 1019 const struct pipe_texture *texture = samp->texture; 1020 unsigned level0, j; 1021 int width, height, depth; 1022 int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4]; 1023 float xw[4], yw[4], zw[4]; /* interpolation weights */ 1024 1025 level0 = samp->level; 1026 width = texture->width[level0]; 1027 height = texture->height[level0]; 1028 depth = texture->depth[level0]; 1029 1030 assert(width > 0); 1031 assert(height > 0); 1032 assert(depth > 0); 1033 1034 samp->linear_texcoord_s(s, width, x0, x1, xw); 1035 samp->linear_texcoord_t(t, height, y0, y1, yw); 1036 samp->linear_texcoord_p(p, depth, z0, z1, zw); 1037 1038 for (j = 0; j < QUAD_SIZE; j++) { 1039 float tx0[4][4], tx1[4][4]; 1040 int c; 1041 1042 get_texel(tgsi_sampler, 0, level0, x0[j], y0[j], z0[j], tx0, 0); 1043 get_texel(tgsi_sampler, 0, level0, x1[j], y0[j], z0[j], tx0, 1); 1044 get_texel(tgsi_sampler, 0, level0, x0[j], y1[j], z0[j], tx0, 2); 1045 get_texel(tgsi_sampler, 0, level0, x1[j], y1[j], z0[j], tx0, 3); 1046 get_texel(tgsi_sampler, 0, level0, x0[j], y0[j], z1[j], tx1, 0); 1047 get_texel(tgsi_sampler, 0, level0, x1[j], y0[j], z1[j], tx1, 1); 1048 get_texel(tgsi_sampler, 0, level0, x0[j], y1[j], z1[j], tx1, 2); 1049 get_texel(tgsi_sampler, 0, level0, x1[j], y1[j], z1[j], tx1, 3); 1050 1051 /* interpolate R, G, B, A */ 1052 for (c = 0; c < 4; c++) { 1053 rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1054 tx0[c][0], tx0[c][1], 1055 tx0[c][2], tx0[c][3], 1056 tx1[c][0], tx1[c][1], 1057 tx1[c][2], tx1[c][3]); 1058 } 1059 } 1060} 1061 1062 1063 1064 1065 1066 1067 1068static void 1069mip_filter_linear(struct tgsi_sampler *tgsi_sampler, 1070 const float s[QUAD_SIZE], 1071 const float t[QUAD_SIZE], 1072 const float p[QUAD_SIZE], 1073 float lodbias, 1074 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1075{ 1076 struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 1077 const struct pipe_texture *texture = samp->texture; 1078 int level0; 1079 float lambda; 1080 1081 lambda = samp->compute_lambda(samp, s, t, p, lodbias); 1082 level0 = (int)lambda; 1083 1084 if (lambda < 0.0) { 1085 samp->level = 0; 1086 samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba ); 1087 } 1088 else if (level0 >= texture->last_level) { 1089 samp->level = texture->last_level; 1090 samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba ); 1091 } 1092 else { 1093 float levelBlend = lambda - level0; 1094 float rgba0[4][4]; 1095 float rgba1[4][4]; 1096 int c,j; 1097 1098 samp->level = level0; 1099 samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba0 ); 1100 1101 samp->level = level0+1; 1102 samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba1 ); 1103 1104 for (j = 0; j < QUAD_SIZE; j++) { 1105 for (c = 0; c < 4; c++) { 1106 rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]); 1107 } 1108 } 1109 } 1110} 1111 1112 1113 1114static void 1115mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, 1116 const float s[QUAD_SIZE], 1117 const float t[QUAD_SIZE], 1118 const float p[QUAD_SIZE], 1119 float lodbias, 1120 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1121{ 1122 struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 1123 const struct pipe_texture *texture = samp->texture; 1124 float lambda; 1125 1126 lambda = samp->compute_lambda(samp, s, t, p, lodbias); 1127 1128 if (lambda < 0.0) { 1129 samp->level = 0; 1130 samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba ); 1131 } 1132 else { 1133 samp->level = (int)(lambda + 0.5) ; 1134 samp->level = MIN2(samp->level, (int)texture->last_level); 1135 samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba ); 1136 } 1137} 1138 1139 1140static void 1141mip_filter_none(struct tgsi_sampler *tgsi_sampler, 1142 const float s[QUAD_SIZE], 1143 const float t[QUAD_SIZE], 1144 const float p[QUAD_SIZE], 1145 float lodbias, 1146 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1147{ 1148 struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 1149 float lambda = samp->compute_lambda(samp, s, t, p, lodbias); 1150 1151 if (lambda < 0.0) { 1152 samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba ); 1153 } 1154 else { 1155 samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba ); 1156 } 1157} 1158 1159 1160 1161/* Specialized version of mip_filter_linear with hard-wired calls to 1162 * 2d lambda calculation and 2d_linear_repeat_POT img filters. 1163 */ 1164static void 1165mip_filter_linear_2d_linear_repeat_POT( 1166 struct tgsi_sampler *tgsi_sampler, 1167 const float s[QUAD_SIZE], 1168 const float t[QUAD_SIZE], 1169 const float p[QUAD_SIZE], 1170 float lodbias, 1171 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1172{ 1173 struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 1174 const struct pipe_texture *texture = samp->texture; 1175 int level0; 1176 float lambda; 1177 1178 lambda = compute_lambda_2d(samp, s, t, p, lodbias); 1179 level0 = (int)lambda; 1180 1181 /* Catches both negative and large values of level0: 1182 */ 1183 if ((unsigned)level0 >= texture->last_level) { 1184 if (level0 < 0) 1185 samp->level = 0; 1186 else 1187 samp->level = texture->last_level; 1188 1189 img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba ); 1190 } 1191 else { 1192 float levelBlend = lambda - level0; 1193 float rgba0[4][4]; 1194 float rgba1[4][4]; 1195 int c,j; 1196 1197 samp->level = level0; 1198 img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba0 ); 1199 1200 samp->level = level0+1; 1201 img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba1 ); 1202 1203 for (j = 0; j < QUAD_SIZE; j++) { 1204 for (c = 0; c < 4; c++) { 1205 rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]); 1206 } 1207 } 1208 } 1209} 1210 1211 1212 1213/* Compare stage in the little sampling pipeline. 1214 */ 1215static void 1216sample_compare(struct tgsi_sampler *tgsi_sampler, 1217 const float s[QUAD_SIZE], 1218 const float t[QUAD_SIZE], 1219 const float p[QUAD_SIZE], 1220 float lodbias, 1221 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1222{ 1223 struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 1224 const struct pipe_sampler_state *sampler = samp->sampler; 1225 int j, k0, k1, k2, k3; 1226 float val; 1227 1228 samp->mip_filter( tgsi_sampler, s, t, p, lodbias, rgba ); 1229 1230 1231 /** 1232 * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' 1233 * When we sampled the depth texture, the depth value was put into all 1234 * RGBA channels. We look at the red channel here. 1235 */ 1236 1237 /* compare four texcoords vs. four texture samples */ 1238 switch (sampler->compare_func) { 1239 case PIPE_FUNC_LESS: 1240 k0 = p[0] < rgba[0][0]; 1241 k1 = p[1] < rgba[0][1]; 1242 k2 = p[2] < rgba[0][2]; 1243 k3 = p[3] < rgba[0][3]; 1244 break; 1245 case PIPE_FUNC_LEQUAL: 1246 k0 = p[0] <= rgba[0][0]; 1247 k1 = p[1] <= rgba[0][1]; 1248 k2 = p[2] <= rgba[0][2]; 1249 k3 = p[3] <= rgba[0][3]; 1250 break; 1251 case PIPE_FUNC_GREATER: 1252 k0 = p[0] > rgba[0][0]; 1253 k1 = p[1] > rgba[0][1]; 1254 k2 = p[2] > rgba[0][2]; 1255 k3 = p[3] > rgba[0][3]; 1256 break; 1257 case PIPE_FUNC_GEQUAL: 1258 k0 = p[0] >= rgba[0][0]; 1259 k1 = p[1] >= rgba[0][1]; 1260 k2 = p[2] >= rgba[0][2]; 1261 k3 = p[3] >= rgba[0][3]; 1262 break; 1263 case PIPE_FUNC_EQUAL: 1264 k0 = p[0] == rgba[0][0]; 1265 k1 = p[1] == rgba[0][1]; 1266 k2 = p[2] == rgba[0][2]; 1267 k3 = p[3] == rgba[0][3]; 1268 break; 1269 case PIPE_FUNC_NOTEQUAL: 1270 k0 = p[0] != rgba[0][0]; 1271 k1 = p[1] != rgba[0][1]; 1272 k2 = p[2] != rgba[0][2]; 1273 k3 = p[3] != rgba[0][3]; 1274 break; 1275 case PIPE_FUNC_ALWAYS: 1276 k0 = k1 = k2 = k3 = 1; 1277 break; 1278 case PIPE_FUNC_NEVER: 1279 k0 = k1 = k2 = k3 = 0; 1280 break; 1281 default: 1282 k0 = k1 = k2 = k3 = 0; 1283 assert(0); 1284 break; 1285 } 1286 1287 /* convert four pass/fail values to an intensity in [0,1] */ 1288 val = 0.25F * (k0 + k1 + k2 + k3); 1289 1290 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 1291 for (j = 0; j < 4; j++) { 1292 rgba[0][j] = rgba[1][j] = rgba[2][j] = val; 1293 rgba[3][j] = 1.0F; 1294 } 1295} 1296 1297/* Calculate cube faces. 1298 */ 1299static void 1300sample_cube(struct tgsi_sampler *tgsi_sampler, 1301 const float s[QUAD_SIZE], 1302 const float t[QUAD_SIZE], 1303 const float p[QUAD_SIZE], 1304 float lodbias, 1305 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1306{ 1307 struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); 1308 unsigned j; 1309 float ssss[4], tttt[4]; 1310 1311 /* 1312 major axis 1313 direction target sc tc ma 1314 ---------- ------------------------------- --- --- --- 1315 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx 1316 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx 1317 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry 1318 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry 1319 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz 1320 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz 1321 */ 1322 for (j = 0; j < QUAD_SIZE; j++) { 1323 float rx = s[j]; 1324 float ry = t[j]; 1325 float rz = p[j]; 1326 const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); 1327 unsigned face; 1328 float sc, tc, ma; 1329 1330 if (arx > ary && arx > arz) { 1331 if (rx >= 0.0F) { 1332 face = PIPE_TEX_FACE_POS_X; 1333 sc = -rz; 1334 tc = -ry; 1335 ma = arx; 1336 } 1337 else { 1338 face = PIPE_TEX_FACE_NEG_X; 1339 sc = rz; 1340 tc = -ry; 1341 ma = arx; 1342 } 1343 } 1344 else if (ary > arx && ary > arz) { 1345 if (ry >= 0.0F) { 1346 face = PIPE_TEX_FACE_POS_Y; 1347 sc = rx; 1348 tc = rz; 1349 ma = ary; 1350 } 1351 else { 1352 face = PIPE_TEX_FACE_NEG_Y; 1353 sc = rx; 1354 tc = -rz; 1355 ma = ary; 1356 } 1357 } 1358 else { 1359 if (rz > 0.0F) { 1360 face = PIPE_TEX_FACE_POS_Z; 1361 sc = rx; 1362 tc = -ry; 1363 ma = arz; 1364 } 1365 else { 1366 face = PIPE_TEX_FACE_NEG_Z; 1367 sc = -rx; 1368 tc = -ry; 1369 ma = arz; 1370 } 1371 } 1372 1373 ssss[j] = ( sc / ma + 1.0F ) * 0.5F; 1374 tttt[j] = ( tc / ma + 1.0F ) * 0.5F; 1375 samp->faces[j] = face; 1376 } 1377 1378 /* In our little pipeline, the compare stage is next. If compare 1379 * is not active, this will point somewhere deeper into the 1380 * pipeline, eg. to mip_filter or even img_filter. 1381 */ 1382 samp->compare(tgsi_sampler, ssss, tttt, NULL, lodbias, rgba); 1383} 1384 1385 1386 1387 1388static wrap_nearest_func get_nearest_unorm_wrap( unsigned mode ) 1389{ 1390 switch (mode) { 1391 case PIPE_TEX_WRAP_CLAMP: 1392 return wrap_nearest_unorm_clamp; 1393 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 1394 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 1395 return wrap_nearest_unorm_clamp_to_border; 1396 default: 1397 assert(0); 1398 return wrap_nearest_unorm_clamp; 1399 } 1400} 1401 1402 1403static wrap_nearest_func get_nearest_wrap( unsigned mode ) 1404{ 1405 switch (mode) { 1406 case PIPE_TEX_WRAP_REPEAT: 1407 return wrap_nearest_repeat; 1408 case PIPE_TEX_WRAP_CLAMP: 1409 return wrap_nearest_clamp; 1410 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 1411 return wrap_nearest_clamp_to_edge; 1412 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 1413 return wrap_nearest_clamp_to_border; 1414 case PIPE_TEX_WRAP_MIRROR_REPEAT: 1415 return wrap_nearest_mirror_repeat; 1416 case PIPE_TEX_WRAP_MIRROR_CLAMP: 1417 return wrap_nearest_mirror_clamp; 1418 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 1419 return wrap_nearest_mirror_clamp_to_edge; 1420 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 1421 return wrap_nearest_mirror_clamp_to_border; 1422 default: 1423 assert(0); 1424 return wrap_nearest_repeat; 1425 } 1426} 1427 1428static wrap_linear_func get_linear_unorm_wrap( unsigned mode ) 1429{ 1430 switch (mode) { 1431 case PIPE_TEX_WRAP_CLAMP: 1432 return wrap_linear_unorm_clamp; 1433 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 1434 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 1435 return wrap_linear_unorm_clamp_to_border; 1436 default: 1437 assert(0); 1438 return wrap_linear_unorm_clamp; 1439 } 1440} 1441 1442static wrap_linear_func get_linear_wrap( unsigned mode ) 1443{ 1444 switch (mode) { 1445 case PIPE_TEX_WRAP_REPEAT: 1446 return wrap_linear_repeat; 1447 case PIPE_TEX_WRAP_CLAMP: 1448 return wrap_linear_clamp; 1449 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 1450 return wrap_linear_clamp_to_edge; 1451 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 1452 return wrap_linear_clamp_to_border; 1453 case PIPE_TEX_WRAP_MIRROR_REPEAT: 1454 return wrap_linear_mirror_repeat; 1455 case PIPE_TEX_WRAP_MIRROR_CLAMP: 1456 return wrap_linear_mirror_clamp; 1457 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 1458 return wrap_linear_mirror_clamp_to_edge; 1459 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 1460 return wrap_linear_mirror_clamp_to_border; 1461 default: 1462 assert(0); 1463 return wrap_linear_repeat; 1464 } 1465} 1466 1467static compute_lambda_func get_lambda_func( const union sp_sampler_key key ) 1468{ 1469 if (key.bits.processor == TGSI_PROCESSOR_VERTEX) 1470 return compute_lambda_vert; 1471 1472 switch (key.bits.target) { 1473 case PIPE_TEXTURE_1D: 1474 return compute_lambda_1d; 1475 case PIPE_TEXTURE_2D: 1476 case PIPE_TEXTURE_CUBE: 1477 return compute_lambda_2d; 1478 case PIPE_TEXTURE_3D: 1479 return compute_lambda_3d; 1480 default: 1481 assert(0); 1482 return compute_lambda_1d; 1483 } 1484} 1485 1486static filter_func get_img_filter( const union sp_sampler_key key, 1487 unsigned filter, 1488 const struct pipe_sampler_state *sampler ) 1489{ 1490 switch (key.bits.target) { 1491 case PIPE_TEXTURE_1D: 1492 if (filter == PIPE_TEX_FILTER_NEAREST) 1493 return img_filter_1d_nearest; 1494 else 1495 return img_filter_1d_linear; 1496 break; 1497 case PIPE_TEXTURE_2D: 1498 /* Try for fast path: 1499 */ 1500 if (key.bits.is_pot && 1501 sampler->wrap_s == sampler->wrap_t && 1502 sampler->normalized_coords) 1503 { 1504 switch (sampler->wrap_s) { 1505 case PIPE_TEX_WRAP_REPEAT: 1506 switch (filter) { 1507 case PIPE_TEX_FILTER_NEAREST: 1508 return img_filter_2d_nearest_repeat_POT; 1509 case PIPE_TEX_FILTER_LINEAR: 1510 return img_filter_2d_linear_repeat_POT; 1511 default: 1512 break; 1513 } 1514 break; 1515 case PIPE_TEX_WRAP_CLAMP: 1516 switch (filter) { 1517 case PIPE_TEX_FILTER_NEAREST: 1518 return img_filter_2d_nearest_clamp_POT; 1519 default: 1520 break; 1521 } 1522 } 1523 } 1524 /* Fallthrough to default versions: 1525 */ 1526 case PIPE_TEXTURE_CUBE: 1527 if (filter == PIPE_TEX_FILTER_NEAREST) 1528 return img_filter_2d_nearest; 1529 else 1530 return img_filter_2d_linear; 1531 break; 1532 case PIPE_TEXTURE_3D: 1533 if (filter == PIPE_TEX_FILTER_NEAREST) 1534 return img_filter_3d_nearest; 1535 else 1536 return img_filter_3d_linear; 1537 break; 1538 default: 1539 assert(0); 1540 return img_filter_1d_nearest; 1541 } 1542} 1543 1544 1545/** 1546 * Bind the given texture object and texture cache to the sampler varient. 1547 */ 1548void 1549sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp, 1550 struct softpipe_tile_cache *tex_cache, 1551 const struct pipe_texture *texture ) 1552{ 1553 const struct pipe_sampler_state *sampler = samp->sampler; 1554 1555 samp->texture = texture; 1556 samp->cache = tex_cache; 1557 samp->xpot = util_unsigned_logbase2( texture->width[0] ); 1558 samp->ypot = util_unsigned_logbase2( texture->height[0] ); 1559 samp->level = CLAMP((int) sampler->min_lod, 0, (int) texture->last_level); 1560} 1561 1562 1563void 1564sp_sampler_varient_destroy( struct sp_sampler_varient *samp ) 1565{ 1566 FREE(samp); 1567} 1568 1569 1570/* Create a sampler varient for a given set of non-orthogonal state. Currently the 1571 */ 1572struct sp_sampler_varient * 1573sp_create_sampler_varient( const struct pipe_sampler_state *sampler, 1574 const union sp_sampler_key key ) 1575{ 1576 struct sp_sampler_varient *samp = CALLOC_STRUCT(sp_sampler_varient); 1577 if (!samp) 1578 return NULL; 1579 1580 samp->sampler = sampler; 1581 samp->key = key; 1582 1583 /* Note that (for instance) linear_texcoord_s and 1584 * nearest_texcoord_s may be active at the same time, if the 1585 * sampler min_img_filter differs from its mag_img_filter. 1586 */ 1587 if (sampler->normalized_coords) { 1588 samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s ); 1589 samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t ); 1590 samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r ); 1591 1592 samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s ); 1593 samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t ); 1594 samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r ); 1595 } 1596 else { 1597 samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s ); 1598 samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t ); 1599 samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r ); 1600 1601 samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s ); 1602 samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t ); 1603 samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r ); 1604 } 1605 1606 samp->compute_lambda = get_lambda_func( key ); 1607 1608 samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler); 1609 samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler); 1610 1611 switch (sampler->min_mip_filter) { 1612 case PIPE_TEX_MIPFILTER_NONE: 1613 if (sampler->min_img_filter == sampler->mag_img_filter) 1614 samp->mip_filter = samp->min_img_filter; 1615 else 1616 samp->mip_filter = mip_filter_none; 1617 break; 1618 1619 case PIPE_TEX_MIPFILTER_NEAREST: 1620 samp->mip_filter = mip_filter_nearest; 1621 break; 1622 1623 case PIPE_TEX_MIPFILTER_LINEAR: 1624 if (key.bits.is_pot && 1625 sampler->min_img_filter == sampler->mag_img_filter && 1626 sampler->normalized_coords && 1627 sampler->wrap_s == PIPE_TEX_WRAP_REPEAT && 1628 sampler->wrap_t == PIPE_TEX_WRAP_REPEAT && 1629 sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR) 1630 { 1631 samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT; 1632 } 1633 else 1634 { 1635 samp->mip_filter = mip_filter_linear; 1636 } 1637 break; 1638 } 1639 1640 if (sampler->compare_mode != FALSE) { 1641 samp->compare = sample_compare; 1642 } 1643 else { 1644 /* Skip compare operation by promoting the mip_filter function 1645 * pointer: 1646 */ 1647 samp->compare = samp->mip_filter; 1648 } 1649 1650 if (key.bits.target == PIPE_TEXTURE_CUBE) { 1651 samp->base.get_samples = sample_cube; 1652 } 1653 else { 1654 samp->faces[0] = 0; 1655 samp->faces[1] = 0; 1656 samp->faces[2] = 0; 1657 samp->faces[3] = 0; 1658 1659 /* Skip cube face determination by promoting the compare 1660 * function pointer: 1661 */ 1662 samp->base.get_samples = samp->compare; 1663 } 1664 1665 return samp; 1666} 1667 1668 1669 1670 1671 1672 1673