sp_tex_sample.c revision 417aad5a992c8d7659438d20f82b4cf405c9c7b2
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.f; 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.f; 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.f; 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.f; 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.5F) ; 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.5F + s[j] * texture->width0 * scaling; 1819 float tex_v = -0.5F + t[j] * texture->height0 * scaling; 1820 1821 int u0 = (int) floorf(tex_u - box_u); 1822 int u1 = (int) ceilf(tex_u + box_u); 1823 int v0 = (int) floorf(tex_v - box_v); 1824 int v1 = (int) ceilf(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 unsigned 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 unsigned 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.5F * 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 >= (int) 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 if (sampler->mag_img_filter == PIPE_TEX_FILTER_LINEAR) { 2176 /* convert four pass/fail values to an intensity in [0,1] */ 2177 val = 0.25F * (k0 + k1 + k2 + k3); 2178 2179 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 2180 for (j = 0; j < 4; j++) { 2181 rgba[0][j] = rgba[1][j] = rgba[2][j] = val; 2182 rgba[3][j] = 1.0F; 2183 } 2184 } else { 2185 for (j = 0; j < 4; j++) { 2186 rgba[0][j] = k0; 2187 rgba[1][j] = k1; 2188 rgba[2][j] = k2; 2189 rgba[3][j] = 1.0F; 2190 } 2191 } 2192} 2193 2194 2195/** 2196 * Use 3D texcoords to choose a cube face, then sample the 2D cube faces. 2197 * Put face info into the sampler faces[] array. 2198 */ 2199static void 2200sample_cube(struct tgsi_sampler *tgsi_sampler, 2201 const float s[QUAD_SIZE], 2202 const float t[QUAD_SIZE], 2203 const float p[QUAD_SIZE], 2204 const float c0[QUAD_SIZE], 2205 enum tgsi_sampler_control control, 2206 float rgba[NUM_CHANNELS][QUAD_SIZE]) 2207{ 2208 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2209 unsigned j; 2210 float ssss[4], tttt[4]; 2211 2212 /* 2213 major axis 2214 direction target sc tc ma 2215 ---------- ------------------------------- --- --- --- 2216 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx 2217 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx 2218 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry 2219 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry 2220 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz 2221 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz 2222 */ 2223 2224 /* Choose the cube face and compute new s/t coords for the 2D face. 2225 * 2226 * Use the same cube face for all four pixels in the quad. 2227 * 2228 * This isn't ideal, but if we want to use a different cube face 2229 * per pixel in the quad, we'd have to also compute the per-face 2230 * LOD here too. That's because the four post-face-selection 2231 * texcoords are no longer related to each other (they're 2232 * per-face!) so we can't use subtraction to compute the partial 2233 * deriviates to compute the LOD. Doing so (near cube edges 2234 * anyway) gives us pretty much random values. 2235 */ 2236 { 2237 /* use the average of the four pixel's texcoords to choose the face */ 2238 const float rx = 0.25F * (s[0] + s[1] + s[2] + s[3]); 2239 const float ry = 0.25F * (t[0] + t[1] + t[2] + t[3]); 2240 const float rz = 0.25F * (p[0] + p[1] + p[2] + p[3]); 2241 const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); 2242 2243 if (arx >= ary && arx >= arz) { 2244 float sign = (rx >= 0.0F) ? 1.0F : -1.0F; 2245 uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X; 2246 for (j = 0; j < QUAD_SIZE; j++) { 2247 const float ima = -0.5F / fabsf(s[j]); 2248 ssss[j] = sign * p[j] * ima + 0.5F; 2249 tttt[j] = t[j] * ima + 0.5F; 2250 samp->faces[j] = face; 2251 } 2252 } 2253 else if (ary >= arx && ary >= arz) { 2254 float sign = (ry >= 0.0F) ? 1.0F : -1.0F; 2255 uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y; 2256 for (j = 0; j < QUAD_SIZE; j++) { 2257 const float ima = -0.5F / fabsf(t[j]); 2258 ssss[j] = -s[j] * ima + 0.5F; 2259 tttt[j] = sign * -p[j] * ima + 0.5F; 2260 samp->faces[j] = face; 2261 } 2262 } 2263 else { 2264 float sign = (rz >= 0.0F) ? 1.0F : -1.0F; 2265 uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z; 2266 for (j = 0; j < QUAD_SIZE; j++) { 2267 const float ima = -0.5F / fabsf(p[j]); 2268 ssss[j] = sign * -s[j] * ima + 0.5F; 2269 tttt[j] = t[j] * ima + 0.5F; 2270 samp->faces[j] = face; 2271 } 2272 } 2273 } 2274 2275 /* In our little pipeline, the compare stage is next. If compare 2276 * is not active, this will point somewhere deeper into the 2277 * pipeline, eg. to mip_filter or even img_filter. 2278 */ 2279 samp->compare(tgsi_sampler, ssss, tttt, NULL, c0, control, rgba); 2280} 2281 2282 2283static void 2284sample_swizzle(struct tgsi_sampler *tgsi_sampler, 2285 const float s[QUAD_SIZE], 2286 const float t[QUAD_SIZE], 2287 const float p[QUAD_SIZE], 2288 const float c0[QUAD_SIZE], 2289 enum tgsi_sampler_control control, 2290 float rgba[NUM_CHANNELS][QUAD_SIZE]) 2291{ 2292 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2293 float rgba_temp[NUM_CHANNELS][QUAD_SIZE]; 2294 const unsigned swizzle_r = samp->key.bits.swizzle_r; 2295 const unsigned swizzle_g = samp->key.bits.swizzle_g; 2296 const unsigned swizzle_b = samp->key.bits.swizzle_b; 2297 const unsigned swizzle_a = samp->key.bits.swizzle_a; 2298 unsigned j; 2299 2300 samp->sample_target(tgsi_sampler, s, t, p, c0, control, rgba_temp); 2301 2302 switch (swizzle_r) { 2303 case PIPE_SWIZZLE_ZERO: 2304 for (j = 0; j < 4; j++) 2305 rgba[0][j] = 0.0f; 2306 break; 2307 case PIPE_SWIZZLE_ONE: 2308 for (j = 0; j < 4; j++) 2309 rgba[0][j] = 1.0f; 2310 break; 2311 default: 2312 assert(swizzle_r < 4); 2313 for (j = 0; j < 4; j++) 2314 rgba[0][j] = rgba_temp[swizzle_r][j]; 2315 } 2316 2317 switch (swizzle_g) { 2318 case PIPE_SWIZZLE_ZERO: 2319 for (j = 0; j < 4; j++) 2320 rgba[1][j] = 0.0f; 2321 break; 2322 case PIPE_SWIZZLE_ONE: 2323 for (j = 0; j < 4; j++) 2324 rgba[1][j] = 1.0f; 2325 break; 2326 default: 2327 assert(swizzle_g < 4); 2328 for (j = 0; j < 4; j++) 2329 rgba[1][j] = rgba_temp[swizzle_g][j]; 2330 } 2331 2332 switch (swizzle_b) { 2333 case PIPE_SWIZZLE_ZERO: 2334 for (j = 0; j < 4; j++) 2335 rgba[2][j] = 0.0f; 2336 break; 2337 case PIPE_SWIZZLE_ONE: 2338 for (j = 0; j < 4; j++) 2339 rgba[2][j] = 1.0f; 2340 break; 2341 default: 2342 assert(swizzle_b < 4); 2343 for (j = 0; j < 4; j++) 2344 rgba[2][j] = rgba_temp[swizzle_b][j]; 2345 } 2346 2347 switch (swizzle_a) { 2348 case PIPE_SWIZZLE_ZERO: 2349 for (j = 0; j < 4; j++) 2350 rgba[3][j] = 0.0f; 2351 break; 2352 case PIPE_SWIZZLE_ONE: 2353 for (j = 0; j < 4; j++) 2354 rgba[3][j] = 1.0f; 2355 break; 2356 default: 2357 assert(swizzle_a < 4); 2358 for (j = 0; j < 4; j++) 2359 rgba[3][j] = rgba_temp[swizzle_a][j]; 2360 } 2361} 2362 2363 2364static wrap_nearest_func 2365get_nearest_unorm_wrap(unsigned mode) 2366{ 2367 switch (mode) { 2368 case PIPE_TEX_WRAP_CLAMP: 2369 return wrap_nearest_unorm_clamp; 2370 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2371 return wrap_nearest_unorm_clamp_to_edge; 2372 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2373 return wrap_nearest_unorm_clamp_to_border; 2374 default: 2375 assert(0); 2376 return wrap_nearest_unorm_clamp; 2377 } 2378} 2379 2380 2381static wrap_nearest_func 2382get_nearest_wrap(unsigned mode) 2383{ 2384 switch (mode) { 2385 case PIPE_TEX_WRAP_REPEAT: 2386 return wrap_nearest_repeat; 2387 case PIPE_TEX_WRAP_CLAMP: 2388 return wrap_nearest_clamp; 2389 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2390 return wrap_nearest_clamp_to_edge; 2391 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2392 return wrap_nearest_clamp_to_border; 2393 case PIPE_TEX_WRAP_MIRROR_REPEAT: 2394 return wrap_nearest_mirror_repeat; 2395 case PIPE_TEX_WRAP_MIRROR_CLAMP: 2396 return wrap_nearest_mirror_clamp; 2397 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 2398 return wrap_nearest_mirror_clamp_to_edge; 2399 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 2400 return wrap_nearest_mirror_clamp_to_border; 2401 default: 2402 assert(0); 2403 return wrap_nearest_repeat; 2404 } 2405} 2406 2407 2408static wrap_linear_func 2409get_linear_unorm_wrap(unsigned mode) 2410{ 2411 switch (mode) { 2412 case PIPE_TEX_WRAP_CLAMP: 2413 return wrap_linear_unorm_clamp; 2414 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2415 return wrap_linear_unorm_clamp_to_edge; 2416 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2417 return wrap_linear_unorm_clamp_to_border; 2418 default: 2419 assert(0); 2420 return wrap_linear_unorm_clamp; 2421 } 2422} 2423 2424 2425static wrap_linear_func 2426get_linear_wrap(unsigned mode) 2427{ 2428 switch (mode) { 2429 case PIPE_TEX_WRAP_REPEAT: 2430 return wrap_linear_repeat; 2431 case PIPE_TEX_WRAP_CLAMP: 2432 return wrap_linear_clamp; 2433 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2434 return wrap_linear_clamp_to_edge; 2435 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2436 return wrap_linear_clamp_to_border; 2437 case PIPE_TEX_WRAP_MIRROR_REPEAT: 2438 return wrap_linear_mirror_repeat; 2439 case PIPE_TEX_WRAP_MIRROR_CLAMP: 2440 return wrap_linear_mirror_clamp; 2441 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 2442 return wrap_linear_mirror_clamp_to_edge; 2443 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 2444 return wrap_linear_mirror_clamp_to_border; 2445 default: 2446 assert(0); 2447 return wrap_linear_repeat; 2448 } 2449} 2450 2451 2452static compute_lambda_func 2453get_lambda_func(const union sp_sampler_key key) 2454{ 2455 if (key.bits.processor == TGSI_PROCESSOR_VERTEX) 2456 return compute_lambda_vert; 2457 2458 switch (key.bits.target) { 2459 case PIPE_TEXTURE_1D: 2460 case PIPE_TEXTURE_1D_ARRAY: 2461 return compute_lambda_1d; 2462 case PIPE_TEXTURE_2D: 2463 case PIPE_TEXTURE_2D_ARRAY: 2464 case PIPE_TEXTURE_RECT: 2465 case PIPE_TEXTURE_CUBE: 2466 return compute_lambda_2d; 2467 case PIPE_TEXTURE_3D: 2468 return compute_lambda_3d; 2469 default: 2470 assert(0); 2471 return compute_lambda_1d; 2472 } 2473} 2474 2475 2476static filter_func 2477get_img_filter(const union sp_sampler_key key, 2478 unsigned filter, 2479 const struct pipe_sampler_state *sampler) 2480{ 2481 switch (key.bits.target) { 2482 case PIPE_TEXTURE_1D: 2483 if (filter == PIPE_TEX_FILTER_NEAREST) 2484 return img_filter_1d_nearest; 2485 else 2486 return img_filter_1d_linear; 2487 break; 2488 case PIPE_TEXTURE_1D_ARRAY: 2489 if (filter == PIPE_TEX_FILTER_NEAREST) 2490 return img_filter_1d_array_nearest; 2491 else 2492 return img_filter_1d_array_linear; 2493 break; 2494 case PIPE_TEXTURE_2D: 2495 case PIPE_TEXTURE_RECT: 2496 /* Try for fast path: 2497 */ 2498 if (key.bits.is_pot && 2499 sampler->wrap_s == sampler->wrap_t && 2500 sampler->normalized_coords) 2501 { 2502 switch (sampler->wrap_s) { 2503 case PIPE_TEX_WRAP_REPEAT: 2504 switch (filter) { 2505 case PIPE_TEX_FILTER_NEAREST: 2506 return img_filter_2d_nearest_repeat_POT; 2507 case PIPE_TEX_FILTER_LINEAR: 2508 return img_filter_2d_linear_repeat_POT; 2509 default: 2510 break; 2511 } 2512 break; 2513 case PIPE_TEX_WRAP_CLAMP: 2514 switch (filter) { 2515 case PIPE_TEX_FILTER_NEAREST: 2516 return img_filter_2d_nearest_clamp_POT; 2517 default: 2518 break; 2519 } 2520 } 2521 } 2522 /* Otherwise use default versions: 2523 */ 2524 if (filter == PIPE_TEX_FILTER_NEAREST) 2525 return img_filter_2d_nearest; 2526 else 2527 return img_filter_2d_linear; 2528 break; 2529 case PIPE_TEXTURE_2D_ARRAY: 2530 if (filter == PIPE_TEX_FILTER_NEAREST) 2531 return img_filter_2d_array_nearest; 2532 else 2533 return img_filter_2d_array_linear; 2534 break; 2535 case PIPE_TEXTURE_CUBE: 2536 if (filter == PIPE_TEX_FILTER_NEAREST) 2537 return img_filter_cube_nearest; 2538 else 2539 return img_filter_cube_linear; 2540 break; 2541 case PIPE_TEXTURE_3D: 2542 if (filter == PIPE_TEX_FILTER_NEAREST) 2543 return img_filter_3d_nearest; 2544 else 2545 return img_filter_3d_linear; 2546 break; 2547 default: 2548 assert(0); 2549 return img_filter_1d_nearest; 2550 } 2551} 2552 2553 2554/** 2555 * Bind the given texture object and texture cache to the sampler variant. 2556 */ 2557void 2558sp_sampler_variant_bind_view( struct sp_sampler_variant *samp, 2559 struct softpipe_tex_tile_cache *tex_cache, 2560 const struct pipe_sampler_view *view ) 2561{ 2562 const struct pipe_resource *texture = view->texture; 2563 2564 samp->view = view; 2565 samp->cache = tex_cache; 2566 samp->xpot = util_logbase2( texture->width0 ); 2567 samp->ypot = util_logbase2( texture->height0 ); 2568 samp->level = view->u.tex.first_level; 2569} 2570 2571 2572void 2573sp_sampler_variant_destroy( struct sp_sampler_variant *samp ) 2574{ 2575 FREE(samp); 2576} 2577 2578static void 2579sample_get_dims(struct tgsi_sampler *tgsi_sampler, int level, 2580 int dims[4]) 2581{ 2582 struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2583 const struct pipe_sampler_view *view = samp->view; 2584 const struct pipe_resource *texture = view->texture; 2585 2586 /* undefined according to EXT_gpu_program */ 2587 level += view->u.tex.first_level; 2588 if (level > view->u.tex.last_level) 2589 return; 2590 2591 dims[0] = u_minify(texture->width0, level); 2592 2593 switch(texture->target) { 2594 case PIPE_TEXTURE_1D_ARRAY: 2595 dims[1] = texture->array_size; 2596 /* fallthrough */ 2597 case PIPE_TEXTURE_1D: 2598 case PIPE_BUFFER: 2599 return; 2600 case PIPE_TEXTURE_2D_ARRAY: 2601 dims[2] = texture->array_size; 2602 /* fallthrough */ 2603 case PIPE_TEXTURE_2D: 2604 case PIPE_TEXTURE_CUBE: 2605 case PIPE_TEXTURE_RECT: 2606 dims[1] = u_minify(texture->height0, level); 2607 return; 2608 case PIPE_TEXTURE_3D: 2609 dims[1] = u_minify(texture->height0, level); 2610 dims[2] = u_minify(texture->depth0, level); 2611 return; 2612 default: 2613 assert(!"unexpected texture target in sample_get_dims()"); 2614 return; 2615 } 2616} 2617 2618/* this function is only used for unfiltered texel gets 2619 via the TGSI TXF opcode. */ 2620static void 2621sample_get_texels(struct tgsi_sampler *tgsi_sampler, 2622 const int v_i[QUAD_SIZE], 2623 const int v_j[QUAD_SIZE], 2624 const int v_k[QUAD_SIZE], 2625 const int lod[QUAD_SIZE], 2626 const int8_t offset[3], 2627 float rgba[NUM_CHANNELS][QUAD_SIZE]) 2628{ 2629 const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler); 2630 union tex_tile_address addr; 2631 const struct pipe_resource *texture = samp->view->texture; 2632 int j, c; 2633 const float *tx; 2634 2635 addr.value = 0; 2636 /* TODO write a better test for LOD */ 2637 addr.bits.level = lod[0]; 2638 2639 switch(texture->target) { 2640 case PIPE_TEXTURE_1D: 2641 for (j = 0; j < QUAD_SIZE; j++) { 2642 tx = get_texel_2d(samp, addr, v_i[j] + offset[0], 0); 2643 for (c = 0; c < 4; c++) { 2644 rgba[c][j] = tx[c]; 2645 } 2646 } 2647 break; 2648 case PIPE_TEXTURE_1D_ARRAY: 2649 for (j = 0; j < QUAD_SIZE; j++) { 2650 tx = get_texel_1d_array(samp, addr, v_i[j] + offset[0], 2651 v_j[j] + offset[1]); 2652 for (c = 0; c < 4; c++) { 2653 rgba[c][j] = tx[c]; 2654 } 2655 } 2656 break; 2657 case PIPE_TEXTURE_2D: 2658 case PIPE_TEXTURE_RECT: 2659 for (j = 0; j < QUAD_SIZE; j++) { 2660 tx = get_texel_2d(samp, addr, v_i[j] + offset[0], 2661 v_j[j] + offset[1]); 2662 for (c = 0; c < 4; c++) { 2663 rgba[c][j] = tx[c]; 2664 } 2665 } 2666 break; 2667 case PIPE_TEXTURE_2D_ARRAY: 2668 for (j = 0; j < QUAD_SIZE; j++) { 2669 tx = get_texel_2d_array(samp, addr, v_i[j] + offset[0], 2670 v_j[j] + offset[1], 2671 v_k[j] + offset[2]); 2672 for (c = 0; c < 4; c++) { 2673 rgba[c][j] = tx[c]; 2674 } 2675 } 2676 break; 2677 case PIPE_TEXTURE_3D: 2678 for (j = 0; j < QUAD_SIZE; j++) { 2679 tx = get_texel_3d(samp, addr, v_i[j] + offset[0], 2680 v_j[j] + offset[1], 2681 v_k[j] + offset[2]); 2682 for (c = 0; c < 4; c++) { 2683 rgba[c][j] = tx[c]; 2684 } 2685 } 2686 break; 2687 case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */ 2688 default: 2689 assert(!"Unknown or CUBE texture type in TXF processing\n"); 2690 break; 2691 } 2692} 2693/** 2694 * Create a sampler variant for a given set of non-orthogonal state. 2695 */ 2696struct sp_sampler_variant * 2697sp_create_sampler_variant( const struct pipe_sampler_state *sampler, 2698 const union sp_sampler_key key ) 2699{ 2700 struct sp_sampler_variant *samp = CALLOC_STRUCT(sp_sampler_variant); 2701 if (!samp) 2702 return NULL; 2703 2704 samp->sampler = sampler; 2705 samp->key = key; 2706 2707 /* Note that (for instance) linear_texcoord_s and 2708 * nearest_texcoord_s may be active at the same time, if the 2709 * sampler min_img_filter differs from its mag_img_filter. 2710 */ 2711 if (sampler->normalized_coords) { 2712 samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s ); 2713 samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t ); 2714 samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r ); 2715 2716 samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s ); 2717 samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t ); 2718 samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r ); 2719 } 2720 else { 2721 samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s ); 2722 samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t ); 2723 samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r ); 2724 2725 samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s ); 2726 samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t ); 2727 samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r ); 2728 } 2729 2730 samp->compute_lambda = get_lambda_func( key ); 2731 2732 samp->min_img_filter = get_img_filter(key, sampler->min_img_filter, sampler); 2733 samp->mag_img_filter = get_img_filter(key, sampler->mag_img_filter, sampler); 2734 2735 switch (sampler->min_mip_filter) { 2736 case PIPE_TEX_MIPFILTER_NONE: 2737 if (sampler->min_img_filter == sampler->mag_img_filter) 2738 samp->mip_filter = samp->min_img_filter; 2739 else 2740 samp->mip_filter = mip_filter_none; 2741 break; 2742 2743 case PIPE_TEX_MIPFILTER_NEAREST: 2744 samp->mip_filter = mip_filter_nearest; 2745 break; 2746 2747 case PIPE_TEX_MIPFILTER_LINEAR: 2748 if (key.bits.is_pot && 2749 sampler->min_img_filter == sampler->mag_img_filter && 2750 sampler->normalized_coords && 2751 sampler->wrap_s == PIPE_TEX_WRAP_REPEAT && 2752 sampler->wrap_t == PIPE_TEX_WRAP_REPEAT && 2753 sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR) { 2754 samp->mip_filter = mip_filter_linear_2d_linear_repeat_POT; 2755 } 2756 else { 2757 samp->mip_filter = mip_filter_linear; 2758 } 2759 2760 /* Anisotropic filtering extension. */ 2761 if (sampler->max_anisotropy > 1) { 2762 samp->mip_filter = mip_filter_linear_aniso; 2763 2764 /* Override min_img_filter: 2765 * min_img_filter needs to be set to NEAREST since we need to access 2766 * each texture pixel as it is and weight it later; using linear 2767 * filters will have incorrect results. 2768 * By setting the filter to NEAREST here, we can avoid calling the 2769 * generic img_filter_2d_nearest in the anisotropic filter function, 2770 * making it possible to use one of the accelerated implementations 2771 */ 2772 samp->min_img_filter = get_img_filter(key, PIPE_TEX_FILTER_NEAREST, sampler); 2773 2774 /* on first access create the lookup table containing the filter weights. */ 2775 if (!weightLut) { 2776 create_filter_table(); 2777 } 2778 } 2779 2780 break; 2781 } 2782 2783 if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE) { 2784 samp->compare = sample_compare; 2785 } 2786 else { 2787 /* Skip compare operation by promoting the mip_filter function 2788 * pointer: 2789 */ 2790 samp->compare = samp->mip_filter; 2791 } 2792 2793 if (key.bits.target == PIPE_TEXTURE_CUBE) { 2794 samp->sample_target = sample_cube; 2795 } 2796 else { 2797 samp->faces[0] = 0; 2798 samp->faces[1] = 0; 2799 samp->faces[2] = 0; 2800 samp->faces[3] = 0; 2801 2802 /* Skip cube face determination by promoting the compare 2803 * function pointer: 2804 */ 2805 samp->sample_target = samp->compare; 2806 } 2807 2808 if (key.bits.swizzle_r != PIPE_SWIZZLE_RED || 2809 key.bits.swizzle_g != PIPE_SWIZZLE_GREEN || 2810 key.bits.swizzle_b != PIPE_SWIZZLE_BLUE || 2811 key.bits.swizzle_a != PIPE_SWIZZLE_ALPHA) { 2812 samp->base.get_samples = sample_swizzle; 2813 } 2814 else { 2815 samp->base.get_samples = samp->sample_target; 2816 } 2817 2818 samp->base.get_dims = sample_get_dims; 2819 samp->base.get_texel = sample_get_texels; 2820 return samp; 2821} 2822