sp_tex_sample.c revision f4537f99cc83cb8133f66dc97c613e95dc0fe162
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * Copyright 2008-2010 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_tex_tile_cache.h" 45 46 47/** Set to one to help debug texture sampling */ 48#define DEBUG_TEX 0 49 50 51/* 52 * Return fractional part of 'f'. Used for computing interpolation weights. 53 * Need to be careful with negative values. 54 * Note, if this function isn't perfect you'll sometimes see 1-pixel bands 55 * of improperly weighted linear-filtered textures. 56 * The tests/texwrap.c demo is a good test. 57 */ 58static INLINE float 59frac(float f) 60{ 61 return f - floorf(f); 62} 63 64 65 66/** 67 * Linear interpolation macro 68 */ 69static INLINE float 70lerp(float a, float v0, float v1) 71{ 72 return v0 + a * (v1 - v0); 73} 74 75 76/** 77 * Do 2D/bilinear interpolation of float values. 78 * v00, v10, v01 and v11 are typically four texture samples in a square/box. 79 * a and b are the horizontal and vertical interpolants. 80 * It's important that this function is inlined when compiled with 81 * optimization! If we find that's not true on some systems, convert 82 * to a macro. 83 */ 84static INLINE float 85lerp_2d(float a, float b, 86 float v00, float v10, float v01, float v11) 87{ 88 const float temp0 = lerp(a, v00, v10); 89 const float temp1 = lerp(a, v01, v11); 90 return lerp(b, temp0, temp1); 91} 92 93 94/** 95 * As above, but 3D interpolation of 8 values. 96 */ 97static INLINE float 98lerp_3d(float a, float b, float c, 99 float v000, float v100, float v010, float v110, 100 float v001, float v101, float v011, float v111) 101{ 102 const float temp0 = lerp_2d(a, b, v000, v100, v010, v110); 103 const float temp1 = lerp_2d(a, b, v001, v101, v011, v111); 104 return lerp(c, temp0, temp1); 105} 106 107 108 109/** 110 * Compute coord % size for repeat wrap modes. 111 * Note that if coord is negative, coord % size doesn't give the right 112 * value. To avoid that problem we add a large multiple of the size 113 * (rather than using a conditional). 114 */ 115static INLINE int 116repeat(int coord, unsigned size) 117{ 118 return (coord + size * 1024) % size; 119} 120 121 122/** 123 * Apply texture coord wrapping mode and return integer texture indexes 124 * for a vector of four texcoords (S or T or P). 125 * \param wrapMode PIPE_TEX_WRAP_x 126 * \param s the incoming texcoords 127 * \param size the texture image size 128 * \param icoord returns the integer texcoords 129 * \return integer texture index 130 */ 131static void 132wrap_nearest_repeat(const float s[4], unsigned size, int icoord[4]) 133{ 134 uint ch; 135 /* s limited to [0,1) */ 136 /* i limited to [0,size-1] */ 137 for (ch = 0; ch < 4; ch++) { 138 int i = util_ifloor(s[ch] * size); 139 icoord[ch] = repeat(i, size); 140 } 141} 142 143 144static void 145wrap_nearest_clamp(const float s[4], unsigned size, int icoord[4]) 146{ 147 uint ch; 148 /* s limited to [0,1] */ 149 /* i limited to [0,size-1] */ 150 for (ch = 0; ch < 4; ch++) { 151 if (s[ch] <= 0.0F) 152 icoord[ch] = 0; 153 else if (s[ch] >= 1.0F) 154 icoord[ch] = size - 1; 155 else 156 icoord[ch] = util_ifloor(s[ch] * size); 157 } 158} 159 160 161static void 162wrap_nearest_clamp_to_edge(const float s[4], unsigned size, int icoord[4]) 163{ 164 uint ch; 165 /* s limited to [min,max] */ 166 /* i limited to [0, size-1] */ 167 const float min = 1.0F / (2.0F * size); 168 const float max = 1.0F - min; 169 for (ch = 0; ch < 4; ch++) { 170 if (s[ch] < min) 171 icoord[ch] = 0; 172 else if (s[ch] > max) 173 icoord[ch] = size - 1; 174 else 175 icoord[ch] = util_ifloor(s[ch] * size); 176 } 177} 178 179 180static void 181wrap_nearest_clamp_to_border(const float s[4], unsigned size, int icoord[4]) 182{ 183 uint ch; 184 /* s limited to [min,max] */ 185 /* i limited to [-1, size] */ 186 const float min = -1.0F / (2.0F * size); 187 const float max = 1.0F - min; 188 for (ch = 0; ch < 4; ch++) { 189 if (s[ch] <= min) 190 icoord[ch] = -1; 191 else if (s[ch] >= max) 192 icoord[ch] = size; 193 else 194 icoord[ch] = util_ifloor(s[ch] * size); 195 } 196} 197 198 199static void 200wrap_nearest_mirror_repeat(const float s[4], unsigned size, int icoord[4]) 201{ 202 uint ch; 203 const float min = 1.0F / (2.0F * size); 204 const float max = 1.0F - min; 205 for (ch = 0; ch < 4; ch++) { 206 const int flr = util_ifloor(s[ch]); 207 float u = frac(s[ch]); 208 if (flr & 1) 209 u = 1.0F - u; 210 if (u < min) 211 icoord[ch] = 0; 212 else if (u > max) 213 icoord[ch] = size - 1; 214 else 215 icoord[ch] = util_ifloor(u * size); 216 } 217} 218 219 220static void 221wrap_nearest_mirror_clamp(const float s[4], unsigned size, int icoord[4]) 222{ 223 uint ch; 224 for (ch = 0; ch < 4; ch++) { 225 /* s limited to [0,1] */ 226 /* i limited to [0,size-1] */ 227 const float u = fabsf(s[ch]); 228 if (u <= 0.0F) 229 icoord[ch] = 0; 230 else if (u >= 1.0F) 231 icoord[ch] = size - 1; 232 else 233 icoord[ch] = util_ifloor(u * size); 234 } 235} 236 237 238static void 239wrap_nearest_mirror_clamp_to_edge(const float s[4], unsigned size, 240 int icoord[4]) 241{ 242 uint ch; 243 /* s limited to [min,max] */ 244 /* i limited to [0, size-1] */ 245 const float min = 1.0F / (2.0F * size); 246 const float max = 1.0F - min; 247 for (ch = 0; ch < 4; ch++) { 248 const float u = fabsf(s[ch]); 249 if (u < min) 250 icoord[ch] = 0; 251 else if (u > max) 252 icoord[ch] = size - 1; 253 else 254 icoord[ch] = util_ifloor(u * size); 255 } 256} 257 258 259static void 260wrap_nearest_mirror_clamp_to_border(const float s[4], unsigned size, 261 int icoord[4]) 262{ 263 uint ch; 264 /* s limited to [min,max] */ 265 /* i limited to [0, size-1] */ 266 const float min = -1.0F / (2.0F * size); 267 const float max = 1.0F - min; 268 for (ch = 0; ch < 4; ch++) { 269 const float u = fabsf(s[ch]); 270 if (u < min) 271 icoord[ch] = -1; 272 else if (u > max) 273 icoord[ch] = size; 274 else 275 icoord[ch] = util_ifloor(u * size); 276 } 277} 278 279 280/** 281 * Used to compute texel locations for linear sampling for four texcoords. 282 * \param wrapMode PIPE_TEX_WRAP_x 283 * \param s the texcoords 284 * \param size the texture image size 285 * \param icoord0 returns first texture indexes 286 * \param icoord1 returns second texture indexes (usually icoord0 + 1) 287 * \param w returns blend factor/weight between texture indexes 288 * \param icoord returns the computed integer texture coords 289 */ 290static void 291wrap_linear_repeat(const float s[4], unsigned size, 292 int icoord0[4], int icoord1[4], float w[4]) 293{ 294 uint ch; 295 for (ch = 0; ch < 4; ch++) { 296 float u = s[ch] * size - 0.5F; 297 icoord0[ch] = repeat(util_ifloor(u), size); 298 icoord1[ch] = repeat(icoord0[ch] + 1, size); 299 w[ch] = frac(u); 300 } 301} 302 303 304static void 305wrap_linear_clamp(const float s[4], unsigned size, 306 int icoord0[4], int icoord1[4], float w[4]) 307{ 308 uint ch; 309 for (ch = 0; ch < 4; ch++) { 310 float u = CLAMP(s[ch], 0.0F, 1.0F); 311 u = u * size - 0.5f; 312 icoord0[ch] = util_ifloor(u); 313 icoord1[ch] = icoord0[ch] + 1; 314 w[ch] = frac(u); 315 } 316} 317 318 319static void 320wrap_linear_clamp_to_edge(const float s[4], unsigned size, 321 int icoord0[4], int icoord1[4], float w[4]) 322{ 323 uint ch; 324 for (ch = 0; ch < 4; ch++) { 325 float u = CLAMP(s[ch], 0.0F, 1.0F); 326 u = u * size - 0.5f; 327 icoord0[ch] = util_ifloor(u); 328 icoord1[ch] = icoord0[ch] + 1; 329 if (icoord0[ch] < 0) 330 icoord0[ch] = 0; 331 if (icoord1[ch] >= (int) size) 332 icoord1[ch] = size - 1; 333 w[ch] = frac(u); 334 } 335} 336 337 338static void 339wrap_linear_clamp_to_border(const float s[4], unsigned size, 340 int icoord0[4], int icoord1[4], float w[4]) 341{ 342 const float min = -1.0F / (2.0F * size); 343 const float max = 1.0F - min; 344 uint ch; 345 for (ch = 0; ch < 4; ch++) { 346 float u = CLAMP(s[ch], min, max); 347 u = u * size - 0.5f; 348 icoord0[ch] = util_ifloor(u); 349 icoord1[ch] = icoord0[ch] + 1; 350 w[ch] = frac(u); 351 } 352} 353 354 355static void 356wrap_linear_mirror_repeat(const float s[4], unsigned size, 357 int icoord0[4], int icoord1[4], float w[4]) 358{ 359 uint ch; 360 for (ch = 0; ch < 4; ch++) { 361 const int flr = util_ifloor(s[ch]); 362 float u = frac(s[ch]); 363 if (flr & 1) 364 u = 1.0F - u; 365 u = u * size - 0.5F; 366 icoord0[ch] = util_ifloor(u); 367 icoord1[ch] = icoord0[ch] + 1; 368 if (icoord0[ch] < 0) 369 icoord0[ch] = 0; 370 if (icoord1[ch] >= (int) size) 371 icoord1[ch] = size - 1; 372 w[ch] = frac(u); 373 } 374} 375 376 377static void 378wrap_linear_mirror_clamp(const float s[4], unsigned size, 379 int icoord0[4], int icoord1[4], float w[4]) 380{ 381 uint ch; 382 for (ch = 0; ch < 4; ch++) { 383 float u = fabsf(s[ch]); 384 if (u >= 1.0F) 385 u = (float) size; 386 else 387 u *= size; 388 u -= 0.5F; 389 icoord0[ch] = util_ifloor(u); 390 icoord1[ch] = icoord0[ch] + 1; 391 w[ch] = frac(u); 392 } 393} 394 395 396static void 397wrap_linear_mirror_clamp_to_edge(const float s[4], unsigned size, 398 int icoord0[4], int icoord1[4], float w[4]) 399{ 400 uint ch; 401 for (ch = 0; ch < 4; ch++) { 402 float u = fabsf(s[ch]); 403 if (u >= 1.0F) 404 u = (float) size; 405 else 406 u *= size; 407 u -= 0.5F; 408 icoord0[ch] = util_ifloor(u); 409 icoord1[ch] = icoord0[ch] + 1; 410 if (icoord0[ch] < 0) 411 icoord0[ch] = 0; 412 if (icoord1[ch] >= (int) size) 413 icoord1[ch] = size - 1; 414 w[ch] = frac(u); 415 } 416} 417 418 419static void 420wrap_linear_mirror_clamp_to_border(const float s[4], unsigned size, 421 int icoord0[4], int icoord1[4], float w[4]) 422{ 423 const float min = -1.0F / (2.0F * size); 424 const float max = 1.0F - min; 425 uint ch; 426 for (ch = 0; ch < 4; ch++) { 427 float u = fabsf(s[ch]); 428 if (u <= min) 429 u = min * size; 430 else if (u >= max) 431 u = max * size; 432 else 433 u *= size; 434 u -= 0.5F; 435 icoord0[ch] = util_ifloor(u); 436 icoord1[ch] = icoord0[ch] + 1; 437 w[ch] = frac(u); 438 } 439} 440 441 442/** 443 * PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords. 444 */ 445static void 446wrap_nearest_unorm_clamp(const float s[4], unsigned size, int icoord[4]) 447{ 448 uint ch; 449 for (ch = 0; ch < 4; ch++) { 450 int i = util_ifloor(s[ch]); 451 icoord[ch]= CLAMP(i, 0, (int) size-1); 452 } 453} 454 455 456/** 457 * PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords. 458 */ 459static void 460wrap_nearest_unorm_clamp_to_border(const float s[4], unsigned size, 461 int icoord[4]) 462{ 463 uint ch; 464 for (ch = 0; ch < 4; ch++) { 465 icoord[ch]= util_ifloor( CLAMP(s[ch], -0.5F, (float) size + 0.5F) ); 466 } 467} 468 469 470/** 471 * PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords. 472 */ 473static void 474wrap_nearest_unorm_clamp_to_edge(const float s[4], unsigned size, 475 int icoord[4]) 476{ 477 uint ch; 478 for (ch = 0; ch < 4; ch++) { 479 icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) ); 480 } 481} 482 483 484/** 485 * PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords. 486 */ 487static void 488wrap_linear_unorm_clamp(const float s[4], unsigned size, 489 int icoord0[4], int icoord1[4], float w[4]) 490{ 491 uint ch; 492 for (ch = 0; ch < 4; ch++) { 493 /* Not exactly what the spec says, but it matches NVIDIA output */ 494 float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f); 495 icoord0[ch] = util_ifloor(u); 496 icoord1[ch] = icoord0[ch] + 1; 497 w[ch] = frac(u); 498 } 499} 500 501 502/** 503 * PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords. 504 */ 505static void 506wrap_linear_unorm_clamp_to_border(const float s[4], unsigned size, 507 int icoord0[4], int icoord1[4], float w[4]) 508{ 509 uint ch; 510 for (ch = 0; ch < 4; ch++) { 511 float u = CLAMP(s[ch], -0.5F, (float) size + 0.5F); 512 u -= 0.5F; 513 icoord0[ch] = util_ifloor(u); 514 icoord1[ch] = icoord0[ch] + 1; 515 if (icoord1[ch] > (int) size - 1) 516 icoord1[ch] = size - 1; 517 w[ch] = frac(u); 518 } 519} 520 521 522/** 523 * PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords. 524 */ 525static void 526wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size, 527 int icoord0[4], int icoord1[4], float w[4]) 528{ 529 uint ch; 530 for (ch = 0; ch < 4; ch++) { 531 float u = CLAMP(s[ch], +0.5F, (float) size - 0.5F); 532 u -= 0.5F; 533 icoord0[ch] = util_ifloor(u); 534 icoord1[ch] = icoord0[ch] + 1; 535 if (icoord1[ch] > (int) size - 1) 536 icoord1[ch] = size - 1; 537 w[ch] = frac(u); 538 } 539} 540 541 542/** 543 * Do coordinate to array index conversion. For array textures. 544 */ 545static INLINE void 546wrap_array_layer(const float coord[4], unsigned size, int layer[4]) 547{ 548 uint ch; 549 for (ch = 0; ch < 4; ch++) { 550 int c = util_ifloor(coord[ch] + 0.5F); 551 layer[ch] = CLAMP(c, 0, size - 1); 552 } 553} 554 555 556/** 557 * Examine the quad's texture coordinates to compute the partial 558 * derivatives w.r.t X and Y, then compute lambda (level of detail). 559 */ 560static float 561compute_lambda_1d(const struct sp_sampler_variant *samp, 562 const float s[QUAD_SIZE], 563 const float t[QUAD_SIZE], 564 const float p[QUAD_SIZE]) 565{ 566 const struct pipe_resource *texture = samp->view->texture; 567 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); 568 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); 569 float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, samp->view->u.tex.first_level); 570 571 return util_fast_log2(rho); 572} 573 574 575static float 576compute_lambda_2d(const struct sp_sampler_variant *samp, 577 const float s[QUAD_SIZE], 578 const float t[QUAD_SIZE], 579 const float p[QUAD_SIZE]) 580{ 581 const struct pipe_resource *texture = samp->view->texture; 582 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); 583 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); 584 float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); 585 float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]); 586 float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, samp->view->u.tex.first_level); 587 float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, samp->view->u.tex.first_level); 588 float rho = MAX2(maxx, maxy); 589 590 return util_fast_log2(rho); 591} 592 593 594static float 595compute_lambda_3d(const struct sp_sampler_variant *samp, 596 const float s[QUAD_SIZE], 597 const float t[QUAD_SIZE], 598 const float p[QUAD_SIZE]) 599{ 600 const struct pipe_resource *texture = samp->view->texture; 601 float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); 602 float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); 603 float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); 604 float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]); 605 float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]); 606 float dpdy = fabsf(p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]); 607 float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, samp->view->u.tex.first_level); 608 float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, samp->view->u.tex.first_level); 609 float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, samp->view->u.tex.first_level); 610 float rho; 611 612 rho = MAX2(maxx, maxy); 613 rho = MAX2(rho, maxz); 614 615 return util_fast_log2(rho); 616} 617 618 619/** 620 * Compute lambda for a vertex texture sampler. 621 * Since there aren't derivatives to use, just return 0. 622 */ 623static float 624compute_lambda_vert(const struct sp_sampler_variant *samp, 625 const float s[QUAD_SIZE], 626 const float t[QUAD_SIZE], 627 const float p[QUAD_SIZE]) 628{ 629 return 0.0f; 630} 631 632 633 634/** 635 * Get a texel from a texture, using the texture tile cache. 636 * 637 * \param addr the template tex address containing cube, z, face info. 638 * \param x the x coord of texel within 2D image 639 * \param y the y coord of texel within 2D image 640 * \param rgba the quad to put the texel/color into 641 * 642 * XXX maybe move this into sp_tex_tile_cache.c and merge with the 643 * sp_get_cached_tile_tex() function. Also, get 4 texels instead of 1... 644 */ 645 646 647 648 649static INLINE const float * 650get_texel_2d_no_border(const struct sp_sampler_variant *samp, 651 union tex_tile_address addr, int x, int y) 652{ 653 const struct softpipe_tex_cached_tile *tile; 654 655 addr.bits.x = x / TILE_SIZE; 656 addr.bits.y = y / TILE_SIZE; 657 y %= TILE_SIZE; 658 x %= TILE_SIZE; 659 660 tile = sp_get_cached_tile_tex(samp->cache, addr); 661 662 return &tile->data.color[y][x][0]; 663} 664 665 666static INLINE const float * 667get_texel_2d(const struct sp_sampler_variant *samp, 668 union tex_tile_address addr, int x, int y) 669{ 670 const struct pipe_resource *texture = samp->view->texture; 671 unsigned level = addr.bits.level; 672 673 if (x < 0 || x >= (int) u_minify(texture->width0, level) || 674 y < 0 || y >= (int) u_minify(texture->height0, level)) { 675 return samp->sampler->border_color; 676 } 677 else { 678 return get_texel_2d_no_border( samp, addr, x, y ); 679 } 680} 681 682 683/* Gather a quad of adjacent texels within a tile: 684 */ 685static INLINE void 686get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_variant *samp, 687 union tex_tile_address addr, 688 unsigned x, unsigned y, 689 const float *out[4]) 690{ 691 const struct softpipe_tex_cached_tile *tile; 692 693 addr.bits.x = x / TILE_SIZE; 694 addr.bits.y = y / TILE_SIZE; 695 y %= TILE_SIZE; 696 x %= TILE_SIZE; 697 698 tile = sp_get_cached_tile_tex(samp->cache, addr); 699 700 out[0] = &tile->data.color[y ][x ][0]; 701 out[1] = &tile->data.color[y ][x+1][0]; 702 out[2] = &tile->data.color[y+1][x ][0]; 703 out[3] = &tile->data.color[y+1][x+1][0]; 704} 705 706 707/* Gather a quad of potentially non-adjacent texels: 708 */ 709static INLINE void 710get_texel_quad_2d_no_border(const struct sp_sampler_variant *samp, 711 union tex_tile_address addr, 712 int x0, int y0, 713 int x1, int y1, 714 const float *out[4]) 715{ 716 out[0] = get_texel_2d_no_border( samp, addr, x0, y0 ); 717 out[1] = get_texel_2d_no_border( samp, addr, x1, y0 ); 718 out[2] = get_texel_2d_no_border( samp, addr, x0, y1 ); 719 out[3] = get_texel_2d_no_border( samp, addr, x1, y1 ); 720} 721 722/* Can involve a lot of unnecessary checks for border color: 723 */ 724static INLINE void 725get_texel_quad_2d(const struct sp_sampler_variant *samp, 726 union tex_tile_address addr, 727 int x0, int y0, 728 int x1, int y1, 729 const float *out[4]) 730{ 731 out[0] = get_texel_2d( samp, addr, x0, y0 ); 732 out[1] = get_texel_2d( samp, addr, x1, y0 ); 733 out[3] = get_texel_2d( samp, addr, x1, y1 ); 734 out[2] = get_texel_2d( samp, addr, x0, y1 ); 735} 736 737 738 739/* 3d variants: 740 */ 741static INLINE const float * 742get_texel_3d_no_border(const struct sp_sampler_variant *samp, 743 union tex_tile_address addr, int x, int y, int z) 744{ 745 const struct softpipe_tex_cached_tile *tile; 746 747 addr.bits.x = x / TILE_SIZE; 748 addr.bits.y = y / TILE_SIZE; 749 addr.bits.z = z; 750 y %= TILE_SIZE; 751 x %= TILE_SIZE; 752 753 tile = sp_get_cached_tile_tex(samp->cache, addr); 754 755 return &tile->data.color[y][x][0]; 756} 757 758 759static INLINE const float * 760get_texel_3d(const struct sp_sampler_variant *samp, 761 union tex_tile_address addr, int x, int y, int z) 762{ 763 const struct pipe_resource *texture = samp->view->texture; 764 unsigned level = addr.bits.level; 765 766 if (x < 0 || x >= (int) u_minify(texture->width0, level) || 767 y < 0 || y >= (int) u_minify(texture->height0, level) || 768 z < 0 || z >= (int) u_minify(texture->depth0, level)) { 769 return samp->sampler->border_color; 770 } 771 else { 772 return get_texel_3d_no_border( samp, addr, x, y, z ); 773 } 774} 775 776 777/* Get texel pointer for 1D array texture */ 778static INLINE const float * 779get_texel_1d_array(const struct sp_sampler_variant *samp, 780 union tex_tile_address addr, int x, int y) 781{ 782 const struct pipe_resource *texture = samp->view->texture; 783 unsigned level = addr.bits.level; 784 785 if (x < 0 || x >= (int) u_minify(texture->width0, level)) { 786 return samp->sampler->border_color; 787 } 788 else { 789 return get_texel_2d_no_border(samp, addr, x, y); 790 } 791} 792 793 794/* Get texel pointer for 2D array texture */ 795static INLINE const float * 796get_texel_2d_array(const struct sp_sampler_variant *samp, 797 union tex_tile_address addr, int x, int y, int layer) 798{ 799 const struct pipe_resource *texture = samp->view->texture; 800 unsigned level = addr.bits.level; 801 802 assert(layer < texture->array_size); 803 804 if (x < 0 || x >= (int) u_minify(texture->width0, level) || 805 y < 0 || y >= (int) u_minify(texture->height0, level)) { 806 return samp->sampler->border_color; 807 } 808 else { 809 return get_texel_3d_no_border(samp, addr, x, y, layer); 810 } 811} 812 813 814/** 815 * Given the logbase2 of a mipmap's base level size and a mipmap level, 816 * return the size (in texels) of that mipmap level. 817 * For example, if level[0].width = 256 then base_pot will be 8. 818 * If level = 2, then we'll return 64 (the width at level=2). 819 * Return 1 if level > base_pot. 820 */ 821static INLINE unsigned 822pot_level_size(unsigned base_pot, unsigned level) 823{ 824 return (base_pot >= level) ? (1 << (base_pot - level)) : 1; 825} 826 827 828static void 829print_sample(const char *function, float rgba[NUM_CHANNELS][QUAD_SIZE]) 830{ 831 debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n", 832 function, 833 rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0], 834 rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1], 835 rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2], 836 rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]); 837} 838 839 840/* Some image-filter fastpaths: 841 */ 842static INLINE void 843img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler, 844 const float s[QUAD_SIZE], 845 const float t[QUAD_SIZE], 846 const float p[QUAD_SIZE], 847 const float c0[QUAD_SIZE], 848 enum tgsi_sampler_control control, 849 float rgba[NUM_CHANNELS][QUAD_SIZE]) 850{ 851 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 852 unsigned j; 853 unsigned level = samp->level; 854 unsigned xpot = pot_level_size(samp->xpot, level); 855 unsigned ypot = pot_level_size(samp->ypot, level); 856 unsigned xmax = (xpot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, xpot) - 1; */ 857 unsigned ymax = (ypot - 1) & (TILE_SIZE - 1); /* MIN2(TILE_SIZE, ypot) - 1; */ 858 union tex_tile_address addr; 859 860 addr.value = 0; 861 addr.bits.level = samp->level; 862 863 for (j = 0; j < QUAD_SIZE; j++) { 864 int c; 865 866 float u = s[j] * xpot - 0.5F; 867 float v = t[j] * ypot - 0.5F; 868 869 int uflr = util_ifloor(u); 870 int vflr = util_ifloor(v); 871 872 float xw = u - (float)uflr; 873 float yw = v - (float)vflr; 874 875 int x0 = uflr & (xpot - 1); 876 int y0 = vflr & (ypot - 1); 877 878 const float *tx[4]; 879 880 /* Can we fetch all four at once: 881 */ 882 if (x0 < xmax && y0 < ymax) { 883 get_texel_quad_2d_no_border_single_tile(samp, addr, x0, y0, tx); 884 } 885 else { 886 unsigned x1 = (x0 + 1) & (xpot - 1); 887 unsigned y1 = (y0 + 1) & (ypot - 1); 888 get_texel_quad_2d_no_border(samp, addr, x0, y0, x1, y1, tx); 889 } 890 891 /* interpolate R, G, B, A */ 892 for (c = 0; c < 4; c++) { 893 rgba[c][j] = lerp_2d(xw, yw, 894 tx[0][c], tx[1][c], 895 tx[2][c], tx[3][c]); 896 } 897 } 898 899 if (DEBUG_TEX) { 900 print_sample(__FUNCTION__, rgba); 901 } 902} 903 904 905static INLINE void 906img_filter_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler, 907 const float s[QUAD_SIZE], 908 const float t[QUAD_SIZE], 909 const float p[QUAD_SIZE], 910 const float c0[QUAD_SIZE], 911 enum tgsi_sampler_control control, 912 float rgba[NUM_CHANNELS][QUAD_SIZE]) 913{ 914 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 915 unsigned j; 916 unsigned level = samp->level; 917 unsigned xpot = pot_level_size(samp->xpot, level); 918 unsigned ypot = pot_level_size(samp->ypot, level); 919 union tex_tile_address addr; 920 921 addr.value = 0; 922 addr.bits.level = samp->level; 923 924 for (j = 0; j < QUAD_SIZE; j++) { 925 int c; 926 927 float u = s[j] * xpot; 928 float v = t[j] * ypot; 929 930 int uflr = util_ifloor(u); 931 int vflr = util_ifloor(v); 932 933 int x0 = uflr & (xpot - 1); 934 int y0 = vflr & (ypot - 1); 935 936 const float *out = get_texel_2d_no_border(samp, addr, x0, y0); 937 938 for (c = 0; c < 4; c++) { 939 rgba[c][j] = out[c]; 940 } 941 } 942 943 if (DEBUG_TEX) { 944 print_sample(__FUNCTION__, rgba); 945 } 946} 947 948 949static INLINE void 950img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler, 951 const float s[QUAD_SIZE], 952 const float t[QUAD_SIZE], 953 const float p[QUAD_SIZE], 954 const float c0[QUAD_SIZE], 955 enum tgsi_sampler_control control, 956 float rgba[NUM_CHANNELS][QUAD_SIZE]) 957{ 958 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 959 unsigned j; 960 unsigned level = samp->level; 961 unsigned xpot = pot_level_size(samp->xpot, level); 962 unsigned ypot = pot_level_size(samp->ypot, level); 963 union tex_tile_address addr; 964 965 addr.value = 0; 966 addr.bits.level = samp->level; 967 968 for (j = 0; j < QUAD_SIZE; j++) { 969 int c; 970 971 float u = s[j] * xpot; 972 float v = t[j] * ypot; 973 974 int x0, y0; 975 const float *out; 976 977 x0 = util_ifloor(u); 978 if (x0 < 0) 979 x0 = 0; 980 else if (x0 > xpot - 1) 981 x0 = xpot - 1; 982 983 y0 = util_ifloor(v); 984 if (y0 < 0) 985 y0 = 0; 986 else if (y0 > ypot - 1) 987 y0 = ypot - 1; 988 989 out = get_texel_2d_no_border(samp, addr, x0, y0); 990 991 for (c = 0; c < 4; c++) { 992 rgba[c][j] = out[c]; 993 } 994 } 995 996 if (DEBUG_TEX) { 997 print_sample(__FUNCTION__, rgba); 998 } 999} 1000 1001 1002static void 1003img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler, 1004 const float s[QUAD_SIZE], 1005 const float t[QUAD_SIZE], 1006 const float p[QUAD_SIZE], 1007 const float c0[QUAD_SIZE], 1008 enum tgsi_sampler_control control, 1009 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1010{ 1011 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1012 const struct pipe_resource *texture = samp->view->texture; 1013 unsigned level0, j; 1014 int width; 1015 int x[4]; 1016 union tex_tile_address addr; 1017 1018 level0 = samp->level; 1019 width = u_minify(texture->width0, level0); 1020 1021 assert(width > 0); 1022 1023 addr.value = 0; 1024 addr.bits.level = samp->level; 1025 1026 samp->nearest_texcoord_s(s, width, x); 1027 1028 for (j = 0; j < QUAD_SIZE; j++) { 1029 const float *out = get_texel_2d(samp, addr, x[j], 0); 1030 int c; 1031 for (c = 0; c < 4; c++) { 1032 rgba[c][j] = out[c]; 1033 } 1034 } 1035 1036 if (DEBUG_TEX) { 1037 print_sample(__FUNCTION__, rgba); 1038 } 1039} 1040 1041 1042static void 1043img_filter_1d_array_nearest(struct tgsi_sampler *tgsi_sampler, 1044 const float s[QUAD_SIZE], 1045 const float t[QUAD_SIZE], 1046 const float p[QUAD_SIZE], 1047 const float c0[QUAD_SIZE], 1048 enum tgsi_sampler_control control, 1049 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1050{ 1051 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1052 const struct pipe_resource *texture = samp->view->texture; 1053 unsigned level0, j; 1054 int width; 1055 int x[4], layer[4]; 1056 union tex_tile_address addr; 1057 1058 level0 = samp->level; 1059 width = u_minify(texture->width0, level0); 1060 1061 assert(width > 0); 1062 1063 addr.value = 0; 1064 addr.bits.level = samp->level; 1065 1066 samp->nearest_texcoord_s(s, width, x); 1067 wrap_array_layer(t, texture->array_size, layer); 1068 1069 for (j = 0; j < QUAD_SIZE; j++) { 1070 const float *out = get_texel_1d_array(samp, addr, x[j], layer[j]); 1071 int c; 1072 for (c = 0; c < 4; c++) { 1073 rgba[c][j] = out[c]; 1074 } 1075 } 1076 1077 if (DEBUG_TEX) { 1078 print_sample(__FUNCTION__, rgba); 1079 } 1080} 1081 1082 1083static void 1084img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, 1085 const float s[QUAD_SIZE], 1086 const float t[QUAD_SIZE], 1087 const float p[QUAD_SIZE], 1088 const float c0[QUAD_SIZE], 1089 enum tgsi_sampler_control control, 1090 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1091{ 1092 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1093 const struct pipe_resource *texture = samp->view->texture; 1094 unsigned level0, j; 1095 int width, height; 1096 int x[4], y[4]; 1097 union tex_tile_address addr; 1098 1099 1100 level0 = samp->level; 1101 width = u_minify(texture->width0, level0); 1102 height = u_minify(texture->height0, level0); 1103 1104 assert(width > 0); 1105 assert(height > 0); 1106 1107 addr.value = 0; 1108 addr.bits.level = samp->level; 1109 1110 samp->nearest_texcoord_s(s, width, x); 1111 samp->nearest_texcoord_t(t, height, y); 1112 1113 for (j = 0; j < QUAD_SIZE; j++) { 1114 const float *out = get_texel_2d(samp, addr, x[j], y[j]); 1115 int c; 1116 for (c = 0; c < 4; c++) { 1117 rgba[c][j] = out[c]; 1118 } 1119 } 1120 1121 if (DEBUG_TEX) { 1122 print_sample(__FUNCTION__, rgba); 1123 } 1124} 1125 1126 1127static void 1128img_filter_2d_array_nearest(struct tgsi_sampler *tgsi_sampler, 1129 const float s[QUAD_SIZE], 1130 const float t[QUAD_SIZE], 1131 const float p[QUAD_SIZE], 1132 const float c0[QUAD_SIZE], 1133 enum tgsi_sampler_control control, 1134 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1135{ 1136 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1137 const struct pipe_resource *texture = samp->view->texture; 1138 unsigned level0, j; 1139 int width, height; 1140 int x[4], y[4], layer[4]; 1141 union tex_tile_address addr; 1142 1143 level0 = samp->level; 1144 width = u_minify(texture->width0, level0); 1145 height = u_minify(texture->height0, level0); 1146 1147 assert(width > 0); 1148 assert(height > 0); 1149 1150 addr.value = 0; 1151 addr.bits.level = samp->level; 1152 1153 samp->nearest_texcoord_s(s, width, x); 1154 samp->nearest_texcoord_t(t, height, y); 1155 wrap_array_layer(p, texture->array_size, layer); 1156 1157 for (j = 0; j < QUAD_SIZE; j++) { 1158 const float *out = get_texel_2d_array(samp, addr, x[j], y[j], layer[j]); 1159 int c; 1160 for (c = 0; c < 4; c++) { 1161 rgba[c][j] = out[c]; 1162 } 1163 } 1164 1165 if (DEBUG_TEX) { 1166 print_sample(__FUNCTION__, rgba); 1167 } 1168} 1169 1170 1171static INLINE union tex_tile_address 1172face(union tex_tile_address addr, unsigned face ) 1173{ 1174 addr.bits.face = face; 1175 return addr; 1176} 1177 1178 1179static void 1180img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler, 1181 const float s[QUAD_SIZE], 1182 const float t[QUAD_SIZE], 1183 const float p[QUAD_SIZE], 1184 const float c0[QUAD_SIZE], 1185 enum tgsi_sampler_control control, 1186 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1187{ 1188 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1189 const struct pipe_resource *texture = samp->view->texture; 1190 const unsigned *faces = samp->faces; /* zero when not cube-mapping */ 1191 unsigned level0, j; 1192 int width, height; 1193 int x[4], y[4]; 1194 union tex_tile_address addr; 1195 1196 level0 = samp->level; 1197 width = u_minify(texture->width0, level0); 1198 height = u_minify(texture->height0, level0); 1199 1200 assert(width > 0); 1201 assert(height > 0); 1202 1203 addr.value = 0; 1204 addr.bits.level = samp->level; 1205 1206 samp->nearest_texcoord_s(s, width, x); 1207 samp->nearest_texcoord_t(t, height, y); 1208 1209 for (j = 0; j < QUAD_SIZE; j++) { 1210 const float *out = get_texel_2d(samp, face(addr, faces[j]), x[j], y[j]); 1211 int c; 1212 for (c = 0; c < 4; c++) { 1213 rgba[c][j] = out[c]; 1214 } 1215 } 1216 1217 if (DEBUG_TEX) { 1218 print_sample(__FUNCTION__, rgba); 1219 } 1220} 1221 1222 1223static void 1224img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler, 1225 const float s[QUAD_SIZE], 1226 const float t[QUAD_SIZE], 1227 const float p[QUAD_SIZE], 1228 const float c0[QUAD_SIZE], 1229 enum tgsi_sampler_control control, 1230 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1231{ 1232 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1233 const struct pipe_resource *texture = samp->view->texture; 1234 unsigned level0, j; 1235 int width, height, depth; 1236 int x[4], y[4], z[4]; 1237 union tex_tile_address addr; 1238 1239 level0 = samp->level; 1240 width = u_minify(texture->width0, level0); 1241 height = u_minify(texture->height0, level0); 1242 depth = u_minify(texture->depth0, level0); 1243 1244 assert(width > 0); 1245 assert(height > 0); 1246 assert(depth > 0); 1247 1248 samp->nearest_texcoord_s(s, width, x); 1249 samp->nearest_texcoord_t(t, height, y); 1250 samp->nearest_texcoord_p(p, depth, z); 1251 1252 addr.value = 0; 1253 addr.bits.level = samp->level; 1254 1255 for (j = 0; j < QUAD_SIZE; j++) { 1256 const float *out = get_texel_3d(samp, addr, x[j], y[j], z[j]); 1257 int c; 1258 for (c = 0; c < 4; c++) { 1259 rgba[c][j] = out[c]; 1260 } 1261 } 1262} 1263 1264 1265static void 1266img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler, 1267 const float s[QUAD_SIZE], 1268 const float t[QUAD_SIZE], 1269 const float p[QUAD_SIZE], 1270 const float c0[QUAD_SIZE], 1271 enum tgsi_sampler_control control, 1272 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1273{ 1274 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1275 const struct pipe_resource *texture = samp->view->texture; 1276 unsigned level0, j; 1277 int width; 1278 int x0[4], x1[4]; 1279 float xw[4]; /* weights */ 1280 union tex_tile_address addr; 1281 1282 level0 = samp->level; 1283 width = u_minify(texture->width0, level0); 1284 1285 assert(width > 0); 1286 1287 addr.value = 0; 1288 addr.bits.level = samp->level; 1289 1290 samp->linear_texcoord_s(s, width, x0, x1, xw); 1291 1292 for (j = 0; j < QUAD_SIZE; j++) { 1293 const float *tx0 = get_texel_2d(samp, addr, x0[j], 0); 1294 const float *tx1 = get_texel_2d(samp, addr, x1[j], 0); 1295 int c; 1296 1297 /* interpolate R, G, B, A */ 1298 for (c = 0; c < 4; c++) { 1299 rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]); 1300 } 1301 } 1302} 1303 1304 1305static void 1306img_filter_1d_array_linear(struct tgsi_sampler *tgsi_sampler, 1307 const float s[QUAD_SIZE], 1308 const float t[QUAD_SIZE], 1309 const float p[QUAD_SIZE], 1310 const float c0[QUAD_SIZE], 1311 enum tgsi_sampler_control control, 1312 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1313{ 1314 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1315 const struct pipe_resource *texture = samp->view->texture; 1316 unsigned level0, j; 1317 int width; 1318 int x0[4], x1[4], layer[4]; 1319 float xw[4]; /* weights */ 1320 union tex_tile_address addr; 1321 1322 level0 = samp->level; 1323 width = u_minify(texture->width0, level0); 1324 1325 assert(width > 0); 1326 1327 addr.value = 0; 1328 addr.bits.level = samp->level; 1329 1330 samp->linear_texcoord_s(s, width, x0, x1, xw); 1331 wrap_array_layer(t, texture->array_size, layer); 1332 1333 for (j = 0; j < QUAD_SIZE; j++) { 1334 const float *tx0 = get_texel_1d_array(samp, addr, x0[j], layer[j]); 1335 const float *tx1 = get_texel_1d_array(samp, addr, x1[j], layer[j]); 1336 int c; 1337 1338 /* interpolate R, G, B, A */ 1339 for (c = 0; c < 4; c++) { 1340 rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]); 1341 } 1342 } 1343} 1344 1345 1346static void 1347img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, 1348 const float s[QUAD_SIZE], 1349 const float t[QUAD_SIZE], 1350 const float p[QUAD_SIZE], 1351 const float c0[QUAD_SIZE], 1352 enum tgsi_sampler_control control, 1353 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1354{ 1355 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1356 const struct pipe_resource *texture = samp->view->texture; 1357 unsigned level0, j; 1358 int width, height; 1359 int x0[4], y0[4], x1[4], y1[4]; 1360 float xw[4], yw[4]; /* weights */ 1361 union tex_tile_address addr; 1362 1363 level0 = samp->level; 1364 width = u_minify(texture->width0, level0); 1365 height = u_minify(texture->height0, level0); 1366 1367 assert(width > 0); 1368 assert(height > 0); 1369 1370 addr.value = 0; 1371 addr.bits.level = samp->level; 1372 1373 samp->linear_texcoord_s(s, width, x0, x1, xw); 1374 samp->linear_texcoord_t(t, height, y0, y1, yw); 1375 1376 for (j = 0; j < QUAD_SIZE; j++) { 1377 const float *tx0 = get_texel_2d(samp, addr, x0[j], y0[j]); 1378 const float *tx1 = get_texel_2d(samp, addr, x1[j], y0[j]); 1379 const float *tx2 = get_texel_2d(samp, addr, x0[j], y1[j]); 1380 const float *tx3 = get_texel_2d(samp, addr, x1[j], y1[j]); 1381 int c; 1382 1383 /* interpolate R, G, B, A */ 1384 for (c = 0; c < 4; c++) { 1385 rgba[c][j] = lerp_2d(xw[j], yw[j], 1386 tx0[c], tx1[c], 1387 tx2[c], tx3[c]); 1388 } 1389 } 1390} 1391 1392 1393static void 1394img_filter_2d_array_linear(struct tgsi_sampler *tgsi_sampler, 1395 const float s[QUAD_SIZE], 1396 const float t[QUAD_SIZE], 1397 const float p[QUAD_SIZE], 1398 const float c0[QUAD_SIZE], 1399 enum tgsi_sampler_control control, 1400 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1401{ 1402 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1403 const struct pipe_resource *texture = samp->view->texture; 1404 unsigned level0, j; 1405 int width, height; 1406 int x0[4], y0[4], x1[4], y1[4], layer[4]; 1407 float xw[4], yw[4]; /* weights */ 1408 union tex_tile_address addr; 1409 1410 level0 = samp->level; 1411 width = u_minify(texture->width0, level0); 1412 height = u_minify(texture->height0, level0); 1413 1414 assert(width > 0); 1415 assert(height > 0); 1416 1417 addr.value = 0; 1418 addr.bits.level = samp->level; 1419 1420 samp->linear_texcoord_s(s, width, x0, x1, xw); 1421 samp->linear_texcoord_t(t, height, y0, y1, yw); 1422 wrap_array_layer(p, texture->array_size, layer); 1423 1424 for (j = 0; j < QUAD_SIZE; j++) { 1425 const float *tx0 = get_texel_2d_array(samp, addr, x0[j], y0[j], layer[j]); 1426 const float *tx1 = get_texel_2d_array(samp, addr, x1[j], y0[j], layer[j]); 1427 const float *tx2 = get_texel_2d_array(samp, addr, x0[j], y1[j], layer[j]); 1428 const float *tx3 = get_texel_2d_array(samp, addr, x1[j], y1[j], layer[j]); 1429 int c; 1430 1431 /* interpolate R, G, B, A */ 1432 for (c = 0; c < 4; c++) { 1433 rgba[c][j] = lerp_2d(xw[j], yw[j], 1434 tx0[c], tx1[c], 1435 tx2[c], tx3[c]); 1436 } 1437 } 1438} 1439 1440 1441static void 1442img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler, 1443 const float s[QUAD_SIZE], 1444 const float t[QUAD_SIZE], 1445 const float p[QUAD_SIZE], 1446 const float c0[QUAD_SIZE], 1447 enum tgsi_sampler_control control, 1448 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1449{ 1450 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1451 const struct pipe_resource *texture = samp->view->texture; 1452 const unsigned *faces = samp->faces; /* zero when not cube-mapping */ 1453 unsigned level0, j; 1454 int width, height; 1455 int x0[4], y0[4], x1[4], y1[4]; 1456 float xw[4], yw[4]; /* weights */ 1457 union tex_tile_address addr; 1458 1459 level0 = samp->level; 1460 width = u_minify(texture->width0, level0); 1461 height = u_minify(texture->height0, level0); 1462 1463 assert(width > 0); 1464 assert(height > 0); 1465 1466 addr.value = 0; 1467 addr.bits.level = samp->level; 1468 1469 samp->linear_texcoord_s(s, width, x0, x1, xw); 1470 samp->linear_texcoord_t(t, height, y0, y1, yw); 1471 1472 for (j = 0; j < QUAD_SIZE; j++) { 1473 union tex_tile_address addrj = face(addr, faces[j]); 1474 const float *tx0 = get_texel_2d(samp, addrj, x0[j], y0[j]); 1475 const float *tx1 = get_texel_2d(samp, addrj, x1[j], y0[j]); 1476 const float *tx2 = get_texel_2d(samp, addrj, x0[j], y1[j]); 1477 const float *tx3 = get_texel_2d(samp, addrj, x1[j], y1[j]); 1478 int c; 1479 1480 /* interpolate R, G, B, A */ 1481 for (c = 0; c < 4; c++) { 1482 rgba[c][j] = lerp_2d(xw[j], yw[j], 1483 tx0[c], tx1[c], 1484 tx2[c], tx3[c]); 1485 } 1486 } 1487} 1488 1489 1490static void 1491img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler, 1492 const float s[QUAD_SIZE], 1493 const float t[QUAD_SIZE], 1494 const float p[QUAD_SIZE], 1495 const float c0[QUAD_SIZE], 1496 enum tgsi_sampler_control control, 1497 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1498{ 1499 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1500 const struct pipe_resource *texture = samp->view->texture; 1501 unsigned level0, j; 1502 int width, height, depth; 1503 int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4]; 1504 float xw[4], yw[4], zw[4]; /* interpolation weights */ 1505 union tex_tile_address addr; 1506 1507 level0 = samp->level; 1508 width = u_minify(texture->width0, level0); 1509 height = u_minify(texture->height0, level0); 1510 depth = u_minify(texture->depth0, level0); 1511 1512 addr.value = 0; 1513 addr.bits.level = level0; 1514 1515 assert(width > 0); 1516 assert(height > 0); 1517 assert(depth > 0); 1518 1519 samp->linear_texcoord_s(s, width, x0, x1, xw); 1520 samp->linear_texcoord_t(t, height, y0, y1, yw); 1521 samp->linear_texcoord_p(p, depth, z0, z1, zw); 1522 1523 for (j = 0; j < QUAD_SIZE; j++) { 1524 int c; 1525 1526 const float *tx00 = get_texel_3d(samp, addr, x0[j], y0[j], z0[j]); 1527 const float *tx01 = get_texel_3d(samp, addr, x1[j], y0[j], z0[j]); 1528 const float *tx02 = get_texel_3d(samp, addr, x0[j], y1[j], z0[j]); 1529 const float *tx03 = get_texel_3d(samp, addr, x1[j], y1[j], z0[j]); 1530 1531 const float *tx10 = get_texel_3d(samp, addr, x0[j], y0[j], z1[j]); 1532 const float *tx11 = get_texel_3d(samp, addr, x1[j], y0[j], z1[j]); 1533 const float *tx12 = get_texel_3d(samp, addr, x0[j], y1[j], z1[j]); 1534 const float *tx13 = get_texel_3d(samp, addr, x1[j], y1[j], z1[j]); 1535 1536 /* interpolate R, G, B, A */ 1537 for (c = 0; c < 4; c++) { 1538 rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1539 tx00[c], tx01[c], 1540 tx02[c], tx03[c], 1541 tx10[c], tx11[c], 1542 tx12[c], tx13[c]); 1543 } 1544 } 1545} 1546 1547 1548/* Calculate level of detail for every fragment. 1549 * Note that lambda has already been biased by global LOD bias. 1550 */ 1551static INLINE void 1552compute_lod(const struct pipe_sampler_state *sampler, 1553 const float biased_lambda, 1554 const float lodbias[QUAD_SIZE], 1555 float lod[QUAD_SIZE]) 1556{ 1557 uint i; 1558 1559 for (i = 0; i < QUAD_SIZE; i++) { 1560 lod[i] = biased_lambda + lodbias[i]; 1561 lod[i] = CLAMP(lod[i], sampler->min_lod, sampler->max_lod); 1562 } 1563} 1564 1565 1566static void 1567mip_filter_linear(struct tgsi_sampler *tgsi_sampler, 1568 const float s[QUAD_SIZE], 1569 const float t[QUAD_SIZE], 1570 const float p[QUAD_SIZE], 1571 const float c0[QUAD_SIZE], 1572 enum tgsi_sampler_control control, 1573 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1574{ 1575 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1576 const struct pipe_resource *texture = samp->view->texture; 1577 int level0; 1578 float lambda; 1579 float lod[QUAD_SIZE]; 1580 1581 if (control == tgsi_sampler_lod_bias) { 1582 lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; 1583 compute_lod(samp->sampler, lambda, c0, lod); 1584 } else { 1585 assert(control == tgsi_sampler_lod_explicit); 1586 1587 memcpy(lod, c0, sizeof(lod)); 1588 } 1589 1590 /* XXX: Take into account all lod values. 1591 */ 1592 lambda = lod[0]; 1593 level0 = samp->view->u.tex.first_level + (int)lambda; 1594 1595 if (lambda < 0.0) { 1596 samp->level = samp->view->u.tex.first_level; 1597 samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 1598 } 1599 else if (level0 >= texture->last_level) { 1600 samp->level = texture->last_level; 1601 samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 1602 } 1603 else { 1604 float levelBlend = frac(lambda); 1605 float rgba0[4][4]; 1606 float rgba1[4][4]; 1607 int c,j; 1608 1609 samp->level = level0; 1610 samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba0); 1611 1612 samp->level = level0+1; 1613 samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba1); 1614 1615 for (j = 0; j < QUAD_SIZE; j++) { 1616 for (c = 0; c < 4; c++) { 1617 rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]); 1618 } 1619 } 1620 } 1621 1622 if (DEBUG_TEX) { 1623 print_sample(__FUNCTION__, rgba); 1624 } 1625} 1626 1627 1628/** 1629 * Compute nearest mipmap level from texcoords. 1630 * Then sample the texture level for four elements of a quad. 1631 * \param c0 the LOD bias factors, or absolute LODs (depending on control) 1632 */ 1633static void 1634mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, 1635 const float s[QUAD_SIZE], 1636 const float t[QUAD_SIZE], 1637 const float p[QUAD_SIZE], 1638 const float c0[QUAD_SIZE], 1639 enum tgsi_sampler_control control, 1640 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1641{ 1642 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1643 const struct pipe_resource *texture = samp->view->texture; 1644 float lambda; 1645 float lod[QUAD_SIZE]; 1646 1647 if (control == tgsi_sampler_lod_bias) { 1648 lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; 1649 compute_lod(samp->sampler, lambda, c0, lod); 1650 } else { 1651 assert(control == tgsi_sampler_lod_explicit); 1652 1653 memcpy(lod, c0, sizeof(lod)); 1654 } 1655 1656 /* XXX: Take into account all lod values. 1657 */ 1658 lambda = lod[0]; 1659 1660 if (lambda < 0.0) { 1661 samp->level = samp->view->u.tex.first_level; 1662 samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 1663 } 1664 else { 1665 samp->level = samp->view->u.tex.first_level + (int)(lambda + 0.5) ; 1666 samp->level = MIN2(samp->level, (int)texture->last_level); 1667 samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 1668 } 1669 1670 if (DEBUG_TEX) { 1671 print_sample(__FUNCTION__, rgba); 1672 } 1673} 1674 1675 1676static void 1677mip_filter_none(struct tgsi_sampler *tgsi_sampler, 1678 const float s[QUAD_SIZE], 1679 const float t[QUAD_SIZE], 1680 const float p[QUAD_SIZE], 1681 const float c0[QUAD_SIZE], 1682 enum tgsi_sampler_control control, 1683 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1684{ 1685 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1686 float lambda; 1687 float lod[QUAD_SIZE]; 1688 1689 if (control == tgsi_sampler_lod_bias) { 1690 lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; 1691 compute_lod(samp->sampler, lambda, c0, lod); 1692 } else { 1693 assert(control == tgsi_sampler_lod_explicit); 1694 1695 memcpy(lod, c0, sizeof(lod)); 1696 } 1697 1698 /* XXX: Take into account all lod values. 1699 */ 1700 lambda = lod[0]; 1701 1702 samp->level = samp->view->u.tex.first_level; 1703 if (lambda < 0.0) { 1704 samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 1705 } 1706 else { 1707 samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 1708 } 1709} 1710 1711 1712/* For anisotropic filtering */ 1713#define WEIGHT_LUT_SIZE 1024 1714 1715static float *weightLut = NULL; 1716 1717/** 1718 * Creates the look-up table used to speed-up EWA sampling 1719 */ 1720static void 1721create_filter_table(void) 1722{ 1723 unsigned i; 1724 if (!weightLut) { 1725 weightLut = (float *) malloc(WEIGHT_LUT_SIZE * sizeof(float)); 1726 1727 for (i = 0; i < WEIGHT_LUT_SIZE; ++i) { 1728 float alpha = 2; 1729 float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1); 1730 float weight = (float) exp(-alpha * r2); 1731 weightLut[i] = weight; 1732 } 1733 } 1734} 1735 1736 1737/** 1738 * Elliptical weighted average (EWA) filter for producing high quality 1739 * anisotropic filtered results. 1740 * Based on the Higher Quality Elliptical Weighted Avarage Filter 1741 * published by Paul S. Heckbert in his Master's Thesis 1742 * "Fundamentals of Texture Mapping and Image Warping" (1989) 1743 */ 1744static void 1745img_filter_2d_ewa(struct tgsi_sampler *tgsi_sampler, 1746 const float s[QUAD_SIZE], 1747 const float t[QUAD_SIZE], 1748 const float p[QUAD_SIZE], 1749 const float c0[QUAD_SIZE], 1750 enum tgsi_sampler_control control, 1751 const float dudx, const float dvdx, 1752 const float dudy, const float dvdy, 1753 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1754{ 1755 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1756 const struct pipe_resource *texture = samp->view->texture; 1757 1758 unsigned level0 = samp->level > 0 ? samp->level : 0; 1759 float scaling = 1.0 / (1 << level0); 1760 int width = u_minify(texture->width0, level0); 1761 int height = u_minify(texture->height0, level0); 1762 1763 float ux = dudx * scaling; 1764 float vx = dvdx * scaling; 1765 float uy = dudy * scaling; 1766 float vy = dvdy * scaling; 1767 1768 /* compute ellipse coefficients to bound the region: 1769 * A*x*x + B*x*y + C*y*y = F. 1770 */ 1771 float A = vx*vx+vy*vy+1; 1772 float B = -2*(ux*vx+uy*vy); 1773 float C = ux*ux+uy*uy+1; 1774 float F = A*C-B*B/4.0; 1775 1776 /* check if it is an ellipse */ 1777 /* ASSERT(F > 0.0); */ 1778 1779 /* Compute the ellipse's (u,v) bounding box in texture space */ 1780 float d = -B*B+4.0*C*A; 1781 float box_u = 2.0 / d * sqrt(d*C*F); /* box_u -> half of bbox with */ 1782 float box_v = 2.0 / d * sqrt(A*d*F); /* box_v -> half of bbox height */ 1783 1784 float rgba_temp[NUM_CHANNELS][QUAD_SIZE]; 1785 float s_buffer[QUAD_SIZE]; 1786 float t_buffer[QUAD_SIZE]; 1787 float weight_buffer[QUAD_SIZE]; 1788 unsigned buffer_next; 1789 int j; 1790 float den;// = 0.0F; 1791 float ddq; 1792 float U;// = u0 - tex_u; 1793 int v; 1794 1795 /* Scale ellipse formula to directly index the Filter Lookup Table. 1796 * i.e. scale so that F = WEIGHT_LUT_SIZE-1 1797 */ 1798 double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F; 1799 A *= formScale; 1800 B *= formScale; 1801 C *= formScale; 1802 /* F *= formScale; */ /* no need to scale F as we don't use it below here */ 1803 1804 /* For each quad, the du and dx values are the same and so the ellipse is 1805 * also the same. Note that texel/image access can only be performed using 1806 * a quad, i.e. it is not possible to get the pixel value for a single 1807 * tex coord. In order to have a better performance, the access is buffered 1808 * using the s_buffer/t_buffer and weight_buffer. Only when the buffer is full, 1809 * then the pixel values are read from the image. 1810 */ 1811 ddq = 2 * A; 1812 1813 for (j = 0; j < QUAD_SIZE; j++) { 1814 /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse 1815 * and incrementally update the value of Ax^2+Bxy*Cy^2; when this 1816 * value, q, is less than F, we're inside the ellipse 1817 */ 1818 float tex_u=-0.5 + s[j] * texture->width0 * scaling; 1819 float tex_v=-0.5 + t[j] * texture->height0 * scaling; 1820 1821 int u0 = floor(tex_u - box_u); 1822 int u1 = ceil (tex_u + box_u); 1823 int v0 = floor(tex_v - box_v); 1824 int v1 = ceil (tex_v + box_v); 1825 1826 float num[4] = {0.0F, 0.0F, 0.0F, 0.0F}; 1827 buffer_next = 0; 1828 den = 0; 1829 U = u0 - tex_u; 1830 for (v = v0; v <= v1; ++v) { 1831 float V = v - tex_v; 1832 float dq = A * (2 * U + 1) + B * V; 1833 float q = (C * V + B * U) * V + A * U * U; 1834 1835 int u; 1836 for (u = u0; u <= u1; ++u) { 1837 /* Note that the ellipse has been pre-scaled so F = WEIGHT_LUT_SIZE - 1 */ 1838 if (q < WEIGHT_LUT_SIZE) { 1839 /* as a LUT is used, q must never be negative; 1840 * should not happen, though 1841 */ 1842 const int qClamped = q >= 0.0F ? q : 0; 1843 float weight = weightLut[qClamped]; 1844 1845 weight_buffer[buffer_next] = weight; 1846 s_buffer[buffer_next] = u / ((float) width); 1847 t_buffer[buffer_next] = v / ((float) height); 1848 1849 buffer_next++; 1850 if (buffer_next == QUAD_SIZE) { 1851 /* 4 texel coords are in the buffer -> read it now */ 1852 int jj; 1853 /* it is assumed that samp->min_img_filter is set to 1854 * img_filter_2d_nearest or one of the 1855 * accelerated img_filter_2d_nearest_XXX functions. 1856 */ 1857 samp->min_img_filter(tgsi_sampler, s_buffer, t_buffer, p, NULL, 1858 tgsi_sampler_lod_bias, rgba_temp); 1859 for (jj = 0; jj < buffer_next; jj++) { 1860 num[0] += weight_buffer[jj] * rgba_temp[0][jj]; 1861 num[1] += weight_buffer[jj] * rgba_temp[1][jj]; 1862 num[2] += weight_buffer[jj] * rgba_temp[2][jj]; 1863 num[3] += weight_buffer[jj] * rgba_temp[3][jj]; 1864 } 1865 1866 buffer_next = 0; 1867 } 1868 1869 den += weight; 1870 } 1871 q += dq; 1872 dq += ddq; 1873 } 1874 } 1875 1876 /* if the tex coord buffer contains unread values, we will read them now. 1877 * Note that in most cases we have to read more pixel values than required, 1878 * however, as the img_filter_2d_nearest function(s) does not have a count 1879 * parameter, we need to read the whole quad and ignore the unused values 1880 */ 1881 if (buffer_next > 0) { 1882 int jj; 1883 /* it is assumed that samp->min_img_filter is set to 1884 * img_filter_2d_nearest or one of the 1885 * accelerated img_filter_2d_nearest_XXX functions. 1886 */ 1887 samp->min_img_filter(tgsi_sampler, s_buffer, t_buffer, p, NULL, 1888 tgsi_sampler_lod_bias, rgba_temp); 1889 for (jj = 0; jj < buffer_next; jj++) { 1890 num[0] += weight_buffer[jj] * rgba_temp[0][jj]; 1891 num[1] += weight_buffer[jj] * rgba_temp[1][jj]; 1892 num[2] += weight_buffer[jj] * rgba_temp[2][jj]; 1893 num[3] += weight_buffer[jj] * rgba_temp[3][jj]; 1894 } 1895 } 1896 1897 if (den <= 0.0F) { 1898 /* Reaching this place would mean 1899 * that no pixels intersected the ellipse. 1900 * This should never happen because 1901 * the filter we use always 1902 * intersects at least one pixel. 1903 */ 1904 1905 /*rgba[0]=0; 1906 rgba[1]=0; 1907 rgba[2]=0; 1908 rgba[3]=0;*/ 1909 /* not enough pixels in resampling, resort to direct interpolation */ 1910 samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba_temp); 1911 den = 1; 1912 num[0] = rgba_temp[0][j]; 1913 num[1] = rgba_temp[1][j]; 1914 num[2] = rgba_temp[2][j]; 1915 num[3] = rgba_temp[3][j]; 1916 } 1917 1918 rgba[0][j] = num[0] / den; 1919 rgba[1][j] = num[1] / den; 1920 rgba[2][j] = num[2] / den; 1921 rgba[3][j] = num[3] / den; 1922 } 1923} 1924 1925 1926/** 1927 * Sample 2D texture using an anisotropic filter. 1928 */ 1929static void 1930mip_filter_linear_aniso(struct tgsi_sampler *tgsi_sampler, 1931 const float s[QUAD_SIZE], 1932 const float t[QUAD_SIZE], 1933 const float p[QUAD_SIZE], 1934 const float c0[QUAD_SIZE], 1935 enum tgsi_sampler_control control, 1936 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1937{ 1938 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 1939 const struct pipe_resource *texture = samp->view->texture; 1940 int level0; 1941 float lambda; 1942 float lod[QUAD_SIZE]; 1943 1944 float s_to_u = u_minify(texture->width0, samp->view->u.tex.first_level); 1945 float t_to_v = u_minify(texture->height0, samp->view->u.tex.first_level); 1946 float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u; 1947 float dudy = (s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]) * s_to_u; 1948 float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v; 1949 float dvdy = (t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]) * t_to_v; 1950 1951 if (control == tgsi_sampler_lod_bias) { 1952 /* note: instead of working with Px and Py, we will use the 1953 * squared length instead, to avoid sqrt. 1954 */ 1955 float Px2 = dudx * dudx + dvdx * dvdx; 1956 float Py2 = dudy * dudy + dvdy * dvdy; 1957 1958 float Pmax2; 1959 float Pmin2; 1960 float e; 1961 const float maxEccentricity = samp->sampler->max_anisotropy * samp->sampler->max_anisotropy; 1962 1963 if (Px2 < Py2) { 1964 Pmax2 = Py2; 1965 Pmin2 = Px2; 1966 } 1967 else { 1968 Pmax2 = Px2; 1969 Pmin2 = Py2; 1970 } 1971 1972 /* if the eccentricity of the ellipse is too big, scale up the shorter 1973 * of the two vectors to limit the maximum amount of work per pixel 1974 */ 1975 e = Pmax2 / Pmin2; 1976 if (e > maxEccentricity) { 1977 /* float s=e / maxEccentricity; 1978 minor[0] *= s; 1979 minor[1] *= s; 1980 Pmin2 *= s; */ 1981 Pmin2 = Pmax2 / maxEccentricity; 1982 } 1983 1984 /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid 1985 * this since 0.5*log(x) = log(sqrt(x)) 1986 */ 1987 lambda = 0.5 * util_fast_log2(Pmin2) + samp->sampler->lod_bias; 1988 compute_lod(samp->sampler, lambda, c0, lod); 1989 } 1990 else { 1991 assert(control == tgsi_sampler_lod_explicit); 1992 1993 memcpy(lod, c0, sizeof(lod)); 1994 } 1995 1996 /* XXX: Take into account all lod values. 1997 */ 1998 lambda = lod[0]; 1999 level0 = samp->view->u.tex.first_level + (int)lambda; 2000 2001 /* If the ellipse covers the whole image, we can 2002 * simply return the average of the whole image. 2003 */ 2004 if (level0 >= texture->last_level) { 2005 samp->level = texture->last_level; 2006 samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 2007 } 2008 else { 2009 /* don't bother interpolating between multiple LODs; it doesn't 2010 * seem to be worth the extra running time. 2011 */ 2012 samp->level = level0; 2013 img_filter_2d_ewa(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, 2014 dudx, dvdx, dudy, dvdy, rgba); 2015 } 2016 2017 if (DEBUG_TEX) { 2018 print_sample(__FUNCTION__, rgba); 2019 } 2020} 2021 2022 2023 2024/** 2025 * Specialized version of mip_filter_linear with hard-wired calls to 2026 * 2d lambda calculation and 2d_linear_repeat_POT img filters. 2027 */ 2028static void 2029mip_filter_linear_2d_linear_repeat_POT( 2030 struct tgsi_sampler *tgsi_sampler, 2031 const float s[QUAD_SIZE], 2032 const float t[QUAD_SIZE], 2033 const float p[QUAD_SIZE], 2034 const float c0[QUAD_SIZE], 2035 enum tgsi_sampler_control control, 2036 float rgba[NUM_CHANNELS][QUAD_SIZE]) 2037{ 2038 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2039 const struct pipe_resource *texture = samp->view->texture; 2040 int level0; 2041 float lambda; 2042 float lod[QUAD_SIZE]; 2043 2044 if (control == tgsi_sampler_lod_bias) { 2045 lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; 2046 compute_lod(samp->sampler, lambda, c0, lod); 2047 } else { 2048 assert(control == tgsi_sampler_lod_explicit); 2049 2050 memcpy(lod, c0, sizeof(lod)); 2051 } 2052 2053 /* XXX: Take into account all lod values. 2054 */ 2055 lambda = lod[0]; 2056 level0 = samp->view->u.tex.first_level + (int)lambda; 2057 2058 /* Catches both negative and large values of level0: 2059 */ 2060 if ((unsigned)level0 >= texture->last_level) { 2061 if (level0 < 0) 2062 samp->level = samp->view->u.tex.first_level; 2063 else 2064 samp->level = texture->last_level; 2065 2066 img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); 2067 } 2068 else { 2069 float levelBlend = frac(lambda); 2070 float rgba0[4][4]; 2071 float rgba1[4][4]; 2072 int c,j; 2073 2074 samp->level = level0; 2075 img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba0); 2076 2077 samp->level = level0+1; 2078 img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba1); 2079 2080 for (j = 0; j < QUAD_SIZE; j++) { 2081 for (c = 0; c < 4; c++) { 2082 rgba[c][j] = lerp(levelBlend, rgba0[c][j], rgba1[c][j]); 2083 } 2084 } 2085 } 2086 2087 if (DEBUG_TEX) { 2088 print_sample(__FUNCTION__, rgba); 2089 } 2090} 2091 2092 2093 2094/** 2095 * Do shadow/depth comparisons. 2096 */ 2097static void 2098sample_compare(struct tgsi_sampler *tgsi_sampler, 2099 const float s[QUAD_SIZE], 2100 const float t[QUAD_SIZE], 2101 const float p[QUAD_SIZE], 2102 const float c0[QUAD_SIZE], 2103 enum tgsi_sampler_control control, 2104 float rgba[NUM_CHANNELS][QUAD_SIZE]) 2105{ 2106 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2107 const struct pipe_sampler_state *sampler = samp->sampler; 2108 int j, k0, k1, k2, k3; 2109 float val; 2110 float pc0, pc1, pc2, pc3; 2111 2112 samp->mip_filter(tgsi_sampler, s, t, p, c0, control, rgba); 2113 2114 /** 2115 * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' 2116 * When we sampled the depth texture, the depth value was put into all 2117 * RGBA channels. We look at the red channel here. 2118 */ 2119 2120 pc0 = CLAMP(p[0], 0.0F, 1.0F); 2121 pc1 = CLAMP(p[1], 0.0F, 1.0F); 2122 pc2 = CLAMP(p[2], 0.0F, 1.0F); 2123 pc3 = CLAMP(p[3], 0.0F, 1.0F); 2124 2125 /* compare four texcoords vs. four texture samples */ 2126 switch (sampler->compare_func) { 2127 case PIPE_FUNC_LESS: 2128 k0 = pc0 < rgba[0][0]; 2129 k1 = pc1 < rgba[0][1]; 2130 k2 = pc2 < rgba[0][2]; 2131 k3 = pc3 < rgba[0][3]; 2132 break; 2133 case PIPE_FUNC_LEQUAL: 2134 k0 = pc0 <= rgba[0][0]; 2135 k1 = pc1 <= rgba[0][1]; 2136 k2 = pc2 <= rgba[0][2]; 2137 k3 = pc3 <= rgba[0][3]; 2138 break; 2139 case PIPE_FUNC_GREATER: 2140 k0 = pc0 > rgba[0][0]; 2141 k1 = pc1 > rgba[0][1]; 2142 k2 = pc2 > rgba[0][2]; 2143 k3 = pc3 > rgba[0][3]; 2144 break; 2145 case PIPE_FUNC_GEQUAL: 2146 k0 = pc0 >= rgba[0][0]; 2147 k1 = pc1 >= rgba[0][1]; 2148 k2 = pc2 >= rgba[0][2]; 2149 k3 = pc3 >= rgba[0][3]; 2150 break; 2151 case PIPE_FUNC_EQUAL: 2152 k0 = pc0 == rgba[0][0]; 2153 k1 = pc1 == rgba[0][1]; 2154 k2 = pc2 == rgba[0][2]; 2155 k3 = pc3 == rgba[0][3]; 2156 break; 2157 case PIPE_FUNC_NOTEQUAL: 2158 k0 = pc0 != rgba[0][0]; 2159 k1 = pc1 != rgba[0][1]; 2160 k2 = pc2 != rgba[0][2]; 2161 k3 = pc3 != rgba[0][3]; 2162 break; 2163 case PIPE_FUNC_ALWAYS: 2164 k0 = k1 = k2 = k3 = 1; 2165 break; 2166 case PIPE_FUNC_NEVER: 2167 k0 = k1 = k2 = k3 = 0; 2168 break; 2169 default: 2170 k0 = k1 = k2 = k3 = 0; 2171 assert(0); 2172 break; 2173 } 2174 2175 /* convert four pass/fail values to an intensity in [0,1] */ 2176 val = 0.25F * (k0 + k1 + k2 + k3); 2177 2178 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 2179 for (j = 0; j < 4; j++) { 2180 rgba[0][j] = rgba[1][j] = rgba[2][j] = val; 2181 rgba[3][j] = 1.0F; 2182 } 2183} 2184 2185 2186/** 2187 * Use 3D texcoords to choose a cube face, then sample the 2D cube faces. 2188 * Put face info into the sampler faces[] array. 2189 */ 2190static void 2191sample_cube(struct tgsi_sampler *tgsi_sampler, 2192 const float s[QUAD_SIZE], 2193 const float t[QUAD_SIZE], 2194 const float p[QUAD_SIZE], 2195 const float c0[QUAD_SIZE], 2196 enum tgsi_sampler_control control, 2197 float rgba[NUM_CHANNELS][QUAD_SIZE]) 2198{ 2199 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2200 unsigned j; 2201 float ssss[4], tttt[4]; 2202 2203 /* 2204 major axis 2205 direction target sc tc ma 2206 ---------- ------------------------------- --- --- --- 2207 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx 2208 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx 2209 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry 2210 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry 2211 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz 2212 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz 2213 */ 2214 2215 /* Choose the cube face and compute new s/t coords for the 2D face. 2216 * 2217 * Use the same cube face for all four pixels in the quad. 2218 * 2219 * This isn't ideal, but if we want to use a different cube face 2220 * per pixel in the quad, we'd have to also compute the per-face 2221 * LOD here too. That's because the four post-face-selection 2222 * texcoords are no longer related to each other (they're 2223 * per-face!) so we can't use subtraction to compute the partial 2224 * deriviates to compute the LOD. Doing so (near cube edges 2225 * anyway) gives us pretty much random values. 2226 */ 2227 { 2228 /* use the average of the four pixel's texcoords to choose the face */ 2229 const float rx = 0.25 * (s[0] + s[1] + s[2] + s[3]); 2230 const float ry = 0.25 * (t[0] + t[1] + t[2] + t[3]); 2231 const float rz = 0.25 * (p[0] + p[1] + p[2] + p[3]); 2232 const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); 2233 2234 if (arx >= ary && arx >= arz) { 2235 float sign = (rx >= 0.0F) ? 1.0F : -1.0F; 2236 uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X; 2237 for (j = 0; j < QUAD_SIZE; j++) { 2238 const float ima = -0.5F / fabsf(s[j]); 2239 ssss[j] = sign * p[j] * ima + 0.5F; 2240 tttt[j] = t[j] * ima + 0.5F; 2241 samp->faces[j] = face; 2242 } 2243 } 2244 else if (ary >= arx && ary >= arz) { 2245 float sign = (ry >= 0.0F) ? 1.0F : -1.0F; 2246 uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y; 2247 for (j = 0; j < QUAD_SIZE; j++) { 2248 const float ima = -0.5F / fabsf(t[j]); 2249 ssss[j] = -s[j] * ima + 0.5F; 2250 tttt[j] = sign * -p[j] * ima + 0.5F; 2251 samp->faces[j] = face; 2252 } 2253 } 2254 else { 2255 float sign = (rz >= 0.0F) ? 1.0F : -1.0F; 2256 uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z; 2257 for (j = 0; j < QUAD_SIZE; j++) { 2258 const float ima = -0.5 / fabsf(p[j]); 2259 ssss[j] = sign * -s[j] * ima + 0.5F; 2260 tttt[j] = t[j] * ima + 0.5F; 2261 samp->faces[j] = face; 2262 } 2263 } 2264 } 2265 2266 /* In our little pipeline, the compare stage is next. If compare 2267 * is not active, this will point somewhere deeper into the 2268 * pipeline, eg. to mip_filter or even img_filter. 2269 */ 2270 samp->compare(tgsi_sampler, ssss, tttt, NULL, c0, control, rgba); 2271} 2272 2273 2274static void 2275sample_swizzle(struct tgsi_sampler *tgsi_sampler, 2276 const float s[QUAD_SIZE], 2277 const float t[QUAD_SIZE], 2278 const float p[QUAD_SIZE], 2279 const float c0[QUAD_SIZE], 2280 enum tgsi_sampler_control control, 2281 float rgba[NUM_CHANNELS][QUAD_SIZE]) 2282{ 2283 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2284 float rgba_temp[NUM_CHANNELS][QUAD_SIZE]; 2285 const unsigned swizzle_r = samp->key.bits.swizzle_r; 2286 const unsigned swizzle_g = samp->key.bits.swizzle_g; 2287 const unsigned swizzle_b = samp->key.bits.swizzle_b; 2288 const unsigned swizzle_a = samp->key.bits.swizzle_a; 2289 unsigned j; 2290 2291 samp->sample_target(tgsi_sampler, s, t, p, c0, control, rgba_temp); 2292 2293 switch (swizzle_r) { 2294 case PIPE_SWIZZLE_ZERO: 2295 for (j = 0; j < 4; j++) 2296 rgba[0][j] = 0.0f; 2297 break; 2298 case PIPE_SWIZZLE_ONE: 2299 for (j = 0; j < 4; j++) 2300 rgba[0][j] = 1.0f; 2301 break; 2302 default: 2303 assert(swizzle_r < 4); 2304 for (j = 0; j < 4; j++) 2305 rgba[0][j] = rgba_temp[swizzle_r][j]; 2306 } 2307 2308 switch (swizzle_g) { 2309 case PIPE_SWIZZLE_ZERO: 2310 for (j = 0; j < 4; j++) 2311 rgba[1][j] = 0.0f; 2312 break; 2313 case PIPE_SWIZZLE_ONE: 2314 for (j = 0; j < 4; j++) 2315 rgba[1][j] = 1.0f; 2316 break; 2317 default: 2318 assert(swizzle_g < 4); 2319 for (j = 0; j < 4; j++) 2320 rgba[1][j] = rgba_temp[swizzle_g][j]; 2321 } 2322 2323 switch (swizzle_b) { 2324 case PIPE_SWIZZLE_ZERO: 2325 for (j = 0; j < 4; j++) 2326 rgba[2][j] = 0.0f; 2327 break; 2328 case PIPE_SWIZZLE_ONE: 2329 for (j = 0; j < 4; j++) 2330 rgba[2][j] = 1.0f; 2331 break; 2332 default: 2333 assert(swizzle_b < 4); 2334 for (j = 0; j < 4; j++) 2335 rgba[2][j] = rgba_temp[swizzle_b][j]; 2336 } 2337 2338 switch (swizzle_a) { 2339 case PIPE_SWIZZLE_ZERO: 2340 for (j = 0; j < 4; j++) 2341 rgba[3][j] = 0.0f; 2342 break; 2343 case PIPE_SWIZZLE_ONE: 2344 for (j = 0; j < 4; j++) 2345 rgba[3][j] = 1.0f; 2346 break; 2347 default: 2348 assert(swizzle_a < 4); 2349 for (j = 0; j < 4; j++) 2350 rgba[3][j] = rgba_temp[swizzle_a][j]; 2351 } 2352} 2353 2354 2355static wrap_nearest_func 2356get_nearest_unorm_wrap(unsigned mode) 2357{ 2358 switch (mode) { 2359 case PIPE_TEX_WRAP_CLAMP: 2360 return wrap_nearest_unorm_clamp; 2361 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2362 return wrap_nearest_unorm_clamp_to_edge; 2363 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2364 return wrap_nearest_unorm_clamp_to_border; 2365 default: 2366 assert(0); 2367 return wrap_nearest_unorm_clamp; 2368 } 2369} 2370 2371 2372static wrap_nearest_func 2373get_nearest_wrap(unsigned mode) 2374{ 2375 switch (mode) { 2376 case PIPE_TEX_WRAP_REPEAT: 2377 return wrap_nearest_repeat; 2378 case PIPE_TEX_WRAP_CLAMP: 2379 return wrap_nearest_clamp; 2380 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2381 return wrap_nearest_clamp_to_edge; 2382 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2383 return wrap_nearest_clamp_to_border; 2384 case PIPE_TEX_WRAP_MIRROR_REPEAT: 2385 return wrap_nearest_mirror_repeat; 2386 case PIPE_TEX_WRAP_MIRROR_CLAMP: 2387 return wrap_nearest_mirror_clamp; 2388 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 2389 return wrap_nearest_mirror_clamp_to_edge; 2390 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 2391 return wrap_nearest_mirror_clamp_to_border; 2392 default: 2393 assert(0); 2394 return wrap_nearest_repeat; 2395 } 2396} 2397 2398 2399static wrap_linear_func 2400get_linear_unorm_wrap(unsigned mode) 2401{ 2402 switch (mode) { 2403 case PIPE_TEX_WRAP_CLAMP: 2404 return wrap_linear_unorm_clamp; 2405 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2406 return wrap_linear_unorm_clamp_to_edge; 2407 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2408 return wrap_linear_unorm_clamp_to_border; 2409 default: 2410 assert(0); 2411 return wrap_linear_unorm_clamp; 2412 } 2413} 2414 2415 2416static wrap_linear_func 2417get_linear_wrap(unsigned mode) 2418{ 2419 switch (mode) { 2420 case PIPE_TEX_WRAP_REPEAT: 2421 return wrap_linear_repeat; 2422 case PIPE_TEX_WRAP_CLAMP: 2423 return wrap_linear_clamp; 2424 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2425 return wrap_linear_clamp_to_edge; 2426 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2427 return wrap_linear_clamp_to_border; 2428 case PIPE_TEX_WRAP_MIRROR_REPEAT: 2429 return wrap_linear_mirror_repeat; 2430 case PIPE_TEX_WRAP_MIRROR_CLAMP: 2431 return wrap_linear_mirror_clamp; 2432 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 2433 return wrap_linear_mirror_clamp_to_edge; 2434 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 2435 return wrap_linear_mirror_clamp_to_border; 2436 default: 2437 assert(0); 2438 return wrap_linear_repeat; 2439 } 2440} 2441 2442 2443static compute_lambda_func 2444get_lambda_func(const union sp_sampler_key key) 2445{ 2446 if (key.bits.processor == TGSI_PROCESSOR_VERTEX) 2447 return compute_lambda_vert; 2448 2449 switch (key.bits.target) { 2450 case PIPE_TEXTURE_1D: 2451 case PIPE_TEXTURE_1D_ARRAY: 2452 return compute_lambda_1d; 2453 case PIPE_TEXTURE_2D: 2454 case PIPE_TEXTURE_2D_ARRAY: 2455 case PIPE_TEXTURE_RECT: 2456 case PIPE_TEXTURE_CUBE: 2457 return compute_lambda_2d; 2458 case PIPE_TEXTURE_3D: 2459 return compute_lambda_3d; 2460 default: 2461 assert(0); 2462 return compute_lambda_1d; 2463 } 2464} 2465 2466 2467static filter_func 2468get_img_filter(const union sp_sampler_key key, 2469 unsigned filter, 2470 const struct pipe_sampler_state *sampler) 2471{ 2472 switch (key.bits.target) { 2473 case PIPE_TEXTURE_1D: 2474 if (filter == PIPE_TEX_FILTER_NEAREST) 2475 return img_filter_1d_nearest; 2476 else 2477 return img_filter_1d_linear; 2478 break; 2479 case PIPE_TEXTURE_1D_ARRAY: 2480 if (filter == PIPE_TEX_FILTER_NEAREST) 2481 return img_filter_1d_array_nearest; 2482 else 2483 return img_filter_1d_array_linear; 2484 break; 2485 case PIPE_TEXTURE_2D: 2486 case PIPE_TEXTURE_RECT: 2487 /* Try for fast path: 2488 */ 2489 if (key.bits.is_pot && 2490 sampler->wrap_s == sampler->wrap_t && 2491 sampler->normalized_coords) 2492 { 2493 switch (sampler->wrap_s) { 2494 case PIPE_TEX_WRAP_REPEAT: 2495 switch (filter) { 2496 case PIPE_TEX_FILTER_NEAREST: 2497 return img_filter_2d_nearest_repeat_POT; 2498 case PIPE_TEX_FILTER_LINEAR: 2499 return img_filter_2d_linear_repeat_POT; 2500 default: 2501 break; 2502 } 2503 break; 2504 case PIPE_TEX_WRAP_CLAMP: 2505 switch (filter) { 2506 case PIPE_TEX_FILTER_NEAREST: 2507 return img_filter_2d_nearest_clamp_POT; 2508 default: 2509 break; 2510 } 2511 } 2512 } 2513 /* Otherwise use default versions: 2514 */ 2515 if (filter == PIPE_TEX_FILTER_NEAREST) 2516 return img_filter_2d_nearest; 2517 else 2518 return img_filter_2d_linear; 2519 break; 2520 case PIPE_TEXTURE_2D_ARRAY: 2521 if (filter == PIPE_TEX_FILTER_NEAREST) 2522 return img_filter_2d_array_nearest; 2523 else 2524 return img_filter_2d_array_linear; 2525 break; 2526 case PIPE_TEXTURE_CUBE: 2527 if (filter == PIPE_TEX_FILTER_NEAREST) 2528 return img_filter_cube_nearest; 2529 else 2530 return img_filter_cube_linear; 2531 break; 2532 case PIPE_TEXTURE_3D: 2533 if (filter == PIPE_TEX_FILTER_NEAREST) 2534 return img_filter_3d_nearest; 2535 else 2536 return img_filter_3d_linear; 2537 break; 2538 default: 2539 assert(0); 2540 return img_filter_1d_nearest; 2541 } 2542} 2543 2544 2545/** 2546 * Bind the given texture object and texture cache to the sampler variant. 2547 */ 2548void 2549sp_sampler_variant_bind_view( struct sp_sampler_variant *samp, 2550 struct softpipe_tex_tile_cache *tex_cache, 2551 const struct pipe_sampler_view *view ) 2552{ 2553 const struct pipe_resource *texture = view->texture; 2554 2555 samp->view = view; 2556 samp->cache = tex_cache; 2557 samp->xpot = util_logbase2( texture->width0 ); 2558 samp->ypot = util_logbase2( texture->height0 ); 2559 samp->level = view->u.tex.first_level; 2560} 2561 2562 2563void 2564sp_sampler_variant_destroy( struct sp_sampler_variant *samp ) 2565{ 2566 FREE(samp); 2567} 2568 2569 2570/** 2571 * Create a sampler variant for a given set of non-orthogonal state. 2572 */ 2573struct sp_sampler_variant * 2574sp_create_sampler_variant( const struct pipe_sampler_state *sampler, 2575 const union sp_sampler_key key ) 2576{ 2577 struct sp_sampler_variant *samp = CALLOC_STRUCT(sp_sampler_variant); 2578 if (!samp) 2579 return NULL; 2580 2581 samp->sampler = sampler; 2582 samp->key = key; 2583 2584 /* Note that (for instance) linear_texcoord_s and 2585 * nearest_texcoord_s may be active at the same time, if the 2586 * sampler min_img_filter differs from its mag_img_filter. 2587 */ 2588 if (sampler->normalized_coords) { 2589 samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s ); 2590 samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t ); 2591 samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r ); 2592 2593 samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s ); 2594 samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t ); 2595 samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r ); 2596 } 2597 else { 2598 samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s ); 2599 samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t ); 2600 samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r ); 2601 2602 samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s ); 2603 samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t ); 2604 samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r ); 2605 } 2606 2607 samp->compute_lambda = get_lambda_func( key ); 2608 2609 samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler); 2610 samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler); 2611 2612 switch (sampler->min_mip_filter) { 2613 case PIPE_TEX_MIPFILTER_NONE: 2614 if (sampler->min_img_filter == sampler->mag_img_filter) 2615 samp->mip_filter = samp->min_img_filter; 2616 else 2617 samp->mip_filter = mip_filter_none; 2618 break; 2619 2620 case PIPE_TEX_MIPFILTER_NEAREST: 2621 samp->mip_filter = mip_filter_nearest; 2622 break; 2623 2624 case PIPE_TEX_MIPFILTER_LINEAR: 2625 if (key.bits.is_pot && 2626 sampler->min_img_filter == sampler->mag_img_filter && 2627 sampler->normalized_coords && 2628 sampler->wrap_s == PIPE_TEX_WRAP_REPEAT && 2629 sampler->wrap_t == PIPE_TEX_WRAP_REPEAT && 2630 sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR) { 2631 samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT; 2632 } 2633 else { 2634 samp->mip_filter = mip_filter_linear; 2635 } 2636 2637 /* Anisotropic filtering extension. */ 2638 if (sampler->max_anisotropy > 1) { 2639 samp->mip_filter = mip_filter_linear_aniso; 2640 2641 /* Override min_img_filter: 2642 * min_img_filter needs to be set to NEAREST since we need to access 2643 * each texture pixel as it is and weight it later; using linear 2644 * filters will have incorrect results. 2645 * By setting the filter to NEAREST here, we can avoid calling the 2646 * generic img_filter_2d_nearest in the anisotropic filter function, 2647 * making it possible to use one of the accelerated implementations 2648 */ 2649 samp->min_img_filter = get_img_filter(key, PIPE_TEX_FILTER_NEAREST, sampler); 2650 2651 /* on first access create the lookup table containing the filter weights. */ 2652 if (!weightLut) { 2653 create_filter_table(); 2654 } 2655 } 2656 2657 break; 2658 } 2659 2660 if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE) { 2661 samp->compare = sample_compare; 2662 } 2663 else { 2664 /* Skip compare operation by promoting the mip_filter function 2665 * pointer: 2666 */ 2667 samp->compare = samp->mip_filter; 2668 } 2669 2670 if (key.bits.target == PIPE_TEXTURE_CUBE) { 2671 samp->sample_target = sample_cube; 2672 } 2673 else { 2674 samp->faces[0] = 0; 2675 samp->faces[1] = 0; 2676 samp->faces[2] = 0; 2677 samp->faces[3] = 0; 2678 2679 /* Skip cube face determination by promoting the compare 2680 * function pointer: 2681 */ 2682 samp->sample_target = samp->compare; 2683 } 2684 2685 if (key.bits.swizzle_r != PIPE_SWIZZLE_RED || 2686 key.bits.swizzle_g != PIPE_SWIZZLE_GREEN || 2687 key.bits.swizzle_b != PIPE_SWIZZLE_BLUE || 2688 key.bits.swizzle_a != PIPE_SWIZZLE_ALPHA) { 2689 samp->base.get_samples = sample_swizzle; 2690 } 2691 else { 2692 samp->base.get_samples = samp->sample_target; 2693 } 2694 2695 return samp; 2696} 2697