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