sp_tex_sample.c revision f911c3b9897b90132c8621a72bfeb824eb3b01e5
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 unsigned tx = x % TILE_SIZE; 684 const unsigned ty = y % TILE_SIZE; 685 const struct softpipe_cached_tile *tile; 686 687 tile = sp_get_cached_tile_tex(samp->cache, 688 tile_address(x, y, z, face, level)); 689 690 rgba[0][j] = tile->data.color[ty][tx][0]; 691 rgba[1][j] = tile->data.color[ty][tx][1]; 692 rgba[2][j] = tile->data.color[ty][tx][2]; 693 rgba[3][j] = tile->data.color[ty][tx][3]; 694 if (0) 695 { 696 debug_printf("Get texel %f %f %f %f from %s\n", 697 rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j], 698 pf_name(texture->format)); 699 } 700 } 701} 702 703 704/** 705 * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' 706 * When we sampled the depth texture, the depth value was put into all 707 * RGBA channels. We look at the red channel here. 708 * \param rgba quad of (depth) texel values 709 * \param p texture 'P' components for four pixels in quad 710 * \param j which pixel in the quad to test [0..3] 711 */ 712static INLINE void 713shadow_compare(const struct pipe_sampler_state *sampler, 714 float rgba[NUM_CHANNELS][QUAD_SIZE], 715 const float p[QUAD_SIZE], 716 uint j) 717{ 718 int k; 719 switch (sampler->compare_func) { 720 case PIPE_FUNC_LESS: 721 k = p[j] < rgba[0][j]; 722 break; 723 case PIPE_FUNC_LEQUAL: 724 k = p[j] <= rgba[0][j]; 725 break; 726 case PIPE_FUNC_GREATER: 727 k = p[j] > rgba[0][j]; 728 break; 729 case PIPE_FUNC_GEQUAL: 730 k = p[j] >= rgba[0][j]; 731 break; 732 case PIPE_FUNC_EQUAL: 733 k = p[j] == rgba[0][j]; 734 break; 735 case PIPE_FUNC_NOTEQUAL: 736 k = p[j] != rgba[0][j]; 737 break; 738 case PIPE_FUNC_ALWAYS: 739 k = 1; 740 break; 741 case PIPE_FUNC_NEVER: 742 k = 0; 743 break; 744 default: 745 k = 0; 746 assert(0); 747 break; 748 } 749 750 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 751 rgba[0][j] = rgba[1][j] = rgba[2][j] = (float) k; 752 rgba[3][j] = 1.0F; 753} 754 755 756/** 757 * As above, but do four z/texture comparisons. 758 */ 759static INLINE void 760shadow_compare4(const struct pipe_sampler_state *sampler, 761 float rgba[NUM_CHANNELS][QUAD_SIZE], 762 const float p[QUAD_SIZE]) 763{ 764 int j, k0, k1, k2, k3; 765 float val; 766 767 /* compare four texcoords vs. four texture samples */ 768 switch (sampler->compare_func) { 769 case PIPE_FUNC_LESS: 770 k0 = p[0] < rgba[0][0]; 771 k1 = p[1] < rgba[0][1]; 772 k2 = p[2] < rgba[0][2]; 773 k3 = p[3] < rgba[0][3]; 774 break; 775 case PIPE_FUNC_LEQUAL: 776 k0 = p[0] <= rgba[0][0]; 777 k1 = p[1] <= rgba[0][1]; 778 k2 = p[2] <= rgba[0][2]; 779 k3 = p[3] <= rgba[0][3]; 780 break; 781 case PIPE_FUNC_GREATER: 782 k0 = p[0] > rgba[0][0]; 783 k1 = p[1] > rgba[0][1]; 784 k2 = p[2] > rgba[0][2]; 785 k3 = p[3] > rgba[0][3]; 786 break; 787 case PIPE_FUNC_GEQUAL: 788 k0 = p[0] >= rgba[0][0]; 789 k1 = p[1] >= rgba[0][1]; 790 k2 = p[2] >= rgba[0][2]; 791 k3 = p[3] >= rgba[0][3]; 792 break; 793 case PIPE_FUNC_EQUAL: 794 k0 = p[0] == rgba[0][0]; 795 k1 = p[1] == rgba[0][1]; 796 k2 = p[2] == rgba[0][2]; 797 k3 = p[3] == rgba[0][3]; 798 break; 799 case PIPE_FUNC_NOTEQUAL: 800 k0 = p[0] != rgba[0][0]; 801 k1 = p[1] != rgba[0][1]; 802 k2 = p[2] != rgba[0][2]; 803 k3 = p[3] != rgba[0][3]; 804 break; 805 case PIPE_FUNC_ALWAYS: 806 k0 = k1 = k2 = k3 = 1; 807 break; 808 case PIPE_FUNC_NEVER: 809 k0 = k1 = k2 = k3 = 0; 810 break; 811 default: 812 k0 = k1 = k2 = k3 = 0; 813 assert(0); 814 break; 815 } 816 817 /* convert four pass/fail values to an intensity in [0,1] */ 818 val = 0.25F * (k0 + k1 + k2 + k3); 819 820 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 821 for (j = 0; j < 4; j++) { 822 rgba[0][j] = rgba[1][j] = rgba[2][j] = val; 823 rgba[3][j] = 1.0F; 824 } 825} 826 827 828/** 829 * Common code for sampling 1D/2D/cube textures. 830 * Could probably extend for 3D... 831 */ 832static void 833sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, 834 const float s[QUAD_SIZE], 835 const float t[QUAD_SIZE], 836 const float p[QUAD_SIZE], 837 boolean computeLambda, 838 float lodbias, 839 float rgba[NUM_CHANNELS][QUAD_SIZE], 840 const unsigned faces[4]) 841{ 842 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 843 const struct pipe_texture *texture = samp->texture; 844 const struct pipe_sampler_state *sampler = samp->sampler; 845 unsigned level0, level1, j, imgFilter; 846 int width, height; 847 float levelBlend; 848 849 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 850 &level0, &level1, &levelBlend, &imgFilter); 851 852 assert(sampler->normalized_coords); 853 854 width = texture->width[level0]; 855 height = texture->height[level0]; 856 857 assert(width > 0); 858 859 switch (imgFilter) { 860 case PIPE_TEX_FILTER_NEAREST: 861 { 862 int x[4], y[4]; 863 nearest_texcoord_4(sampler->wrap_s, s, width, x); 864 nearest_texcoord_4(sampler->wrap_t, t, height, y); 865 866 for (j = 0; j < QUAD_SIZE; j++) { 867 get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j); 868 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 869 shadow_compare(sampler, rgba, p, j); 870 } 871 872 if (level0 != level1) { 873 /* get texels from second mipmap level and blend */ 874 float rgba2[4][4]; 875 unsigned c; 876 x[j] /= 2; 877 y[j] /= 2; 878 get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0, 879 rgba2, j); 880 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 881 shadow_compare(sampler, rgba2, p, j); 882 } 883 884 for (c = 0; c < NUM_CHANNELS; c++) { 885 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 886 } 887 } 888 } 889 } 890 break; 891 case PIPE_TEX_FILTER_LINEAR: 892 case PIPE_TEX_FILTER_ANISO: 893 { 894 int x0[4], y0[4], x1[4], y1[4]; 895 float xw[4], yw[4]; /* weights */ 896 897 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); 898 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); 899 900 for (j = 0; j < QUAD_SIZE; j++) { 901 float tx[4][4]; /* texels */ 902 int c; 903 get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0); 904 get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1); 905 get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2); 906 get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3); 907 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 908 shadow_compare4(sampler, tx, p); 909 } 910 911 /* interpolate R, G, B, A */ 912 for (c = 0; c < 4; c++) { 913 rgba[c][j] = lerp_2d(xw[j], yw[j], 914 tx[c][0], tx[c][1], 915 tx[c][2], tx[c][3]); 916 } 917 918 if (level0 != level1) { 919 /* get texels from second mipmap level and blend */ 920 float rgba2[4][4]; 921 x0[j] /= 2; 922 y0[j] /= 2; 923 x1[j] /= 2; 924 y1[j] /= 2; 925 get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0); 926 get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1); 927 get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2); 928 get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3); 929 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 930 shadow_compare4(sampler, tx, p); 931 } 932 933 /* interpolate R, G, B, A */ 934 for (c = 0; c < 4; c++) { 935 rgba2[c][j] = lerp_2d(xw[j], yw[j], 936 tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 937 } 938 939 for (c = 0; c < NUM_CHANNELS; c++) { 940 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 941 } 942 } 943 } 944 } 945 break; 946 default: 947 assert(0); 948 } 949} 950 951 952static INLINE void 953sp_get_samples_1d(const struct tgsi_sampler *sampler, 954 const float s[QUAD_SIZE], 955 const float t[QUAD_SIZE], 956 const float p[QUAD_SIZE], 957 boolean computeLambda, 958 float lodbias, 959 float rgba[NUM_CHANNELS][QUAD_SIZE]) 960{ 961 static const unsigned faces[4] = {0, 0, 0, 0}; 962 static const float tzero[4] = {0, 0, 0, 0}; 963 sp_get_samples_2d_common(sampler, s, tzero, NULL, 964 computeLambda, lodbias, rgba, faces); 965} 966 967 968static INLINE void 969sp_get_samples_2d(const struct tgsi_sampler *sampler, 970 const float s[QUAD_SIZE], 971 const float t[QUAD_SIZE], 972 const float p[QUAD_SIZE], 973 boolean computeLambda, 974 float lodbias, 975 float rgba[NUM_CHANNELS][QUAD_SIZE]) 976{ 977 static const unsigned faces[4] = {0, 0, 0, 0}; 978 sp_get_samples_2d_common(sampler, s, t, p, 979 computeLambda, lodbias, rgba, faces); 980} 981 982 983static INLINE void 984sp_get_samples_3d(const struct tgsi_sampler *tgsi_sampler, 985 const float s[QUAD_SIZE], 986 const float t[QUAD_SIZE], 987 const float p[QUAD_SIZE], 988 boolean computeLambda, 989 float lodbias, 990 float rgba[NUM_CHANNELS][QUAD_SIZE]) 991{ 992 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 993 const struct pipe_texture *texture = samp->texture; 994 const struct pipe_sampler_state *sampler = samp->sampler; 995 /* get/map pipe_surfaces corresponding to 3D tex slices */ 996 unsigned level0, level1, j, imgFilter; 997 int width, height, depth; 998 float levelBlend; 999 const uint face = 0; 1000 1001 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 1002 &level0, &level1, &levelBlend, &imgFilter); 1003 1004 assert(sampler->normalized_coords); 1005 1006 width = texture->width[level0]; 1007 height = texture->height[level0]; 1008 depth = texture->depth[level0]; 1009 1010 assert(width > 0); 1011 assert(height > 0); 1012 assert(depth > 0); 1013 1014 switch (imgFilter) { 1015 case PIPE_TEX_FILTER_NEAREST: 1016 { 1017 int x[4], y[4], z[4]; 1018 nearest_texcoord_4(sampler->wrap_s, s, width, x); 1019 nearest_texcoord_4(sampler->wrap_t, t, height, y); 1020 nearest_texcoord_4(sampler->wrap_r, p, depth, z); 1021 for (j = 0; j < QUAD_SIZE; j++) { 1022 get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j); 1023 if (level0 != level1) { 1024 /* get texels from second mipmap level and blend */ 1025 float rgba2[4][4]; 1026 unsigned c; 1027 x[j] /= 2; 1028 y[j] /= 2; 1029 z[j] /= 2; 1030 get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j); 1031 for (c = 0; c < NUM_CHANNELS; c++) { 1032 rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]); 1033 } 1034 } 1035 } 1036 } 1037 break; 1038 case PIPE_TEX_FILTER_LINEAR: 1039 case PIPE_TEX_FILTER_ANISO: 1040 { 1041 int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4]; 1042 float xw[4], yw[4], zw[4]; /* interpolation weights */ 1043 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); 1044 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); 1045 linear_texcoord_4(sampler->wrap_r, p, depth, z0, z1, zw); 1046 1047 for (j = 0; j < QUAD_SIZE; j++) { 1048 int c; 1049 float tx0[4][4], tx1[4][4]; 1050 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0); 1051 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1); 1052 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2); 1053 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3); 1054 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0); 1055 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1); 1056 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2); 1057 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3); 1058 1059 /* interpolate R, G, B, A */ 1060 for (c = 0; c < 4; c++) { 1061 rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1062 tx0[c][0], tx0[c][1], 1063 tx0[c][2], tx0[c][3], 1064 tx1[c][0], tx1[c][1], 1065 tx1[c][2], tx1[c][3]); 1066 } 1067 1068 if (level0 != level1) { 1069 /* get texels from second mipmap level and blend */ 1070 float rgba2[4][4]; 1071 x0[j] /= 2; 1072 y0[j] /= 2; 1073 z0[j] /= 2; 1074 x1[j] /= 2; 1075 y1[j] /= 2; 1076 z1[j] /= 2; 1077 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0); 1078 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1); 1079 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2); 1080 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3); 1081 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0); 1082 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1); 1083 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2); 1084 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3); 1085 1086 /* interpolate R, G, B, A */ 1087 for (c = 0; c < 4; c++) { 1088 rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1089 tx0[c][0], tx0[c][1], 1090 tx0[c][2], tx0[c][3], 1091 tx1[c][0], tx1[c][1], 1092 tx1[c][2], tx1[c][3]); 1093 } 1094 1095 /* blend mipmap levels */ 1096 for (c = 0; c < NUM_CHANNELS; c++) { 1097 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 1098 } 1099 } 1100 } 1101 } 1102 break; 1103 default: 1104 assert(0); 1105 } 1106} 1107 1108 1109static void 1110sp_get_samples_cube(const struct tgsi_sampler *sampler, 1111 const float s[QUAD_SIZE], 1112 const float t[QUAD_SIZE], 1113 const float p[QUAD_SIZE], 1114 boolean computeLambda, 1115 float lodbias, 1116 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1117{ 1118 unsigned faces[QUAD_SIZE], j; 1119 float ssss[4], tttt[4]; 1120 for (j = 0; j < QUAD_SIZE; j++) { 1121 faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j); 1122 } 1123 sp_get_samples_2d_common(sampler, ssss, tttt, NULL, 1124 computeLambda, lodbias, rgba, faces); 1125} 1126 1127 1128static void 1129sp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler, 1130 const float s[QUAD_SIZE], 1131 const float t[QUAD_SIZE], 1132 const float p[QUAD_SIZE], 1133 boolean computeLambda, 1134 float lodbias, 1135 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1136{ 1137 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 1138 const struct pipe_texture *texture = samp->texture; 1139 const struct pipe_sampler_state *sampler = samp->sampler; 1140 const uint face = 0; 1141 unsigned level0, level1, j, imgFilter; 1142 int width, height; 1143 float levelBlend; 1144 1145 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 1146 &level0, &level1, &levelBlend, &imgFilter); 1147 1148 /* texture RECTS cannot be mipmapped */ 1149 assert(level0 == level1); 1150 1151 width = texture->width[level0]; 1152 height = texture->height[level0]; 1153 1154 assert(width > 0); 1155 1156 switch (imgFilter) { 1157 case PIPE_TEX_FILTER_NEAREST: 1158 { 1159 int x[4], y[4]; 1160 nearest_texcoord_unnorm_4(sampler->wrap_s, s, width, x); 1161 nearest_texcoord_unnorm_4(sampler->wrap_t, t, height, y); 1162 for (j = 0; j < QUAD_SIZE; j++) { 1163 get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j); 1164 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 1165 shadow_compare(sampler, rgba, p, j); 1166 } 1167 } 1168 } 1169 break; 1170 case PIPE_TEX_FILTER_LINEAR: 1171 case PIPE_TEX_FILTER_ANISO: 1172 { 1173 int x0[4], y0[4], x1[4], y1[4]; 1174 float xw[4], yw[4]; /* weights */ 1175 linear_texcoord_unnorm_4(sampler->wrap_s, s, width, x0, x1, xw); 1176 linear_texcoord_unnorm_4(sampler->wrap_t, t, height, y0, y1, yw); 1177 for (j = 0; j < QUAD_SIZE; j++) { 1178 float tx[4][4]; /* texels */ 1179 int c; 1180 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], 0, tx, 0); 1181 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], 0, tx, 1); 1182 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2); 1183 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3); 1184 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 1185 shadow_compare4(sampler, tx, p); 1186 } 1187 for (c = 0; c < 4; c++) { 1188 rgba[c][j] = lerp_2d(xw[j], yw[j], 1189 tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 1190 } 1191 } 1192 } 1193 break; 1194 default: 1195 assert(0); 1196 } 1197} 1198 1199 1200/** 1201 * Common code for vertex/fragment program texture sampling. 1202 */ 1203static INLINE void 1204sp_get_samples(struct tgsi_sampler *tgsi_sampler, 1205 const float s[QUAD_SIZE], 1206 const float t[QUAD_SIZE], 1207 const float p[QUAD_SIZE], 1208 boolean computeLambda, 1209 float lodbias, 1210 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1211{ 1212 const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); 1213 const struct pipe_texture *texture = samp->texture; 1214 const struct pipe_sampler_state *sampler = samp->sampler; 1215 1216 if (!texture) 1217 return; 1218 1219 switch (texture->target) { 1220 case PIPE_TEXTURE_1D: 1221 assert(sampler->normalized_coords); 1222 sp_get_samples_1d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1223 break; 1224 case PIPE_TEXTURE_2D: 1225 if (sampler->normalized_coords) 1226 sp_get_samples_2d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1227 else 1228 sp_get_samples_rect(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1229 break; 1230 case PIPE_TEXTURE_3D: 1231 assert(sampler->normalized_coords); 1232 sp_get_samples_3d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1233 break; 1234 case PIPE_TEXTURE_CUBE: 1235 assert(sampler->normalized_coords); 1236 sp_get_samples_cube(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1237 break; 1238 default: 1239 assert(0); 1240 } 1241 1242#if 0 /* DEBUG */ 1243 { 1244 int i; 1245 printf("Sampled at %f, %f, %f:\n", s[0], t[0], p[0]); 1246 for (i = 0; i < 4; i++) { 1247 printf("Frag %d: %f %f %f %f\n", i, 1248 rgba[0][i], 1249 rgba[1][i], 1250 rgba[2][i], 1251 rgba[3][i]); 1252 } 1253 } 1254#endif 1255} 1256 1257 1258/** 1259 * Called via tgsi_sampler::get_samples() when running a fragment shader. 1260 * Get four filtered RGBA values from the sampler's texture. 1261 */ 1262void 1263sp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler, 1264 const float s[QUAD_SIZE], 1265 const float t[QUAD_SIZE], 1266 const float p[QUAD_SIZE], 1267 float lodbias, 1268 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1269{ 1270 sp_get_samples(tgsi_sampler, s, t, p, TRUE, lodbias, rgba); 1271} 1272 1273 1274/** 1275 * Called via tgsi_sampler::get_samples() when running a vertex shader. 1276 * Get four filtered RGBA values from the sampler's texture. 1277 */ 1278void 1279sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler, 1280 const float s[QUAD_SIZE], 1281 const float t[QUAD_SIZE], 1282 const float p[QUAD_SIZE], 1283 float lodbias, 1284 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1285{ 1286 sp_get_samples(tgsi_sampler, s, t, p, FALSE, lodbias, rgba); 1287} 1288