ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

s_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.