lp_tex_sample.c revision 946f432a08112148d743eb9faf6b27bb8cc7fa76
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 "lp_context.h" 37#include "lp_quad.h" 38#include "lp_surface.h" 39#include "lp_texture.h" 40#include "lp_tex_sample.h" 41#include "lp_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 lp_tile_cache.c and merge with the 663 * lp_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 lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler); 671 struct llvmpipe_context *lp = samp->lp; 672 const uint unit = samp->unit; 673 const struct pipe_texture *texture = lp->texture[unit]; 674 const struct pipe_sampler_state *sampler = lp->sampler[unit]; 675 676 if (x < 0 || x >= (int) texture->width[level] || 677 y < 0 || y >= (int) texture->height[level] || 678 z < 0 || z >= (int) texture->depth[level]) { 679 rgba[0][j] = sampler->border_color[0]; 680 rgba[1][j] = sampler->border_color[1]; 681 rgba[2][j] = sampler->border_color[2]; 682 rgba[3][j] = sampler->border_color[3]; 683 } 684 else { 685 const int tx = x % TILE_SIZE; 686 const int ty = y % TILE_SIZE; 687 const struct llvmpipe_cached_tile *tile 688 = lp_get_cached_tile_tex(lp, samp->cache, 689 x, y, z, face, level); 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 833lp_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 lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler); 843 const struct llvmpipe_context *lp = samp->lp; 844 const uint unit = samp->unit; 845 const struct pipe_texture *texture = lp->texture[unit]; 846 const struct pipe_sampler_state *sampler = lp->sampler[unit]; 847 unsigned level0, level1, j, imgFilter; 848 int width, height; 849 float levelBlend; 850 851 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 852 &level0, &level1, &levelBlend, &imgFilter); 853 854 assert(sampler->normalized_coords); 855 856 width = texture->width[level0]; 857 height = texture->height[level0]; 858 859 assert(width > 0); 860 861 switch (imgFilter) { 862 case PIPE_TEX_FILTER_NEAREST: 863 { 864 int x[4], y[4]; 865 nearest_texcoord_4(sampler->wrap_s, s, width, x); 866 nearest_texcoord_4(sampler->wrap_t, t, height, y); 867 868 for (j = 0; j < QUAD_SIZE; j++) { 869 get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j); 870 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 871 shadow_compare(sampler, rgba, p, j); 872 } 873 874 if (level0 != level1) { 875 /* get texels from second mipmap level and blend */ 876 float rgba2[4][4]; 877 unsigned c; 878 x[j] /= 2; 879 y[j] /= 2; 880 get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0, 881 rgba2, j); 882 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 883 shadow_compare(sampler, rgba2, p, j); 884 } 885 886 for (c = 0; c < NUM_CHANNELS; c++) { 887 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 888 } 889 } 890 } 891 } 892 break; 893 case PIPE_TEX_FILTER_LINEAR: 894 case PIPE_TEX_FILTER_ANISO: 895 { 896 int x0[4], y0[4], x1[4], y1[4]; 897 float xw[4], yw[4]; /* weights */ 898 899 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); 900 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); 901 902 for (j = 0; j < QUAD_SIZE; j++) { 903 float tx[4][4]; /* texels */ 904 int c; 905 get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0); 906 get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1); 907 get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2); 908 get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3); 909 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 910 shadow_compare4(sampler, tx, p); 911 } 912 913 /* interpolate R, G, B, A */ 914 for (c = 0; c < 4; c++) { 915 rgba[c][j] = lerp_2d(xw[j], yw[j], 916 tx[c][0], tx[c][1], 917 tx[c][2], tx[c][3]); 918 } 919 920 if (level0 != level1) { 921 /* get texels from second mipmap level and blend */ 922 float rgba2[4][4]; 923 x0[j] /= 2; 924 y0[j] /= 2; 925 x1[j] /= 2; 926 y1[j] /= 2; 927 get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0); 928 get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1); 929 get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2); 930 get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3); 931 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ 932 shadow_compare4(sampler, tx, p); 933 } 934 935 /* interpolate R, G, B, A */ 936 for (c = 0; c < 4; c++) { 937 rgba2[c][j] = lerp_2d(xw[j], yw[j], 938 tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 939 } 940 941 for (c = 0; c < NUM_CHANNELS; c++) { 942 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 943 } 944 } 945 } 946 } 947 break; 948 default: 949 assert(0); 950 } 951} 952 953 954static INLINE void 955lp_get_samples_1d(const struct tgsi_sampler *sampler, 956 const float s[QUAD_SIZE], 957 const float t[QUAD_SIZE], 958 const float p[QUAD_SIZE], 959 boolean computeLambda, 960 float lodbias, 961 float rgba[NUM_CHANNELS][QUAD_SIZE]) 962{ 963 static const unsigned faces[4] = {0, 0, 0, 0}; 964 static const float tzero[4] = {0, 0, 0, 0}; 965 lp_get_samples_2d_common(sampler, s, tzero, NULL, 966 computeLambda, lodbias, rgba, faces); 967} 968 969 970static INLINE void 971lp_get_samples_2d(const struct tgsi_sampler *sampler, 972 const float s[QUAD_SIZE], 973 const float t[QUAD_SIZE], 974 const float p[QUAD_SIZE], 975 boolean computeLambda, 976 float lodbias, 977 float rgba[NUM_CHANNELS][QUAD_SIZE]) 978{ 979 static const unsigned faces[4] = {0, 0, 0, 0}; 980 lp_get_samples_2d_common(sampler, s, t, p, 981 computeLambda, lodbias, rgba, faces); 982} 983 984 985static INLINE void 986lp_get_samples_3d(const struct tgsi_sampler *tgsi_sampler, 987 const float s[QUAD_SIZE], 988 const float t[QUAD_SIZE], 989 const float p[QUAD_SIZE], 990 boolean computeLambda, 991 float lodbias, 992 float rgba[NUM_CHANNELS][QUAD_SIZE]) 993{ 994 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler); 995 const struct llvmpipe_context *lp = samp->lp; 996 const uint unit = samp->unit; 997 const struct pipe_texture *texture = lp->texture[unit]; 998 const struct pipe_sampler_state *sampler = lp->sampler[unit]; 999 /* get/map pipe_surfaces corresponding to 3D tex slices */ 1000 unsigned level0, level1, j, imgFilter; 1001 int width, height, depth; 1002 float levelBlend; 1003 const uint face = 0; 1004 1005 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 1006 &level0, &level1, &levelBlend, &imgFilter); 1007 1008 assert(sampler->normalized_coords); 1009 1010 width = texture->width[level0]; 1011 height = texture->height[level0]; 1012 depth = texture->depth[level0]; 1013 1014 assert(width > 0); 1015 assert(height > 0); 1016 assert(depth > 0); 1017 1018 switch (imgFilter) { 1019 case PIPE_TEX_FILTER_NEAREST: 1020 { 1021 int x[4], y[4], z[4]; 1022 nearest_texcoord_4(sampler->wrap_s, s, width, x); 1023 nearest_texcoord_4(sampler->wrap_t, t, height, y); 1024 nearest_texcoord_4(sampler->wrap_r, p, depth, z); 1025 for (j = 0; j < QUAD_SIZE; j++) { 1026 get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j); 1027 if (level0 != level1) { 1028 /* get texels from second mipmap level and blend */ 1029 float rgba2[4][4]; 1030 unsigned c; 1031 x[j] /= 2; 1032 y[j] /= 2; 1033 z[j] /= 2; 1034 get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j); 1035 for (c = 0; c < NUM_CHANNELS; c++) { 1036 rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]); 1037 } 1038 } 1039 } 1040 } 1041 break; 1042 case PIPE_TEX_FILTER_LINEAR: 1043 case PIPE_TEX_FILTER_ANISO: 1044 { 1045 int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4]; 1046 float xw[4], yw[4], zw[4]; /* interpolation weights */ 1047 linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); 1048 linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); 1049 linear_texcoord_4(sampler->wrap_r, p, depth, z0, z1, zw); 1050 1051 for (j = 0; j < QUAD_SIZE; j++) { 1052 int c; 1053 float tx0[4][4], tx1[4][4]; 1054 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0); 1055 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1); 1056 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2); 1057 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3); 1058 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0); 1059 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1); 1060 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2); 1061 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3); 1062 1063 /* interpolate R, G, B, A */ 1064 for (c = 0; c < 4; c++) { 1065 rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1066 tx0[c][0], tx0[c][1], 1067 tx0[c][2], tx0[c][3], 1068 tx1[c][0], tx1[c][1], 1069 tx1[c][2], tx1[c][3]); 1070 } 1071 1072 if (level0 != level1) { 1073 /* get texels from second mipmap level and blend */ 1074 float rgba2[4][4]; 1075 x0[j] /= 2; 1076 y0[j] /= 2; 1077 z0[j] /= 2; 1078 x1[j] /= 2; 1079 y1[j] /= 2; 1080 z1[j] /= 2; 1081 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0); 1082 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1); 1083 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2); 1084 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3); 1085 get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0); 1086 get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1); 1087 get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2); 1088 get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3); 1089 1090 /* interpolate R, G, B, A */ 1091 for (c = 0; c < 4; c++) { 1092 rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j], 1093 tx0[c][0], tx0[c][1], 1094 tx0[c][2], tx0[c][3], 1095 tx1[c][0], tx1[c][1], 1096 tx1[c][2], tx1[c][3]); 1097 } 1098 1099 /* blend mipmap levels */ 1100 for (c = 0; c < NUM_CHANNELS; c++) { 1101 rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); 1102 } 1103 } 1104 } 1105 } 1106 break; 1107 default: 1108 assert(0); 1109 } 1110} 1111 1112 1113static void 1114lp_get_samples_cube(const struct tgsi_sampler *sampler, 1115 const float s[QUAD_SIZE], 1116 const float t[QUAD_SIZE], 1117 const float p[QUAD_SIZE], 1118 boolean computeLambda, 1119 float lodbias, 1120 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1121{ 1122 unsigned faces[QUAD_SIZE], j; 1123 float ssss[4], tttt[4]; 1124 for (j = 0; j < QUAD_SIZE; j++) { 1125 faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j); 1126 } 1127 lp_get_samples_2d_common(sampler, ssss, tttt, NULL, 1128 computeLambda, lodbias, rgba, faces); 1129} 1130 1131 1132static void 1133lp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler, 1134 const float s[QUAD_SIZE], 1135 const float t[QUAD_SIZE], 1136 const float p[QUAD_SIZE], 1137 boolean computeLambda, 1138 float lodbias, 1139 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1140{ 1141 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler); 1142 const struct llvmpipe_context *lp = samp->lp; 1143 const uint unit = samp->unit; 1144 const struct pipe_texture *texture = lp->texture[unit]; 1145 const struct pipe_sampler_state *sampler = lp->sampler[unit]; 1146 const uint face = 0; 1147 unsigned level0, level1, j, imgFilter; 1148 int width, height; 1149 float levelBlend; 1150 1151 choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, 1152 &level0, &level1, &levelBlend, &imgFilter); 1153 1154 /* texture RECTS cannot be mipmapped */ 1155 assert(level0 == level1); 1156 1157 width = texture->width[level0]; 1158 height = texture->height[level0]; 1159 1160 assert(width > 0); 1161 1162 switch (imgFilter) { 1163 case PIPE_TEX_FILTER_NEAREST: 1164 { 1165 int x[4], y[4]; 1166 nearest_texcoord_unnorm_4(sampler->wrap_s, s, width, x); 1167 nearest_texcoord_unnorm_4(sampler->wrap_t, t, height, y); 1168 for (j = 0; j < QUAD_SIZE; j++) { 1169 get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j); 1170 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 1171 shadow_compare(sampler, rgba, p, j); 1172 } 1173 } 1174 } 1175 break; 1176 case PIPE_TEX_FILTER_LINEAR: 1177 case PIPE_TEX_FILTER_ANISO: 1178 { 1179 int x0[4], y0[4], x1[4], y1[4]; 1180 float xw[4], yw[4]; /* weights */ 1181 linear_texcoord_unnorm_4(sampler->wrap_s, s, width, x0, x1, xw); 1182 linear_texcoord_unnorm_4(sampler->wrap_t, t, height, y0, y1, yw); 1183 for (j = 0; j < QUAD_SIZE; j++) { 1184 float tx[4][4]; /* texels */ 1185 int c; 1186 get_texel(tgsi_sampler, face, level0, x0[j], y0[j], 0, tx, 0); 1187 get_texel(tgsi_sampler, face, level0, x1[j], y0[j], 0, tx, 1); 1188 get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2); 1189 get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3); 1190 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 1191 shadow_compare4(sampler, tx, p); 1192 } 1193 for (c = 0; c < 4; c++) { 1194 rgba[c][j] = lerp_2d(xw[j], yw[j], 1195 tx[c][0], tx[c][1], tx[c][2], tx[c][3]); 1196 } 1197 } 1198 } 1199 break; 1200 default: 1201 assert(0); 1202 } 1203} 1204 1205 1206/** 1207 * Common code for vertex/fragment program texture sampling. 1208 */ 1209static INLINE void 1210lp_get_samples(struct tgsi_sampler *tgsi_sampler, 1211 const float s[QUAD_SIZE], 1212 const float t[QUAD_SIZE], 1213 const float p[QUAD_SIZE], 1214 boolean computeLambda, 1215 float lodbias, 1216 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1217{ 1218 const struct lp_shader_sampler *samp = lp_shader_sampler(tgsi_sampler); 1219 const struct llvmpipe_context *lp = samp->lp; 1220 const uint unit = samp->unit; 1221 const struct pipe_texture *texture = lp->texture[unit]; 1222 const struct pipe_sampler_state *sampler = lp->sampler[unit]; 1223 1224 if (!texture) 1225 return; 1226 1227 switch (texture->target) { 1228 case PIPE_TEXTURE_1D: 1229 assert(sampler->normalized_coords); 1230 lp_get_samples_1d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1231 break; 1232 case PIPE_TEXTURE_2D: 1233 if (sampler->normalized_coords) 1234 lp_get_samples_2d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1235 else 1236 lp_get_samples_rect(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1237 break; 1238 case PIPE_TEXTURE_3D: 1239 assert(sampler->normalized_coords); 1240 lp_get_samples_3d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1241 break; 1242 case PIPE_TEXTURE_CUBE: 1243 assert(sampler->normalized_coords); 1244 lp_get_samples_cube(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba); 1245 break; 1246 default: 1247 assert(0); 1248 } 1249 1250#if 0 /* DEBUG */ 1251 { 1252 int i; 1253 printf("Sampled at %f, %f, %f:\n", s[0], t[0], p[0]); 1254 for (i = 0; i < 4; i++) { 1255 printf("Frag %d: %f %f %f %f\n", i, 1256 rgba[0][i], 1257 rgba[1][i], 1258 rgba[2][i], 1259 rgba[3][i]); 1260 } 1261 } 1262#endif 1263} 1264 1265 1266/** 1267 * Called via tgsi_sampler::get_samples() when running a fragment shader. 1268 * Get four filtered RGBA values from the sampler's texture. 1269 */ 1270void 1271lp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler, 1272 const float s[QUAD_SIZE], 1273 const float t[QUAD_SIZE], 1274 const float p[QUAD_SIZE], 1275 float lodbias, 1276 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1277{ 1278 lp_get_samples(tgsi_sampler, s, t, p, TRUE, lodbias, rgba); 1279} 1280 1281 1282/** 1283 * Called via tgsi_sampler::get_samples() when running a vertex shader. 1284 * Get four filtered RGBA values from the sampler's texture. 1285 */ 1286void 1287lp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler, 1288 const float s[QUAD_SIZE], 1289 const float t[QUAD_SIZE], 1290 const float p[QUAD_SIZE], 1291 float lodbias, 1292 float rgba[NUM_CHANNELS][QUAD_SIZE]) 1293{ 1294 lp_get_samples(tgsi_sampler, s, t, p, FALSE, lodbias, rgba); 1295} 1296