sp_tex_sample.c revision aa5db684382bd8662a83ca09ed000e4a5a1013f9
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * Copyright 2008 VMware, Inc. All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29/** 30 * Texture sampling 31 * 32 * Authors: 33 * Brian Paul 34 */ 35 36#include "sp_context.h" 37#include "sp_quad.h" 38#include "sp_surface.h" 39#include "sp_texture.h" 40#include "sp_tex_sample.h" 41#include "sp_tile_cache.h" 42#include "pipe/p_context.h" 43#include "pipe/p_defines.h" 44#include "util/u_math.h" 45#include "util/u_memory.h" 46 47 48 49/* 50 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes 51 * see 1-pixel bands of improperly weighted linear-filtered textures. 52 * The tests/texwrap.c demo is a good test. 53 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0. 54 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x). 55 */ 56#define FRAC(f) ((f) - util_ifloor(f)) 57 58 59/** 60 * Linear interpolation macro 61 */ 62static INLINE float 63lerp(float a, float v0, float v1) 64{ 65 return v0 + a * (v1 - v0); 66} 67 68 69/** 70 * Do 2D/biliner interpolation of float values. 71 * v00, v10, v01 and v11 are typically four texture samples in a square/box. 72 * a and b are the horizontal and vertical interpolants. 73 * It's important that this function is inlined when compiled with 74 * optimization! If we find that's not true on some systems, convert 75 * to a macro. 76 */ 77static INLINE float 78lerp_2d(float a, float b, 79 float v00, float v10, float v01, float v11) 80{ 81 const float temp0 = lerp(a, v00, v10); 82 const float temp1 = lerp(a, v01, v11); 83 return lerp(b, temp0, temp1); 84} 85 86 87/** 88 * As above, but 3D interpolation of 8 values. 89 */ 90static INLINE float 91lerp_3d(float a, float b, float c, 92 float v000, float v100, float v010, float v110, 93 float v001, float v101, float v011, float v111) 94{ 95 const float temp0 = lerp_2d(a, b, v000, v100, v010, v110); 96 const float temp1 = lerp_2d(a, b, v001, v101, v011, v111); 97 return lerp(c, temp0, temp1); 98} 99 100 101 102/** 103 * If A is a signed integer, A % B doesn't give the right value for A < 0 104 * (in terms of texture repeat). Just casting to unsigned fixes that. 105 */ 106#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B)) 107 108 109/** 110 * Apply texture coord wrapping mode and return integer texture indexes 111 * for a vector of four texcoords (S or T or P). 112 * \param wrapMode PIPE_TEX_WRAP_x 113 * \param s the incoming texcoords 114 * \param size the texture image size 115 * \param icoord returns the integer texcoords 116 * \return integer texture index 117 */ 118static INLINE void 119nearest_texcoord_4(unsigned wrapMode, const float s[4], unsigned size, 120 int icoord[4]) 121{ 122 uint ch; 123 switch (wrapMode) { 124 case PIPE_TEX_WRAP_REPEAT: 125 /* s limited to [0,1) */ 126 /* i limited to [0,size-1] */ 127 for (ch = 0; ch < 4; ch++) { 128 int i = util_ifloor(s[ch] * size); 129 icoord[ch] = REMAINDER(i, size); 130 } 131 return; 132 case PIPE_TEX_WRAP_CLAMP: 133 /* s limited to [0,1] */ 134 /* i limited to [0,size-1] */ 135 for (ch = 0; ch < 4; ch++) { 136 if (s[ch] <= 0.0F) 137 icoord[ch] = 0; 138 else if (s[ch] >= 1.0F) 139 icoord[ch] = size - 1; 140 else 141 icoord[ch] = util_ifloor(s[ch] * size); 142 } 143 return; 144 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 145 { 146 /* s limited to [min,max] */ 147 /* i limited to [0, size-1] */ 148 const float min = 1.0F / (2.0F * size); 149 const float max = 1.0F - min; 150 for (ch = 0; ch < 4; ch++) { 151 if (s[ch] < min) 152 icoord[ch] = 0; 153 else if (s[ch] > max) 154 icoord[ch] = size - 1; 155 else 156 icoord[ch] = util_ifloor(s[ch] * size); 157 } 158 } 159 return; 160 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 161 { 162 /* s limited to [min,max] */ 163 /* i limited to [-1, size] */ 164 const float min = -1.0F / (2.0F * size); 165 const float max = 1.0F - min; 166 for (ch = 0; ch < 4; ch++) { 167 if (s[ch] <= min) 168 icoord[ch] = -1; 169 else if (s[ch] >= max) 170 icoord[ch] = size; 171 else 172 icoord[ch] = util_ifloor(s[ch] * size); 173 } 174 } 175 return; 176 case PIPE_TEX_WRAP_MIRROR_REPEAT: 177 { 178 const float min = 1.0F / (2.0F * size); 179 const float max = 1.0F - min; 180 for (ch = 0; ch < 4; ch++) { 181 const int flr = util_ifloor(s[ch]); 182 float u; 183 if (flr & 1) 184 u = 1.0F - (s[ch] - (float) flr); 185 else 186 u = s[ch] - (float) flr; 187 if (u < min) 188 icoord[ch] = 0; 189 else if (u > max) 190 icoord[ch] = size - 1; 191 else 192 icoord[ch] = util_ifloor(u * size); 193 } 194 } 195 return; 196 case PIPE_TEX_WRAP_MIRROR_CLAMP: 197 for (ch = 0; ch < 4; ch++) { 198 /* s limited to [0,1] */ 199 /* i limited to [0,size-1] */ 200 const float u = fabsf(s[ch]); 201 if (u <= 0.0F) 202 icoord[ch] = 0; 203 else if (u >= 1.0F) 204 icoord[ch] = size - 1; 205 else 206 icoord[ch] = util_ifloor(u * size); 207 } 208 return; 209 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 210 { 211 /* s limited to [min,max] */ 212 /* i limited to [0, size-1] */ 213 const float min = 1.0F / (2.0F * size); 214 const float max = 1.0F - min; 215 for (ch = 0; ch < 4; ch++) { 216 const float u = fabsf(s[ch]); 217 if (u < min) 218 icoord[ch] = 0; 219 else if (u > max) 220 icoord[ch] = size - 1; 221 else 222 icoord[ch] = util_ifloor(u * size); 223 } 224 } 225 return; 226 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 227 { 228 /* s limited to [min,max] */ 229 /* i limited to [0, size-1] */ 230 const float min = -1.0F / (2.0F * size); 231 const float max = 1.0F - min; 232 for (ch = 0; ch < 4; ch++) { 233 const float u = fabsf(s[ch]); 234 if (u < min) 235 icoord[ch] = -1; 236 else if (u > max) 237 icoord[ch] = size; 238 else 239 icoord[ch] = util_ifloor(u * size); 240 } 241 } 242 return; 243 default: 244 assert(0); 245 } 246} 247 248 249/** 250 * Used to compute texel locations for linear sampling for four texcoords. 251 * \param wrapMode PIPE_TEX_WRAP_x 252 * \param s the texcoords 253 * \param size the texture image size 254 * \param icoord0 returns first texture indexes 255 * \param icoord1 returns second texture indexes (usually icoord0 + 1) 256 * \param w returns blend factor/weight between texture indexes 257 * \param icoord returns the computed integer texture coords 258 */ 259static INLINE void 260linear_texcoord_4(unsigned wrapMode, const float s[4], unsigned size, 261 int icoord0[4], int icoord1[4], float w[4]) 262{ 263 uint ch; 264 265 switch (wrapMode) { 266 case PIPE_TEX_WRAP_REPEAT: 267 for (ch = 0; ch < 4; ch++) { 268 float u = s[ch] * size - 0.5F; 269 icoord0[ch] = REMAINDER(util_ifloor(u), size); 270 icoord1[ch] = REMAINDER(icoord0[ch] + 1, size); 271 w[ch] = FRAC(u); 272 } 273 break;; 274 case PIPE_TEX_WRAP_CLAMP: 275 for (ch = 0; ch < 4; ch++) { 276 float u = CLAMP(s[ch], 0.0F, 1.0F); 277 u = u * size - 0.5f; 278 icoord0[ch] = util_ifloor(u); 279 icoord1[ch] = icoord0[ch] + 1; 280 w[ch] = FRAC(u); 281 } 282 break;; 283 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 284 for (ch = 0; ch < 4; ch++) { 285 float u = CLAMP(s[ch], 0.0F, 1.0F); 286 u = u * size - 0.5f; 287 icoord0[ch] = util_ifloor(u); 288 icoord1[ch] = icoord0[ch] + 1; 289 if (icoord0[ch] < 0) 290 icoord0[ch] = 0; 291 if (icoord1[ch] >= (int) size) 292 icoord1[ch] = size - 1; 293 w[ch] = FRAC(u); 294 } 295 break;; 296 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 297 { 298 const float min = -1.0F / (2.0F * size); 299 const float max = 1.0F - min; 300 for (ch = 0; ch < 4; ch++) { 301 float u = CLAMP(s[ch], min, max); 302 u = u * size - 0.5f; 303 icoord0[ch] = util_ifloor(u); 304 icoord1[ch] = icoord0[ch] + 1; 305 w[ch] = FRAC(u); 306 } 307 } 308 break;; 309 case PIPE_TEX_WRAP_MIRROR_REPEAT: 310 for (ch = 0; ch < 4; ch++) { 311 const int flr = util_ifloor(s[ch]); 312 float u; 313 if (flr & 1) 314 u = 1.0F - (s[ch] - (float) flr); 315 else 316 u = s[ch] - (float) flr; 317 u = u * size - 0.5F; 318 icoord0[ch] = util_ifloor(u); 319 icoord1[ch] = icoord0[ch] + 1; 320 if (icoord0[ch] < 0) 321 icoord0[ch] = 0; 322 if (icoord1[ch] >= (int) size) 323 icoord1[ch] = size - 1; 324 w[ch] = FRAC(u); 325 } 326 break;; 327 case PIPE_TEX_WRAP_MIRROR_CLAMP: 328 for (ch = 0; ch < 4; ch++) { 329 float u = fabsf(s[ch]); 330 if (u >= 1.0F) 331 u = (float) size; 332 else 333 u *= size; 334 u -= 0.5F; 335 icoord0[ch] = util_ifloor(u); 336 icoord1[ch] = icoord0[ch] + 1; 337 w[ch] = FRAC(u); 338 } 339 break;; 340 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 341 for (ch = 0; ch < 4; ch++) { 342 float u = fabsf(s[ch]); 343 if (u >= 1.0F) 344 u = (float) size; 345 else 346 u *= size; 347 u -= 0.5F; 348 icoord0[ch] = util_ifloor(u); 349 icoord1[ch] = icoord0[ch] + 1; 350 if (icoord0[ch] < 0) 351 icoord0[ch] = 0; 352 if (icoord1[ch] >= (int) size) 353 icoord1[ch] = size - 1; 354 w[ch] = FRAC(u); 355 } 356 break;; 357 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 358 { 359 const float min = -1.0F / (2.0F * size); 360 const float max = 1.0F - min; 361 for (ch = 0; ch < 4; ch++) { 362 float u = fabsf(s[ch]); 363 if (u <= min) 364 u = min * size; 365 else if (u >= max) 366 u = max * size; 367 else 368 u *= size; 369 u -= 0.5F; 370 icoord0[ch] = util_ifloor(u); 371 icoord1[ch] = icoord0[ch] + 1; 372 w[ch] = FRAC(u); 373 } 374 } 375 break;; 376 default: 377 assert(0); 378 } 379} 380 381 382/** 383 * For RECT textures / unnormalized texcoords 384 * Only a subset of wrap modes supported. 385 */ 386static INLINE void 387nearest_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size, 388 int icoord[4]) 389{ 390 uint ch; 391 switch (wrapMode) { 392 case PIPE_TEX_WRAP_CLAMP: 393 for (ch = 0; ch < 4; ch++) { 394 int i = util_ifloor(s[ch]); 395 icoord[ch]= CLAMP(i, 0, (int) size-1); 396 } 397 return; 398 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 399 /* fall-through */ 400 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 401 for (ch = 0; ch < 4; ch++) { 402 icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) ); 403 } 404 return; 405 default: 406 assert(0); 407 } 408} 409 410 411/** 412 * For RECT textures / unnormalized texcoords. 413 * Only a subset of wrap modes supported. 414 */ 415static INLINE void 416linear_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size, 417 int icoord0[4], int icoord1[4], float w[4]) 418{ 419 uint ch; 420 switch (wrapMode) { 421 case PIPE_TEX_WRAP_CLAMP: 422 for (ch = 0; ch < 4; ch++) { 423 /* Not exactly what the spec says, but it matches NVIDIA output */ 424 float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f); 425 icoord0[ch] = util_ifloor(u); 426 icoord1[ch] = icoord0[ch] + 1; 427 w[ch] = FRAC(u); 428 } 429 return; 430 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 431 /* fall-through */ 432 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 433 for (ch = 0; ch < 4; ch++) { 434 float u = CLAMP(s[ch], 0.5F, (float) size - 0.5F); 435 u -= 0.5F; 436 icoord0[ch] = util_ifloor(u); 437 icoord1[ch] = icoord0[ch] + 1; 438 if (icoord1[ch] > (int) size - 1) 439 icoord1[ch] = size - 1; 440 w[ch] = FRAC(u); 441 } 442 break; 443 default: 444 assert(0); 445 } 446} 447 448 449static unsigned 450choose_cube_face(float rx, float ry, float rz, float *newS, float *newT) 451{ 452 /* 453 major axis 454 direction target sc tc ma 455 ---------- ------------------------------- --- --- --- 456 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx 457 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx 458 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry 459 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry 460 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz 461 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz 462 */ 463 const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); 464 unsigned face; 465 float sc, tc, ma; 466 467 if (arx > ary && arx > arz) { 468 if (rx >= 0.0F) { 469 face = PIPE_TEX_FACE_POS_X; 470 sc = -rz; 471 tc = -ry; 472 ma = arx; 473 } 474 else { 475 face = PIPE_TEX_FACE_NEG_X; 476 sc = rz; 477 tc = -ry; 478 ma = arx; 479 } 480 } 481 else if (ary > arx && ary > arz) { 482 if (ry >= 0.0F) { 483 face = PIPE_TEX_FACE_POS_Y; 484 sc = rx; 485 tc = rz; 486 ma = ary; 487 } 488 else { 489 face = PIPE_TEX_FACE_NEG_Y; 490 sc = rx; 491 tc = -rz; 492 ma = ary; 493 } 494 } 495 else { 496 if (rz > 0.0F) { 497 face = PIPE_TEX_FACE_POS_Z; 498 sc = rx; 499 tc = -ry; 500 ma = arz; 501 } 502 else { 503 face = PIPE_TEX_FACE_NEG_Z; 504 sc = -rx; 505 tc = -ry; 506 ma = arz; 507 } 508 } 509 510 *newS = ( sc / ma + 1.0F ) * 0.5F; 511 *newT = ( tc / ma + 1.0F ) * 0.5F; 512 513 return face; 514} 515 516 517/** 518 * Examine the quad's texture coordinates to compute the partial 519 * derivatives w.r.t X and Y, then compute lambda (level of detail). 520 * 521 * This is only done for fragment shaders, not vertex shaders. 522 */ 523static float 524compute_lambda(const struct pipe_texture *tex, 525 const struct pipe_sampler_state *sampler, 526 const float s[QUAD_SIZE], 527 const float t[QUAD_SIZE], 528 const float p[QUAD_SIZE], 529 float lodbias) 530{ 531 float rho, lambda; 532 533 assert(sampler->normalized_coords); 534 535 assert(s); 536 { 537 float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]; 538 float dsdy = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]; 539 dsdx = fabsf(dsdx); 540 dsdy = fabsf(dsdy); 541 rho = MAX2(dsdx, dsdy) * tex->width[0]; 542 } 543 if (t) { 544 float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]; 545 float dtdy = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]; 546 float max; 547 dtdx = fabsf(dtdx); 548 dtdy = fabsf(dtdy); 549 max = MAX2(dtdx, dtdy) * tex->height[0]; 550 rho = MAX2(rho, max); 551 } 552 if (p) { 553 float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]; 554 float dpdy = p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]; 555 float max; 556 dpdx = fabsf(dpdx); 557 dpdy = fabsf(dpdy); 558 max = MAX2(dpdx, dpdy) * tex->depth[0]; 559 rho = MAX2(rho, max); 560 } 561 562 lambda = util_fast_log2(rho); 563 lambda += lodbias + sampler->lod_bias; 564 lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod); 565 566 return lambda; 567} 568 569 570/** 571 * Do several things here: 572 * 1. Compute lambda from the texcoords, if needed 573 * 2. Determine if we're minifying or magnifying 574 * 3. If minifying, choose mipmap levels 575 * 4. Return image filter to use within mipmap images 576 * \param level0 Returns first mipmap level to sample from 577 * \param level1 Returns second mipmap level to sample from 578 * \param levelBlend Returns blend factor between levels, in [0,1] 579 * \param imgFilter Returns either the min or mag filter, depending on lambda 580 */ 581static void 582choose_mipmap_levels(const struct pipe_texture *texture, 583 const struct pipe_sampler_state *sampler, 584 const float s[QUAD_SIZE], 585 const float t[QUAD_SIZE], 586 const float p[QUAD_SIZE], 587 boolean computeLambda, 588 float lodbias, 589 unsigned *level0, unsigned *level1, float *levelBlend, 590 unsigned *imgFilter) 591{ 592 if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 593 /* no mipmap selection needed */ 594 *level0 = *level1 = CLAMP((int) sampler->min_lod, 595 0, (int) texture->last_level); 596 597 if (sampler->min_img_filter != sampler->mag_img_filter) { 598 /* non-mipmapped texture, but still need to determine if doing 599 * minification or magnification. 600 */ 601 float lambda = compute_lambda(texture, sampler, s, t, p, lodbias); 602 if (lambda <= 0.0) { 603 *imgFilter = sampler->mag_img_filter; 604 } 605 else { 606 *imgFilter = sampler->min_img_filter; 607 } 608 } 609 else { 610 *imgFilter = sampler->mag_img_filter; 611 } 612 } 613 else { 614 float lambda; 615 616 if (computeLambda) 617 /* fragment shader */ 618 lambda = compute_lambda(texture, sampler, s, t, p, lodbias); 619 else 620 /* vertex shader */ 621 lambda = lodbias; /* not really a bias, but absolute LOD */ 622 623 if (lambda <= 0.0) { /* XXX threshold depends on the filter */ 624 /* magnifying */ 625 *imgFilter = sampler->mag_img_filter; 626 *level0 = *level1 = 0; 627 } 628 else { 629 /* minifying */ 630 *imgFilter = sampler->min_img_filter; 631 632 /* choose mipmap level(s) and compute the blend factor between them */ 633 if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { 634 /* Nearest mipmap level */ 635 const int lvl = (int) (lambda + 0.5); 636 *level0 = 637 *level1 = CLAMP(lvl, 0, (int) texture->last_level); 638 } 639 else { 640 /* Linear interpolation between mipmap levels */ 641 const int lvl = (int) lambda; 642 *level0 = CLAMP(lvl, 0, (int) texture->last_level); 643 *level1 = CLAMP(lvl + 1, 0, (int) texture->last_level); 644 *levelBlend = FRAC(lambda); /* blending weight between levels */ 645 } 646 } 647 } 648} 649 650 651/** 652 * Get a texel from a texture, using the texture tile cache. 653 * 654 * \param face the cube face in 0..5 655 * \param level the mipmap level 656 * \param x the x coord of texel within 2D image 657 * \param y the y coord of texel within 2D image 658 * \param z which slice of a 3D texture 659 * \param rgba the quad to put the texel/color into 660 * \param j which element of the rgba quad to write to 661 * 662 * XXX maybe move this into sp_tile_cache.c and merge with the 663 * sp_get_cached_tile_tex() function. Also, get 4 texels instead of 1... 664 */ 665static void 666get_texel(const struct tgsi_sampler *tgsi_sampler, 667 unsigned face, unsigned level, int x, int y, int z, 668 float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j) 669{ 670 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 671 const struct pipe_texture *texture = samp->texture; 672 const struct pipe_sampler_state *sampler = samp->sampler; 673 674 if (x < 0 || x >= (int) texture->width[level] || 675 y < 0 || y >= (int) texture->height[level] || 676 z < 0 || z >= (int) texture->depth[level]) { 677 rgba[0][j] = sampler->border_color[0]; 678 rgba[1][j] = sampler->border_color[1]; 679 rgba[2][j] = sampler->border_color[2]; 680 rgba[3][j] = sampler->border_color[3]; 681 } 682 else { 683 const int tx = x % TILE_SIZE; 684 const int ty = y % TILE_SIZE; 685 const struct softpipe_cached_tile *tile 686 = sp_get_cached_tile_tex(samp->cache, 687 x, y, z, face, level); 688 rgba[0][j] = tile->data.color[ty][tx][0]; 689 rgba[1][j] = tile->data.color[ty][tx][1]; 690 rgba[2][j] = tile->data.color[ty][tx][2]; 691 rgba[3][j] = tile->data.color[ty][tx][3]; 692 if (0) 693 { 694 debug_printf("Get texel %f %f %f %f from %s\n", 695 rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j], 696 pf_name(texture->format)); 697 } 698 } 699} 700 701 702/** 703 * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' 704 * When we sampled the depth texture, the depth value was put into all 705 * RGBA channels. We look at the red channel here. 706 * \param rgba quad of (depth) texel values 707 * \param p texture 'P' components for four pixels in quad 708 * \param j which pixel in the quad to test [0..3] 709 */ 710static INLINE void 711shadow_compare(const struct pipe_sampler_state *sampler, 712 float rgba[NUM_CHANNELS][QUAD_SIZE], 713 const float p[QUAD_SIZE], 714 uint j) 715{ 716 int k; 717 switch (sampler->compare_func) { 718 case PIPE_FUNC_LESS: 719 k = p[j] < rgba[0][j]; 720 break; 721 case PIPE_FUNC_LEQUAL: 722 k = p[j] <= rgba[0][j]; 723 break; 724 case PIPE_FUNC_GREATER: 725 k = p[j] > rgba[0][j]; 726 break; 727 case PIPE_FUNC_GEQUAL: 728 k = p[j] >= rgba[0][j]; 729 break; 730 case PIPE_FUNC_EQUAL: 731 k = p[j] == rgba[0][j]; 732 break; 733 case PIPE_FUNC_NOTEQUAL: 734 k = p[j] != rgba[0][j]; 735 break; 736 case PIPE_FUNC_ALWAYS: 737 k = 1; 738 break; 739 case PIPE_FUNC_NEVER: 740 k = 0; 741 break; 742 default: 743 k = 0; 744 assert(0); 745 break; 746 } 747 748 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 749 rgba[0][j] = rgba[1][j] = rgba[2][j] = (float) k; 750 rgba[3][j] = 1.0F; 751} 752 753 754/** 755 * As above, but do four z/texture comparisons. 756 */ 757static INLINE void 758shadow_compare4(const struct pipe_sampler_state *sampler, 759 float rgba[NUM_CHANNELS][QUAD_SIZE], 760 const float p[QUAD_SIZE]) 761{ 762 int j, k0, k1, k2, k3; 763 float val; 764 765 /* compare four texcoords vs. four texture samples */ 766 switch (sampler->compare_func) { 767 case PIPE_FUNC_LESS: 768 k0 = p[0] < rgba[0][0]; 769 k1 = p[1] < rgba[0][1]; 770 k2 = p[2] < rgba[0][2]; 771 k3 = p[3] < rgba[0][3]; 772 break; 773 case PIPE_FUNC_LEQUAL: 774 k0 = p[0] <= rgba[0][0]; 775 k1 = p[1] <= rgba[0][1]; 776 k2 = p[2] <= rgba[0][2]; 777 k3 = p[3] <= rgba[0][3]; 778 break; 779 case PIPE_FUNC_GREATER: 780 k0 = p[0] > rgba[0][0]; 781 k1 = p[1] > rgba[0][1]; 782 k2 = p[2] > rgba[0][2]; 783 k3 = p[3] > rgba[0][3]; 784 break; 785 case PIPE_FUNC_GEQUAL: 786 k0 = p[0] >= rgba[0][0]; 787 k1 = p[1] >= rgba[0][1]; 788 k2 = p[2] >= rgba[0][2]; 789 k3 = p[3] >= rgba[0][3]; 790 break; 791 case PIPE_FUNC_EQUAL: 792 k0 = p[0] == rgba[0][0]; 793 k1 = p[1] == rgba[0][1]; 794 k2 = p[2] == rgba[0][2]; 795 k3 = p[3] == rgba[0][3]; 796 break; 797 case PIPE_FUNC_NOTEQUAL: 798 k0 = p[0] != rgba[0][0]; 799 k1 = p[1] != rgba[0][1]; 800 k2 = p[2] != rgba[0][2]; 801 k3 = p[3] != rgba[0][3]; 802 break; 803 case PIPE_FUNC_ALWAYS: 804 k0 = k1 = k2 = k3 = 1; 805 break; 806 case PIPE_FUNC_NEVER: 807 k0 = k1 = k2 = k3 = 0; 808 break; 809 default: 810 k0 = k1 = k2 = k3 = 0; 811 assert(0); 812 break; 813 } 814 815 /* convert four pass/fail values to an intensity in [0,1] */ 816 val = 0.25F * (k0 + k1 + k2 + k3); 817 818 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 819 for (j = 0; j < 4; j++) { 820 rgba[0][j] = rgba[1][j] = rgba[2][j] = val; 821 rgba[3][j] = 1.0F; 822 } 823} 824 825 826/** 827 * Common code for sampling 1D/2D/cube textures. 828 * Could probably extend for 3D... 829 */ 830static void 831sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, 832 const float s[QUAD_SIZE], 833 const float t[QUAD_SIZE], 834 const float p[QUAD_SIZE], 835 boolean computeLambda, 836 float lodbias, 837 float rgba[NUM_CHANNELS][QUAD_SIZE], 838 const unsigned faces[4]) 839{ 840 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 841 const struct pipe_texture *texture = samp->texture; 842 const struct pipe_sampler_state *sampler = samp->sampler; 843 unsigned level0, level1, j, imgFilter; 844 int width, height; 845 float levelBlend; 846 847 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 848 &level0, &level1, &levelBlend, &imgFilter); 849 850 assert(sampler->normalized_coords); 851 852 width = texture->width[level0]; 853 height = texture->height[level0]; 854 855 assert(width > 0); 856 857 switch (imgFilter) { 858 case PIPE_TEX_FILTER_NEAREST: 859 { 860 int x[4], y[4]; 861 nearest_texcoord_4(sampler->wrap_s, s, width, x); 862 nearest_texcoord_4(sampler->wrap_t, t, height, y); 863 864 for (j = 0; j < QUAD_SIZE; j++) { 865 get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j); 866 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 867 shadow_compare(sampler, rgba, p, j); 868 } 869 870 if (level0 != level1) { 871 /* get texels from second mipmap level and blend */ 872 float rgba2[4][4]; 873 unsigned c; 874 x[j] /= 2; 875 y[j] /= 2; 876 get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0, 877 rgba2, j); 878 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 879 shadow_compare(sampler, rgba2, p, j); 880 } 881 882 for (c = 0; c < NUM_CHANNELS; c++) { 883 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 884 } 885 } 886 } 887 } 888 break; 889 case PIPE_TEX_FILTER_LINEAR: 890 case PIPE_TEX_FILTER_ANISO: 891 { 892 int x0[4], y0[4], x1[4], y1[4]; 893 float xw[4], yw[4]; /* weights */ 894 895 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); 896 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); 897 898 for (j = 0; j < QUAD_SIZE; j++) { 899 float tx[4][4]; /* texels */ 900 int c; 901 get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0); 902 get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1); 903 get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2); 904 get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3); 905 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 906 shadow_compare4(sampler, tx, p); 907 } 908 909 /* interpolate R, G, B, A */ 910 for (c = 0; c < 4; c++) { 911 rgba[c][j] = lerp_2d(xw[j], yw[j], 912 tx[c][0], tx[c][1], 913 tx[c][2], tx[c][3]); 914 } 915 916 if (level0 != level1) { 917 /* get texels from second mipmap level and blend */ 918 float rgba2[4][4]; 919 x0[j] /= 2; 920 y0[j] /= 2; 921 x1[j] /= 2; 922 y1[j] /= 2; 923 get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0); 924 get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1); 925 get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2); 926 get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3); 927 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 928 shadow_compare4(sampler, tx, p); 929 } 930 931 /* interpolate R, G, B, A */ 932 for (c = 0; c < 4; c++) { 933 rgba2[c][j] = lerp_2d(xw[j], yw[j], 934 tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 935 } 936 937 for (c = 0; c < NUM_CHANNELS; c++) { 938 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 939 } 940 } 941 } 942 } 943 break; 944 default: 945 assert(0); 946 } 947} 948 949 950static INLINE void 951sp_get_samples_1d(const struct tgsi_sampler *sampler, 952 const float s[QUAD_SIZE], 953 const float t[QUAD_SIZE], 954 const float p[QUAD_SIZE], 955 boolean computeLambda, 956 float lodbias, 957 float rgba[NUM_CHANNELS][QUAD_SIZE]) 958{ 959 static const unsigned faces[4] = {0, 0, 0, 0}; 960 static const float tzero[4] = {0, 0, 0, 0}; 961 sp_get_samples_2d_common(sampler, s, tzero, NULL, 962 computeLambda, lodbias, rgba, faces); 963} 964 965 966static INLINE void 967sp_get_samples_2d(const struct tgsi_sampler *sampler, 968 const float s[QUAD_SIZE], 969 const float t[QUAD_SIZE], 970 const float p[QUAD_SIZE], 971 boolean computeLambda, 972 float lodbias, 973 float rgba[NUM_CHANNELS][QUAD_SIZE]) 974{ 975 static const unsigned faces[4] = {0, 0, 0, 0}; 976 sp_get_samples_2d_common(sampler, s, t, p, 977 computeLambda, lodbias, rgba, faces); 978} 979 980 981static INLINE void 982sp_get_samples_3d(const struct tgsi_sampler *tgsi_sampler, 983 const float s[QUAD_SIZE], 984 const float t[QUAD_SIZE], 985 const float p[QUAD_SIZE], 986 boolean computeLambda, 987 float lodbias, 988 float rgba[NUM_CHANNELS][QUAD_SIZE]) 989{ 990 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 991 const struct pipe_texture *texture = samp->texture; 992 const struct pipe_sampler_state *sampler = samp->sampler; 993 /* get/map pipe_surfaces corresponding to 3D tex slices */ 994 unsigned level0, level1, j, imgFilter; 995 int width, height, depth; 996 float levelBlend; 997 const uint face = 0; 998 999 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 1000 &level0, &level1, &levelBlend, &imgFilter); 1001 1002 assert(sampler->normalized_coords); 1003 1004 width = texture->width[level0]; 1005 height = texture->height[level0]; 1006 depth = texture->depth[level0]; 1007 1008 assert(width > 0); 1009 assert(height > 0); 1010 assert(depth > 0); 1011 1012 switch (imgFilter) { 1013 case PIPE_TEX_FILTER_NEAREST: 1014 { 1015 int x[4], y[4], z[4]; 1016 nearest_texcoord_4(sampler->wrap_s, s, width, x); 1017 nearest_texcoord_4(sampler->wrap_t, t, height, y); 1018 nearest_texcoord_4(sampler->wrap_r, p, depth, z); 1019 for (j = 0; j < QUAD_SIZE; j++) { 1020 get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j); 1021 if (level0 != level1) { 1022 /* get texels from second mipmap level and blend */ 1023 float rgba2[4][4]; 1024 unsigned c; 1025 x[j] /= 2; 1026 y[j] /= 2; 1027 z[j] /= 2; 1028 get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j); 1029 for (c = 0; c < NUM_CHANNELS; c++) { 1030 rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]); 1031 } 1032 } 1033 } 1034 } 1035 break; 1036 case PIPE_TEX_FILTER_LINEAR: 1037 case PIPE_TEX_FILTER_ANISO: 1038 { 1039 int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4]; 1040 float xw[4], yw[4], zw[4]; /* interpolation weights */ 1041 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); 1042 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); 1043 linear_texcoord_4(sampler->wrap_r, p, depth, z0, z1, zw); 1044 1045 for (j = 0; j < QUAD_SIZE; j++) { 1046 int c; 1047 float tx0[4][4], tx1[4][4]; 1048 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0); 1049 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1); 1050 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2); 1051 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3); 1052 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0); 1053 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1); 1054 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2); 1055 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3); 1056 1057 /* interpolate R, G, B, A */ 1058 for (c = 0; c < 4; c++) { 1059 rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1060 tx0[c][0], tx0[c][1], 1061 tx0[c][2], tx0[c][3], 1062 tx1[c][0], tx1[c][1], 1063 tx1[c][2], tx1[c][3]); 1064 } 1065 1066 if (level0 != level1) { 1067 /* get texels from second mipmap level and blend */ 1068 float rgba2[4][4]; 1069 x0[j] /= 2; 1070 y0[j] /= 2; 1071 z0[j] /= 2; 1072 x1[j] /= 2; 1073 y1[j] /= 2; 1074 z1[j] /= 2; 1075 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0); 1076 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1); 1077 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2); 1078 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3); 1079 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0); 1080 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1); 1081 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2); 1082 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3); 1083 1084 /* interpolate R, G, B, A */ 1085 for (c = 0; c < 4; c++) { 1086 rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1087 tx0[c][0], tx0[c][1], 1088 tx0[c][2], tx0[c][3], 1089 tx1[c][0], tx1[c][1], 1090 tx1[c][2], tx1[c][3]); 1091 } 1092 1093 /* blend mipmap levels */ 1094 for (c = 0; c < NUM_CHANNELS; c++) { 1095 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 1096 } 1097 } 1098 } 1099 } 1100 break; 1101 default: 1102 assert(0); 1103 } 1104} 1105 1106 1107static void 1108sp_get_samples_cube(const struct tgsi_sampler *sampler, 1109 const float s[QUAD_SIZE], 1110 const float t[QUAD_SIZE], 1111 const float p[QUAD_SIZE], 1112 boolean computeLambda, 1113 float lodbias, 1114 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1115{ 1116 unsigned faces[QUAD_SIZE], j; 1117 float ssss[4], tttt[4]; 1118 for (j = 0; j < QUAD_SIZE; j++) { 1119 faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j); 1120 } 1121 sp_get_samples_2d_common(sampler, ssss, tttt, NULL, 1122 computeLambda, lodbias, rgba, faces); 1123} 1124 1125 1126static void 1127sp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler, 1128 const float s[QUAD_SIZE], 1129 const float t[QUAD_SIZE], 1130 const float p[QUAD_SIZE], 1131 boolean computeLambda, 1132 float lodbias, 1133 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1134{ 1135 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 1136 const struct pipe_texture *texture = samp->texture; 1137 const struct pipe_sampler_state *sampler = samp->sampler; 1138 const uint face = 0; 1139 unsigned level0, level1, j, imgFilter; 1140 int width, height; 1141 float levelBlend; 1142 1143 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 1144 &level0, &level1, &levelBlend, &imgFilter); 1145 1146 /* texture RECTS cannot be mipmapped */ 1147 assert(level0 == level1); 1148 1149 width = texture->width[level0]; 1150 height = texture->height[level0]; 1151 1152 assert(width > 0); 1153 1154 switch (imgFilter) { 1155 case PIPE_TEX_FILTER_NEAREST: 1156 { 1157 int x[4], y[4]; 1158 nearest_texcoord_unnorm_4(sampler->wrap_s, s, width, x); 1159 nearest_texcoord_unnorm_4(sampler->wrap_t, t, height, y); 1160 for (j = 0; j < QUAD_SIZE; j++) { 1161 get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j); 1162 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 1163 shadow_compare(sampler, rgba, p, j); 1164 } 1165 } 1166 } 1167 break; 1168 case PIPE_TEX_FILTER_LINEAR: 1169 case PIPE_TEX_FILTER_ANISO: 1170 { 1171 int x0[4], y0[4], x1[4], y1[4]; 1172 float xw[4], yw[4]; /* weights */ 1173 linear_texcoord_unnorm_4(sampler->wrap_s, s, width, x0, x1, xw); 1174 linear_texcoord_unnorm_4(sampler->wrap_t, t, height, y0, y1, yw); 1175 for (j = 0; j < QUAD_SIZE; j++) { 1176 float tx[4][4]; /* texels */ 1177 int c; 1178 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], 0, tx, 0); 1179 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], 0, tx, 1); 1180 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2); 1181 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3); 1182 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 1183 shadow_compare4(sampler, tx, p); 1184 } 1185 for (c = 0; c < 4; c++) { 1186 rgba[c][j] = lerp_2d(xw[j], yw[j], 1187 tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 1188 } 1189 } 1190 } 1191 break; 1192 default: 1193 assert(0); 1194 } 1195} 1196 1197 1198/** 1199 * Common code for vertex/fragment program texture sampling. 1200 */ 1201static INLINE void 1202sp_get_samples(struct tgsi_sampler *tgsi_sampler, 1203 const float s[QUAD_SIZE], 1204 const float t[QUAD_SIZE], 1205 const float p[QUAD_SIZE], 1206 boolean computeLambda, 1207 float lodbias, 1208 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1209{ 1210 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 1211 const struct pipe_texture *texture = samp->texture; 1212 const struct pipe_sampler_state *sampler = samp->sampler; 1213 1214 if (!texture) 1215 return; 1216 1217 switch (texture->target) { 1218 case PIPE_TEXTURE_1D: 1219 assert(sampler->normalized_coords); 1220 sp_get_samples_1d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1221 break; 1222 case PIPE_TEXTURE_2D: 1223 if (sampler->normalized_coords) 1224 sp_get_samples_2d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1225 else 1226 sp_get_samples_rect(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1227 break; 1228 case PIPE_TEXTURE_3D: 1229 assert(sampler->normalized_coords); 1230 sp_get_samples_3d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1231 break; 1232 case PIPE_TEXTURE_CUBE: 1233 assert(sampler->normalized_coords); 1234 sp_get_samples_cube(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1235 break; 1236 default: 1237 assert(0); 1238 } 1239 1240#if 0 /* DEBUG */ 1241 { 1242 int i; 1243 printf("Sampled at %f, %f, %f:\n", s[0], t[0], p[0]); 1244 for (i = 0; i < 4; i++) { 1245 printf("Frag %d: %f %f %f %f\n", i, 1246 rgba[0][i], 1247 rgba[1][i], 1248 rgba[2][i], 1249 rgba[3][i]); 1250 } 1251 } 1252#endif 1253} 1254 1255 1256/** 1257 * Called via tgsi_sampler::get_samples() when running a fragment shader. 1258 * Get four filtered RGBA values from the sampler's texture. 1259 */ 1260void 1261sp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler, 1262 const float s[QUAD_SIZE], 1263 const float t[QUAD_SIZE], 1264 const float p[QUAD_SIZE], 1265 float lodbias, 1266 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1267{ 1268 sp_get_samples(tgsi_sampler, s, t, p, TRUE, lodbias, rgba); 1269} 1270 1271 1272/** 1273 * Called via tgsi_sampler::get_samples() when running a vertex shader. 1274 * Get four filtered RGBA values from the sampler's texture. 1275 */ 1276void 1277sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler, 1278 const float s[QUAD_SIZE], 1279 const float t[QUAD_SIZE], 1280 const float p[QUAD_SIZE], 1281 float lodbias, 1282 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1283{ 1284 sp_get_samples(tgsi_sampler, s, t, p, FALSE, lodbias, rgba); 1285} 1286