Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygens_texfilter.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.3 00004 * 00005 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 #include "main/glheader.h" 00027 #include "main/context.h" 00028 #include "main/colormac.h" 00029 #include "main/imports.h" 00030 #include "main/texformat.h" 00031 00032 #include "s_context.h" 00033 #include "s_texfilter.h" 00034 00035 00036 /* 00037 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes 00038 * see 1-pixel bands of improperly weighted linear-filtered textures. 00039 * The tests/texwrap.c demo is a good test. 00040 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0. 00041 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x). 00042 */ 00043 #define FRAC(f) ((f) - IFLOOR(f)) 00044 00045 00049 #define ILERP_SCALE 65536.0F 00050 #define ILERP_SHIFT 16 00051 00052 00056 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) ) 00057 #define ILERP(IT, A, B) ( (A) + (((IT) * ((B) - (A))) >> ILERP_SHIFT) ) 00058 00059 00068 static INLINE GLfloat 00069 lerp_2d(GLfloat a, GLfloat b, 00070 GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11) 00071 { 00072 const GLfloat temp0 = LERP(a, v00, v10); 00073 const GLfloat temp1 = LERP(a, v01, v11); 00074 return LERP(b, temp0, temp1); 00075 } 00076 00077 00082 static INLINE GLint 00083 ilerp_2d(GLint ia, GLint ib, 00084 GLint v00, GLint v10, GLint v01, GLint v11) 00085 { 00086 /* fixed point interpolants in [0, ILERP_SCALE] */ 00087 const GLint temp0 = ILERP(ia, v00, v10); 00088 const GLint temp1 = ILERP(ia, v01, v11); 00089 return ILERP(ib, temp0, temp1); 00090 } 00091 00092 00097 static INLINE GLfloat 00098 lerp_3d(GLfloat a, GLfloat b, GLfloat c, 00099 GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110, 00100 GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111) 00101 { 00102 const GLfloat temp00 = LERP(a, v000, v100); 00103 const GLfloat temp10 = LERP(a, v010, v110); 00104 const GLfloat temp01 = LERP(a, v001, v101); 00105 const GLfloat temp11 = LERP(a, v011, v111); 00106 const GLfloat temp0 = LERP(b, temp00, temp10); 00107 const GLfloat temp1 = LERP(b, temp01, temp11); 00108 return LERP(c, temp0, temp1); 00109 } 00110 00111 00116 static INLINE GLint 00117 ilerp_3d(GLint ia, GLint ib, GLint ic, 00118 GLint v000, GLint v100, GLint v010, GLint v110, 00119 GLint v001, GLint v101, GLint v011, GLint v111) 00120 { 00121 /* fixed point interpolants in [0, ILERP_SCALE] */ 00122 const GLint temp00 = ILERP(ia, v000, v100); 00123 const GLint temp10 = ILERP(ia, v010, v110); 00124 const GLint temp01 = ILERP(ia, v001, v101); 00125 const GLint temp11 = ILERP(ia, v011, v111); 00126 const GLint temp0 = ILERP(ib, temp00, temp10); 00127 const GLint temp1 = ILERP(ib, temp01, temp11); 00128 return ILERP(ic, temp0, temp1); 00129 } 00130 00131 00135 static INLINE void 00136 lerp_rgba(GLchan result[4], GLfloat t, const GLchan a[4], const GLchan b[4]) 00137 { 00138 #if CHAN_TYPE == GL_FLOAT 00139 result[0] = LERP(t, a[0], b[0]); 00140 result[1] = LERP(t, a[1], b[1]); 00141 result[2] = LERP(t, a[2], b[2]); 00142 result[3] = LERP(t, a[3], b[3]); 00143 #elif CHAN_TYPE == GL_UNSIGNED_SHORT 00144 result[0] = (GLchan) (LERP(t, a[0], b[0]) + 0.5); 00145 result[1] = (GLchan) (LERP(t, a[1], b[1]) + 0.5); 00146 result[2] = (GLchan) (LERP(t, a[2], b[2]) + 0.5); 00147 result[3] = (GLchan) (LERP(t, a[3], b[3]) + 0.5); 00148 #else 00149 /* fixed point interpolants in [0, ILERP_SCALE] */ 00150 const GLint it = IROUND_POS(t * ILERP_SCALE); 00151 ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE); 00152 result[0] = ILERP(it, a[0], b[0]); 00153 result[1] = ILERP(it, a[1], b[1]); 00154 result[2] = ILERP(it, a[2], b[2]); 00155 result[3] = ILERP(it, a[3], b[3]); 00156 #endif 00157 } 00158 00159 00163 static INLINE void 00164 lerp_rgba_2d(GLchan result[4], GLfloat a, GLfloat b, 00165 const GLchan t00[4], const GLchan t10[4], 00166 const GLchan t01[4], const GLchan t11[4]) 00167 { 00168 #if CHAN_TYPE == GL_FLOAT 00169 result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]); 00170 result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]); 00171 result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]); 00172 result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]); 00173 #elif CHAN_TYPE == GL_UNSIGNED_SHORT 00174 result[0] = (GLchan) (lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]) + 0.5); 00175 result[1] = (GLchan) (lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]) + 0.5); 00176 result[2] = (GLchan) (lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]) + 0.5); 00177 result[3] = (GLchan) (lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]) + 0.5); 00178 #else 00179 const GLint ia = IROUND_POS(a * ILERP_SCALE); 00180 const GLint ib = IROUND_POS(b * ILERP_SCALE); 00181 ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE); 00182 result[0] = ilerp_2d(ia, ib, t00[0], t10[0], t01[0], t11[0]); 00183 result[1] = ilerp_2d(ia, ib, t00[1], t10[1], t01[1], t11[1]); 00184 result[2] = ilerp_2d(ia, ib, t00[2], t10[2], t01[2], t11[2]); 00185 result[3] = ilerp_2d(ia, ib, t00[3], t10[3], t01[3], t11[3]); 00186 #endif 00187 } 00188 00189 00193 static INLINE void 00194 lerp_rgba_3d(GLchan result[4], GLfloat a, GLfloat b, GLfloat c, 00195 const GLchan t000[4], const GLchan t100[4], 00196 const GLchan t010[4], const GLchan t110[4], 00197 const GLchan t001[4], const GLchan t101[4], 00198 const GLchan t011[4], const GLchan t111[4]) 00199 { 00200 GLuint k; 00201 /* compiler should unroll these short loops */ 00202 #if CHAN_TYPE == GL_FLOAT 00203 for (k = 0; k < 4; k++) { 00204 result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k], 00205 t001[k], t101[k], t011[k], t111[k]); 00206 } 00207 #elif CHAN_TYPE == GL_UNSIGNED_SHORT 00208 for (k = 0; k < 4; k++) { 00209 result[k] = (GLchan)(lerp_3d(a, b, c, 00210 t000[k], t100[k], t010[k], t110[k], 00211 t001[k], t101[k], t011[k], t111[k]) + 0.5F); 00212 } 00213 #else 00214 GLint ia = IROUND_POS(a * ILERP_SCALE); 00215 GLint ib = IROUND_POS(b * ILERP_SCALE); 00216 GLint ic = IROUND_POS(c * ILERP_SCALE); 00217 for (k = 0; k < 4; k++) { 00218 result[k] = ilerp_3d(ia, ib, ic, t000[k], t100[k], t010[k], t110[k], 00219 t001[k], t101[k], t011[k], t111[k]); 00220 } 00221 #endif 00222 } 00223 00224 00229 #define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B)) 00230 00231 00242 static INLINE void 00243 linear_texel_locations(GLenum wrapMode, 00244 const struct gl_texture_image *img, 00245 GLint size, GLfloat s, 00246 GLint *i0, GLint *i1, GLfloat *weight) 00247 { 00248 GLfloat u; 00249 switch (wrapMode) { 00250 case GL_REPEAT: 00251 u = s * size - 0.5F; 00252 if (img->_IsPowerOfTwo) { 00253 *i0 = IFLOOR(u) & (size - 1); 00254 *i1 = (*i0 + 1) & (size - 1); 00255 } 00256 else { 00257 *i0 = REMAINDER(IFLOOR(u), size); 00258 *i1 = REMAINDER(*i0 + 1, size); 00259 } 00260 break; 00261 case GL_CLAMP_TO_EDGE: 00262 if (s <= 0.0F) 00263 u = 0.0F; 00264 else if (s >= 1.0F) 00265 u = (GLfloat) size; 00266 else 00267 u = s * size; 00268 u -= 0.5F; 00269 *i0 = IFLOOR(u); 00270 *i1 = *i0 + 1; 00271 if (*i0 < 0) 00272 *i0 = 0; 00273 if (*i1 >= (GLint) size) 00274 *i1 = size - 1; 00275 break; 00276 case GL_CLAMP_TO_BORDER: 00277 { 00278 const GLfloat min = -1.0F / (2.0F * size); 00279 const GLfloat max = 1.0F - min; 00280 if (s <= min) 00281 u = min * size; 00282 else if (s >= max) 00283 u = max * size; 00284 else 00285 u = s * size; 00286 u -= 0.5F; 00287 *i0 = IFLOOR(u); 00288 *i1 = *i0 + 1; 00289 } 00290 break; 00291 case GL_MIRRORED_REPEAT: 00292 { 00293 const GLint flr = IFLOOR(s); 00294 if (flr & 1) 00295 u = 1.0F - (s - (GLfloat) flr); 00296 else 00297 u = s - (GLfloat) flr; 00298 u = (u * size) - 0.5F; 00299 *i0 = IFLOOR(u); 00300 *i1 = *i0 + 1; 00301 if (*i0 < 0) 00302 *i0 = 0; 00303 if (*i1 >= (GLint) size) 00304 *i1 = size - 1; 00305 } 00306 break; 00307 case GL_MIRROR_CLAMP_EXT: 00308 u = FABSF(s); 00309 if (u >= 1.0F) 00310 u = (GLfloat) size; 00311 else 00312 u *= size; 00313 u -= 0.5F; 00314 *i0 = IFLOOR(u); 00315 *i1 = *i0 + 1; 00316 break; 00317 case GL_MIRROR_CLAMP_TO_EDGE_EXT: 00318 u = FABSF(s); 00319 if (u >= 1.0F) 00320 u = (GLfloat) size; 00321 else 00322 u *= size; 00323 u -= 0.5F; 00324 *i0 = IFLOOR(u); 00325 *i1 = *i0 + 1; 00326 if (*i0 < 0) 00327 *i0 = 0; 00328 if (*i1 >= (GLint) size) 00329 *i1 = size - 1; 00330 break; 00331 case GL_MIRROR_CLAMP_TO_BORDER_EXT: 00332 { 00333 const GLfloat min = -1.0F / (2.0F * size); 00334 const GLfloat max = 1.0F - min; 00335 u = FABSF(s); 00336 if (u <= min) 00337 u = min * size; 00338 else if (u >= max) 00339 u = max * size; 00340 else 00341 u *= size; 00342 u -= 0.5F; 00343 *i0 = IFLOOR(u); 00344 *i1 = *i0 + 1; 00345 } 00346 break; 00347 case GL_CLAMP: 00348 if (s <= 0.0F) 00349 u = 0.0F; 00350 else if (s >= 1.0F) 00351 u = (GLfloat) size; 00352 else 00353 u = s * size; 00354 u -= 0.5F; 00355 *i0 = IFLOOR(u); 00356 *i1 = *i0 + 1; 00357 break; 00358 default: 00359 _mesa_problem(NULL, "Bad wrap mode"); 00360 u = 0.0F; 00361 } 00362 *weight = FRAC(u); 00363 } 00364 00365 00369 static INLINE GLint 00370 nearest_texel_location(GLenum wrapMode, 00371 const struct gl_texture_image *img, 00372 GLint size, GLfloat s) 00373 { 00374 GLint i; 00375 00376 switch (wrapMode) { 00377 case GL_REPEAT: 00378 /* s limited to [0,1) */ 00379 /* i limited to [0,size-1] */ 00380 i = IFLOOR(s * size); 00381 if (img->_IsPowerOfTwo) 00382 i &= (size - 1); 00383 else 00384 i = REMAINDER(i, size); 00385 return i; 00386 case GL_CLAMP_TO_EDGE: 00387 { 00388 /* s limited to [min,max] */ 00389 /* i limited to [0, size-1] */ 00390 const GLfloat min = 1.0F / (2.0F * size); 00391 const GLfloat max = 1.0F - min; 00392 if (s < min) 00393 i = 0; 00394 else if (s > max) 00395 i = size - 1; 00396 else 00397 i = IFLOOR(s * size); 00398 } 00399 return i; 00400 case GL_CLAMP_TO_BORDER: 00401 { 00402 /* s limited to [min,max] */ 00403 /* i limited to [-1, size] */ 00404 const GLfloat min = -1.0F / (2.0F * size); 00405 const GLfloat max = 1.0F - min; 00406 if (s <= min) 00407 i = -1; 00408 else if (s >= max) 00409 i = size; 00410 else 00411 i = IFLOOR(s * size); 00412 } 00413 return i; 00414 case GL_MIRRORED_REPEAT: 00415 { 00416 const GLfloat min = 1.0F / (2.0F * size); 00417 const GLfloat max = 1.0F - min; 00418 const GLint flr = IFLOOR(s); 00419 GLfloat u; 00420 if (flr & 1) 00421 u = 1.0F - (s - (GLfloat) flr); 00422 else 00423 u = s - (GLfloat) flr; 00424 if (u < min) 00425 i = 0; 00426 else if (u > max) 00427 i = size - 1; 00428 else 00429 i = IFLOOR(u * size); 00430 } 00431 return i; 00432 case GL_MIRROR_CLAMP_EXT: 00433 { 00434 /* s limited to [0,1] */ 00435 /* i limited to [0,size-1] */ 00436 const GLfloat u = FABSF(s); 00437 if (u <= 0.0F) 00438 i = 0; 00439 else if (u >= 1.0F) 00440 i = size - 1; 00441 else 00442 i = IFLOOR(u * size); 00443 } 00444 return i; 00445 case GL_MIRROR_CLAMP_TO_EDGE_EXT: 00446 { 00447 /* s limited to [min,max] */ 00448 /* i limited to [0, size-1] */ 00449 const GLfloat min = 1.0F / (2.0F * size); 00450 const GLfloat max = 1.0F - min; 00451 const GLfloat u = FABSF(s); 00452 if (u < min) 00453 i = 0; 00454 else if (u > max) 00455 i = size - 1; 00456 else 00457 i = IFLOOR(u * size); 00458 } 00459 return i; 00460 case GL_MIRROR_CLAMP_TO_BORDER_EXT: 00461 { 00462 /* s limited to [min,max] */ 00463 /* i limited to [0, size-1] */ 00464 const GLfloat min = -1.0F / (2.0F * size); 00465 const GLfloat max = 1.0F - min; 00466 const GLfloat u = FABSF(s); 00467 if (u < min) 00468 i = -1; 00469 else if (u > max) 00470 i = size; 00471 else 00472 i = IFLOOR(u * size); 00473 } 00474 return i; 00475 case GL_CLAMP: 00476 /* s limited to [0,1] */ 00477 /* i limited to [0,size-1] */ 00478 if (s <= 0.0F) 00479 i = 0; 00480 else if (s >= 1.0F) 00481 i = size - 1; 00482 else 00483 i = IFLOOR(s * size); 00484 return i; 00485 default: 00486 _mesa_problem(NULL, "Bad wrap mode"); 00487 return 0; 00488 } 00489 } 00490 00491 00492 /* Power of two image sizes only */ 00493 static INLINE void 00494 linear_repeat_texel_location(GLuint size, GLfloat s, 00495 GLint *i0, GLint *i1, GLfloat *weight) 00496 { 00497 GLfloat u = s * size - 0.5F; 00498 *i0 = IFLOOR(u) & (size - 1); 00499 *i1 = (*i0 + 1) & (size - 1); 00500 *weight = FRAC(u); 00501 } 00502 00503 00508 static INLINE GLint 00509 linear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) 00510 { 00511 if (lambda < 0.0F) 00512 return tObj->BaseLevel; 00513 else if (lambda > tObj->_MaxLambda) 00514 return (GLint) (tObj->BaseLevel + tObj->_MaxLambda); 00515 else 00516 return (GLint) (tObj->BaseLevel + lambda); 00517 } 00518 00519 00523 static INLINE GLint 00524 nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) 00525 { 00526 GLfloat l; 00527 GLint level; 00528 if (lambda <= 0.5F) 00529 l = 0.0F; 00530 else if (lambda > tObj->_MaxLambda + 0.4999F) 00531 l = tObj->_MaxLambda + 0.4999F; 00532 else 00533 l = lambda; 00534 level = (GLint) (tObj->BaseLevel + l + 0.5F); 00535 if (level > tObj->_MaxLevel) 00536 level = tObj->_MaxLevel; 00537 return level; 00538 } 00539 00540 00541 00542 /* 00543 * Bitflags for texture border color sampling. 00544 */ 00545 #define I0BIT 1 00546 #define I1BIT 2 00547 #define J0BIT 4 00548 #define J1BIT 8 00549 #define K0BIT 16 00550 #define K1BIT 32 00551 00552 00553 00559 static INLINE void 00560 compute_min_mag_ranges(const struct gl_texture_object *tObj, 00561 GLuint n, const GLfloat lambda[], 00562 GLuint *minStart, GLuint *minEnd, 00563 GLuint *magStart, GLuint *magEnd) 00564 { 00565 GLfloat minMagThresh; 00566 00567 /* we shouldn't be here if minfilter == magfilter */ 00568 ASSERT(tObj->MinFilter != tObj->MagFilter); 00569 00570 /* This bit comes from the OpenGL spec: */ 00571 if (tObj->MagFilter == GL_LINEAR 00572 && (tObj->MinFilter == GL_NEAREST_MIPMAP_NEAREST || 00573 tObj->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) { 00574 minMagThresh = 0.5F; 00575 } 00576 else { 00577 minMagThresh = 0.0F; 00578 } 00579 00580 #if 0 00581 /* DEBUG CODE: Verify that lambda[] is monotonic. 00582 * We can't really use this because the inaccuracy in the LOG2 function 00583 * causes this test to fail, yet the resulting texturing is correct. 00584 */ 00585 if (n > 1) { 00586 GLuint i; 00587 printf("lambda delta = %g\n", lambda[0] - lambda[n-1]); 00588 if (lambda[0] >= lambda[n-1]) { /* decreasing */ 00589 for (i = 0; i < n - 1; i++) { 00590 ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10)); 00591 } 00592 } 00593 else { /* increasing */ 00594 for (i = 0; i < n - 1; i++) { 00595 ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10)); 00596 } 00597 } 00598 } 00599 #endif /* DEBUG */ 00600 00601 if (lambda[0] <= minMagThresh && (n <= 1 || lambda[n-1] <= minMagThresh)) { 00602 /* magnification for whole span */ 00603 *magStart = 0; 00604 *magEnd = n; 00605 *minStart = *minEnd = 0; 00606 } 00607 else if (lambda[0] > minMagThresh && (n <=1 || lambda[n-1] > minMagThresh)) { 00608 /* minification for whole span */ 00609 *minStart = 0; 00610 *minEnd = n; 00611 *magStart = *magEnd = 0; 00612 } 00613 else { 00614 /* a mix of minification and magnification */ 00615 GLuint i; 00616 if (lambda[0] > minMagThresh) { 00617 /* start with minification */ 00618 for (i = 1; i < n; i++) { 00619 if (lambda[i] <= minMagThresh) 00620 break; 00621 } 00622 *minStart = 0; 00623 *minEnd = i; 00624 *magStart = i; 00625 *magEnd = n; 00626 } 00627 else { 00628 /* start with magnification */ 00629 for (i = 1; i < n; i++) { 00630 if (lambda[i] > minMagThresh) 00631 break; 00632 } 00633 *magStart = 0; 00634 *magEnd = i; 00635 *minStart = i; 00636 *minEnd = n; 00637 } 00638 } 00639 00640 #if 0 00641 /* Verify the min/mag Start/End values 00642 * We don't use this either (see above) 00643 */ 00644 { 00645 GLint i; 00646 for (i = 0; i < n; i++) { 00647 if (lambda[i] > minMagThresh) { 00648 /* minification */ 00649 ASSERT(i >= *minStart); 00650 ASSERT(i < *minEnd); 00651 } 00652 else { 00653 /* magnification */ 00654 ASSERT(i >= *magStart); 00655 ASSERT(i < *magEnd); 00656 } 00657 } 00658 } 00659 #endif 00660 } 00661 00662 00663 /**********************************************************************/ 00664 /* 1-D Texture Sampling Functions */ 00665 /**********************************************************************/ 00666 00670 static INLINE void 00671 sample_1d_nearest(GLcontext *ctx, 00672 const struct gl_texture_object *tObj, 00673 const struct gl_texture_image *img, 00674 const GLfloat texcoord[4], GLchan rgba[4]) 00675 { 00676 const GLint width = img->Width2; /* without border, power of two */ 00677 GLint i; 00678 i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]); 00679 /* skip over the border, if any */ 00680 i += img->Border; 00681 if (i < 0 || i >= (GLint) img->Width) { 00682 /* Need this test for GL_CLAMP_TO_BORDER mode */ 00683 COPY_CHAN4(rgba, tObj->_BorderChan); 00684 } 00685 else { 00686 img->FetchTexelc(img, i, 0, 0, rgba); 00687 } 00688 } 00689 00690 00694 static INLINE void 00695 sample_1d_linear(GLcontext *ctx, 00696 const struct gl_texture_object *tObj, 00697 const struct gl_texture_image *img, 00698 const GLfloat texcoord[4], GLchan rgba[4]) 00699 { 00700 const GLint width = img->Width2; 00701 GLint i0, i1; 00702 GLbitfield useBorderColor = 0x0; 00703 GLfloat a; 00704 GLchan t0[4], t1[4]; /* texels */ 00705 00706 linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a); 00707 00708 if (img->Border) { 00709 i0 += img->Border; 00710 i1 += img->Border; 00711 } 00712 else { 00713 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; 00714 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; 00715 } 00716 00717 /* fetch texel colors */ 00718 if (useBorderColor & I0BIT) { 00719 COPY_CHAN4(t0, tObj->_BorderChan); 00720 } 00721 else { 00722 img->FetchTexelc(img, i0, 0, 0, t0); 00723 } 00724 if (useBorderColor & I1BIT) { 00725 COPY_CHAN4(t1, tObj->_BorderChan); 00726 } 00727 else { 00728 img->FetchTexelc(img, i1, 0, 0, t1); 00729 } 00730 00731 lerp_rgba(rgba, a, t0, t1); 00732 } 00733 00734 00735 static void 00736 sample_1d_nearest_mipmap_nearest(GLcontext *ctx, 00737 const struct gl_texture_object *tObj, 00738 GLuint n, const GLfloat texcoord[][4], 00739 const GLfloat lambda[], GLchan rgba[][4]) 00740 { 00741 GLuint i; 00742 ASSERT(lambda != NULL); 00743 for (i = 0; i < n; i++) { 00744 GLint level = nearest_mipmap_level(tObj, lambda[i]); 00745 sample_1d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); 00746 } 00747 } 00748 00749 00750 static void 00751 sample_1d_linear_mipmap_nearest(GLcontext *ctx, 00752 const struct gl_texture_object *tObj, 00753 GLuint n, const GLfloat texcoord[][4], 00754 const GLfloat lambda[], GLchan rgba[][4]) 00755 { 00756 GLuint i; 00757 ASSERT(lambda != NULL); 00758 for (i = 0; i < n; i++) { 00759 GLint level = nearest_mipmap_level(tObj, lambda[i]); 00760 sample_1d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); 00761 } 00762 } 00763 00764 00765 static void 00766 sample_1d_nearest_mipmap_linear(GLcontext *ctx, 00767 const struct gl_texture_object *tObj, 00768 GLuint n, const GLfloat texcoord[][4], 00769 const GLfloat lambda[], GLchan rgba[][4]) 00770 { 00771 GLuint i; 00772 ASSERT(lambda != NULL); 00773 for (i = 0; i < n; i++) { 00774 GLint level = linear_mipmap_level(tObj, lambda[i]); 00775 if (level >= tObj->_MaxLevel) { 00776 sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 00777 texcoord[i], rgba[i]); 00778 } 00779 else { 00780 GLchan t0[4], t1[4]; 00781 const GLfloat f = FRAC(lambda[i]); 00782 sample_1d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 00783 sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 00784 lerp_rgba(rgba[i], f, t0, t1); 00785 } 00786 } 00787 } 00788 00789 00790 static void 00791 sample_1d_linear_mipmap_linear(GLcontext *ctx, 00792 const struct gl_texture_object *tObj, 00793 GLuint n, const GLfloat texcoord[][4], 00794 const GLfloat lambda[], GLchan rgba[][4]) 00795 { 00796 GLuint i; 00797 ASSERT(lambda != NULL); 00798 for (i = 0; i < n; i++) { 00799 GLint level = linear_mipmap_level(tObj, lambda[i]); 00800 if (level >= tObj->_MaxLevel) { 00801 sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 00802 texcoord[i], rgba[i]); 00803 } 00804 else { 00805 GLchan t0[4], t1[4]; 00806 const GLfloat f = FRAC(lambda[i]); 00807 sample_1d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 00808 sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 00809 lerp_rgba(rgba[i], f, t0, t1); 00810 } 00811 } 00812 } 00813 00814 00816 static void 00817 sample_nearest_1d( GLcontext *ctx, 00818 const struct gl_texture_object *tObj, GLuint n, 00819 const GLfloat texcoords[][4], const GLfloat lambda[], 00820 GLchan rgba[][4] ) 00821 { 00822 GLuint i; 00823 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 00824 (void) lambda; 00825 for (i = 0; i < n; i++) { 00826 sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); 00827 } 00828 } 00829 00830 00832 static void 00833 sample_linear_1d( GLcontext *ctx, 00834 const struct gl_texture_object *tObj, GLuint n, 00835 const GLfloat texcoords[][4], const GLfloat lambda[], 00836 GLchan rgba[][4] ) 00837 { 00838 GLuint i; 00839 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 00840 (void) lambda; 00841 for (i = 0; i < n; i++) { 00842 sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]); 00843 } 00844 } 00845 00846 00848 static void 00849 sample_lambda_1d( GLcontext *ctx, 00850 const struct gl_texture_object *tObj, GLuint n, 00851 const GLfloat texcoords[][4], 00852 const GLfloat lambda[], GLchan rgba[][4] ) 00853 { 00854 GLuint minStart, minEnd; /* texels with minification */ 00855 GLuint magStart, magEnd; /* texels with magnification */ 00856 GLuint i; 00857 00858 ASSERT(lambda != NULL); 00859 compute_min_mag_ranges(tObj, n, lambda, 00860 &minStart, &minEnd, &magStart, &magEnd); 00861 00862 if (minStart < minEnd) { 00863 /* do the minified texels */ 00864 const GLuint m = minEnd - minStart; 00865 switch (tObj->MinFilter) { 00866 case GL_NEAREST: 00867 for (i = minStart; i < minEnd; i++) 00868 sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 00869 texcoords[i], rgba[i]); 00870 break; 00871 case GL_LINEAR: 00872 for (i = minStart; i < minEnd; i++) 00873 sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 00874 texcoords[i], rgba[i]); 00875 break; 00876 case GL_NEAREST_MIPMAP_NEAREST: 00877 sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, 00878 lambda + minStart, rgba + minStart); 00879 break; 00880 case GL_LINEAR_MIPMAP_NEAREST: 00881 sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, 00882 lambda + minStart, rgba + minStart); 00883 break; 00884 case GL_NEAREST_MIPMAP_LINEAR: 00885 sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, 00886 lambda + minStart, rgba + minStart); 00887 break; 00888 case GL_LINEAR_MIPMAP_LINEAR: 00889 sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, 00890 lambda + minStart, rgba + minStart); 00891 break; 00892 default: 00893 _mesa_problem(ctx, "Bad min filter in sample_1d_texture"); 00894 return; 00895 } 00896 } 00897 00898 if (magStart < magEnd) { 00899 /* do the magnified texels */ 00900 switch (tObj->MagFilter) { 00901 case GL_NEAREST: 00902 for (i = magStart; i < magEnd; i++) 00903 sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 00904 texcoords[i], rgba[i]); 00905 break; 00906 case GL_LINEAR: 00907 for (i = magStart; i < magEnd; i++) 00908 sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 00909 texcoords[i], rgba[i]); 00910 break; 00911 default: 00912 _mesa_problem(ctx, "Bad mag filter in sample_1d_texture"); 00913 return; 00914 } 00915 } 00916 } 00917 00918 00919 /**********************************************************************/ 00920 /* 2-D Texture Sampling Functions */ 00921 /**********************************************************************/ 00922 00923 00927 static INLINE void 00928 sample_2d_nearest(GLcontext *ctx, 00929 const struct gl_texture_object *tObj, 00930 const struct gl_texture_image *img, 00931 const GLfloat texcoord[4], 00932 GLchan rgba[]) 00933 { 00934 const GLint width = img->Width2; /* without border, power of two */ 00935 const GLint height = img->Height2; /* without border, power of two */ 00936 GLint i, j; 00937 (void) ctx; 00938 00939 i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]); 00940 j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]); 00941 00942 /* skip over the border, if any */ 00943 i += img->Border; 00944 j += img->Border; 00945 00946 if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) { 00947 /* Need this test for GL_CLAMP_TO_BORDER mode */ 00948 COPY_CHAN4(rgba, tObj->_BorderChan); 00949 } 00950 else { 00951 img->FetchTexelc(img, i, j, 0, rgba); 00952 } 00953 } 00954 00955 00960 static INLINE void 00961 sample_2d_linear(GLcontext *ctx, 00962 const struct gl_texture_object *tObj, 00963 const struct gl_texture_image *img, 00964 const GLfloat texcoord[4], 00965 GLchan rgba[]) 00966 { 00967 const GLint width = img->Width2; 00968 const GLint height = img->Height2; 00969 GLint i0, j0, i1, j1; 00970 GLbitfield useBorderColor = 0x0; 00971 GLfloat a, b; 00972 GLchan t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */ 00973 00974 linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a); 00975 linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b); 00976 00977 if (img->Border) { 00978 i0 += img->Border; 00979 i1 += img->Border; 00980 j0 += img->Border; 00981 j1 += img->Border; 00982 } 00983 else { 00984 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; 00985 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; 00986 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; 00987 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; 00988 } 00989 00990 /* fetch four texel colors */ 00991 if (useBorderColor & (I0BIT | J0BIT)) { 00992 COPY_CHAN4(t00, tObj->_BorderChan); 00993 } 00994 else { 00995 img->FetchTexelc(img, i0, j0, 0, t00); 00996 } 00997 if (useBorderColor & (I1BIT | J0BIT)) { 00998 COPY_CHAN4(t10, tObj->_BorderChan); 00999 } 01000 else { 01001 img->FetchTexelc(img, i1, j0, 0, t10); 01002 } 01003 if (useBorderColor & (I0BIT | J1BIT)) { 01004 COPY_CHAN4(t01, tObj->_BorderChan); 01005 } 01006 else { 01007 img->FetchTexelc(img, i0, j1, 0, t01); 01008 } 01009 if (useBorderColor & (I1BIT | J1BIT)) { 01010 COPY_CHAN4(t11, tObj->_BorderChan); 01011 } 01012 else { 01013 img->FetchTexelc(img, i1, j1, 0, t11); 01014 } 01015 01016 lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11); 01017 } 01018 01019 01024 static INLINE void 01025 sample_2d_linear_repeat(GLcontext *ctx, 01026 const struct gl_texture_object *tObj, 01027 const struct gl_texture_image *img, 01028 const GLfloat texcoord[4], 01029 GLchan rgba[]) 01030 { 01031 const GLint width = img->Width2; 01032 const GLint height = img->Height2; 01033 GLint i0, j0, i1, j1; 01034 GLfloat wi, wj; 01035 GLchan t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */ 01036 01037 (void) ctx; 01038 01039 ASSERT(tObj->WrapS == GL_REPEAT); 01040 ASSERT(tObj->WrapT == GL_REPEAT); 01041 ASSERT(img->Border == 0); 01042 ASSERT(img->TexFormat->BaseFormat != GL_COLOR_INDEX); 01043 ASSERT(img->_IsPowerOfTwo); 01044 01045 linear_repeat_texel_location(width, texcoord[0], &i0, &i1, &wi); 01046 linear_repeat_texel_location(height, texcoord[1], &j0, &j1, &wj); 01047 01048 img->FetchTexelc(img, i0, j0, 0, t00); 01049 img->FetchTexelc(img, i1, j0, 0, t10); 01050 img->FetchTexelc(img, i0, j1, 0, t01); 01051 img->FetchTexelc(img, i1, j1, 0, t11); 01052 01053 lerp_rgba_2d(rgba, wi, wj, t00, t10, t01, t11); 01054 } 01055 01056 01057 static void 01058 sample_2d_nearest_mipmap_nearest(GLcontext *ctx, 01059 const struct gl_texture_object *tObj, 01060 GLuint n, const GLfloat texcoord[][4], 01061 const GLfloat lambda[], GLchan rgba[][4]) 01062 { 01063 GLuint i; 01064 for (i = 0; i < n; i++) { 01065 GLint level = nearest_mipmap_level(tObj, lambda[i]); 01066 sample_2d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); 01067 } 01068 } 01069 01070 01071 static void 01072 sample_2d_linear_mipmap_nearest(GLcontext *ctx, 01073 const struct gl_texture_object *tObj, 01074 GLuint n, const GLfloat texcoord[][4], 01075 const GLfloat lambda[], GLchan rgba[][4]) 01076 { 01077 GLuint i; 01078 ASSERT(lambda != NULL); 01079 for (i = 0; i < n; i++) { 01080 GLint level = nearest_mipmap_level(tObj, lambda[i]); 01081 sample_2d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); 01082 } 01083 } 01084 01085 01086 static void 01087 sample_2d_nearest_mipmap_linear(GLcontext *ctx, 01088 const struct gl_texture_object *tObj, 01089 GLuint n, const GLfloat texcoord[][4], 01090 const GLfloat lambda[], GLchan rgba[][4]) 01091 { 01092 GLuint i; 01093 ASSERT(lambda != NULL); 01094 for (i = 0; i < n; i++) { 01095 GLint level = linear_mipmap_level(tObj, lambda[i]); 01096 if (level >= tObj->_MaxLevel) { 01097 sample_2d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 01098 texcoord[i], rgba[i]); 01099 } 01100 else { 01101 GLchan t0[4], t1[4]; /* texels */ 01102 const GLfloat f = FRAC(lambda[i]); 01103 sample_2d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 01104 sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 01105 lerp_rgba(rgba[i], f, t0, t1); 01106 } 01107 } 01108 } 01109 01110 01111 static void 01112 sample_2d_linear_mipmap_linear( GLcontext *ctx, 01113 const struct gl_texture_object *tObj, 01114 GLuint n, const GLfloat texcoord[][4], 01115 const GLfloat lambda[], GLchan rgba[][4] ) 01116 { 01117 GLuint i; 01118 ASSERT(lambda != NULL); 01119 for (i = 0; i < n; i++) { 01120 GLint level = linear_mipmap_level(tObj, lambda[i]); 01121 if (level >= tObj->_MaxLevel) { 01122 sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 01123 texcoord[i], rgba[i]); 01124 } 01125 else { 01126 GLchan t0[4], t1[4]; /* texels */ 01127 const GLfloat f = FRAC(lambda[i]); 01128 sample_2d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 01129 sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 01130 lerp_rgba(rgba[i], f, t0, t1); 01131 } 01132 } 01133 } 01134 01135 01136 static void 01137 sample_2d_linear_mipmap_linear_repeat(GLcontext *ctx, 01138 const struct gl_texture_object *tObj, 01139 GLuint n, const GLfloat texcoord[][4], 01140 const GLfloat lambda[], GLchan rgba[][4]) 01141 { 01142 GLuint i; 01143 ASSERT(lambda != NULL); 01144 ASSERT(tObj->WrapS == GL_REPEAT); 01145 ASSERT(tObj->WrapT == GL_REPEAT); 01146 for (i = 0; i < n; i++) { 01147 GLint level = linear_mipmap_level(tObj, lambda[i]); 01148 if (level >= tObj->_MaxLevel) { 01149 sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 01150 texcoord[i], rgba[i]); 01151 } 01152 else { 01153 GLchan t0[4], t1[4]; /* texels */ 01154 const GLfloat f = FRAC(lambda[i]); 01155 sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level ], 01156 texcoord[i], t0); 01157 sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level+1], 01158 texcoord[i], t1); 01159 lerp_rgba(rgba[i], f, t0, t1); 01160 } 01161 } 01162 } 01163 01164 01166 static void 01167 sample_nearest_2d(GLcontext *ctx, 01168 const struct gl_texture_object *tObj, GLuint n, 01169 const GLfloat texcoords[][4], 01170 const GLfloat lambda[], GLchan rgba[][4]) 01171 { 01172 GLuint i; 01173 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 01174 (void) lambda; 01175 for (i = 0; i < n; i++) { 01176 sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); 01177 } 01178 } 01179 01180 01182 static void 01183 sample_linear_2d(GLcontext *ctx, 01184 const struct gl_texture_object *tObj, GLuint n, 01185 const GLfloat texcoords[][4], 01186 const GLfloat lambda[], GLchan rgba[][4]) 01187 { 01188 GLuint i; 01189 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 01190 (void) lambda; 01191 if (tObj->WrapS == GL_REPEAT && 01192 tObj->WrapT == GL_REPEAT && 01193 image->_IsPowerOfTwo && 01194 image->Border == 0) { 01195 for (i = 0; i < n; i++) { 01196 sample_2d_linear_repeat(ctx, tObj, image, texcoords[i], rgba[i]); 01197 } 01198 } 01199 else { 01200 for (i = 0; i < n; i++) { 01201 sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]); 01202 } 01203 } 01204 } 01205 01206 01215 static void 01216 opt_sample_rgb_2d(GLcontext *ctx, 01217 const struct gl_texture_object *tObj, 01218 GLuint n, const GLfloat texcoords[][4], 01219 const GLfloat lambda[], GLchan rgba[][4]) 01220 { 01221 const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel]; 01222 const GLfloat width = (GLfloat) img->Width; 01223 const GLfloat height = (GLfloat) img->Height; 01224 const GLint colMask = img->Width - 1; 01225 const GLint rowMask = img->Height - 1; 01226 const GLint shift = img->WidthLog2; 01227 GLuint k; 01228 (void) ctx; 01229 (void) lambda; 01230 ASSERT(tObj->WrapS==GL_REPEAT); 01231 ASSERT(tObj->WrapT==GL_REPEAT); 01232 ASSERT(img->Border==0); 01233 ASSERT(img->TexFormat->MesaFormat==MESA_FORMAT_RGB); 01234 ASSERT(img->_IsPowerOfTwo); 01235 01236 for (k=0; k<n; k++) { 01237 GLint i = IFLOOR(texcoords[k][0] * width) & colMask; 01238 GLint j = IFLOOR(texcoords[k][1] * height) & rowMask; 01239 GLint pos = (j << shift) | i; 01240 GLchan *texel = ((GLchan *) img->Data) + 3*pos; 01241 rgba[k][RCOMP] = texel[0]; 01242 rgba[k][GCOMP] = texel[1]; 01243 rgba[k][BCOMP] = texel[2]; 01244 } 01245 } 01246 01247 01256 static void 01257 opt_sample_rgba_2d(GLcontext *ctx, 01258 const struct gl_texture_object *tObj, 01259 GLuint n, const GLfloat texcoords[][4], 01260 const GLfloat lambda[], GLchan rgba[][4]) 01261 { 01262 const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel]; 01263 const GLfloat width = (GLfloat) img->Width; 01264 const GLfloat height = (GLfloat) img->Height; 01265 const GLint colMask = img->Width - 1; 01266 const GLint rowMask = img->Height - 1; 01267 const GLint shift = img->WidthLog2; 01268 GLuint i; 01269 (void) ctx; 01270 (void) lambda; 01271 ASSERT(tObj->WrapS==GL_REPEAT); 01272 ASSERT(tObj->WrapT==GL_REPEAT); 01273 ASSERT(img->Border==0); 01274 ASSERT(img->TexFormat->MesaFormat==MESA_FORMAT_RGBA); 01275 ASSERT(img->_IsPowerOfTwo); 01276 01277 for (i = 0; i < n; i++) { 01278 const GLint col = IFLOOR(texcoords[i][0] * width) & colMask; 01279 const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask; 01280 const GLint pos = (row << shift) | col; 01281 const GLchan *texel = ((GLchan *) img->Data) + (pos << 2); /* pos*4 */ 01282 COPY_CHAN4(rgba[i], texel); 01283 } 01284 } 01285 01286 01288 static void 01289 sample_lambda_2d(GLcontext *ctx, 01290 const struct gl_texture_object *tObj, 01291 GLuint n, const GLfloat texcoords[][4], 01292 const GLfloat lambda[], GLchan rgba[][4]) 01293 { 01294 const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel]; 01295 GLuint minStart, minEnd; /* texels with minification */ 01296 GLuint magStart, magEnd; /* texels with magnification */ 01297 01298 const GLboolean repeatNoBorderPOT = (tObj->WrapS == GL_REPEAT) 01299 && (tObj->WrapT == GL_REPEAT) 01300 && (tImg->Border == 0 && (tImg->Width == tImg->RowStride)) 01301 && (tImg->TexFormat->BaseFormat != GL_COLOR_INDEX) 01302 && tImg->_IsPowerOfTwo; 01303 01304 ASSERT(lambda != NULL); 01305 compute_min_mag_ranges(tObj, n, lambda, 01306 &minStart, &minEnd, &magStart, &magEnd); 01307 01308 if (minStart < minEnd) { 01309 /* do the minified texels */ 01310 const GLuint m = minEnd - minStart; 01311 switch (tObj->MinFilter) { 01312 case GL_NEAREST: 01313 if (repeatNoBorderPOT) { 01314 switch (tImg->TexFormat->MesaFormat) { 01315 case MESA_FORMAT_RGB: 01316 opt_sample_rgb_2d(ctx, tObj, m, texcoords + minStart, 01317 NULL, rgba + minStart); 01318 break; 01319 case MESA_FORMAT_RGBA: 01320 opt_sample_rgba_2d(ctx, tObj, m, texcoords + minStart, 01321 NULL, rgba + minStart); 01322 break; 01323 default: 01324 sample_nearest_2d(ctx, tObj, m, texcoords + minStart, 01325 NULL, rgba + minStart ); 01326 } 01327 } 01328 else { 01329 sample_nearest_2d(ctx, tObj, m, texcoords + minStart, 01330 NULL, rgba + minStart); 01331 } 01332 break; 01333 case GL_LINEAR: 01334 sample_linear_2d(ctx, tObj, m, texcoords + minStart, 01335 NULL, rgba + minStart); 01336 break; 01337 case GL_NEAREST_MIPMAP_NEAREST: 01338 sample_2d_nearest_mipmap_nearest(ctx, tObj, m, 01339 texcoords + minStart, 01340 lambda + minStart, rgba + minStart); 01341 break; 01342 case GL_LINEAR_MIPMAP_NEAREST: 01343 sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, 01344 lambda + minStart, rgba + minStart); 01345 break; 01346 case GL_NEAREST_MIPMAP_LINEAR: 01347 sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, 01348 lambda + minStart, rgba + minStart); 01349 break; 01350 case GL_LINEAR_MIPMAP_LINEAR: 01351 if (repeatNoBorderPOT) 01352 sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m, 01353 texcoords + minStart, lambda + minStart, rgba + minStart); 01354 else 01355 sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, 01356 lambda + minStart, rgba + minStart); 01357 break; 01358 default: 01359 _mesa_problem(ctx, "Bad min filter in sample_2d_texture"); 01360 return; 01361 } 01362 } 01363 01364 if (magStart < magEnd) { 01365 /* do the magnified texels */ 01366 const GLuint m = magEnd - magStart; 01367 01368 switch (tObj->MagFilter) { 01369 case GL_NEAREST: 01370 if (repeatNoBorderPOT) { 01371 switch (tImg->TexFormat->MesaFormat) { 01372 case MESA_FORMAT_RGB: 01373 opt_sample_rgb_2d(ctx, tObj, m, texcoords + magStart, 01374 NULL, rgba + magStart); 01375 break; 01376 case MESA_FORMAT_RGBA: 01377 opt_sample_rgba_2d(ctx, tObj, m, texcoords + magStart, 01378 NULL, rgba + magStart); 01379 break; 01380 default: 01381 sample_nearest_2d(ctx, tObj, m, texcoords + magStart, 01382 NULL, rgba + magStart ); 01383 } 01384 } 01385 else { 01386 sample_nearest_2d(ctx, tObj, m, texcoords + magStart, 01387 NULL, rgba + magStart); 01388 } 01389 break; 01390 case GL_LINEAR: 01391 sample_linear_2d(ctx, tObj, m, texcoords + magStart, 01392 NULL, rgba + magStart); 01393 break; 01394 default: 01395 _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d"); 01396 } 01397 } 01398 } 01399 01400 01401 01402 /**********************************************************************/ 01403 /* 3-D Texture Sampling Functions */ 01404 /**********************************************************************/ 01405 01409 static INLINE void 01410 sample_3d_nearest(GLcontext *ctx, 01411 const struct gl_texture_object *tObj, 01412 const struct gl_texture_image *img, 01413 const GLfloat texcoord[4], 01414 GLchan rgba[4]) 01415 { 01416 const GLint width = img->Width2; /* without border, power of two */ 01417 const GLint height = img->Height2; /* without border, power of two */ 01418 const GLint depth = img->Depth2; /* without border, power of two */ 01419 GLint i, j, k; 01420 (void) ctx; 01421 01422 i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]); 01423 j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]); 01424 k = nearest_texel_location(tObj->WrapR, img, depth, texcoord[2]); 01425 01426 if (i < 0 || i >= (GLint) img->Width || 01427 j < 0 || j >= (GLint) img->Height || 01428 k < 0 || k >= (GLint) img->Depth) { 01429 /* Need this test for GL_CLAMP_TO_BORDER mode */ 01430 COPY_CHAN4(rgba, tObj->_BorderChan); 01431 } 01432 else { 01433 img->FetchTexelc(img, i, j, k, rgba); 01434 } 01435 } 01436 01437 01441 static void 01442 sample_3d_linear(GLcontext *ctx, 01443 const struct gl_texture_object *tObj, 01444 const struct gl_texture_image *img, 01445 const GLfloat texcoord[4], 01446 GLchan rgba[4]) 01447 { 01448 const GLint width = img->Width2; 01449 const GLint height = img->Height2; 01450 const GLint depth = img->Depth2; 01451 GLint i0, j0, k0, i1, j1, k1; 01452 GLbitfield useBorderColor = 0x0; 01453 GLfloat a, b, c; 01454 GLchan t000[4], t010[4], t001[4], t011[4]; 01455 GLchan t100[4], t110[4], t101[4], t111[4]; 01456 01457 linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a); 01458 linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b); 01459 linear_texel_locations(tObj->WrapR, img, depth, texcoord[2], &k0, &k1, &c); 01460 01461 if (img->Border) { 01462 i0 += img->Border; 01463 i1 += img->Border; 01464 j0 += img->Border; 01465 j1 += img->Border; 01466 k0 += img->Border; 01467 k1 += img->Border; 01468 } 01469 else { 01470 /* check if sampling texture border color */ 01471 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; 01472 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; 01473 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; 01474 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; 01475 if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT; 01476 if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT; 01477 } 01478 01479 /* Fetch texels */ 01480 if (useBorderColor & (I0BIT | J0BIT | K0BIT)) { 01481 COPY_CHAN4(t000, tObj->_BorderChan); 01482 } 01483 else { 01484 img->FetchTexelc(img, i0, j0, k0, t000); 01485 } 01486 if (useBorderColor & (I1BIT | J0BIT | K0BIT)) { 01487 COPY_CHAN4(t100, tObj->_BorderChan); 01488 } 01489 else { 01490 img->FetchTexelc(img, i1, j0, k0, t100); 01491 } 01492 if (useBorderColor & (I0BIT | J1BIT | K0BIT)) { 01493 COPY_CHAN4(t010, tObj->_BorderChan); 01494 } 01495 else { 01496 img->FetchTexelc(img, i0, j1, k0, t010); 01497 } 01498 if (useBorderColor & (I1BIT | J1BIT | K0BIT)) { 01499 COPY_CHAN4(t110, tObj->_BorderChan); 01500 } 01501 else { 01502 img->FetchTexelc(img, i1, j1, k0, t110); 01503 } 01504 01505 if (useBorderColor & (I0BIT | J0BIT | K1BIT)) { 01506 COPY_CHAN4(t001, tObj->_BorderChan); 01507 } 01508 else { 01509 img->FetchTexelc(img, i0, j0, k1, t001); 01510 } 01511 if (useBorderColor & (I1BIT | J0BIT | K1BIT)) { 01512 COPY_CHAN4(t101, tObj->_BorderChan); 01513 } 01514 else { 01515 img->FetchTexelc(img, i1, j0, k1, t101); 01516 } 01517 if (useBorderColor & (I0BIT | J1BIT | K1BIT)) { 01518 COPY_CHAN4(t011, tObj->_BorderChan); 01519 } 01520 else { 01521 img->FetchTexelc(img, i0, j1, k1, t011); 01522 } 01523 if (useBorderColor & (I1BIT | J1BIT | K1BIT)) { 01524 COPY_CHAN4(t111, tObj->_BorderChan); 01525 } 01526 else { 01527 img->FetchTexelc(img, i1, j1, k1, t111); 01528 } 01529 01530 /* trilinear interpolation of samples */ 01531 lerp_rgba_3d(rgba, a, b, c, t000, t100, t010, t110, t001, t101, t011, t111); 01532 } 01533 01534 01535 static void 01536 sample_3d_nearest_mipmap_nearest(GLcontext *ctx, 01537 const struct gl_texture_object *tObj, 01538 GLuint n, const GLfloat texcoord[][4], 01539 const GLfloat lambda[], GLchan rgba[][4] ) 01540 { 01541 GLuint i; 01542 for (i = 0; i < n; i++) { 01543 GLint level = nearest_mipmap_level(tObj, lambda[i]); 01544 sample_3d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); 01545 } 01546 } 01547 01548 01549 static void 01550 sample_3d_linear_mipmap_nearest(GLcontext *ctx, 01551 const struct gl_texture_object *tObj, 01552 GLuint n, const GLfloat texcoord[][4], 01553 const GLfloat lambda[], GLchan rgba[][4]) 01554 { 01555 GLuint i; 01556 ASSERT(lambda != NULL); 01557 for (i = 0; i < n; i++) { 01558 GLint level = nearest_mipmap_level(tObj, lambda[i]); 01559 sample_3d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); 01560 } 01561 } 01562 01563 01564 static void 01565 sample_3d_nearest_mipmap_linear(GLcontext *ctx, 01566 const struct gl_texture_object *tObj, 01567 GLuint n, const GLfloat texcoord[][4], 01568 const GLfloat lambda[], GLchan rgba[][4]) 01569 { 01570 GLuint i; 01571 ASSERT(lambda != NULL); 01572 for (i = 0; i < n; i++) { 01573 GLint level = linear_mipmap_level(tObj, lambda[i]); 01574 if (level >= tObj->_MaxLevel) { 01575 sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 01576 texcoord[i], rgba[i]); 01577 } 01578 else { 01579 GLchan t0[4], t1[4]; /* texels */ 01580 const GLfloat f = FRAC(lambda[i]); 01581 sample_3d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 01582 sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 01583 lerp_rgba(rgba[i], f, t0, t1); 01584 } 01585 } 01586 } 01587 01588 01589 static void 01590 sample_3d_linear_mipmap_linear(GLcontext *ctx, 01591 const struct gl_texture_object *tObj, 01592 GLuint n, const GLfloat texcoord[][4], 01593 const GLfloat lambda[], GLchan rgba[][4]) 01594 { 01595 GLuint i; 01596 ASSERT(lambda != NULL); 01597 for (i = 0; i < n; i++) { 01598 GLint level = linear_mipmap_level(tObj, lambda[i]); 01599 if (level >= tObj->_MaxLevel) { 01600 sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 01601 texcoord[i], rgba[i]); 01602 } 01603 else { 01604 GLchan t0[4], t1[4]; /* texels */ 01605 const GLfloat f = FRAC(lambda[i]); 01606 sample_3d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 01607 sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 01608 lerp_rgba(rgba[i], f, t0, t1); 01609 } 01610 } 01611 } 01612 01613 01615 static void 01616 sample_nearest_3d(GLcontext *ctx, 01617 const struct gl_texture_object *tObj, GLuint n, 01618 const GLfloat texcoords[][4], const GLfloat lambda[], 01619 GLchan rgba[][4]) 01620 { 01621 GLuint i; 01622 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 01623 (void) lambda; 01624 for (i = 0; i < n; i++) { 01625 sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); 01626 } 01627 } 01628 01629 01631 static void 01632 sample_linear_3d(GLcontext *ctx, 01633 const struct gl_texture_object *tObj, GLuint n, 01634 const GLfloat texcoords[][4], 01635 const GLfloat lambda[], GLchan rgba[][4]) 01636 { 01637 GLuint i; 01638 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 01639 (void) lambda; 01640 for (i = 0; i < n; i++) { 01641 sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]); 01642 } 01643 } 01644 01645 01647 static void 01648 sample_lambda_3d(GLcontext *ctx, 01649 const struct gl_texture_object *tObj, GLuint n, 01650 const GLfloat texcoords[][4], const GLfloat lambda[], 01651 GLchan rgba[][4]) 01652 { 01653 GLuint minStart, minEnd; /* texels with minification */ 01654 GLuint magStart, magEnd; /* texels with magnification */ 01655 GLuint i; 01656 01657 ASSERT(lambda != NULL); 01658 compute_min_mag_ranges(tObj, n, lambda, 01659 &minStart, &minEnd, &magStart, &magEnd); 01660 01661 if (minStart < minEnd) { 01662 /* do the minified texels */ 01663 GLuint m = minEnd - minStart; 01664 switch (tObj->MinFilter) { 01665 case GL_NEAREST: 01666 for (i = minStart; i < minEnd; i++) 01667 sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 01668 texcoords[i], rgba[i]); 01669 break; 01670 case GL_LINEAR: 01671 for (i = minStart; i < minEnd; i++) 01672 sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 01673 texcoords[i], rgba[i]); 01674 break; 01675 case GL_NEAREST_MIPMAP_NEAREST: 01676 sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, 01677 lambda + minStart, rgba + minStart); 01678 break; 01679 case GL_LINEAR_MIPMAP_NEAREST: 01680 sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, 01681 lambda + minStart, rgba + minStart); 01682 break; 01683 case GL_NEAREST_MIPMAP_LINEAR: 01684 sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, 01685 lambda + minStart, rgba + minStart); 01686 break; 01687 case GL_LINEAR_MIPMAP_LINEAR: 01688 sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, 01689 lambda + minStart, rgba + minStart); 01690 break; 01691 default: 01692 _mesa_problem(ctx, "Bad min filter in sample_3d_texture"); 01693 return; 01694 } 01695 } 01696 01697 if (magStart < magEnd) { 01698 /* do the magnified texels */ 01699 switch (tObj->MagFilter) { 01700 case GL_NEAREST: 01701 for (i = magStart; i < magEnd; i++) 01702 sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 01703 texcoords[i], rgba[i]); 01704 break; 01705 case GL_LINEAR: 01706 for (i = magStart; i < magEnd; i++) 01707 sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 01708 texcoords[i], rgba[i]); 01709 break; 01710 default: 01711 _mesa_problem(ctx, "Bad mag filter in sample_3d_texture"); 01712 return; 01713 } 01714 } 01715 } 01716 01717 01718 /**********************************************************************/ 01719 /* Texture Cube Map Sampling Functions */ 01720 /**********************************************************************/ 01721 01727 static const struct gl_texture_image ** 01728 choose_cube_face(const struct gl_texture_object *texObj, 01729 const GLfloat texcoord[4], GLfloat newCoord[4]) 01730 { 01731 /* 01732 major axis 01733 direction target sc tc ma 01734 ---------- ------------------------------- --- --- --- 01735 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx 01736 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx 01737 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry 01738 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry 01739 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz 01740 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz 01741 */ 01742 const GLfloat rx = texcoord[0]; 01743 const GLfloat ry = texcoord[1]; 01744 const GLfloat rz = texcoord[2]; 01745 const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz); 01746 GLuint face; 01747 GLfloat sc, tc, ma; 01748 01749 if (arx > ary && arx > arz) { 01750 if (rx >= 0.0F) { 01751 face = FACE_POS_X; 01752 sc = -rz; 01753 tc = -ry; 01754 ma = arx; 01755 } 01756 else { 01757 face = FACE_NEG_X; 01758 sc = rz; 01759 tc = -ry; 01760 ma = arx; 01761 } 01762 } 01763 else if (ary > arx && ary > arz) { 01764 if (ry >= 0.0F) { 01765 face = FACE_POS_Y; 01766 sc = rx; 01767 tc = rz; 01768 ma = ary; 01769 } 01770 else { 01771 face = FACE_NEG_Y; 01772 sc = rx; 01773 tc = -rz; 01774 ma = ary; 01775 } 01776 } 01777 else { 01778 if (rz > 0.0F) { 01779 face = FACE_POS_Z; 01780 sc = rx; 01781 tc = -ry; 01782 ma = arz; 01783 } 01784 else { 01785 face = FACE_NEG_Z; 01786 sc = -rx; 01787 tc = -ry; 01788 ma = arz; 01789 } 01790 } 01791 01792 newCoord[0] = ( sc / ma + 1.0F ) * 0.5F; 01793 newCoord[1] = ( tc / ma + 1.0F ) * 0.5F; 01794 return (const struct gl_texture_image **) texObj->Image[face]; 01795 } 01796 01797 01798 static void 01799 sample_nearest_cube(GLcontext *ctx, 01800 const struct gl_texture_object *tObj, GLuint n, 01801 const GLfloat texcoords[][4], const GLfloat lambda[], 01802 GLchan rgba[][4]) 01803 { 01804 GLuint i; 01805 (void) lambda; 01806 for (i = 0; i < n; i++) { 01807 const struct gl_texture_image **images; 01808 GLfloat newCoord[4]; 01809 images = choose_cube_face(tObj, texcoords[i], newCoord); 01810 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel], 01811 newCoord, rgba[i]); 01812 } 01813 } 01814 01815 01816 static void 01817 sample_linear_cube(GLcontext *ctx, 01818 const struct gl_texture_object *tObj, GLuint n, 01819 const GLfloat texcoords[][4], 01820 const GLfloat lambda[], GLchan rgba[][4]) 01821 { 01822 GLuint i; 01823 (void) lambda; 01824 for (i = 0; i < n; i++) { 01825 const struct gl_texture_image **images; 01826 GLfloat newCoord[4]; 01827 images = choose_cube_face(tObj, texcoords[i], newCoord); 01828 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel], 01829 newCoord, rgba[i]); 01830 } 01831 } 01832 01833 01834 static void 01835 sample_cube_nearest_mipmap_nearest(GLcontext *ctx, 01836 const struct gl_texture_object *tObj, 01837 GLuint n, const GLfloat texcoord[][4], 01838 const GLfloat lambda[], GLchan rgba[][4]) 01839 { 01840 GLuint i; 01841 ASSERT(lambda != NULL); 01842 for (i = 0; i < n; i++) { 01843 const struct gl_texture_image **images; 01844 GLfloat newCoord[4]; 01845 GLint level; 01846 images = choose_cube_face(tObj, texcoord[i], newCoord); 01847 01848 /* XXX we actually need to recompute lambda here based on the newCoords. 01849 * But we would need the texcoords of adjacent fragments to compute that 01850 * properly, and we don't have those here. 01851 * For now, do an approximation: subtracting 1 from the chosen mipmap 01852 * level seems to work in some test cases. 01853 * The same adjustment is done in the next few functions. 01854 */ 01855 level = nearest_mipmap_level(tObj, lambda[i]); 01856 level = MAX2(level - 1, 0); 01857 01858 sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]); 01859 } 01860 } 01861 01862 01863 static void 01864 sample_cube_linear_mipmap_nearest(GLcontext *ctx, 01865 const struct gl_texture_object *tObj, 01866 GLuint n, const GLfloat texcoord[][4], 01867 const GLfloat lambda[], GLchan rgba[][4]) 01868 { 01869 GLuint i; 01870 ASSERT(lambda != NULL); 01871 for (i = 0; i < n; i++) { 01872 const struct gl_texture_image **images; 01873 GLfloat newCoord[4]; 01874 GLint level = nearest_mipmap_level(tObj, lambda[i]); 01875 level = MAX2(level - 1, 0); /* see comment above */ 01876 images = choose_cube_face(tObj, texcoord[i], newCoord); 01877 sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]); 01878 } 01879 } 01880 01881 01882 static void 01883 sample_cube_nearest_mipmap_linear(GLcontext *ctx, 01884 const struct gl_texture_object *tObj, 01885 GLuint n, const GLfloat texcoord[][4], 01886 const GLfloat lambda[], GLchan rgba[][4]) 01887 { 01888 GLuint i; 01889 ASSERT(lambda != NULL); 01890 for (i = 0; i < n; i++) { 01891 const struct gl_texture_image **images; 01892 GLfloat newCoord[4]; 01893 GLint level = linear_mipmap_level(tObj, lambda[i]); 01894 level = MAX2(level - 1, 0); /* see comment above */ 01895 images = choose_cube_face(tObj, texcoord[i], newCoord); 01896 if (level >= tObj->_MaxLevel) { 01897 sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], 01898 newCoord, rgba[i]); 01899 } 01900 else { 01901 GLchan t0[4], t1[4]; /* texels */ 01902 const GLfloat f = FRAC(lambda[i]); 01903 sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0); 01904 sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1); 01905 lerp_rgba(rgba[i], f, t0, t1); 01906 } 01907 } 01908 } 01909 01910 01911 static void 01912 sample_cube_linear_mipmap_linear(GLcontext *ctx, 01913 const struct gl_texture_object *tObj, 01914 GLuint n, const GLfloat texcoord[][4], 01915 const GLfloat lambda[], GLchan rgba[][4]) 01916 { 01917 GLuint i; 01918 ASSERT(lambda != NULL); 01919 for (i = 0; i < n; i++) { 01920 const struct gl_texture_image **images; 01921 GLfloat newCoord[4]; 01922 GLint level = linear_mipmap_level(tObj, lambda[i]); 01923 level = MAX2(level - 1, 0); /* see comment above */ 01924 images = choose_cube_face(tObj, texcoord[i], newCoord); 01925 if (level >= tObj->_MaxLevel) { 01926 sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], 01927 newCoord, rgba[i]); 01928 } 01929 else { 01930 GLchan t0[4], t1[4]; 01931 const GLfloat f = FRAC(lambda[i]); 01932 sample_2d_linear(ctx, tObj, images[level ], newCoord, t0); 01933 sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1); 01934 lerp_rgba(rgba[i], f, t0, t1); 01935 } 01936 } 01937 } 01938 01939 01941 static void 01942 sample_lambda_cube(GLcontext *ctx, 01943 const struct gl_texture_object *tObj, GLuint n, 01944 const GLfloat texcoords[][4], const GLfloat lambda[], 01945 GLchan rgba[][4]) 01946 { 01947 GLuint minStart, minEnd; /* texels with minification */ 01948 GLuint magStart, magEnd; /* texels with magnification */ 01949 01950 ASSERT(lambda != NULL); 01951 compute_min_mag_ranges(tObj, n, lambda, 01952 &minStart, &minEnd, &magStart, &magEnd); 01953 01954 if (minStart < minEnd) { 01955 /* do the minified texels */ 01956 const GLuint m = minEnd - minStart; 01957 switch (tObj->MinFilter) { 01958 case GL_NEAREST: 01959 sample_nearest_cube(ctx, tObj, m, texcoords + minStart, 01960 lambda + minStart, rgba + minStart); 01961 break; 01962 case GL_LINEAR: 01963 sample_linear_cube(ctx, tObj, m, texcoords + minStart, 01964 lambda + minStart, rgba + minStart); 01965 break; 01966 case GL_NEAREST_MIPMAP_NEAREST: 01967 sample_cube_nearest_mipmap_nearest(ctx, tObj, m, 01968 texcoords + minStart, 01969 lambda + minStart, rgba + minStart); 01970 break; 01971 case GL_LINEAR_MIPMAP_NEAREST: 01972 sample_cube_linear_mipmap_nearest(ctx, tObj, m, 01973 texcoords + minStart, 01974 lambda + minStart, rgba + minStart); 01975 break; 01976 case GL_NEAREST_MIPMAP_LINEAR: 01977 sample_cube_nearest_mipmap_linear(ctx, tObj, m, 01978 texcoords + minStart, 01979 lambda + minStart, rgba + minStart); 01980 break; 01981 case GL_LINEAR_MIPMAP_LINEAR: 01982 sample_cube_linear_mipmap_linear(ctx, tObj, m, 01983 texcoords + minStart, 01984 lambda + minStart, rgba + minStart); 01985 break; 01986 default: 01987 _mesa_problem(ctx, "Bad min filter in sample_lambda_cube"); 01988 } 01989 } 01990 01991 if (magStart < magEnd) { 01992 /* do the magnified texels */ 01993 const GLuint m = magEnd - magStart; 01994 switch (tObj->MagFilter) { 01995 case GL_NEAREST: 01996 sample_nearest_cube(ctx, tObj, m, texcoords + magStart, 01997 lambda + magStart, rgba + magStart); 01998 break; 01999 case GL_LINEAR: 02000 sample_linear_cube(ctx, tObj, m, texcoords + magStart, 02001 lambda + magStart, rgba + magStart); 02002 break; 02003 default: 02004 _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube"); 02005 } 02006 } 02007 } 02008 02009 02010 /**********************************************************************/ 02011 /* Texture Rectangle Sampling Functions */ 02012 /**********************************************************************/ 02013 02014 02018 static INLINE GLint 02019 clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max) 02020 { 02021 switch (wrapMode) { 02022 case GL_CLAMP: 02023 return IFLOOR( CLAMP(coord, 0.0F, max - 1) ); 02024 case GL_CLAMP_TO_EDGE: 02025 return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) ); 02026 case GL_CLAMP_TO_BORDER: 02027 return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) ); 02028 default: 02029 _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest"); 02030 return 0; 02031 } 02032 } 02033 02034 02038 static INLINE void 02039 clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max, 02040 GLint *i0out, GLint *i1out, GLfloat *weight) 02041 { 02042 GLfloat fcol; 02043 GLint i0, i1; 02044 switch (wrapMode) { 02045 case GL_CLAMP: 02046 /* Not exactly what the spec says, but it matches NVIDIA output */ 02047 fcol = CLAMP(coord - 0.5F, 0.0, max-1); 02048 i0 = IFLOOR(fcol); 02049 i1 = i0 + 1; 02050 break; 02051 case GL_CLAMP_TO_EDGE: 02052 fcol = CLAMP(coord, 0.5F, max - 0.5F); 02053 fcol -= 0.5F; 02054 i0 = IFLOOR(fcol); 02055 i1 = i0 + 1; 02056 if (i1 > max - 1) 02057 i1 = max - 1; 02058 break; 02059 case GL_CLAMP_TO_BORDER: 02060 fcol = CLAMP(coord, -0.5F, max + 0.5F); 02061 fcol -= 0.5F; 02062 i0 = IFLOOR(fcol); 02063 i1 = i0 + 1; 02064 default: 02065 _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear"); 02066 i0 = i1 = 0; 02067 fcol = 0.0F; 02068 } 02069 *i0out = i0; 02070 *i1out = i1; 02071 *weight = FRAC(fcol); 02072 } 02073 02074 02075 static void 02076 sample_nearest_rect(GLcontext *ctx, 02077 const struct gl_texture_object *tObj, GLuint n, 02078 const GLfloat texcoords[][4], const GLfloat lambda[], 02079 GLchan rgba[][4]) 02080 { 02081 const struct gl_texture_image *img = tObj->Image[0][0]; 02082 const GLint width = img->Width; 02083 const GLint height = img->Height; 02084 GLuint i; 02085 02086 (void) ctx; 02087 (void) lambda; 02088 02089 ASSERT(tObj->WrapS == GL_CLAMP || 02090 tObj->WrapS == GL_CLAMP_TO_EDGE || 02091 tObj->WrapS == GL_CLAMP_TO_BORDER); 02092 ASSERT(tObj->WrapT == GL_CLAMP || 02093 tObj->WrapT == GL_CLAMP_TO_EDGE || 02094 tObj->WrapT == GL_CLAMP_TO_BORDER); 02095 ASSERT(img->TexFormat->BaseFormat != GL_COLOR_INDEX); 02096 02097 for (i = 0; i < n; i++) { 02098 GLint row, col; 02099 col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width); 02100 row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height); 02101 if (col < 0 || col >= width || row < 0 || row >= height) 02102 COPY_CHAN4(rgba[i], tObj->_BorderChan); 02103 else 02104 img->FetchTexelc(img, col, row, 0, rgba[i]); 02105 } 02106 } 02107 02108 02109 static void 02110 sample_linear_rect(GLcontext *ctx, 02111 const struct gl_texture_object *tObj, GLuint n, 02112 const GLfloat texcoords[][4], 02113 const GLfloat lambda[], GLchan rgba[][4]) 02114 { 02115 const struct gl_texture_image *img = tObj->Image[0][0]; 02116 const GLint width = img->Width; 02117 const GLint height = img->Height; 02118 GLuint i; 02119 02120 (void) ctx; 02121 (void) lambda; 02122 02123 ASSERT(tObj->WrapS == GL_CLAMP || 02124 tObj->WrapS == GL_CLAMP_TO_EDGE || 02125 tObj->WrapS == GL_CLAMP_TO_BORDER); 02126 ASSERT(tObj->WrapT == GL_CLAMP || 02127 tObj->WrapT == GL_CLAMP_TO_EDGE || 02128 tObj->WrapT == GL_CLAMP_TO_BORDER); 02129 ASSERT(img->TexFormat->BaseFormat != GL_COLOR_INDEX); 02130 02131 for (i = 0; i < n; i++) { 02132 GLint i0, j0, i1, j1; 02133 GLchan t00[4], t01[4], t10[4], t11[4]; 02134 GLfloat a, b; 02135 GLbitfield useBorderColor = 0x0; 02136 02137 clamp_rect_coord_linear(tObj->WrapS, texcoords[i][0], width, 02138 &i0, &i1, &a); 02139 clamp_rect_coord_linear(tObj->WrapT, texcoords[i][1], height, 02140 &j0, &j1, &b); 02141 02142 /* compute integer rows/columns */ 02143 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; 02144 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; 02145 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; 02146 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; 02147 02148 /* get four texel samples */ 02149 if (useBorderColor & (I0BIT | J0BIT)) 02150 COPY_CHAN4(t00, tObj->_BorderChan); 02151 else 02152 img->FetchTexelc(img, i0, j0, 0, t00); 02153 02154 if (useBorderColor & (I1BIT | J0BIT)) 02155 COPY_CHAN4(t10, tObj->_BorderChan); 02156 else 02157 img->FetchTexelc(img, i1, j0, 0, t10); 02158 02159 if (useBorderColor & (I0BIT | J1BIT)) 02160 COPY_CHAN4(t01, tObj->_BorderChan); 02161 else 02162 img->FetchTexelc(img, i0, j1, 0, t01); 02163 02164 if (useBorderColor & (I1BIT | J1BIT)) 02165 COPY_CHAN4(t11, tObj->_BorderChan); 02166 else 02167 img->FetchTexelc(img, i1, j1, 0, t11); 02168 02169 lerp_rgba_2d(rgba[i], a, b, t00, t10, t01, t11); 02170 } 02171 } 02172 02173 02175 static void 02176 sample_lambda_rect(GLcontext *ctx, 02177 const struct gl_texture_object *tObj, GLuint n, 02178 const GLfloat texcoords[][4], const GLfloat lambda[], 02179 GLchan rgba[][4]) 02180 { 02181 GLuint minStart, minEnd, magStart, magEnd; 02182 02183 /* We only need lambda to decide between minification and magnification. 02184 * There is no mipmapping with rectangular textures. 02185 */ 02186 compute_min_mag_ranges(tObj, n, lambda, 02187 &minStart, &minEnd, &magStart, &magEnd); 02188 02189 if (minStart < minEnd) { 02190 if (tObj->MinFilter == GL_NEAREST) { 02191 sample_nearest_rect(ctx, tObj, minEnd - minStart, 02192 texcoords + minStart, NULL, rgba + minStart); 02193 } 02194 else { 02195 sample_linear_rect(ctx, tObj, minEnd - minStart, 02196 texcoords + minStart, NULL, rgba + minStart); 02197 } 02198 } 02199 if (magStart < magEnd) { 02200 if (tObj->MagFilter == GL_NEAREST) { 02201 sample_nearest_rect(ctx, tObj, magEnd - magStart, 02202 texcoords + magStart, NULL, rgba + magStart); 02203 } 02204 else { 02205 sample_linear_rect(ctx, tObj, magEnd - magStart, 02206 texcoords + magStart, NULL, rgba + magStart); 02207 } 02208 } 02209 } 02210 02211 02212 02213 /**********************************************************************/ 02214 /* 2D Texture Array Sampling Functions */ 02215 /**********************************************************************/ 02216 02220 static void 02221 sample_2d_array_nearest(GLcontext *ctx, 02222 const struct gl_texture_object *tObj, 02223 const struct gl_texture_image *img, 02224 const GLfloat texcoord[4], 02225 GLchan rgba[4]) 02226 { 02227 const GLint width = img->Width2; /* without border, power of two */ 02228 const GLint height = img->Height2; /* without border, power of two */ 02229 const GLint depth = img->Depth; 02230 GLint i, j; 02231 GLint array; 02232 (void) ctx; 02233 02234 i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]); 02235 j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]); 02236 array = clamp_rect_coord_nearest(tObj->WrapR, texcoord[2], depth); 02237 02238 if (i < 0 || i >= (GLint) img->Width || 02239 j < 0 || j >= (GLint) img->Height || 02240 array < 0 || array >= (GLint) img->Depth) { 02241 /* Need this test for GL_CLAMP_TO_BORDER mode */ 02242 COPY_CHAN4(rgba, tObj->_BorderChan); 02243 } 02244 else { 02245 img->FetchTexelc(img, i, j, array, rgba); 02246 } 02247 } 02248 02249 02253 static void 02254 sample_2d_array_linear(GLcontext *ctx, 02255 const struct gl_texture_object *tObj, 02256 const struct gl_texture_image *img, 02257 const GLfloat texcoord[4], 02258 GLchan rgba[4]) 02259 { 02260 const GLint width = img->Width2; 02261 const GLint height = img->Height2; 02262 const GLint depth = img->Depth; 02263 GLint i0, j0, i1, j1; 02264 GLint array; 02265 GLbitfield useBorderColor = 0x0; 02266 GLfloat a, b; 02267 GLchan t00[4], t01[4], t10[4], t11[4]; 02268 02269 linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a); 02270 linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b); 02271 array = clamp_rect_coord_nearest(tObj->WrapR, texcoord[2], depth); 02272 02273 if (array < 0 || array >= depth) { 02274 COPY_CHAN4(rgba, tObj->_BorderChan); 02275 } 02276 else { 02277 if (img->Border) { 02278 i0 += img->Border; 02279 i1 += img->Border; 02280 j0 += img->Border; 02281 j1 += img->Border; 02282 } 02283 else { 02284 /* check if sampling texture border color */ 02285 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; 02286 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; 02287 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; 02288 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; 02289 } 02290 02291 /* Fetch texels */ 02292 if (useBorderColor & (I0BIT | J0BIT)) { 02293 COPY_CHAN4(t00, tObj->_BorderChan); 02294 } 02295 else { 02296 img->FetchTexelc(img, i0, j0, array, t00); 02297 } 02298 if (useBorderColor & (I1BIT | J0BIT)) { 02299 COPY_CHAN4(t10, tObj->_BorderChan); 02300 } 02301 else { 02302 img->FetchTexelc(img, i1, j0, array, t10); 02303 } 02304 if (useBorderColor & (I0BIT | J1BIT)) { 02305 COPY_CHAN4(t01, tObj->_BorderChan); 02306 } 02307 else { 02308 img->FetchTexelc(img, i0, j1, array, t01); 02309 } 02310 if (useBorderColor & (I1BIT | J1BIT)) { 02311 COPY_CHAN4(t11, tObj->_BorderChan); 02312 } 02313 else { 02314 img->FetchTexelc(img, i1, j1, array, t11); 02315 } 02316 02317 /* trilinear interpolation of samples */ 02318 lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11); 02319 } 02320 } 02321 02322 02323 static void 02324 sample_2d_array_nearest_mipmap_nearest(GLcontext *ctx, 02325 const struct gl_texture_object *tObj, 02326 GLuint n, const GLfloat texcoord[][4], 02327 const GLfloat lambda[], GLchan rgba[][4]) 02328 { 02329 GLuint i; 02330 for (i = 0; i < n; i++) { 02331 GLint level = nearest_mipmap_level(tObj, lambda[i]); 02332 sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], 02333 rgba[i]); 02334 } 02335 } 02336 02337 02338 static void 02339 sample_2d_array_linear_mipmap_nearest(GLcontext *ctx, 02340 const struct gl_texture_object *tObj, 02341 GLuint n, const GLfloat texcoord[][4], 02342 const GLfloat lambda[], GLchan rgba[][4]) 02343 { 02344 GLuint i; 02345 ASSERT(lambda != NULL); 02346 for (i = 0; i < n; i++) { 02347 GLint level = nearest_mipmap_level(tObj, lambda[i]); 02348 sample_2d_array_linear(ctx, tObj, tObj->Image[0][level], 02349 texcoord[i], rgba[i]); 02350 } 02351 } 02352 02353 02354 static void 02355 sample_2d_array_nearest_mipmap_linear(GLcontext *ctx, 02356 const struct gl_texture_object *tObj, 02357 GLuint n, const GLfloat texcoord[][4], 02358 const GLfloat lambda[], GLchan rgba[][4]) 02359 { 02360 GLuint i; 02361 ASSERT(lambda != NULL); 02362 for (i = 0; i < n; i++) { 02363 GLint level = linear_mipmap_level(tObj, lambda[i]); 02364 if (level >= tObj->_MaxLevel) { 02365 sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 02366 texcoord[i], rgba[i]); 02367 } 02368 else { 02369 GLchan t0[4], t1[4]; /* texels */ 02370 const GLfloat f = FRAC(lambda[i]); 02371 sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level ], 02372 texcoord[i], t0); 02373 sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level+1], 02374 texcoord[i], t1); 02375 lerp_rgba(rgba[i], f, t0, t1); 02376 } 02377 } 02378 } 02379 02380 02381 static void 02382 sample_2d_array_linear_mipmap_linear(GLcontext *ctx, 02383 const struct gl_texture_object *tObj, 02384 GLuint n, const GLfloat texcoord[][4], 02385 const GLfloat lambda[], GLchan rgba[][4]) 02386 { 02387 GLuint i; 02388 ASSERT(lambda != NULL); 02389 for (i = 0; i < n; i++) { 02390 GLint level = linear_mipmap_level(tObj, lambda[i]); 02391 if (level >= tObj->_MaxLevel) { 02392 sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 02393 texcoord[i], rgba[i]); 02394 } 02395 else { 02396 GLchan t0[4], t1[4]; /* texels */ 02397 const GLfloat f = FRAC(lambda[i]); 02398 sample_2d_array_linear(ctx, tObj, tObj->Image[0][level ], 02399 texcoord[i], t0); 02400 sample_2d_array_linear(ctx, tObj, tObj->Image[0][level+1], 02401 texcoord[i], t1); 02402 lerp_rgba(rgba[i], f, t0, t1); 02403 } 02404 } 02405 } 02406 02407 02409 static void 02410 sample_nearest_2d_array(GLcontext *ctx, 02411 const struct gl_texture_object *tObj, GLuint n, 02412 const GLfloat texcoords[][4], const GLfloat lambda[], 02413 GLchan rgba[][4]) 02414 { 02415 GLuint i; 02416 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 02417 (void) lambda; 02418 for (i = 0; i < n; i++) { 02419 sample_2d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]); 02420 } 02421 } 02422 02423 02424 02426 static void 02427 sample_linear_2d_array(GLcontext *ctx, 02428 const struct gl_texture_object *tObj, GLuint n, 02429 const GLfloat texcoords[][4], 02430 const GLfloat lambda[], GLchan rgba[][4]) 02431 { 02432 GLuint i; 02433 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 02434 (void) lambda; 02435 for (i = 0; i < n; i++) { 02436 sample_2d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]); 02437 } 02438 } 02439 02440 02442 static void 02443 sample_lambda_2d_array(GLcontext *ctx, 02444 const struct gl_texture_object *tObj, GLuint n, 02445 const GLfloat texcoords[][4], const GLfloat lambda[], 02446 GLchan rgba[][4]) 02447 { 02448 GLuint minStart, minEnd; /* texels with minification */ 02449 GLuint magStart, magEnd; /* texels with magnification */ 02450 GLuint i; 02451 02452 ASSERT(lambda != NULL); 02453 compute_min_mag_ranges(tObj, n, lambda, 02454 &minStart, &minEnd, &magStart, &magEnd); 02455 02456 if (minStart < minEnd) { 02457 /* do the minified texels */ 02458 GLuint m = minEnd - minStart; 02459 switch (tObj->MinFilter) { 02460 case GL_NEAREST: 02461 for (i = minStart; i < minEnd; i++) 02462 sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02463 texcoords[i], rgba[i]); 02464 break; 02465 case GL_LINEAR: 02466 for (i = minStart; i < minEnd; i++) 02467 sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02468 texcoords[i], rgba[i]); 02469 break; 02470 case GL_NEAREST_MIPMAP_NEAREST: 02471 sample_2d_array_nearest_mipmap_nearest(ctx, tObj, m, 02472 texcoords + minStart, 02473 lambda + minStart, 02474 rgba + minStart); 02475 break; 02476 case GL_LINEAR_MIPMAP_NEAREST: 02477 sample_2d_array_linear_mipmap_nearest(ctx, tObj, m, 02478 texcoords + minStart, 02479 lambda + minStart, 02480 rgba + minStart); 02481 break; 02482 case GL_NEAREST_MIPMAP_LINEAR: 02483 sample_2d_array_nearest_mipmap_linear(ctx, tObj, m, 02484 texcoords + minStart, 02485 lambda + minStart, 02486 rgba + minStart); 02487 break; 02488 case GL_LINEAR_MIPMAP_LINEAR: 02489 sample_2d_array_linear_mipmap_linear(ctx, tObj, m, 02490 texcoords + minStart, 02491 lambda + minStart, 02492 rgba + minStart); 02493 break; 02494 default: 02495 _mesa_problem(ctx, "Bad min filter in sample_2d_array_texture"); 02496 return; 02497 } 02498 } 02499 02500 if (magStart < magEnd) { 02501 /* do the magnified texels */ 02502 switch (tObj->MagFilter) { 02503 case GL_NEAREST: 02504 for (i = magStart; i < magEnd; i++) 02505 sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02506 texcoords[i], rgba[i]); 02507 break; 02508 case GL_LINEAR: 02509 for (i = magStart; i < magEnd; i++) 02510 sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02511 texcoords[i], rgba[i]); 02512 break; 02513 default: 02514 _mesa_problem(ctx, "Bad mag filter in sample_2d_array_texture"); 02515 return; 02516 } 02517 } 02518 } 02519 02520 02521 02522 02523 /**********************************************************************/ 02524 /* 1D Texture Array Sampling Functions */ 02525 /**********************************************************************/ 02526 02530 static void 02531 sample_1d_array_nearest(GLcontext *ctx, 02532 const struct gl_texture_object *tObj, 02533 const struct gl_texture_image *img, 02534 const GLfloat texcoord[4], 02535 GLchan rgba[4]) 02536 { 02537 const GLint width = img->Width2; /* without border, power of two */ 02538 const GLint height = img->Height; 02539 GLint i; 02540 GLint array; 02541 (void) ctx; 02542 02543 i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]); 02544 array = clamp_rect_coord_nearest(tObj->WrapT, texcoord[1], height); 02545 02546 if (i < 0 || i >= (GLint) img->Width || 02547 array < 0 || array >= (GLint) img->Height) { 02548 /* Need this test for GL_CLAMP_TO_BORDER mode */ 02549 COPY_CHAN4(rgba, tObj->_BorderChan); 02550 } 02551 else { 02552 img->FetchTexelc(img, i, array, 0, rgba); 02553 } 02554 } 02555 02556 02560 static void 02561 sample_1d_array_linear(GLcontext *ctx, 02562 const struct gl_texture_object *tObj, 02563 const struct gl_texture_image *img, 02564 const GLfloat texcoord[4], 02565 GLchan rgba[4]) 02566 { 02567 const GLint width = img->Width2; 02568 const GLint height = img->Height; 02569 GLint i0, i1; 02570 GLint array; 02571 GLbitfield useBorderColor = 0x0; 02572 GLfloat a; 02573 GLchan t0[4], t1[4]; 02574 02575 linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a); 02576 array = clamp_rect_coord_nearest(tObj->WrapT, texcoord[1], height); 02577 02578 if (img->Border) { 02579 i0 += img->Border; 02580 i1 += img->Border; 02581 } 02582 else { 02583 /* check if sampling texture border color */ 02584 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; 02585 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; 02586 } 02587 02588 if (array < 0 || array >= height) useBorderColor |= K0BIT; 02589 02590 /* Fetch texels */ 02591 if (useBorderColor & (I0BIT | K0BIT)) { 02592 COPY_CHAN4(t0, tObj->_BorderChan); 02593 } 02594 else { 02595 img->FetchTexelc(img, i0, array, 0, t0); 02596 } 02597 if (useBorderColor & (I1BIT | K0BIT)) { 02598 COPY_CHAN4(t1, tObj->_BorderChan); 02599 } 02600 else { 02601 img->FetchTexelc(img, i1, array, 0, t1); 02602 } 02603 02604 /* bilinear interpolation of samples */ 02605 lerp_rgba(rgba, a, t0, t1); 02606 } 02607 02608 02609 static void 02610 sample_1d_array_nearest_mipmap_nearest(GLcontext *ctx, 02611 const struct gl_texture_object *tObj, 02612 GLuint n, const GLfloat texcoord[][4], 02613 const GLfloat lambda[], GLchan rgba[][4]) 02614 { 02615 GLuint i; 02616 for (i = 0; i < n; i++) { 02617 GLint level = nearest_mipmap_level(tObj, lambda[i]); 02618 sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], 02619 rgba[i]); 02620 } 02621 } 02622 02623 02624 static void 02625 sample_1d_array_linear_mipmap_nearest(GLcontext *ctx, 02626 const struct gl_texture_object *tObj, 02627 GLuint n, const GLfloat texcoord[][4], 02628 const GLfloat lambda[], GLchan rgba[][4]) 02629 { 02630 GLuint i; 02631 ASSERT(lambda != NULL); 02632 for (i = 0; i < n; i++) { 02633 GLint level = nearest_mipmap_level(tObj, lambda[i]); 02634 sample_1d_array_linear(ctx, tObj, tObj->Image[0][level], 02635 texcoord[i], rgba[i]); 02636 } 02637 } 02638 02639 02640 static void 02641 sample_1d_array_nearest_mipmap_linear(GLcontext *ctx, 02642 const struct gl_texture_object *tObj, 02643 GLuint n, const GLfloat texcoord[][4], 02644 const GLfloat lambda[], GLchan rgba[][4]) 02645 { 02646 GLuint i; 02647 ASSERT(lambda != NULL); 02648 for (i = 0; i < n; i++) { 02649 GLint level = linear_mipmap_level(tObj, lambda[i]); 02650 if (level >= tObj->_MaxLevel) { 02651 sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 02652 texcoord[i], rgba[i]); 02653 } 02654 else { 02655 GLchan t0[4], t1[4]; /* texels */ 02656 const GLfloat f = FRAC(lambda[i]); 02657 sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 02658 sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 02659 lerp_rgba(rgba[i], f, t0, t1); 02660 } 02661 } 02662 } 02663 02664 02665 static void 02666 sample_1d_array_linear_mipmap_linear(GLcontext *ctx, 02667 const struct gl_texture_object *tObj, 02668 GLuint n, const GLfloat texcoord[][4], 02669 const GLfloat lambda[], GLchan rgba[][4]) 02670 { 02671 GLuint i; 02672 ASSERT(lambda != NULL); 02673 for (i = 0; i < n; i++) { 02674 GLint level = linear_mipmap_level(tObj, lambda[i]); 02675 if (level >= tObj->_MaxLevel) { 02676 sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], 02677 texcoord[i], rgba[i]); 02678 } 02679 else { 02680 GLchan t0[4], t1[4]; /* texels */ 02681 const GLfloat f = FRAC(lambda[i]); 02682 sample_1d_array_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); 02683 sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); 02684 lerp_rgba(rgba[i], f, t0, t1); 02685 } 02686 } 02687 } 02688 02689 02691 static void 02692 sample_nearest_1d_array(GLcontext *ctx, 02693 const struct gl_texture_object *tObj, GLuint n, 02694 const GLfloat texcoords[][4], const GLfloat lambda[], 02695 GLchan rgba[][4]) 02696 { 02697 GLuint i; 02698 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 02699 (void) lambda; 02700 for (i = 0; i < n; i++) { 02701 sample_1d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]); 02702 } 02703 } 02704 02705 02707 static void 02708 sample_linear_1d_array(GLcontext *ctx, 02709 const struct gl_texture_object *tObj, GLuint n, 02710 const GLfloat texcoords[][4], 02711 const GLfloat lambda[], GLchan rgba[][4]) 02712 { 02713 GLuint i; 02714 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; 02715 (void) lambda; 02716 for (i = 0; i < n; i++) { 02717 sample_1d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]); 02718 } 02719 } 02720 02721 02723 static void 02724 sample_lambda_1d_array(GLcontext *ctx, 02725 const struct gl_texture_object *tObj, GLuint n, 02726 const GLfloat texcoords[][4], const GLfloat lambda[], 02727 GLchan rgba[][4]) 02728 { 02729 GLuint minStart, minEnd; /* texels with minification */ 02730 GLuint magStart, magEnd; /* texels with magnification */ 02731 GLuint i; 02732 02733 ASSERT(lambda != NULL); 02734 compute_min_mag_ranges(tObj, n, lambda, 02735 &minStart, &minEnd, &magStart, &magEnd); 02736 02737 if (minStart < minEnd) { 02738 /* do the minified texels */ 02739 GLuint m = minEnd - minStart; 02740 switch (tObj->MinFilter) { 02741 case GL_NEAREST: 02742 for (i = minStart; i < minEnd; i++) 02743 sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02744 texcoords[i], rgba[i]); 02745 break; 02746 case GL_LINEAR: 02747 for (i = minStart; i < minEnd; i++) 02748 sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02749 texcoords[i], rgba[i]); 02750 break; 02751 case GL_NEAREST_MIPMAP_NEAREST: 02752 sample_1d_array_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, 02753 lambda + minStart, rgba + minStart); 02754 break; 02755 case GL_LINEAR_MIPMAP_NEAREST: 02756 sample_1d_array_linear_mipmap_nearest(ctx, tObj, m, 02757 texcoords + minStart, 02758 lambda + minStart, 02759 rgba + minStart); 02760 break; 02761 case GL_NEAREST_MIPMAP_LINEAR: 02762 sample_1d_array_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, 02763 lambda + minStart, rgba + minStart); 02764 break; 02765 case GL_LINEAR_MIPMAP_LINEAR: 02766 sample_1d_array_linear_mipmap_linear(ctx, tObj, m, 02767 texcoords + minStart, 02768 lambda + minStart, 02769 rgba + minStart); 02770 break; 02771 default: 02772 _mesa_problem(ctx, "Bad min filter in sample_1d_array_texture"); 02773 return; 02774 } 02775 } 02776 02777 if (magStart < magEnd) { 02778 /* do the magnified texels */ 02779 switch (tObj->MagFilter) { 02780 case GL_NEAREST: 02781 for (i = magStart; i < magEnd; i++) 02782 sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02783 texcoords[i], rgba[i]); 02784 break; 02785 case GL_LINEAR: 02786 for (i = magStart; i < magEnd; i++) 02787 sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], 02788 texcoords[i], rgba[i]); 02789 break; 02790 default: 02791 _mesa_problem(ctx, "Bad mag filter in sample_1d_array_texture"); 02792 return; 02793 } 02794 } 02795 } 02796 02797 02801 static void 02802 sample_depth_texture( GLcontext *ctx, 02803 const struct gl_texture_object *tObj, GLuint n, 02804 const GLfloat texcoords[][4], const GLfloat lambda[], 02805 GLchan texel[][4] ) 02806 { 02807 const GLint baseLevel = tObj->BaseLevel; 02808 const struct gl_texture_image *img = tObj->Image[0][baseLevel]; 02809 const GLint width = img->Width; 02810 const GLint height = img->Height; 02811 const GLint depth = img->Depth; 02812 const GLuint compare_coord = (tObj->Target == GL_TEXTURE_2D_ARRAY_EXT) 02813 ? 3 : 2; 02814 GLchan ambient; 02815 GLenum function; 02816 GLchan result; 02817 02818 (void) lambda; 02819 02820 ASSERT(img->TexFormat->BaseFormat == GL_DEPTH_COMPONENT || 02821 img->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT); 02822 02823 ASSERT(tObj->Target == GL_TEXTURE_1D || 02824 tObj->Target == GL_TEXTURE_2D || 02825 tObj->Target == GL_TEXTURE_RECTANGLE_NV || 02826 tObj->Target == GL_TEXTURE_1D_ARRAY_EXT || 02827 tObj->Target == GL_TEXTURE_2D_ARRAY_EXT); 02828 02829 UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient); 02830 02831 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */ 02832 02833 function = tObj->_Function; 02834 if (tObj->MagFilter == GL_NEAREST) { 02835 GLuint i; 02836 for (i = 0; i < n; i++) { 02837 GLfloat depthSample; 02838 GLint col, row, slice; 02839 02840 switch (tObj->Target) { 02841 case GL_TEXTURE_RECTANGLE_ARB: 02842 col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width); 02843 row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height); 02844 slice = 0; 02845 break; 02846 02847 case GL_TEXTURE_1D: 02848 col = nearest_texel_location(tObj->WrapS, img, width, 02849 texcoords[i][0]); 02850 row = 0; 02851 slice = 0; 02852 break; 02853 02854 case GL_TEXTURE_2D: 02855 col = nearest_texel_location(tObj->WrapS, img, width, 02856 texcoords[i][0]); 02857 row = nearest_texel_location(tObj->WrapT, img, height, 02858 texcoords[i][1]); 02859 slice = 0; 02860 break; 02861 02862 case GL_TEXTURE_1D_ARRAY_EXT: 02863 col = nearest_texel_location(tObj->WrapS, img, width, 02864 texcoords[i][0]); 02865 row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height); 02866 slice = 0; 02867 break; 02868 02869 case GL_TEXTURE_2D_ARRAY_EXT: 02870 col = nearest_texel_location(tObj->WrapS, img, width, 02871 texcoords[i][0]); 02872 row = nearest_texel_location(tObj->WrapT, img, height, 02873 texcoords[i][1]); 02874 slice = clamp_rect_coord_nearest(tObj->WrapR, texcoords[i][2], depth); 02875 break; 02876 default: 02877 col = row = slice = 0; 02878 } 02879 02880 if (col >= 0 && row >= 0 && col < width && row < height && 02881 slice >= 0 && slice < depth) { 02882 img->FetchTexelf(img, col, row, slice, &depthSample); 02883 } 02884 else { 02885 depthSample = tObj->BorderColor[0]; 02886 } 02887 02888 switch (function) { 02889 case GL_LEQUAL: 02890 result = (texcoords[i][compare_coord] <= depthSample) ? CHAN_MAX : ambient; 02891 break; 02892 case GL_GEQUAL: 02893 result = (texcoords[i][compare_coord] >= depthSample) ? CHAN_MAX : ambient; 02894 break; 02895 case GL_LESS: 02896 result = (texcoords[i][compare_coord] < depthSample) ? CHAN_MAX : ambient; 02897 break; 02898 case GL_GREATER: 02899 result = (texcoords[i][compare_coord] > depthSample) ? CHAN_MAX : ambient; 02900 break; 02901 case GL_EQUAL: 02902 result = (texcoords[i][compare_coord] == depthSample) ? CHAN_MAX : ambient; 02903 break; 02904 case GL_NOTEQUAL: 02905 result = (texcoords[i][compare_coord] != depthSample) ? CHAN_MAX : ambient; 02906 break; 02907 case GL_ALWAYS: 02908 result = CHAN_MAX; 02909 break; 02910 case GL_NEVER: 02911 result = ambient; 02912 break; 02913 case GL_NONE: 02914 CLAMPED_FLOAT_TO_CHAN(result, depthSample); 02915 break; 02916 default: 02917 _mesa_problem(ctx, "Bad compare func in sample_depth_texture"); 02918 return; 02919 } 02920 02921 switch (tObj->DepthMode) { 02922 case GL_LUMINANCE: 02923 texel[i][RCOMP] = result; 02924 texel[i][GCOMP] = result; 02925 texel[i][BCOMP] = result; 02926 texel[i][ACOMP] = CHAN_MAX; 02927 break; 02928 case GL_INTENSITY: 02929 texel[i][RCOMP] = result; 02930 texel[i][GCOMP] = result; 02931 texel[i][BCOMP] = result; 02932 texel[i][ACOMP] = result; 02933 break; 02934 case GL_ALPHA: 02935 texel[i][RCOMP] = 0; 02936 texel[i][GCOMP] = 0; 02937 texel[i][BCOMP] = 0; 02938 texel[i][ACOMP] = result; 02939 break; 02940 default: 02941 _mesa_problem(ctx, "Bad depth texture mode"); 02942 } 02943 } 02944 } 02945 else { 02946 GLuint i; 02947 ASSERT(tObj->MagFilter == GL_LINEAR); 02948 for (i = 0; i < n; i++) { 02949 GLfloat depth00, depth01, depth10, depth11; 02950 GLint i0, i1, j0, j1; 02951 GLint slice; 02952 GLfloat a, b; 02953 GLuint useBorderTexel; 02954 02955 switch (tObj->Target) { 02956 case GL_TEXTURE_RECTANGLE_ARB: 02957 clamp_rect_coord_linear(tObj->WrapS, texcoords[i][0], 02958 width, &i0, &i1, &a); 02959 clamp_rect_coord_linear(tObj->WrapT, texcoords[i][1], 02960 height, &j0, &j1, &b); 02961 slice = 0; 02962 break; 02963 02964 case GL_TEXTURE_1D: 02965 case GL_TEXTURE_2D: 02966 linear_texel_locations(tObj->WrapS, img, width, 02967 texcoords[i][0], &i0, &i1, &a); 02968 linear_texel_locations(tObj->WrapT, img, height, 02969 texcoords[i][1], &j0, &j1, &b); 02970 slice = 0; 02971 break; 02972 02973 case GL_TEXTURE_1D_ARRAY_EXT: 02974 linear_texel_locations(tObj->WrapS, img, width, 02975 texcoords[i][0], &i0, &i1, &a); 02976 j0 = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height); 02977 j1 = j0; 02978 slice = 0; 02979 break; 02980 02981 case GL_TEXTURE_2D_ARRAY_EXT: 02982 linear_texel_locations(tObj->WrapS, img, width, 02983 texcoords[i][0], &i0, &i1, &a); 02984 linear_texel_locations(tObj->WrapT, img, height, 02985 texcoords[i][1], &j0, &j1, &b); 02986 slice = clamp_rect_coord_nearest(tObj->WrapR, texcoords[i][2], depth); 02987 break; 02988 default: 02989 slice = 0; 02990 } 02991 02992 useBorderTexel = 0; 02993 if (img->Border) { 02994 i0 += img->Border; 02995 i1 += img->Border; 02996 if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) { 02997 j0 += img->Border; 02998 j1 += img->Border; 02999 } 03000 } 03001 else { 03002 if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT; 03003 if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT; 03004 if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT; 03005 if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT; 03006 } 03007 03008 if (slice < 0 || slice >= (GLint) depth) { 03009 depth00 = tObj->BorderColor[0]; 03010 depth01 = tObj->BorderColor[0]; 03011 depth10 = tObj->BorderColor[0]; 03012 depth11 = tObj->BorderColor[0]; 03013 } 03014 else { 03015 /* get four depth samples from the texture */ 03016 if (useBorderTexel & (I0BIT | J0BIT)) { 03017 depth00 = tObj->BorderColor[0]; 03018 } 03019 else { 03020 img->FetchTexelf(img, i0, j0, slice, &depth00); 03021 } 03022 if (useBorderTexel & (I1BIT | J0BIT)) { 03023 depth10 = tObj->BorderColor[0]; 03024 } 03025 else { 03026 img->FetchTexelf(img, i1, j0, slice, &depth10); 03027 } 03028 03029 if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) { 03030 if (useBorderTexel & (I0BIT | J1BIT)) { 03031 depth01 = tObj->BorderColor[0]; 03032 } 03033 else { 03034 img->FetchTexelf(img, i0, j1, slice, &depth01); 03035 } 03036 if (useBorderTexel & (I1BIT | J1BIT)) { 03037 depth11 = tObj->BorderColor[0]; 03038 } 03039 else { 03040 img->FetchTexelf(img, i1, j1, slice, &depth11); 03041 } 03042 } 03043 else { 03044 depth01 = depth00; 03045 depth11 = depth10; 03046 } 03047 } 03048 03049 if (0) { 03050 /* compute a single weighted depth sample and do one comparison */ 03051 const GLfloat depthSample 03052 = lerp_2d(a, b, depth00, depth10, depth01, depth11); 03053 if ((depthSample <= texcoords[i][compare_coord] && function == GL_LEQUAL) || 03054 (depthSample >= texcoords[i][compare_coord] && function == GL_GEQUAL)) { 03055 result = ambient; 03056 } 03057 else { 03058 result = CHAN_MAX; 03059 } 03060 } 03061 else { 03062 /* Do four depth/R comparisons and compute a weighted result. 03063 * If this touches on somebody's I.P., I'll remove this code 03064 * upon request. 03065 */ 03066 const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F; 03067 GLfloat luminance = CHAN_MAXF; 03068 03069 switch (function) { 03070 case GL_LEQUAL: 03071 if (depth00 <= texcoords[i][compare_coord]) luminance -= d; 03072 if (depth01 <= texcoords[i][compare_coord]) luminance -= d; 03073 if (depth10 <= texcoords[i][compare_coord]) luminance -= d; 03074 if (depth11 <= texcoords[i][compare_coord]) luminance -= d; 03075 result = (GLchan) luminance; 03076 break; 03077 case GL_GEQUAL: 03078 if (depth00 >= texcoords[i][compare_coord]) luminance -= d; 03079 if (depth01 >= texcoords[i][compare_coord]) luminance -= d; 03080 if (depth10 >= texcoords[i][compare_coord]) luminance -= d; 03081 if (depth11 >= texcoords[i][compare_coord]) luminance -= d; 03082 result = (GLchan) luminance; 03083 break; 03084 case GL_LESS: 03085 if (depth00 < texcoords[i][compare_coord]) luminance -= d; 03086 if (depth01 < texcoords[i][compare_coord]) luminance -= d; 03087 if (depth10 < texcoords[i][compare_coord]) luminance -= d; 03088 if (depth11 < texcoords[i][compare_coord]) luminance -= d; 03089 result = (GLchan) luminance; 03090 break; 03091 case GL_GREATER: 03092 if (depth00 > texcoords[i][compare_coord]) luminance -= d; 03093 if (depth01 > texcoords[i][compare_coord]) luminance -= d; 03094 if (depth10 > texcoords[i][compare_coord]) luminance -= d; 03095 if (depth11 > texcoords[i][compare_coord]) luminance -= d; 03096 result = (GLchan) luminance; 03097 break; 03098 case GL_EQUAL: 03099 if (depth00 == texcoords[i][compare_coord]) luminance -= d; 03100 if (depth01 == texcoords[i][compare_coord]) luminance -= d; 03101 if (depth10 == texcoords[i][compare_coord]) luminance -= d; 03102 if (depth11 == texcoords[i][compare_coord]) luminance -= d; 03103 result = (GLchan) luminance; 03104 break; 03105 case GL_NOTEQUAL: 03106 if (depth00 != texcoords[i][compare_coord]) luminance -= d; 03107 if (depth01 != texcoords[i][compare_coord]) luminance -= d; 03108 if (depth10 != texcoords[i][compare_coord]) luminance -= d; 03109 if (depth11 != texcoords[i][compare_coord]) luminance -= d; 03110 result = (GLchan) luminance; 03111 break; 03112 case GL_ALWAYS: 03113 result = 0; 03114 break; 03115 case GL_NEVER: 03116 result = CHAN_MAX; 03117 break; 03118 case GL_NONE: 03119 /* ordinary bilinear filtering */ 03120 { 03121 const GLfloat depthSample 03122 = lerp_2d(a, b, depth00, depth10, depth01, depth11); 03123 CLAMPED_FLOAT_TO_CHAN(result, depthSample); 03124 } 03125 break; 03126 default: 03127 _mesa_problem(ctx, "Bad compare func in sample_depth_texture"); 03128 return; 03129 } 03130 } 03131 03132 switch (tObj->DepthMode) { 03133 case GL_LUMINANCE: 03134 texel[i][RCOMP] = result; 03135 texel[i][GCOMP] = result; 03136 texel[i][BCOMP] = result; 03137 texel[i][ACOMP] = CHAN_MAX; 03138 break; 03139 case GL_INTENSITY: 03140 texel[i][RCOMP] = result; 03141 texel[i][GCOMP] = result; 03142 texel[i][BCOMP] = result; 03143 texel[i][ACOMP] = result; 03144 break; 03145 case GL_ALPHA: 03146 texel[i][RCOMP] = 0; 03147 texel[i][GCOMP] = 0; 03148 texel[i][BCOMP] = 0; 03149 texel[i][ACOMP] = result; 03150 break; 03151 default: 03152 _mesa_problem(ctx, "Bad depth texture mode"); 03153 } 03154 } /* for */ 03155 } /* if filter */ 03156 } 03157 03158 03159 #if 0 03160 /* 03161 * Experimental depth texture sampling function. 03162 */ 03163 static void 03164 sample_depth_texture2(const GLcontext *ctx, 03165 const struct gl_texture_unit *texUnit, 03166 GLuint n, const GLfloat texcoords[][4], 03167 GLchan texel[][4]) 03168 { 03169 const struct gl_texture_object *texObj = texUnit->_Current; 03170 const GLint baseLevel = texObj->BaseLevel; 03171 const struct gl_texture_image *texImage = texObj->Image[0][baseLevel]; 03172 const GLuint width = texImage->Width; 03173 const GLuint height = texImage->Height; 03174 GLchan ambient; 03175 GLboolean lequal, gequal; 03176 03177 if (texObj->Target != GL_TEXTURE_2D) { 03178 _mesa_problem(ctx, "only 2-D depth textures supported at this time"); 03179 return; 03180 } 03181 03182 if (texObj->MinFilter != texObj->MagFilter) { 03183 _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); 03184 return; 03185 } 03186 03187 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if 03188 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object 03189 * isn't a depth texture. 03190 */ 03191 if (texImage->TexFormat->BaseFormat != GL_DEPTH_COMPONENT) { 03192 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture"); 03193 return; 03194 } 03195 03196 UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient); 03197 03198 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { 03199 lequal = GL_TRUE; 03200 gequal = GL_FALSE; 03201 } 03202 else { 03203 lequal = GL_FALSE; 03204 gequal = GL_TRUE; 03205 } 03206 03207 { 03208 GLuint i; 03209 for (i = 0; i < n; i++) { 03210 const GLint K = 3; 03211 GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count; 03212 GLfloat w; 03213 GLchan lum; 03214 col = nearest_texel_location(texObj->WrapS, img, width, 03215 texcoords[i][0]); 03216 row = nearest_texel_location(texObj->WrapT, img, height, 03217 texcoords[i][1]); 03218 03219 imin = col - K; 03220 imax = col + K; 03221 jmin = row - K; 03222 jmax = row + K; 03223 03224 if (imin < 0) imin = 0; 03225 if (imax >= width) imax = width - 1; 03226 if (jmin < 0) jmin = 0; 03227 if (jmax >= height) jmax = height - 1; 03228 03229 samples = (imax - imin + 1) * (jmax - jmin + 1); 03230 count = 0; 03231 for (jj = jmin; jj <= jmax; jj++) { 03232 for (ii = imin; ii <= imax; ii++) { 03233 GLfloat depthSample; 03234 texImage->FetchTexelf(texImage, ii, jj, 0, &depthSample); 03235 if ((depthSample <= r[i] && lequal) || 03236 (depthSample >= r[i] && gequal)) { 03237 count++; 03238 } 03239 } 03240 } 03241 03242 w = (GLfloat) count / (GLfloat) samples; 03243 w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient); 03244 lum = (GLint) w; 03245 03246 texel[i][RCOMP] = lum; 03247 texel[i][GCOMP] = lum; 03248 texel[i][BCOMP] = lum; 03249 texel[i][ACOMP] = CHAN_MAX; 03250 } 03251 } 03252 } 03253 #endif 03254 03255 03262 static void 03263 null_sample_func( GLcontext *ctx, 03264 const struct gl_texture_object *tObj, GLuint n, 03265 const GLfloat texcoords[][4], const GLfloat lambda[], 03266 GLchan rgba[][4]) 03267 { 03268 GLuint i; 03269 (void) ctx; 03270 (void) tObj; 03271 (void) texcoords; 03272 (void) lambda; 03273 for (i = 0; i < n; i++) { 03274 rgba[i][RCOMP] = 0; 03275 rgba[i][GCOMP] = 0; 03276 rgba[i][BCOMP] = 0; 03277 rgba[i][ACOMP] = CHAN_MAX; 03278 } 03279 } 03280 03281 03285 texture_sample_func 03286 _swrast_choose_texture_sample_func( GLcontext *ctx, 03287 const struct gl_texture_object *t ) 03288 { 03289 if (!t || !t->_Complete) { 03290 return &null_sample_func; 03291 } 03292 else { 03293 const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter); 03294 const GLenum format = t->Image[0][t->BaseLevel]->TexFormat->BaseFormat; 03295 03296 switch (t->Target) { 03297 case GL_TEXTURE_1D: 03298 if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) { 03299 return &sample_depth_texture; 03300 } 03301 else if (needLambda) { 03302 return &sample_lambda_1d; 03303 } 03304 else if (t->MinFilter == GL_LINEAR) { 03305 return &sample_linear_1d; 03306 } 03307 else { 03308 ASSERT(t->MinFilter == GL_NEAREST); 03309 return &sample_nearest_1d; 03310 } 03311 case GL_TEXTURE_2D: 03312 if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) { 03313 return &sample_depth_texture; 03314 } 03315 else if (needLambda) { 03316 return &sample_lambda_2d; 03317 } 03318 else if (t->MinFilter == GL_LINEAR) { 03319 return &sample_linear_2d; 03320 } 03321 else { 03322 /* check for a few optimized cases */ 03323 const struct gl_texture_image *img = t->Image[0][t->BaseLevel]; 03324 ASSERT(t->MinFilter == GL_NEAREST); 03325 if (t->WrapS == GL_REPEAT && 03326 t->WrapT == GL_REPEAT && 03327 img->_IsPowerOfTwo && 03328 img->Border == 0 && 03329 img->TexFormat->MesaFormat == MESA_FORMAT_RGB) { 03330 return &opt_sample_rgb_2d; 03331 } 03332 else if (t->WrapS == GL_REPEAT && 03333 t->WrapT == GL_REPEAT && 03334 img->_IsPowerOfTwo && 03335 img->Border == 0 && 03336 img->TexFormat->MesaFormat == MESA_FORMAT_RGBA) { 03337 return &opt_sample_rgba_2d; 03338 } 03339 else { 03340 return &sample_nearest_2d; 03341 } 03342 } 03343 case GL_TEXTURE_3D: 03344 if (needLambda) { 03345 return &sample_lambda_3d; 03346 } 03347 else if (t->MinFilter == GL_LINEAR) { 03348 return &sample_linear_3d; 03349 } 03350 else { 03351 ASSERT(t->MinFilter == GL_NEAREST); 03352 return &sample_nearest_3d; 03353 } 03354 case GL_TEXTURE_CUBE_MAP: 03355 if (needLambda) { 03356 return &sample_lambda_cube; 03357 } 03358 else if (t->MinFilter == GL_LINEAR) { 03359 return &sample_linear_cube; 03360 } 03361 else { 03362 ASSERT(t->MinFilter == GL_NEAREST); 03363 return &sample_nearest_cube; 03364 } 03365 case GL_TEXTURE_RECTANGLE_NV: 03366 if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) { 03367 return &sample_depth_texture; 03368 } 03369 else if (needLambda) { 03370 return &sample_lambda_rect; 03371 } 03372 else if (t->MinFilter == GL_LINEAR) { 03373 return &sample_linear_rect; 03374 } 03375 else { 03376 ASSERT(t->MinFilter == GL_NEAREST); 03377 return &sample_nearest_rect; 03378 } 03379 case GL_TEXTURE_1D_ARRAY_EXT: 03380 if (needLambda) { 03381 return &sample_lambda_1d_array; 03382 } 03383 else if (t->MinFilter == GL_LINEAR) { 03384 return &sample_linear_1d_array; 03385 } 03386 else { 03387 ASSERT(t->MinFilter == GL_NEAREST); 03388 return &sample_nearest_1d_array; 03389 } 03390 case GL_TEXTURE_2D_ARRAY_EXT: 03391 if (needLambda) { 03392 return &sample_lambda_2d_array; 03393 } 03394 else if (t->MinFilter == GL_LINEAR) { 03395 return &sample_linear_2d_array; 03396 } 03397 else { 03398 ASSERT(t->MinFilter == GL_NEAREST); 03399 return &sample_nearest_2d_array; 03400 } 03401 default: 03402 _mesa_problem(ctx, 03403 "invalid target in _swrast_choose_texture_sample_func"); 03404 return &null_sample_func; 03405 } 03406 } 03407 } Generated on Fri May 25 2012 04:18:53 for ReactOS by
1.7.6.1
|