home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / texture.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  70.2 KB  |  2,281 lines

  1. /* $Id: texture.c,v 1.36 1997/11/17 02:04:06 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.5
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: texture.c,v $
  26.  * Revision 1.36  1997/11/17 02:04:06  brianp
  27.  * fixed a typo in texture code
  28.  *
  29.  * Revision 1.35  1997/11/13 02:17:32  brianp
  30.  * added a few const keywords
  31.  *
  32.  * Revision 1.34  1997/10/16 01:59:08  brianp
  33.  * added GL_EXT_shared_texture_palette extension
  34.  *
  35.  * Revision 1.33  1997/09/27 00:14:39  brianp
  36.  * added GL_EXT_paletted_texture extension
  37.  *
  38.  * Revision 1.32  1997/08/14 01:03:12  brianp
  39.  * fixed small bug in GL_SPHERE_MAP texgen (Petri Nordlund)
  40.  *
  41.  * Revision 1.31  1997/07/24 01:25:34  brianp
  42.  * changed precompiled header symbol from PCH to PC_HEADER
  43.  *
  44.  * Revision 1.30  1997/07/22 01:23:48  brianp
  45.  * fixed negative texture coord sampling problem (Magnus Lundin)
  46.  *
  47.  * Revision 1.29  1997/07/09 00:32:26  brianp
  48.  * fixed bug involving sampling and incomplete texture objects
  49.  *
  50.  * Revision 1.28  1997/05/28 03:26:49  brianp
  51.  * added precompiled header (PCH) support
  52.  *
  53.  * Revision 1.27  1997/05/17 03:51:10  brianp
  54.  * fixed bug in PROD macro (Waldemar Celes)
  55.  *
  56.  * Revision 1.26  1997/05/03 00:53:56  brianp
  57.  * all-new texture sampling via gl_texture_object's SampleFunc pointer
  58.  *
  59.  * Revision 1.25  1997/05/01 01:40:14  brianp
  60.  * replaced sqrt() with GL_SQRT, use NORMALIZE_3FV instead of NORMALIZE_3V
  61.  *
  62.  * Revision 1.24  1997/04/28 02:04:18  brianp
  63.  * GL_SPHERE_MAP texgen was wrong (Eamon O'Dea)
  64.  *
  65.  * Revision 1.23  1997/04/20 20:29:11  brianp
  66.  * replaced abort() with gl_problem()
  67.  *
  68.  * Revision 1.22  1997/04/16 23:56:41  brianp
  69.  * added a few #include files
  70.  *
  71.  * Revision 1.21  1997/04/14 02:02:39  brianp
  72.  * moved many functions into new texstate.c file
  73.  *
  74.  * Revision 1.20  1997/04/01 04:19:14  brianp
  75.  * call gl_analyze_modelview_matrix instead of gl_compute_modelview_inverse
  76.  *
  77.  * Revision 1.19  1997/03/04 19:55:58  brianp
  78.  * small texture sampling optimizations.  better comments.
  79.  *
  80.  * Revision 1.18  1997/03/04 19:19:20  brianp
  81.  * fixed a number of problems with texture borders
  82.  *
  83.  * Revision 1.17  1997/02/27 19:58:08  brianp
  84.  * call gl_problem() instead of gl_warning()
  85.  *
  86.  * Revision 1.16  1997/02/09 19:53:43  brianp
  87.  * now use TEXTURE_xD enable constants
  88.  *
  89.  * Revision 1.15  1997/02/09 18:53:14  brianp
  90.  * added GL_EXT_texture3D support
  91.  *
  92.  * Revision 1.14  1997/01/30 21:06:03  brianp
  93.  * added some missing glGetTexLevelParameter() GLenums
  94.  *
  95.  * Revision 1.13  1997/01/16 03:36:01  brianp
  96.  * added calls to device driver TexParameter() and TexEnv() functions
  97.  *
  98.  * Revision 1.12  1997/01/09 19:48:30  brianp
  99.  * better error checking
  100.  * added gl_texturing_enabled()
  101.  *
  102.  * Revision 1.11  1996/12/20 20:22:30  brianp
  103.  * linear interpolation between mipmap levels was reverse weighted
  104.  * max mipmap level was incorrectly tested for
  105.  *
  106.  * Revision 1.10  1996/12/12 22:33:05  brianp
  107.  * minor changes to gl_texgen()
  108.  *
  109.  * Revision 1.9  1996/12/07 10:35:41  brianp
  110.  * implmented glGetTexGen*() functions
  111.  *
  112.  * Revision 1.8  1996/11/14 01:03:09  brianp
  113.  * removed const's from gl_texgen() function to avoid VMS compiler warning
  114.  *
  115.  * Revision 1.7  1996/11/08 02:19:52  brianp
  116.  * gl_do_texgen() replaced with gl_texgen()
  117.  *
  118.  * Revision 1.6  1996/10/26 17:17:30  brianp
  119.  * glTexGen GL_EYE_PLANE vector now transformed by inverse modelview matrix
  120.  *
  121.  * Revision 1.5  1996/10/11 03:42:38  brianp
  122.  * replaced old _EXT symbols
  123.  *
  124.  * Revision 1.4  1996/09/27 01:30:24  brianp
  125.  * added missing default cases to switches
  126.  *
  127.  * Revision 1.3  1996/09/15 14:18:55  brianp
  128.  * now use GLframebuffer and GLvisual
  129.  *
  130.  * Revision 1.2  1996/09/15 01:48:58  brianp
  131.  * removed #define NULL 0
  132.  *
  133.  * Revision 1.1  1996/09/13 01:38:16  brianp
  134.  * Initial revision
  135.  *
  136.  */
  137.  
  138.  
  139. #ifdef PC_HEADER
  140. #include "all.h"
  141. #else
  142. #include <math.h>
  143. #include <stdlib.h>
  144. #include "context.h"
  145. #include "macros.h"
  146. #include "mmath.h"
  147. #include "pb.h"
  148. #include "texture.h"
  149. #include "types.h"
  150. #endif
  151.  
  152.  
  153.  
  154. /*
  155.  * Perform automatic texture coordinate generation.
  156.  * Input:  ctx - the context
  157.  *         n - number of texture coordinates to generate
  158.  *         obj - array of vertexes in object coordinate system
  159.  *         eye - array of vertexes in eye coordinate system
  160.  *         normal - array of normal vectores in eye coordinate system
  161.  * Output:  texcoord - array of resuling texture coordinates
  162.  */
  163. void gl_texgen( GLcontext *ctx, GLint n,
  164.                 GLfloat obj[][4], GLfloat eye[][4],
  165.                 GLfloat normal[][3], GLfloat texcoord[][4] )
  166. {
  167.    /* special case: S and T sphere mapping */
  168.    if (ctx->Texture.TexGenEnabled==(S_BIT|T_BIT)
  169.        && ctx->Texture.GenModeS==GL_SPHERE_MAP
  170.        && ctx->Texture.GenModeT==GL_SPHERE_MAP) {
  171.       GLint i;
  172.       for (i=0;i<n;i++) {
  173.          GLfloat u[3], two_nu, m, fx, fy, fz;
  174.          COPY_3V( u, eye[i] );
  175.          NORMALIZE_3FV( u );
  176.          two_nu = 2.0F * DOT3(normal[i],u);
  177.          fx = u[0] - normal[i][0] * two_nu;
  178.          fy = u[1] - normal[i][1] * two_nu;
  179.          fz = u[2] - normal[i][2] * two_nu;
  180.          m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0F)*(fz+1.0F) );
  181.          if (m==0.0F) {
  182.             texcoord[i][0] = 0.5F;
  183.             texcoord[i][1] = 0.5F;
  184.          }
  185.          else {
  186.             GLfloat mInv = 1.0F / m;
  187.             texcoord[i][0] = fx * mInv + 0.5F;
  188.             texcoord[i][1] = fy * mInv + 0.5F;
  189.          }
  190.       }
  191.       return;
  192.    }
  193.  
  194.    /* general solution */
  195.    if (ctx->Texture.TexGenEnabled & S_BIT) {
  196.       GLint i;
  197.       switch (ctx->Texture.GenModeS) {
  198.          case GL_OBJECT_LINEAR:
  199.             for (i=0;i<n;i++) {
  200.                texcoord[i][0] = DOT4( obj[i], ctx->Texture.ObjectPlaneS );
  201.             }
  202.             break;
  203.          case GL_EYE_LINEAR:
  204.             for (i=0;i<n;i++) {
  205.                texcoord[i][0] = DOT4( eye[i], ctx->Texture.EyePlaneS );
  206.             }
  207.             break;
  208.          case GL_SPHERE_MAP:
  209.             for (i=0;i<n;i++) {
  210.                GLfloat u[3], two_nu, m, fx, fy, fz;
  211.                COPY_3V( u, eye[i] );
  212.                NORMALIZE_3FV( u );
  213.                two_nu = 2.0*DOT3(normal[i],u);
  214.                fx = u[0] - normal[i][0] * two_nu;
  215.                fy = u[1] - normal[i][1] * two_nu;
  216.                fz = u[2] - normal[i][2] * two_nu;
  217.                m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  218.                if (m==0.0F) {
  219.                   texcoord[i][0] = 0.5F;
  220.                }
  221.                else {
  222.                   texcoord[i][0] = fx / m + 0.5F;
  223.                }
  224.             }
  225.             break;
  226.          default:
  227.             gl_problem(ctx, "Bad S texgen");
  228.             return;
  229.       }
  230.    }
  231.  
  232.    if (ctx->Texture.TexGenEnabled & T_BIT) {
  233.       GLint i;
  234.       switch (ctx->Texture.GenModeT) {
  235.          case GL_OBJECT_LINEAR:
  236.             for (i=0;i<n;i++) {
  237.                texcoord[i][1] = DOT4( obj[i], ctx->Texture.ObjectPlaneT );
  238.             }
  239.             break;
  240.          case GL_EYE_LINEAR:
  241.             for (i=0;i<n;i++) {
  242.                texcoord[i][1] = DOT4( eye[i], ctx->Texture.EyePlaneT );
  243.             }
  244.             break;
  245.          case GL_SPHERE_MAP:
  246.             for (i=0;i<n;i++) {
  247.                GLfloat u[3], two_nu, m, fx, fy, fz;
  248.                COPY_3V( u, eye[i] );
  249.                NORMALIZE_3FV( u );
  250.                two_nu = 2.0*DOT3(normal[i],u);
  251.                fx = u[0] - normal[i][0] * two_nu;
  252.                fy = u[1] - normal[i][1] * two_nu;
  253.                fz = u[2] - normal[i][2] * two_nu;
  254.                m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  255.                if (m==0.0F) {
  256.                   texcoord[i][1] = 0.5F;
  257.                }
  258.                else {
  259.                   texcoord[i][1] = fy / m + 0.5F;
  260.                }
  261.             }
  262.             break;
  263.          default:
  264.             gl_problem(ctx, "Bad T texgen");
  265.             return;
  266.       }
  267.    }
  268.  
  269.    if (ctx->Texture.TexGenEnabled & R_BIT) {
  270.       GLint i;
  271.       switch (ctx->Texture.GenModeR) {
  272.          case GL_OBJECT_LINEAR:
  273.             for (i=0;i<n;i++) {
  274.                texcoord[i][2] = DOT4( obj[i], ctx->Texture.ObjectPlaneR );
  275.             }
  276.             break;
  277.          case GL_EYE_LINEAR:
  278.             for (i=0;i<n;i++) {
  279.                texcoord[i][2] = DOT4( eye[i], ctx->Texture.EyePlaneR );
  280.             }
  281.             break;
  282.          default:
  283.             gl_problem(ctx, "Bad R texgen");
  284.             return;
  285.       }
  286.    }
  287.  
  288.    if (ctx->Texture.TexGenEnabled & Q_BIT) {
  289.       GLint i;
  290.       switch (ctx->Texture.GenModeQ) {
  291.          case GL_OBJECT_LINEAR:
  292.             for (i=0;i<n;i++) {
  293.                texcoord[i][3] = DOT4( obj[i], ctx->Texture.ObjectPlaneQ );
  294.             }
  295.             break;
  296.          case GL_EYE_LINEAR:
  297.             for (i=0;i<n;i++) {
  298.                texcoord[i][3] = DOT4( eye[i], ctx->Texture.EyePlaneQ );
  299.             }
  300.             break;
  301.          default:
  302.             gl_problem(ctx, "Bad Q texgen");
  303.             return;
  304.       }
  305.    }
  306. }
  307.  
  308.  
  309.  
  310. /*
  311.  * Paletted texture sampling.
  312.  * Input:  tObj - the texture object
  313.  *         index - the palette index (8-bit only)
  314.  * Output:  red, green, blue, alpha - the texel color
  315.  */
  316. static void palette_sample(const struct gl_texture_object *tObj,
  317.                            GLubyte index, GLubyte *red, GLubyte *green,
  318.                            GLubyte *blue, GLubyte *alpha)
  319. {
  320.    GLcontext *ctx = gl_get_current_context();  /* THIS IS A HACK */
  321.    GLint i = index;
  322.    const GLubyte *palette;
  323.  
  324.    if (ctx->Texture.SharedPalette) {
  325.       palette = ctx->Texture.Palette;
  326.    }
  327.    else {
  328.       palette = tObj->Palette;
  329.    }
  330.  
  331.    switch (tObj->PaletteFormat) {
  332.       case GL_ALPHA:
  333.          *alpha = tObj->Palette[index];
  334.          return;
  335.       case GL_LUMINANCE:
  336.       case GL_INTENSITY:
  337.          *red = palette[index];
  338.          return;
  339.       case GL_LUMINANCE_ALPHA:
  340.          *red   = palette[(index << 1) + 0];
  341.          *alpha = palette[(index << 1) + 1];
  342.          return;
  343.       case GL_RGB:
  344.          *red   = palette[index * 3 + 0];
  345.          *green = palette[index * 3 + 1];
  346.          *blue  = palette[index * 3 + 2];
  347.          return;
  348.       case GL_RGBA:
  349.          *red   = palette[(i << 2) + 0];
  350.          *green = palette[(i << 2) + 1];
  351.          *blue  = palette[(i << 2) + 2];
  352.          *alpha = palette[(i << 2) + 3];
  353.          return;
  354.       default:
  355.          gl_problem(NULL, "Bad palette format in palette_sample");
  356.    }
  357. }
  358.  
  359.  
  360.  
  361.  
  362. /**********************************************************************/
  363. /*                    1-D Texture Sampling Functions                  */
  364. /**********************************************************************/
  365.  
  366.  
  367. /*
  368.  * Return the fractional part of x.
  369.  */
  370. #define frac(x) ((GLfloat)(x)-floor((GLfloat)x))
  371.  
  372.  
  373.  
  374. /*
  375.  * Given 1-D texture image and an (i) texel column coordinate, return the
  376.  * texel color.
  377.  */
  378. static void get_1d_texel( const struct gl_texture_object *tObj,
  379.                           const struct gl_texture_image *img, GLint i,
  380.                           GLubyte *red, GLubyte *green, GLubyte *blue,
  381.                           GLubyte *alpha )
  382. {
  383.    GLubyte *texel;
  384.  
  385. #ifdef DEBUG
  386.    GLint width = img->Width;
  387.    if (i<0 || i>=width)  abort();
  388. #endif
  389.  
  390.    switch (img->Format) {
  391.       case GL_COLOR_INDEX:
  392.          {
  393.             GLubyte index = img->Data[i];
  394.             palette_sample(tObj, index, red, green, blue, alpha);
  395.             return;
  396.          }
  397.          return;
  398.       case GL_ALPHA:
  399.          *alpha = img->Data[ i ];
  400.          return;
  401.       case GL_LUMINANCE:
  402.       case GL_INTENSITY:
  403.          *red   = img->Data[ i ];
  404.          return;
  405.       case GL_LUMINANCE_ALPHA:
  406.          texel = img->Data + i * 2;
  407.          *red   = texel[0];
  408.          *alpha = texel[1];
  409.          return;
  410.       case GL_RGB:
  411.          texel = img->Data + i * 3;
  412.          *red   = texel[0];
  413.          *green = texel[1];
  414.          *blue  = texel[2];
  415.          return;
  416.       case GL_RGBA:
  417.          texel = img->Data + i * 4;
  418.          *red   = texel[0];
  419.          *green = texel[1];
  420.          *blue  = texel[2];
  421.          *alpha = texel[3];
  422.          return;
  423.       default:
  424.          gl_problem(NULL, "Bad format in get_1d_texel");
  425.          return;
  426.    }
  427. }
  428.  
  429.  
  430.  
  431. /*
  432.  * Return the texture sample for coordinate (s) using GL_NEAREST filter.
  433.  */
  434. static void sample_1d_nearest( const struct gl_texture_object *tObj,
  435.                                const struct gl_texture_image *img,
  436.                                GLfloat s,
  437.                                GLubyte *red, GLubyte *green,
  438.                                GLubyte *blue, GLubyte *alpha )
  439. {
  440.    GLint width = img->Width2;  /* without border, power of two */
  441.    GLint i;
  442.    GLubyte *texel;
  443.  
  444.    /* Clamp/Repeat S and convert to integer texel coordinate */
  445.    if (tObj->WrapS==GL_REPEAT) {
  446.       /* s limited to [0,1) */
  447.       /* i limited to [0,width-1] */
  448.       i = (GLint) (s * width);
  449.       if (s<0.0F)  i -= 1;
  450.       i &= (width-1);
  451.    }
  452.    else {
  453.       /* s limited to [0,1] */
  454.       /* i limited to [0,width-1] */
  455.       if (s<0.0F)        i = 0;
  456.       else if (s>1.0F)   i = width-1;
  457.       else               i = (GLint) (s * width);
  458.    }
  459.  
  460.    /* skip over the border, if any */
  461.    i += img->Border;
  462.  
  463.    /* Get the texel */
  464.    switch (img->Format) {
  465.       case GL_COLOR_INDEX:
  466.          {
  467.             GLubyte index = img->Data[i];
  468.             palette_sample(tObj, index, red, green, blue, alpha);
  469.             return;
  470.          }
  471.       case GL_ALPHA:
  472.          *alpha = img->Data[i];
  473.          return;
  474.       case GL_LUMINANCE:
  475.       case GL_INTENSITY:
  476.          *red   = img->Data[i];
  477.          return;
  478.       case GL_LUMINANCE_ALPHA:
  479.          texel = img->Data + i * 2;
  480.          *red   = texel[0];
  481.          *alpha = texel[1];
  482.          return;
  483.       case GL_RGB:
  484.          texel = img->Data + i * 3;
  485.          *red   = texel[0];
  486.          *green = texel[1];
  487.          *blue  = texel[2];
  488.          return;
  489.       case GL_RGBA:
  490.          texel = img->Data + i * 4;
  491.          *red   = texel[0];
  492.          *green = texel[1];
  493.          *blue  = texel[2];
  494.          *alpha = texel[3];
  495.          return;
  496.       default:
  497.          gl_problem(NULL, "Bad format in sample_1d_nearest");
  498.    }
  499. }
  500.  
  501.  
  502.  
  503. /*
  504.  * Return the texture sample for coordinate (s) using GL_LINEAR filter.
  505.  */
  506. static void sample_1d_linear( const struct gl_texture_object *tObj,
  507.                               const struct gl_texture_image *img,
  508.                               GLfloat s,
  509.                               GLubyte *red, GLubyte *green,
  510.                               GLubyte *blue, GLubyte *alpha )
  511. {
  512.    GLint width = img->Width2;
  513.    GLint i0, i1;
  514.    GLfloat u;
  515.    GLint i0border, i1border;
  516.  
  517.    u = s * width;
  518.    if (tObj->WrapS==GL_REPEAT) {
  519.       i0 = ((GLint) floor(u - 0.5F)) % width;
  520.       i1 = (i0 + 1) & (width-1);
  521.       i0border = i1border = 0;
  522.    }
  523.    else {
  524.       i0 = (GLint) floor(u - 0.5F);
  525.       i1 = i0 + 1;
  526.       i0border = (i0<0) | (i0>=width);
  527.       i1border = (i1<0) | (i1>=width);
  528.    }
  529.  
  530.    if (img->Border) {
  531.       i0 += img->Border;
  532.       i1 += img->Border;
  533.       i0border = i1border = 0;
  534.    }
  535.    else {
  536.       i0 &= (width-1);
  537.    }
  538.  
  539.    {
  540.       GLfloat a = frac(u - 0.5F);
  541.  
  542.       GLint w0 = (GLint) ((1.0F-a) * 256.0F);
  543.       GLint w1 = (GLint) (      a  * 256.0F);
  544.  
  545.       GLubyte red0, green0, blue0, alpha0;
  546.       GLubyte red1, green1, blue1, alpha1;
  547.  
  548.       if (i0border) {
  549.          red0   = tObj->BorderColor[0];
  550.          green0 = tObj->BorderColor[1];
  551.          blue0  = tObj->BorderColor[2];
  552.          alpha0 = tObj->BorderColor[3];
  553.       }
  554.       else {
  555.          get_1d_texel( tObj, img, i0, &red0, &green0, &blue0, &alpha0 );
  556.       }
  557.       if (i1border) {
  558.          red1   = tObj->BorderColor[0];
  559.          green1 = tObj->BorderColor[1];
  560.          blue1  = tObj->BorderColor[2];
  561.          alpha1 = tObj->BorderColor[3];
  562.       }
  563.       else {
  564.          get_1d_texel( tObj, img, i1, &red1, &green1, &blue1, &alpha1 );
  565.       }
  566.  
  567.       *red   = (w0*red0   + w1*red1)   >> 8;
  568.       *green = (w0*green0 + w1*green1) >> 8;
  569.       *blue  = (w0*blue0  + w1*blue1)  >> 8;
  570.       *alpha = (w0*alpha0 + w1*alpha1) >> 8;
  571.    }
  572. }
  573.  
  574.  
  575. static void
  576. sample_1d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
  577.                                   GLfloat s, GLfloat lambda,
  578.                                   GLubyte *red, GLubyte *green,
  579.                                   GLubyte *blue, GLubyte *alpha )
  580. {
  581.    GLint level;
  582.    if (lambda<=0.5F) {
  583.       level = 0;
  584.    }
  585.    else {
  586.       GLint widthlog2 = tObj->Image[0]->WidthLog2;
  587.       level = (GLint) (lambda + 0.499999F);
  588.       if (level>widthlog2 ) {
  589.          level = widthlog2;
  590.       }
  591.    }
  592.    sample_1d_nearest( tObj, tObj->Image[level],
  593.                       s, red, green, blue, alpha );
  594. }
  595.  
  596.  
  597. static void
  598. sample_1d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
  599.                                  GLfloat s, GLfloat lambda,
  600.                                  GLubyte *red, GLubyte *green,
  601.                                  GLubyte *blue, GLubyte *alpha )
  602. {
  603.    GLint level;
  604.    if (lambda<=0.5F) {
  605.       level = 0;
  606.    }
  607.    else {
  608.       GLint widthlog2 = tObj->Image[0]->WidthLog2;
  609.       level = (GLint) (lambda + 0.499999F);
  610.       if (level>widthlog2 ) {
  611.          level = widthlog2;
  612.       }
  613.    }
  614.    sample_1d_linear( tObj, tObj->Image[level],
  615.                      s, red, green, blue, alpha );
  616. }
  617.  
  618.  
  619.  
  620. static void
  621. sample_1d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
  622.                                  GLfloat s, GLfloat lambda,
  623.                                  GLubyte *red, GLubyte *green,
  624.                                  GLubyte *blue, GLubyte *alpha )
  625. {
  626.    GLint max = tObj->Image[0]->MaxLog2;
  627.  
  628.    if (lambda>=max) {
  629.       sample_1d_nearest( tObj, tObj->Image[max],
  630.                          s, red, green, blue, alpha );
  631.    }
  632.    else {
  633.       GLubyte red0, green0, blue0, alpha0;
  634.       GLubyte red1, green1, blue1, alpha1;
  635.       GLfloat f = frac(lambda);
  636.       GLint level = (GLint) (lambda + 1.0F);
  637.       level = CLAMP( level, 1, max );
  638.       sample_1d_nearest( tObj, tObj->Image[level-1],
  639.                          s, &red0, &green0, &blue0, &alpha0 );
  640.       sample_1d_nearest( tObj, tObj->Image[level],
  641.                          s, &red1, &green1, &blue1, &alpha1 );
  642.       *red   = (1.0F-f)*red0   + f*red1;
  643.       *green = (1.0F-f)*green0 + f*green1;
  644.       *blue  = (1.0F-f)*blue0  + f*blue1;
  645.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  646.    }
  647. }
  648.  
  649.  
  650.  
  651. static void
  652. sample_1d_linear_mipmap_linear( const struct gl_texture_object *tObj,
  653.                                 GLfloat s, GLfloat lambda,
  654.                                 GLubyte *red, GLubyte *green,
  655.                                 GLubyte *blue, GLubyte *alpha )
  656. {
  657.    GLint max = tObj->Image[0]->MaxLog2;
  658.  
  659.    if (lambda>=max) {
  660.       sample_1d_linear( tObj, tObj->Image[max],
  661.                         s, red, green, blue, alpha );
  662.    }
  663.    else {
  664.       GLubyte red0, green0, blue0, alpha0;
  665.       GLubyte red1, green1, blue1, alpha1;
  666.       GLfloat f = frac(lambda);
  667.       GLint level = (GLint) (lambda + 1.0F);
  668.       level = CLAMP( level, 1, max );
  669.       sample_1d_linear( tObj, tObj->Image[level-1],
  670.                         s, &red0, &green0, &blue0, &alpha0 );
  671.       sample_1d_linear( tObj, tObj->Image[level],
  672.                         s, &red1, &green1, &blue1, &alpha1 );
  673.       *red   = (1.0F-f)*red0   + f*red1;
  674.       *green = (1.0F-f)*green0 + f*green1;
  675.       *blue  = (1.0F-f)*blue0  + f*blue1;
  676.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  677.    }
  678. }
  679.  
  680.  
  681.  
  682. static void sample_nearest_1d( const struct gl_texture_object *tObj, GLuint n,
  683.                                const GLfloat s[], const GLfloat t[],
  684.                                const GLfloat u[], const GLfloat lambda[],
  685.                                GLubyte red[], GLubyte green[], GLubyte blue[],
  686.                                GLubyte alpha[] )
  687. {
  688.    GLuint i;
  689.    for (i=0;i<n;i++) {
  690.       sample_1d_nearest( tObj, tObj->Image[0], s[i],
  691.                          &red[i], &green[i], &blue[i], &alpha[i]);
  692.    }
  693. }
  694.  
  695.  
  696.  
  697. static void sample_linear_1d( const struct gl_texture_object *tObj, GLuint n,
  698.                               const GLfloat s[], const GLfloat t[],
  699.                               const GLfloat u[], const GLfloat lambda[],
  700.                               GLubyte red[], GLubyte green[], GLubyte blue[],
  701.                               GLubyte alpha[] )
  702. {
  703.    GLuint i;
  704.    for (i=0;i<n;i++) {
  705.       sample_1d_linear( tObj, tObj->Image[0], s[i],
  706.                         &red[i], &green[i], &blue[i], &alpha[i]);
  707.    }
  708. }
  709.  
  710.  
  711. /*
  712.  * Given an (s) texture coordinate and lambda (level of detail) value,
  713.  * return a texture sample.
  714.  *
  715.  */
  716. static void sample_lambda_1d( const struct gl_texture_object *tObj, GLuint n,
  717.                               const GLfloat s[], const GLfloat t[],
  718.                               const GLfloat u[], const GLfloat lambda[],
  719.                               GLubyte red[], GLubyte green[], GLubyte blue[],
  720.                               GLubyte alpha[] )
  721. {
  722.    GLuint i;
  723.  
  724.    for (i=0;i<n;i++) {
  725.       if (lambda[i] > tObj->MinMagThresh) {
  726.          /* minification */
  727.          switch (tObj->MinFilter) {
  728.             case GL_NEAREST:
  729.                sample_1d_nearest( tObj, tObj->Image[0], s[i],
  730.                                   &red[i], &green[i], &blue[i], &alpha[i] );
  731.                break;
  732.             case GL_LINEAR:
  733.                sample_1d_linear( tObj, tObj->Image[0], s[i],
  734.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  735.                break;
  736.             case GL_NEAREST_MIPMAP_NEAREST:
  737.                sample_1d_nearest_mipmap_nearest( tObj, lambda[i], s[i],
  738.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  739.                break;
  740.             case GL_LINEAR_MIPMAP_NEAREST:
  741.                sample_1d_linear_mipmap_nearest( tObj, s[i], lambda[i],
  742.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  743.                break;
  744.             case GL_NEAREST_MIPMAP_LINEAR:
  745.                sample_1d_nearest_mipmap_linear( tObj, s[i], lambda[i],
  746.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  747.                break;
  748.             case GL_LINEAR_MIPMAP_LINEAR:
  749.                sample_1d_linear_mipmap_linear( tObj, s[i], lambda[i],
  750.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  751.                break;
  752.             default:
  753.                gl_problem(NULL, "Bad min filter in sample_1d_texture");
  754.                return;
  755.          }
  756.       }
  757.       else {
  758.          /* magnification */
  759.          switch (tObj->MagFilter) {
  760.             case GL_NEAREST:
  761.                sample_1d_nearest( tObj, tObj->Image[0], s[i],
  762.                                   &red[i], &green[i], &blue[i], &alpha[i] );
  763.                break;
  764.             case GL_LINEAR:
  765.                sample_1d_linear( tObj, tObj->Image[0], s[i],
  766.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  767.                break;
  768.             default:
  769.                gl_problem(NULL, "Bad mag filter in sample_1d_texture");
  770.                return;
  771.          }
  772.       }
  773.    }
  774. }
  775.  
  776.  
  777.  
  778.  
  779. /**********************************************************************/
  780. /*                    2-D Texture Sampling Functions                  */
  781. /**********************************************************************/
  782.  
  783.  
  784. /*
  785.  * Given a texture image and an (i,j) integer texel coordinate, return the
  786.  * texel color.
  787.  */
  788. static void get_2d_texel( const struct gl_texture_object *tObj,
  789.                           const struct gl_texture_image *img, GLint i, GLint j,
  790.                           GLubyte *red, GLubyte *green, GLubyte *blue,
  791.                           GLubyte *alpha )
  792. {
  793.    GLint width = img->Width;    /* includes border */
  794.    GLubyte *texel;
  795.  
  796. #ifdef DEBUG
  797.    GLint height = img->Height;  /* includes border */
  798.    if (i<0 || i>=width)  abort();
  799.    if (j<0 || j>=height)  abort();
  800. #endif
  801.  
  802.    switch (img->Format) {
  803.       case GL_COLOR_INDEX:
  804.          {
  805.             GLubyte index = img->Data[ width *j + i ];
  806.             palette_sample(tObj, index, red, green, blue, alpha);
  807.             return;
  808.          }
  809.       case GL_ALPHA:
  810.          *alpha = img->Data[ width * j + i ];
  811.          return;
  812.       case GL_LUMINANCE:
  813.       case GL_INTENSITY:
  814.          *red   = img->Data[ width * j + i ];
  815.          return;
  816.       case GL_LUMINANCE_ALPHA:
  817.          texel = img->Data + (width * j + i) * 2;
  818.          *red   = texel[0];
  819.          *alpha = texel[1];
  820.          return;
  821.       case GL_RGB:
  822.          texel = img->Data + (width * j + i) * 3;
  823.          *red   = texel[0];
  824.          *green = texel[1];
  825.          *blue  = texel[2];
  826.          return;
  827.       case GL_RGBA:
  828.          texel = img->Data + (width * j + i) * 4;
  829.          *red   = texel[0];
  830.          *green = texel[1];
  831.          *blue  = texel[2];
  832.          *alpha = texel[3];
  833.          return;
  834.       default:
  835.          gl_problem(NULL, "Bad format in get_2d_texel");
  836.    }
  837. }
  838.  
  839.  
  840.  
  841. /*
  842.  * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
  843.  */
  844. static void sample_2d_nearest( const struct gl_texture_object *tObj,
  845.                                const struct gl_texture_image *img,
  846.                                GLfloat s, GLfloat t,
  847.                                GLubyte *red, GLubyte *green,
  848.                                GLubyte *blue, GLubyte *alpha )
  849. {
  850.    GLint imgWidth = img->Width;  /* includes border */
  851.    GLint width = img->Width2;    /* without border, power of two */
  852.    GLint height = img->Height2;  /* without border, power of two */
  853.    GLint i, j;
  854.    GLubyte *texel;
  855.  
  856.    /* Clamp/Repeat S and convert to integer texel coordinate */
  857.    if (tObj->WrapS==GL_REPEAT) {
  858.       /* s limited to [0,1) */
  859.       /* i limited to [0,width-1] */
  860.       i = (GLint) (s * width);
  861.       if (s<0.0F)  i -= 1;
  862.       i &= (width-1);
  863.    }
  864.    else {
  865.       /* s limited to [0,1] */
  866.       /* i limited to [0,width-1] */
  867.       if (s<=0.0F)      i = 0;
  868.       else if (s>1.0F)  i = width-1;
  869.       else              i = (GLint) (s * width);
  870.    }
  871.  
  872.    /* Clamp/Repeat T and convert to integer texel coordinate */
  873.    if (tObj->WrapT==GL_REPEAT) {
  874.       /* t limited to [0,1) */
  875.       /* j limited to [0,height-1] */
  876.       j = (GLint) (t * height);
  877.       if (t<0.0F)  j -= 1;
  878.       j &= (height-1);
  879.    }
  880.    else {
  881.       /* t limited to [0,1] */
  882.       /* j limited to [0,height-1] */
  883.       if (t<=0.0F)      j = 0;
  884.       else if (t>1.0F)  j = height-1;
  885.       else              j = (GLint) (t * height);
  886.    }
  887.  
  888.    /* skip over the border, if any */
  889.    i += img->Border;
  890.    j += img->Border;
  891.  
  892.    switch (img->Format) {
  893.       case GL_COLOR_INDEX:
  894.          {
  895.             GLubyte index = img->Data[ j * imgWidth + i ];
  896.             palette_sample(tObj, index, red, green, blue, alpha);
  897.             return;
  898.          }
  899.       case GL_ALPHA:
  900.          *alpha = img->Data[ j * imgWidth + i ];
  901.          return;
  902.       case GL_LUMINANCE:
  903.       case GL_INTENSITY:
  904.          *red   = img->Data[ j * imgWidth + i ];
  905.          return;
  906.       case GL_LUMINANCE_ALPHA:
  907.          texel = img->Data + ((j * imgWidth + i) << 1);
  908.          *red   = texel[0];
  909.          *alpha = texel[1];
  910.          return;
  911.       case GL_RGB:
  912.          texel = img->Data + (j * imgWidth + i) * 3;
  913.          *red   = texel[0];
  914.          *green = texel[1];
  915.          *blue  = texel[2];
  916.          return;
  917.       case GL_RGBA:
  918.          texel = img->Data + ((j * imgWidth + i) << 2);
  919.          *red   = texel[0];
  920.          *green = texel[1];
  921.          *blue  = texel[2];
  922.          *alpha = texel[3];
  923.          return;
  924.       default:
  925.          gl_problem(NULL, "Bad format in sample_2d_nearest");
  926.    }
  927. }
  928.  
  929.  
  930.  
  931. /*
  932.  * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
  933.  */
  934. static void sample_2d_linear( const struct gl_texture_object *tObj,
  935.                               const struct gl_texture_image *img,
  936.                               GLfloat s, GLfloat t,
  937.                               GLubyte *red, GLubyte *green,
  938.                               GLubyte *blue, GLubyte *alpha )
  939. {
  940.    GLint width = img->Width2;
  941.    GLint height = img->Height2;
  942.    GLint i0, j0, i1, j1;
  943.    GLint i0border, j0border, i1border, j1border;
  944.    GLfloat u, v;
  945.  
  946.    u = s * width;
  947.    if (tObj->WrapS==GL_REPEAT) {
  948.       i0 = ((GLint) floor(u - 0.5F)) % width;
  949.       i1 = (i0 + 1) & (width-1);
  950.       i0border = i1border = 0;
  951.    }
  952.    else {
  953.       i0 = (GLint) floor(u - 0.5F);
  954.       i1 = i0 + 1;
  955.       i0border = (i0<0) | (i0>=width);
  956.       i1border = (i1<0) | (i1>=width);
  957.    }
  958.  
  959.    v = t * height;
  960.    if (tObj->WrapT==GL_REPEAT) {
  961.       j0 = ((GLint) floor(v - 0.5F)) % height;
  962.       j1 = (j0 + 1) & (height-1);
  963.       j0border = j1border = 0;
  964.    }
  965.    else {
  966.       j0 = (GLint) floor(v - 0.5F );
  967.       j1 = j0 + 1;
  968.       j0border = (j0<0) | (j0>=height);
  969.       j1border = (j1<0) | (j1>=height);
  970.    }
  971.  
  972.    if (img->Border) {
  973.       i0 += img->Border;
  974.       i1 += img->Border;
  975.       j0 += img->Border;
  976.       j1 += img->Border;
  977.       i0border = i1border = 0;
  978.       j0border = j1border = 0;
  979.    }
  980.    else {
  981.       i0 &= (width-1);
  982.       j0 &= (height-1);
  983.    }
  984.  
  985.    {
  986.       GLfloat a = frac(u - 0.5F);
  987.       GLfloat b = frac(v - 0.5F);
  988.  
  989.       GLint w00 = (GLint) ((1.0F-a)*(1.0F-b) * 256.0F);
  990.       GLint w10 = (GLint) (      a *(1.0F-b) * 256.0F);
  991.       GLint w01 = (GLint) ((1.0F-a)*      b  * 256.0F);
  992.       GLint w11 = (GLint) (      a *      b  * 256.0F);
  993.  
  994.       GLubyte red00, green00, blue00, alpha00;
  995.       GLubyte red10, green10, blue10, alpha10;
  996.       GLubyte red01, green01, blue01, alpha01;
  997.       GLubyte red11, green11, blue11, alpha11;
  998.  
  999.       if (i0border | j0border) {
  1000.          red00   = tObj->BorderColor[0];
  1001.          green00 = tObj->BorderColor[1];
  1002.          blue00  = tObj->BorderColor[2];
  1003.          alpha00 = tObj->BorderColor[3];
  1004.       }
  1005.       else {
  1006.          get_2d_texel( tObj, img, i0, j0, &red00, &green00, &blue00, &alpha00);
  1007.       }
  1008.       if (i1border | j0border) {
  1009.          red10   = tObj->BorderColor[0];
  1010.          green10 = tObj->BorderColor[1];
  1011.          blue10  = tObj->BorderColor[2];
  1012.          alpha10 = tObj->BorderColor[3];
  1013.       }
  1014.       else {
  1015.          get_2d_texel( tObj, img, i1, j0, &red10, &green10, &blue10, &alpha10);
  1016.       }
  1017.       if (i0border | j1border) {
  1018.          red01   = tObj->BorderColor[0];
  1019.          green01 = tObj->BorderColor[1];
  1020.          blue01  = tObj->BorderColor[2];
  1021.          alpha01 = tObj->BorderColor[3];
  1022.       }
  1023.       else {
  1024.          get_2d_texel( tObj, img, i0, j1, &red01, &green01, &blue01, &alpha01);
  1025.       }
  1026.       if (i1border | j1border) {
  1027.          red11   = tObj->BorderColor[0];
  1028.          green11 = tObj->BorderColor[1];
  1029.          blue11  = tObj->BorderColor[2];
  1030.          alpha11 = tObj->BorderColor[3];
  1031.       }
  1032.       else {
  1033.          get_2d_texel( tObj, img, i1, j1, &red11, &green11, &blue11, &alpha11);
  1034.       }
  1035.  
  1036.       *red   = (w00*red00   + w10*red10   + w01*red01   + w11*red11  ) >> 8;
  1037.       *green = (w00*green00 + w10*green10 + w01*green01 + w11*green11) >> 8;
  1038.       *blue  = (w00*blue00  + w10*blue10  + w01*blue01  + w11*blue11 ) >> 8;
  1039.       *alpha = (w00*alpha00 + w10*alpha10 + w01*alpha01 + w11*alpha11) >> 8;
  1040.    }
  1041. }
  1042.  
  1043.  
  1044.  
  1045. static void
  1046. sample_2d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
  1047.                                   GLfloat s, GLfloat t, GLfloat lambda,
  1048.                                   GLubyte *red, GLubyte *green,
  1049.                                   GLubyte *blue, GLubyte *alpha )
  1050. {
  1051.    GLint level;
  1052.    if (lambda<=0.5F) {
  1053.       level = 0;
  1054.    }
  1055.    else {
  1056.       GLint max = tObj->Image[0]->MaxLog2;
  1057.       level = (GLint) (lambda + 0.499999F);
  1058.       if (level>max) {
  1059.          level = max;
  1060.       }
  1061.    }
  1062.    sample_2d_nearest( tObj, tObj->Image[level],
  1063.                       s, t, red, green, blue, alpha );
  1064. }
  1065.  
  1066.  
  1067.  
  1068. static void
  1069. sample_2d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
  1070.                                  GLfloat s, GLfloat t, GLfloat lambda,
  1071.                                  GLubyte *red, GLubyte *green,
  1072.                                  GLubyte *blue, GLubyte *alpha )
  1073. {
  1074.    GLint level;
  1075.    if (lambda<=0.5F) {
  1076.       level = 0;
  1077.    }
  1078.    else {
  1079.       GLint max = tObj->Image[0]->MaxLog2;
  1080.       level = (GLint) (lambda + 0.499999F);
  1081.       if (level>max) {
  1082.          level = max;
  1083.       }
  1084.    }
  1085.    sample_2d_linear( tObj, tObj->Image[level],
  1086.                      s, t, red, green, blue, alpha );
  1087. }
  1088.  
  1089.  
  1090.  
  1091. static void
  1092. sample_2d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
  1093.                                  GLfloat s, GLfloat t, GLfloat lambda,
  1094.                                  GLubyte *red, GLubyte *green,
  1095.                                  GLubyte *blue, GLubyte *alpha )
  1096. {
  1097.    GLint max = tObj->Image[0]->MaxLog2;
  1098.  
  1099.    if (lambda>=max) {
  1100.       sample_2d_nearest( tObj, tObj->Image[max],
  1101.                          s, t, red, green, blue, alpha );
  1102.    }
  1103.    else {
  1104.       GLubyte red0, green0, blue0, alpha0;
  1105.       GLubyte red1, green1, blue1, alpha1;
  1106.       GLfloat f = frac(lambda);
  1107.       GLint level = (GLint) (lambda + 1.0F);
  1108.       level = CLAMP( level, 1, max );
  1109.       sample_2d_nearest( tObj, tObj->Image[level-1], s, t,
  1110.                          &red0, &green0, &blue0, &alpha0 );
  1111.       sample_2d_nearest( tObj, tObj->Image[level], s, t,
  1112.                          &red1, &green1, &blue1, &alpha1 );
  1113.       *red   = (1.0F-f)*red0   + f*red1;
  1114.       *green = (1.0F-f)*green0 + f*green1;
  1115.       *blue  = (1.0F-f)*blue0  + f*blue1;
  1116.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  1117.    }
  1118. }
  1119.  
  1120.  
  1121.  
  1122. static void
  1123. sample_2d_linear_mipmap_linear( const struct gl_texture_object *tObj,
  1124.                                 GLfloat s, GLfloat t, GLfloat lambda,
  1125.                                 GLubyte *red, GLubyte *green,
  1126.                                 GLubyte *blue, GLubyte *alpha )
  1127. {
  1128.    GLint max = tObj->Image[0]->MaxLog2;
  1129.  
  1130.    if (lambda>=max) {
  1131.       sample_2d_linear( tObj, tObj->Image[max],
  1132.                         s, t, red, green, blue, alpha );
  1133.    }
  1134.    else {
  1135.       GLubyte red0, green0, blue0, alpha0;
  1136.       GLubyte red1, green1, blue1, alpha1;
  1137.       GLfloat f = frac(lambda);
  1138.       GLint level = (GLint) (lambda + 1.0F);
  1139.       level = CLAMP( level, 1, max );
  1140.       sample_2d_linear( tObj, tObj->Image[level-1], s, t,
  1141.                         &red0, &green0, &blue0, &alpha0 );
  1142.       sample_2d_linear( tObj, tObj->Image[level], s, t,
  1143.                         &red1, &green1, &blue1, &alpha1 );
  1144.       *red   = (1.0F-f)*red0   + f*red1;
  1145.       *green = (1.0F-f)*green0 + f*green1;
  1146.       *blue  = (1.0F-f)*blue0  + f*blue1;
  1147.       *alpha = (1.0F-f)*alpha0 + f*alpha1;
  1148.    }
  1149. }
  1150.  
  1151.  
  1152.  
  1153. static void sample_nearest_2d( const struct gl_texture_object *tObj, GLuint n,
  1154.                                const GLfloat s[], const GLfloat t[],
  1155.                                const GLfloat u[], const GLfloat lambda[],
  1156.                                GLubyte red[], GLubyte green[], GLubyte blue[],
  1157.                                GLubyte alpha[] )
  1158. {
  1159.    GLuint i;
  1160.    for (i=0;i<n;i++) {
  1161.       sample_2d_nearest( tObj, tObj->Image[0], s[i], t[i],
  1162.                          &red[i], &green[i], &blue[i], &alpha[i]);
  1163.    }
  1164. }
  1165.  
  1166.  
  1167.  
  1168. static void sample_linear_2d( const struct gl_texture_object *tObj, GLuint n,
  1169.                               const GLfloat s[], const GLfloat t[],
  1170.                               const GLfloat u[], const GLfloat lambda[],
  1171.                               GLubyte red[], GLubyte green[], GLubyte blue[],
  1172.                               GLubyte alpha[] )
  1173. {
  1174.    GLuint i;
  1175.    for (i=0;i<n;i++) {
  1176.       sample_2d_linear( tObj, tObj->Image[0], s[i], t[i],
  1177.                         &red[i], &green[i], &blue[i], &alpha[i]);
  1178.    }
  1179. }
  1180.  
  1181.  
  1182. /*
  1183.  * Given an (s,t) texture coordinate and lambda (level of detail) value,
  1184.  * return a texture sample.
  1185.  */
  1186. static void sample_lambda_2d( const struct gl_texture_object *tObj,
  1187.                               GLuint n,
  1188.                               const GLfloat s[], const GLfloat t[],
  1189.                               const GLfloat u[], const GLfloat lambda[],
  1190.                               GLubyte red[], GLubyte green[], GLubyte blue[],
  1191.                               GLubyte alpha[] )
  1192. {
  1193.    GLuint i;
  1194.    for (i=0;i<n;i++) {
  1195.       if (lambda[i] > tObj->MinMagThresh) {
  1196.          /* minification */
  1197.          switch (tObj->MinFilter) {
  1198.             case GL_NEAREST:
  1199.                sample_2d_nearest( tObj, tObj->Image[0], s[i], t[i],
  1200.                                   &red[i], &green[i], &blue[i], &alpha[i] );
  1201.                break;
  1202.             case GL_LINEAR:
  1203.                sample_2d_linear( tObj, tObj->Image[0], s[i], t[i],
  1204.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1205.                break;
  1206.             case GL_NEAREST_MIPMAP_NEAREST:
  1207.                sample_2d_nearest_mipmap_nearest( tObj, s[i], t[i], lambda[i],
  1208.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1209.                break;
  1210.             case GL_LINEAR_MIPMAP_NEAREST:
  1211.                sample_2d_linear_mipmap_nearest( tObj, s[i], t[i], lambda[i],
  1212.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1213.                break;
  1214.             case GL_NEAREST_MIPMAP_LINEAR:
  1215.                sample_2d_nearest_mipmap_linear( tObj, s[i], t[i], lambda[i],
  1216.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1217.                break;
  1218.             case GL_LINEAR_MIPMAP_LINEAR:
  1219.                sample_2d_linear_mipmap_linear( tObj, s[i], t[i], lambda[i],
  1220.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1221.                break;
  1222.             default:
  1223.                gl_problem(NULL, "Bad min filter in sample_2d_texture");
  1224.                return;
  1225.          }
  1226.       }
  1227.       else {
  1228.          /* magnification */
  1229.          switch (tObj->MagFilter) {
  1230.             case GL_NEAREST:
  1231.                sample_2d_nearest( tObj, tObj->Image[0], s[i], t[i],
  1232.                                   &red[i], &green[i], &blue[i], &alpha[i] );
  1233.                break;
  1234.             case GL_LINEAR:
  1235.                sample_2d_linear( tObj, tObj->Image[0], s[i], t[i],
  1236.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1237.                break;
  1238.             default:
  1239.                gl_problem(NULL, "Bad mag filter in sample_2d_texture");
  1240.          }
  1241.       }
  1242.    }
  1243. }
  1244.  
  1245.  
  1246. /*
  1247.  * Optimized 2-D texture sampling:
  1248.  *    S and T wrap mode == GL_REPEAT
  1249.  *    No border
  1250.  *    Format = GL_RGB
  1251.  */
  1252. static void opt_sample_rgb_2d( const struct gl_texture_object *tObj,
  1253.                                GLuint n, const GLfloat s[], const GLfloat t[],
  1254.                                const GLfloat u[], const GLfloat lamda[],
  1255.                                GLubyte red[], GLubyte green[],
  1256.                                GLubyte blue[], GLubyte alpha[] )
  1257. {
  1258.    const struct gl_texture_image *img = tObj->Image[0];
  1259.    GLfloat width = img->Width, height = img->Height;
  1260.    GLint colMask = img->Width-1, rowMask = img->Height-1;
  1261.    GLint shift = img->WidthLog2;
  1262.    GLuint k;
  1263.  
  1264.    ASSERT(tObj->WrapS==GL_REPEAT);
  1265.    ASSERT(tObj->WrapT==GL_REPEAT);
  1266.    ASSERT(img->Border==0);
  1267.    ASSERT(img->Format==GL_RGB);
  1268.  
  1269.    for (k=0;k<n;k++) {
  1270.       GLint i = (GLint) (s[k] * width) & colMask;
  1271.       GLint j = (GLint) (t[k] * height) & rowMask;
  1272.       GLint pos = (j << shift) | i;
  1273.       GLubyte *texel = img->Data + pos + pos + pos;  /* pos*3 */
  1274.       red[k]   = texel[0];
  1275.       green[k] = texel[1];
  1276.       blue[k]  = texel[2];
  1277.    }
  1278. }
  1279.  
  1280.  
  1281. /*
  1282.  * Optimized 2-D texture sampling:
  1283.  *    S and T wrap mode == GL_REPEAT
  1284.  *    No border
  1285.  *    Format = GL_RGBA
  1286.  */
  1287. static void opt_sample_rgba_2d( const struct gl_texture_object *tObj,
  1288.                                 GLuint n, const GLfloat s[], const GLfloat t[],
  1289.                                 const GLfloat u[], const GLfloat lamda[],
  1290.                                 GLubyte red[], GLubyte green[],
  1291.                                 GLubyte blue[], GLubyte alpha[] )
  1292. {
  1293.    const struct gl_texture_image *img = tObj->Image[0];
  1294.    GLfloat width = img->Width, height = img->Height;
  1295.    GLint colMask = img->Width-1, rowMask = img->Height-1;
  1296.    GLint shift = img->WidthLog2;
  1297.    GLuint k;
  1298.  
  1299.    ASSERT(tObj->WrapS==GL_REPEAT);
  1300.    ASSERT(tObj->WrapT==GL_REPEAT);
  1301.    ASSERT(img->Border==0);
  1302.    ASSERT(img->Format==GL_RGBA);
  1303.  
  1304.    for (k=0;k<n;k++) {
  1305.       GLint i = (GLint) (s[k] * width) & colMask;
  1306.       GLint j = (GLint) (t[k] * height) & rowMask;
  1307.       GLint pos = (j << shift) | i;
  1308.       GLubyte *texel = img->Data + (pos << 2);    /* pos*4 */
  1309.       red[k]   = texel[0];
  1310.       green[k] = texel[1];
  1311.       blue[k]  = texel[2];
  1312.       alpha[k] = texel[3];
  1313.    }
  1314. }
  1315.  
  1316.  
  1317.  
  1318. /**********************************************************************/
  1319. /*                    3-D Texture Sampling Functions                  */
  1320. /**********************************************************************/
  1321.  
  1322. /*
  1323.  * Given a texture image and an (i,j,k) integer texel coordinate, return the
  1324.  * texel color.
  1325.  */
  1326. static void get_3d_texel( const struct gl_texture_object *tObj,
  1327.                           const struct gl_texture_image *img,
  1328.                           GLint i, GLint j, GLint k,
  1329.                           GLubyte *red, GLubyte *green, GLubyte *blue,
  1330.                           GLubyte *alpha )
  1331. {
  1332.    GLint width = img->Width;    /* includes border */
  1333.    GLint height = img->Height;  /* includes border */
  1334.    GLint depth = img->Depth;    /* includes border */
  1335.    GLint rectarea;              /* = width * heigth */
  1336.    GLubyte *texel;
  1337.  
  1338.    rectarea = width*height;
  1339.  
  1340. #ifdef DEBUG
  1341.    if (i<0 || i>=width)  abort();
  1342.    if (j<0 || j>=height)  abort();
  1343.    if (k<0 || k>=depth)  abort();
  1344. #endif
  1345.  
  1346.    switch (img->Format) {
  1347.       case GL_COLOR_INDEX:
  1348.          {
  1349.             GLubyte index = img->Data[ rectarea * k +  width * j + i ];
  1350.             palette_sample(tObj, index, red, green, blue, alpha);
  1351.             return;
  1352.          }
  1353.       case GL_ALPHA:
  1354.          *alpha = img->Data[ rectarea * k +  width * j + i ];
  1355.          return;
  1356.       case GL_LUMINANCE:
  1357.       case GL_INTENSITY:
  1358.          *red   = img->Data[ rectarea * k +  width * j + i ];
  1359.          return;
  1360.       case GL_LUMINANCE_ALPHA:
  1361.          texel = img->Data + ( rectarea * k + width * j + i) * 2;
  1362.          *red   = texel[0];
  1363.          *alpha = texel[1];
  1364.          return;
  1365.       case GL_RGB:
  1366.          texel = img->Data + (rectarea * k + width * j + i) * 3;
  1367.          *red   = texel[0];
  1368.          *green = texel[1];
  1369.          *blue  = texel[2];
  1370.          return;
  1371.       case GL_RGBA:
  1372.          texel = img->Data + (rectarea * k + width * j + i) * 4;
  1373.          *red   = texel[0];
  1374.          *green = texel[1];
  1375.          *blue  = texel[2];
  1376.          *alpha = texel[3];
  1377.          return;
  1378.       default:
  1379.          gl_problem(NULL, "Bad format in get_3d_texel");
  1380.    }
  1381. }
  1382.  
  1383.  
  1384. /*
  1385.  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  1386.  */
  1387. static void sample_3d_nearest( const struct gl_texture_object *tObj,
  1388.                                const struct gl_texture_image *img,
  1389.                                GLfloat s, GLfloat t, GLfloat r,
  1390.                                GLubyte *red, GLubyte *green,
  1391.                                GLubyte *blue, GLubyte *alpha )
  1392. {
  1393.    GLint imgWidth = img->Width;   /* includes border, if any */
  1394.    GLint imgHeight = img->Height; /* includes border, if any */
  1395.    GLint width = img->Width2;     /* without border, power of two */
  1396.    GLint height = img->Height2;   /* without border, power of two */
  1397.    GLint depth = img->Depth2;     /* without border, power of two */
  1398.    GLint rectarea;                /* = width * height */
  1399.    GLint i, j, k;
  1400.    GLubyte *texel;
  1401.  
  1402.    rectarea = imgWidth * imgHeight;
  1403.  
  1404.    /* Clamp/Repeat S and convert to integer texel coordinate */
  1405.    if (tObj->WrapS==GL_REPEAT) {
  1406.       /* s limited to [0,1) */
  1407.       /* i limited to [0,width-1] */
  1408.       i = (GLint) (s * width);
  1409.       if (s<0.0F)  i -= 1;
  1410.       i &= (width-1);
  1411.    }
  1412.    else {
  1413.       /* s limited to [0,1] */
  1414.       /* i limited to [0,width-1] */
  1415.       if (s<0.0F)       i = 0;
  1416.       else if (s>1.0F)  i = width-1;
  1417.       else              i = (GLint) (s * width);
  1418.    }
  1419.  
  1420.    /* Clamp/Repeat T and convert to integer texel coordinate */
  1421.    if (tObj->WrapT==GL_REPEAT) {
  1422.       /* t limited to [0,1) */
  1423.       /* j limited to [0,height-1] */
  1424.       j = (GLint) (t * height);
  1425.       if (t<0.0F)  j -= 1;
  1426.       j &= (height-1);
  1427.    }
  1428.    else {
  1429.       /* t limited to [0,1] */
  1430.       /* j limited to [0,height-1] */
  1431.       if (t<0.0F)       j = 0;
  1432.       else if (t>1.0F)  j = height-1;
  1433.       else              j = (GLint) (t * height);
  1434.    }
  1435.  
  1436.    /* Clamp/Repeat R and convert to integer texel coordinate */
  1437.    if (tObj->WrapR==GL_REPEAT) {
  1438.       /* r limited to [0,1) */
  1439.       /* k limited to [0,depth-1] */
  1440.       k = (GLint) (r * depth);
  1441.       if (r<0.0F)  k -= 1;
  1442.       k &= (depth-1);
  1443.    }
  1444.    else {
  1445.       /* r limited to [0,1] */
  1446.       /* k limited to [0,depth-1] */
  1447.       if (r<0.0F)       k = 0;
  1448.       else if (r>1.0F)  k = depth-1;
  1449.       else              k = (GLint) (r * depth);
  1450.    }
  1451.  
  1452.    switch (tObj->Image[0]->Format) {
  1453.       case GL_COLOR_INDEX:
  1454.          {
  1455.             GLubyte index = img->Data[ rectarea * k + j * imgWidth + i ];
  1456.             palette_sample(tObj, index, red, green, blue, alpha);
  1457.             return;
  1458.          }
  1459.       case GL_ALPHA:
  1460.          *alpha = img->Data[ rectarea * k + j * imgWidth + i ];
  1461.          return;
  1462.       case GL_LUMINANCE:
  1463.       case GL_INTENSITY:
  1464.          *red   = img->Data[ rectarea * k + j * imgWidth + i ];
  1465.          return;
  1466.       case GL_LUMINANCE_ALPHA:
  1467.          texel  = img->Data + ((rectarea * k + j * imgWidth + i) << 1);
  1468.          *red   = texel[0];
  1469.          *alpha = texel[1];
  1470.          return;
  1471.       case GL_RGB:
  1472.          texel = img->Data + ( rectarea * k + j * imgWidth + i) * 3;
  1473.          *red   = texel[0];
  1474.          *green = texel[1];
  1475.          *blue  = texel[2];
  1476.          return;
  1477.       case GL_RGBA:
  1478.          texel = img->Data + ((rectarea * k + j * imgWidth + i) << 2);
  1479.          *red   = texel[0];
  1480.          *green = texel[1];
  1481.          *blue  = texel[2];
  1482.          *alpha = texel[3];
  1483.          return;
  1484.       default:
  1485.          gl_problem(NULL, "Bad format in sample_3d_nearest");
  1486.    }
  1487. }
  1488.  
  1489.  
  1490. /*
  1491.  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  1492.  */
  1493. static void sample_3d_linear( const struct gl_texture_object *tObj,
  1494.                               const struct gl_texture_image *img,
  1495.                               GLfloat s, GLfloat t, GLfloat r,
  1496.                               GLubyte *red, GLubyte *green,
  1497.                               GLubyte *blue, GLubyte *alpha )
  1498. {
  1499.    GLint width = img->Width2;
  1500.    GLint height = img->Height2;
  1501.    GLint depth = img->Depth2;
  1502.    GLint i0, j0, k0, i1, j1, k1;
  1503.    GLint i0border, j0border, k0border, i1border, j1border, k1border;
  1504.    GLfloat u, v, w;
  1505.  
  1506.    u = s * width;
  1507.    if (tObj->WrapS==GL_REPEAT) {
  1508.       i0 = ((GLint) floor(u - 0.5F)) % width;
  1509.       i1 = (i0 + 1) & (width-1);
  1510.       i0border = i1border = 0;
  1511.    }
  1512.    else {
  1513.       i0 = (GLint) floor(u - 0.5F);
  1514.       i1 = i0 + 1;
  1515.       i0border = (i0<0) | (i0>=width);
  1516.       i1border = (i1<0) | (i1>=width);
  1517.    }
  1518.  
  1519.    v = t * height;
  1520.    if (tObj->WrapT==GL_REPEAT) {
  1521.       j0 = ((GLint) floor(v - 0.5F)) % height;
  1522.       j1 = (j0 + 1) & (height-1);
  1523.       j0border = j1border = 0;
  1524.    }
  1525.    else {
  1526.       j0 = (GLint) floor(v - 0.5F);
  1527.       j1 = j0 + 1;
  1528.       j0border = (j0<0) | (j0>=height);
  1529.       j1border = (j1<0) | (j1>=height);
  1530.    }
  1531.  
  1532.    w = r * depth;
  1533.    if (tObj->WrapR==GL_REPEAT) {
  1534.       k0 = ((GLint) floor(w - 0.5F)) % depth;
  1535.       k1 = (k0 + 1) & (depth-1);
  1536.       k0border = k1border = 0;
  1537.    }
  1538.    else {
  1539.       k0 = (GLint) floor(v - 0.5F);
  1540.       k1 = k0 + 1;
  1541.       k0border = (k0<0) | (k0>=depth);
  1542.       k1border = (k1<0) | (k1>=depth);
  1543.    }
  1544.  
  1545.    if (img->Border) {
  1546.       i0 += img->Border;
  1547.       i1 += img->Border;
  1548.       j0 += img->Border;
  1549.       j1 += img->Border;
  1550.       k0 += img->Border;
  1551.       k1 += img->Border;
  1552.       i0border = i1border = 0;
  1553.       j0border = j1border = 0;
  1554.       k0border = k1border = 0;
  1555.    }
  1556.    else {
  1557.       i0 &= (width-1);
  1558.       j0 &= (height-1);
  1559.       k0 &= (depth-1);
  1560.    }
  1561.  
  1562.    {
  1563.       GLfloat a = frac(u - 0.5F);
  1564.       GLfloat b = frac(v - 0.5F);
  1565.       GLfloat c = frac(w - 0.5F);
  1566.  
  1567.       GLint w000 = (GLint) ((1.0F-a)*(1.0F-b) * (1.0F-c) * 256.0F);
  1568.       GLint w010 = (GLint) (      a *(1.0F-b) * (1.0F-c) * 256.0F);
  1569.       GLint w001 = (GLint) ((1.0F-a)*      b  * (1.0F-c) * 256.0F);
  1570.       GLint w011 = (GLint) (      a *      b  * (1.0F-c) * 256.0F);
  1571.       GLint w100 = (GLint) ((1.0F-a)*(1.0F-b) * c * 256.0F);
  1572.       GLint w110 = (GLint) (      a *(1.0F-b) * c * 256.0F);
  1573.       GLint w101 = (GLint) ((1.0F-a)*      b  * c * 256.0F);
  1574.       GLint w111 = (GLint) (      a *      b  * c * 256.0F);
  1575.  
  1576.  
  1577.       GLubyte red000, green000, blue000, alpha000;
  1578.       GLubyte red010, green010, blue010, alpha010;
  1579.       GLubyte red001, green001, blue001, alpha001;
  1580.       GLubyte red011, green011, blue011, alpha011;
  1581.       GLubyte red100, green100, blue100, alpha100;
  1582.       GLubyte red110, green110, blue110, alpha110;
  1583.       GLubyte red101, green101, blue101, alpha101;
  1584.       GLubyte red111, green111, blue111, alpha111;
  1585.  
  1586.       if (k0border | i0border | j0border ) {
  1587.          red000   = tObj->BorderColor[0];
  1588.          green000 = tObj->BorderColor[1];
  1589.          blue000  = tObj->BorderColor[2];
  1590.          alpha000 = tObj->BorderColor[3];
  1591.       }
  1592.       else {
  1593.          get_3d_texel( tObj, img, i0, j0, k0, &red000, &green000, &blue000, &alpha000 );
  1594.       }
  1595.       if (k0border | i1border | j0border) {
  1596.          red010   = tObj->BorderColor[0];
  1597.          green010 = tObj->BorderColor[1];
  1598.          blue010  = tObj->BorderColor[2];
  1599.          alpha010 = tObj->BorderColor[3];
  1600.       }
  1601.       else {
  1602.          get_3d_texel( tObj, img, i1, j0, k0, &red010, &green010, &blue010, &alpha010 );
  1603.       }
  1604.       if (k0border | i0border | j1border) {
  1605.          red001   = tObj->BorderColor[0];
  1606.          green001 = tObj->BorderColor[1];
  1607.          blue001  = tObj->BorderColor[2];
  1608.          alpha001 = tObj->BorderColor[3];
  1609.       }
  1610.       else {
  1611.          get_3d_texel( tObj, img, i0, j1, k0, &red001, &green001, &blue001, &alpha001 );
  1612.       }
  1613.       if (k0border | i1border | j1border) {
  1614.          red011   = tObj->BorderColor[0];
  1615.          green011 = tObj->BorderColor[1];
  1616.          blue011  = tObj->BorderColor[2];
  1617.          alpha011 = tObj->BorderColor[3];
  1618.       }
  1619.       else {
  1620.          get_3d_texel( tObj, img, i1, j1, k0, &red011, &green011, &blue011, &alpha011 );
  1621.       }
  1622.  
  1623.       if (k1border | i0border | j0border ) {
  1624.          red100   = tObj->BorderColor[0];
  1625.          green100 = tObj->BorderColor[1];
  1626.          blue100  = tObj->BorderColor[2];
  1627.          alpha100 = tObj->BorderColor[3];
  1628.       }
  1629.       else {
  1630.          get_3d_texel( tObj, img, i0, j0, k1, &red100, &green100, &blue100, &alpha100 );
  1631.       }
  1632.       if (k1border | i1border | j0border) {
  1633.          red110   = tObj->BorderColor[0];
  1634.          green110 = tObj->BorderColor[1];
  1635.          blue110  = tObj->BorderColor[2];
  1636.          alpha110 = tObj->BorderColor[3];
  1637.       }
  1638.       else {
  1639.          get_3d_texel( tObj, img, i1, j0, k1, &red110, &green110, &blue110, &alpha110 );
  1640.       }
  1641.       if (k1border | i0border | j1border) {
  1642.          red101   = tObj->BorderColor[0];
  1643.          green101 = tObj->BorderColor[1];
  1644.          blue101  = tObj->BorderColor[2];
  1645.          alpha101 = tObj->BorderColor[3];
  1646.       }
  1647.       else {
  1648.          get_3d_texel( tObj, img, i0, j1, k1, &red101, &green101, &blue101, &alpha101 );
  1649.       }
  1650.       if (k1border | i1border | j1border) {
  1651.          red111   = tObj->BorderColor[0];
  1652.          green111 = tObj->BorderColor[1];
  1653.          blue111  = tObj->BorderColor[2];
  1654.          alpha111 = tObj->BorderColor[3];
  1655.       }
  1656.       else {
  1657.          get_3d_texel( tObj, img, i1, j1, k1, &red111, &green111, &blue111, &alpha111 );
  1658.       }
  1659.  
  1660.       *red   = (w000*red000   + w010*red010   + w001*red001   + w011*red011 +
  1661.                 w100*red100   + w110*red110   + w101*red101   + w111*red111  )
  1662.                 >> 8;
  1663.       *green = (w000*green000 + w010*green010 + w001*green001 + w011*green011 +
  1664.                 w100*green100 + w110*green110 + w101*green101 + w111*green111 )
  1665.                 >> 8;
  1666.       *blue  = (w000*blue000  + w010*blue010  + w001*blue001  + w011*blue011 +
  1667.                 w100*blue100  + w110*blue110  + w101*blue101  + w111*blue111 )
  1668.                 >> 8;
  1669.       *alpha = (w000*alpha000 + w010*alpha010 + w001*alpha001 + w011*alpha011 +
  1670.                 w100*alpha100 + w110*alpha110 + w101*alpha101 + w111*alpha111 )
  1671.                 >> 8;
  1672.    }
  1673. }
  1674.  
  1675.  
  1676. static void
  1677. sample_3d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
  1678.                                   GLfloat s, GLfloat t, GLfloat r,
  1679.                                   GLfloat lambda,
  1680.                                   GLubyte *red, GLubyte *green,
  1681.                                   GLubyte *blue, GLubyte *alpha )
  1682. {
  1683.    GLint level;
  1684.    if (lambda<=0.5F) {
  1685.       level = 0;
  1686.    }
  1687.    else {
  1688.       GLint widthlog2 = tObj->Image[0]->WidthLog2;
  1689.       level = (GLint) (lambda + 0.499999F);
  1690.       if (level>widthlog2 ) {
  1691.          level = widthlog2;
  1692.       }
  1693.    }
  1694.    sample_3d_nearest( tObj, tObj->Image[level],
  1695.                       s, t, r, red, green, blue, alpha );
  1696. }
  1697.  
  1698.  
  1699. static void
  1700. sample_3d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
  1701.                                  GLfloat s, GLfloat t, GLfloat r,
  1702.                                  GLfloat lambda,
  1703.                                  GLubyte *red, GLubyte *green,
  1704.                                  GLubyte *blue, GLubyte *alpha )
  1705. {
  1706.    GLint level;
  1707.    if (lambda<=0.5F) {
  1708.       level = 0;
  1709.    }
  1710.    else {
  1711.       GLint widthlog2 = tObj->Image[0]->WidthLog2;
  1712.       level = (GLint) (lambda + 0.499999F);
  1713.       if (level>widthlog2 ) {
  1714.          level = widthlog2;
  1715.       }
  1716.    }
  1717.    sample_3d_linear( tObj, tObj->Image[level],
  1718.                      s, t, r, red, green, blue, alpha );
  1719. }
  1720.  
  1721.  
  1722. static void
  1723. sample_3d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
  1724.                                  GLfloat s, GLfloat t, GLfloat r,
  1725.                                  GLfloat lambda,
  1726.                                  GLubyte *red, GLubyte *green,
  1727.                                  GLubyte *blue, GLubyte *alpha )
  1728. {
  1729.    GLint max = tObj->Image[0]->MaxLog2;
  1730.  
  1731.    if (lambda>=max) {
  1732.       sample_3d_nearest( tObj, tObj->Image[max],
  1733.                          s, t, r, red, green, blue, alpha );
  1734.    }
  1735.    else {
  1736.       GLubyte red0, green0, blue0, alpha0;
  1737.       GLubyte red1, green1, blue1, alpha1;
  1738.       GLfloat f = frac(lambda);
  1739.       GLint level = (GLint) (lambda + 1.0F);
  1740.       level = CLAMP( level, 1, max );
  1741.       sample_3d_nearest( tObj, tObj->Image[level-1], s, t, r,
  1742.                          &red0, &green0, &blue0, &alpha0 );
  1743.       sample_3d_nearest( tObj, tObj->Image[level], s, t, r,
  1744.                          &red1, &green1, &blue1, &alpha1 );
  1745.       *red   = (1.0F-f)*red1   + f*red0;
  1746.       *green = (1.0F-f)*green1 + f*green0;
  1747.       *blue  = (1.0F-f)*blue1  + f*blue0;
  1748.       *alpha = (1.0F-f)*alpha1 + f*alpha0;
  1749.    }
  1750. }
  1751.  
  1752.  
  1753. static void
  1754. sample_3d_linear_mipmap_linear( const struct gl_texture_object *tObj,
  1755.                                 GLfloat s, GLfloat t, GLfloat r,
  1756.                                 GLfloat lambda,
  1757.                                 GLubyte *red, GLubyte *green,
  1758.                                 GLubyte *blue, GLubyte *alpha )
  1759. {
  1760.    GLint max = tObj->Image[0]->MaxLog2;
  1761.  
  1762.    if (lambda>=max) {
  1763.       sample_3d_linear( tObj, tObj->Image[max],
  1764.                         s, t, r, red, green, blue, alpha );
  1765.    }
  1766.    else {
  1767.       GLubyte red0, green0, blue0, alpha0;
  1768.       GLubyte red1, green1, blue1, alpha1;
  1769.       GLfloat f = frac(lambda);
  1770.       GLint level = (GLint) (lambda + 1.0F);
  1771.       level = CLAMP( level, 1, max );
  1772.       sample_3d_linear( tObj, tObj->Image[level-1], s, t, r,
  1773.                         &red0, &green0, &blue0, &alpha0 );
  1774.       sample_3d_linear( tObj, tObj->Image[level], s, t, r,
  1775.                         &red1, &green1, &blue1, &alpha1 );
  1776.       *red   = (1.0F-f)*red1   + f*red0;
  1777.       *green = (1.0F-f)*green1 + f*green0;
  1778.       *blue  = (1.0F-f)*blue1  + f*blue0;
  1779.       *alpha = (1.0F-f)*alpha1 + f*alpha0;
  1780.    }
  1781. }
  1782.  
  1783.  
  1784. static void sample_nearest_3d( const struct gl_texture_object *tObj, GLuint n,
  1785.                                const GLfloat s[], const GLfloat t[],
  1786.                                const GLfloat u[], const GLfloat lambda[],
  1787.                                GLubyte red[], GLubyte green[], GLubyte blue[],
  1788.                                GLubyte alpha[] )
  1789. {
  1790.    GLuint i;
  1791.    for (i=0;i<n;i++) {
  1792.       sample_3d_nearest( tObj, tObj->Image[0], s[i], t[i], u[i],
  1793.                          &red[i], &green[i], &blue[i], &alpha[i]);
  1794.    }
  1795. }
  1796.  
  1797.  
  1798.  
  1799. static void sample_linear_3d( const struct gl_texture_object *tObj, GLuint n,
  1800.                               const GLfloat s[], const GLfloat t[],
  1801.                               const GLfloat u[], const GLfloat lambda[],
  1802.                               GLubyte red[], GLubyte green[], GLubyte blue[],
  1803.                               GLubyte alpha[] )
  1804. {
  1805.    GLuint i;
  1806.    for (i=0;i<n;i++) {
  1807.       sample_3d_linear( tObj, tObj->Image[0], s[i], t[i], u[i],
  1808.                         &red[i], &green[i], &blue[i], &alpha[i]);
  1809.    }
  1810. }
  1811.  
  1812. /*
  1813.  * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
  1814.  * return a texture sample.
  1815.  */
  1816. static void sample_lambda_3d( const struct gl_texture_object *tObj, GLuint n,
  1817.                               const GLfloat s[], const GLfloat t[],
  1818.                               const GLfloat u[], const GLfloat lambda[],
  1819.                               GLubyte red[], GLubyte green[],
  1820.                               GLubyte blue[], GLubyte alpha[] )
  1821. {
  1822.    GLuint i;
  1823.  
  1824.    for (i=0;i<n;i++) {
  1825.  
  1826.       if (lambda[i] > tObj->MinMagThresh) {
  1827.          /* minification */
  1828.          switch (tObj->MinFilter) {
  1829.             case GL_NEAREST:
  1830.                sample_3d_nearest( tObj, tObj->Image[0], s[i], t[i], u[i],
  1831.                                   &red[i], &green[i], &blue[i], &alpha[i] );
  1832.                break;
  1833.             case GL_LINEAR:
  1834.                sample_3d_linear( tObj, tObj->Image[0], s[i], t[i], u[i],
  1835.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1836.                break;
  1837.             case GL_NEAREST_MIPMAP_NEAREST:
  1838.                sample_3d_nearest_mipmap_nearest( tObj, s[i], t[i], u[i],
  1839.                           lambda[i], &red[i], &green[i], &blue[i], &alpha[i] );
  1840.                break;
  1841.             case GL_LINEAR_MIPMAP_NEAREST:
  1842.                sample_3d_linear_mipmap_nearest( tObj, s[i], t[i], u[i],
  1843.                           lambda[i], &red[i], &green[i], &blue[i], &alpha[i] );
  1844.                break;
  1845.             case GL_NEAREST_MIPMAP_LINEAR:
  1846.                sample_3d_nearest_mipmap_linear( tObj, s[i], t[i], u[i],
  1847.                           lambda[i], &red[i], &green[i], &blue[i], &alpha[i] );
  1848.                break;
  1849.             case GL_LINEAR_MIPMAP_LINEAR:
  1850.                sample_3d_linear_mipmap_linear( tObj, s[i], t[i], u[i],
  1851.                           lambda[i], &red[i], &green[i], &blue[i], &alpha[i] );
  1852.                break;
  1853.             default:
  1854.                gl_problem(NULL, "Bad min filterin sample_3d_texture");
  1855.          }
  1856.       }
  1857.       else {
  1858.          /* magnification */
  1859.          switch (tObj->MagFilter) {
  1860.             case GL_NEAREST:
  1861.                sample_3d_nearest( tObj, tObj->Image[0], s[i], t[i], u[i],
  1862.                                   &red[i], &green[i], &blue[i], &alpha[i] );
  1863.                break;
  1864.             case GL_LINEAR:
  1865.                sample_3d_linear( tObj, tObj->Image[0], s[i], t[i], u[i],
  1866.                                  &red[i], &green[i], &blue[i], &alpha[i] );
  1867.                break;
  1868.             default:
  1869.                gl_problem(NULL, "Bad mag filterin sample_3d_texture");
  1870.          }
  1871.       }
  1872.    }
  1873. }
  1874.  
  1875.  
  1876.  
  1877. /**********************************************************************/
  1878. /*                       Texture Sampling Setup                       */
  1879. /**********************************************************************/
  1880.  
  1881.  
  1882. /*
  1883.  * Setup the texture sampling function for this texture object.
  1884.  */
  1885. void gl_set_texture_sampler( struct gl_texture_object *t )
  1886. {
  1887.    if (!t->Complete) {
  1888.       t->SampleFunc = NULL;
  1889.    }
  1890.    else {
  1891.       GLboolean needLambda = (t->MinFilter != t->MagFilter);
  1892.  
  1893.       if (needLambda) {
  1894.          /* Compute min/mag filter threshold */
  1895.          if (t->MagFilter==GL_LINEAR
  1896.              && (t->MinFilter==GL_NEAREST_MIPMAP_NEAREST ||
  1897.                  t->MinFilter==GL_LINEAR_MIPMAP_NEAREST)) {
  1898.             t->MinMagThresh = 0.5F;
  1899.          }
  1900.          else {
  1901.             t->MinMagThresh = 0.0F;
  1902.          }
  1903.       }
  1904.  
  1905.       switch (t->Dimensions) {
  1906.          case 1:
  1907.             if (needLambda) {
  1908.                t->SampleFunc = sample_lambda_1d;
  1909.             }
  1910.             else if (t->MinFilter==GL_LINEAR) {
  1911.                t->SampleFunc = sample_linear_1d;
  1912.             }
  1913.             else {
  1914.                ASSERT(t->MinFilter==GL_NEAREST);
  1915.                t->SampleFunc = sample_nearest_1d;
  1916.             }
  1917.             break;
  1918.          case 2:
  1919.             if (needLambda) {
  1920.                t->SampleFunc = sample_lambda_2d;
  1921.             }
  1922.             else if (t->MinFilter==GL_LINEAR) {
  1923.                t->SampleFunc = sample_linear_2d;
  1924.             }
  1925.             else {
  1926.                ASSERT(t->MinFilter==GL_NEAREST);
  1927.                if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
  1928.                    && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGB) {
  1929.                   t->SampleFunc = opt_sample_rgb_2d;
  1930.                }
  1931.                else if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
  1932.                    && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGBA) {
  1933.                   t->SampleFunc = opt_sample_rgba_2d;
  1934.                }
  1935.                else
  1936.                   t->SampleFunc = sample_nearest_2d;
  1937.             }
  1938.             break;
  1939.          case 3:
  1940.             if (needLambda) {
  1941.                t->SampleFunc = sample_lambda_3d;
  1942.             }
  1943.             else if (t->MinFilter==GL_LINEAR) {
  1944.                t->SampleFunc = sample_linear_3d;
  1945.             }
  1946.             else {
  1947.                ASSERT(t->MinFilter==GL_NEAREST);
  1948.                t->SampleFunc = sample_nearest_3d;
  1949.             }
  1950.             break;
  1951.          default:
  1952.             gl_problem(NULL, "invalid dimensions in gl_set_texture_sampler");
  1953.       }
  1954.    }
  1955. }
  1956.  
  1957.  
  1958.  
  1959. /**********************************************************************/
  1960. /*                      Texture Application                           */
  1961. /**********************************************************************/
  1962.  
  1963.  
  1964. /*
  1965.  * Combine incoming fragment color with texel color to produce output color.
  1966.  * Input:  n - number of fragments
  1967.  *         format - base internal texture format
  1968.  *         env_mode - texture environment mode
  1969.  *         Rt, Gt, Bt, At - array of texel colors
  1970.  * InOut:  red, green, blue, alpha - incoming fragment colors modified
  1971.  *                                   by texel colors according to the
  1972.  *                                   texture environment mode.
  1973.  */
  1974. static void apply_texture( GLcontext *ctx,
  1975.          GLuint n, GLint format, GLenum env_mode,
  1976.      GLubyte red[], GLubyte green[], GLubyte blue[], GLubyte alpha[],
  1977.      GLubyte Rt[], GLubyte Gt[], GLubyte Bt[], GLubyte At[] )
  1978. {
  1979.    GLuint i;
  1980.    GLint Rc, Gc, Bc, Ac;
  1981.  
  1982.    if (!ctx->Visual->EightBitColor) {
  1983.       /* This is a hack!  Rescale input colors from [0,scale] to [0,255]. */
  1984.       GLfloat rscale = 255.0 * ctx->Visual->InvRedScale;
  1985.       GLfloat gscale = 255.0 * ctx->Visual->InvGreenScale;
  1986.       GLfloat bscale = 255.0 * ctx->Visual->InvBlueScale;
  1987.       GLfloat ascale = 255.0 * ctx->Visual->InvAlphaScale;
  1988.       for (i=0;i<n;i++) {
  1989.      red[i]   = (GLint) (red[i]   * rscale);
  1990.      green[i] = (GLint) (green[i] * gscale);
  1991.      blue[i]  = (GLint) (blue[i]  * bscale);
  1992.      alpha[i] = (GLint) (alpha[i] * ascale);
  1993.       }
  1994.    }
  1995.  
  1996. /*
  1997.  * Use (A*(B+1)) >> 8 as a fast approximation of (A*B)/255 for A
  1998.  * and B in [0,255]
  1999.  */
  2000. #define PROD(A,B)   (((GLint)(A) * ((GLint)(B)+1)) >> 8)
  2001.  
  2002.    if (format==GL_COLOR_INDEX) {
  2003.       format = GL_RGBA;  /* XXXX a hack! */
  2004.    }
  2005.  
  2006.    switch (env_mode) {
  2007.       case GL_REPLACE:
  2008.      switch (format) {
  2009.         case GL_ALPHA:
  2010.            for (i=0;i<n;i++) {
  2011.           /* Cv = Cf */
  2012.                   /* Av = At */
  2013.                   alpha[i] = At[i];
  2014.            }
  2015.            break;
  2016.         case GL_LUMINANCE:
  2017.            for (i=0;i<n;i++) {
  2018.           /* Cv = Lt */
  2019.                   GLint Lt = Rt[i];
  2020.                   red[i] = green[i] = blue[i] = Lt;
  2021.                   /* Av = Af */
  2022.            }
  2023.            break;
  2024.         case GL_LUMINANCE_ALPHA:
  2025.            for (i=0;i<n;i++) {
  2026.                   GLint Lt = Rt[i];
  2027.           /* Cv = Lt */
  2028.           red[i] = green[i] = blue[i] = Lt;
  2029.           /* Av = At */
  2030.           alpha[i] = At[i];
  2031.            }
  2032.            break;
  2033.         case GL_INTENSITY:
  2034.            for (i=0;i<n;i++) {
  2035.           /* Cv = It */
  2036.                   GLint It = Rt[i];
  2037.                   red[i] = green[i] = blue[i] = It;
  2038.                   /* Av = It */
  2039.                   alpha[i] = It;
  2040.            }
  2041.            break;
  2042.         case GL_RGB:
  2043.            for (i=0;i<n;i++) {
  2044.           /* Cv = Ct */
  2045.           red[i]   = Rt[i];
  2046.           green[i] = Gt[i];
  2047.           blue[i]  = Bt[i];
  2048.           /* Av = Af */
  2049.            }
  2050.            break;
  2051.         case GL_RGBA:
  2052.            for (i=0;i<n;i++) {
  2053.           /* Cv = Ct */
  2054.           red[i]   = Rt[i];
  2055.           green[i] = Gt[i];
  2056.           blue[i]  = Bt[i];
  2057.           /* Av = At */
  2058.           alpha[i] = At[i];
  2059.            }
  2060.            break;
  2061.             default:
  2062.                gl_problem(ctx, "Bad format in apply_texture");
  2063.                return;
  2064.      }
  2065.      break;
  2066.  
  2067.       case GL_MODULATE:
  2068.          switch (format) {
  2069.         case GL_ALPHA:
  2070.            for (i=0;i<n;i++) {
  2071.           /* Cv = Cf */
  2072.           /* Av = AfAt */
  2073.           alpha[i] = PROD( alpha[i], At[i] );
  2074.            }
  2075.            break;
  2076.         case GL_LUMINANCE:
  2077.            for (i=0;i<n;i++) {
  2078.           /* Cv = LtCf */
  2079.                   GLint Lt = Rt[i];
  2080.           red[i]   = PROD( red[i],   Lt );
  2081.           green[i] = PROD( green[i], Lt );
  2082.           blue[i]  = PROD( blue[i],  Lt );
  2083.           /* Av = Af */
  2084.            }
  2085.            break;
  2086.         case GL_LUMINANCE_ALPHA:
  2087.            for (i=0;i<n;i++) {
  2088.           /* Cv = CfLt */
  2089.                   GLint Lt = Rt[i];
  2090.           red[i]   = PROD( red[i],   Lt );
  2091.           green[i] = PROD( green[i], Lt );
  2092.           blue[i]  = PROD( blue[i],  Lt );
  2093.           /* Av = AfAt */
  2094.           alpha[i] = PROD( alpha[i], At[i] );
  2095.            }
  2096.            break;
  2097.         case GL_INTENSITY:
  2098.            for (i=0;i<n;i++) {
  2099.           /* Cv = CfIt */
  2100.                   GLint It = Rt[i];
  2101.           red[i]   = PROD( red[i],   It );
  2102.           green[i] = PROD( green[i], It );
  2103.           blue[i]  = PROD( blue[i],  It );
  2104.           /* Av = AfIt */
  2105.           alpha[i] = PROD( alpha[i], It );
  2106.            }
  2107.            break;
  2108.         case GL_RGB:
  2109.            for (i=0;i<n;i++) {
  2110.           /* Cv = CfCt */
  2111.           red[i]   = PROD( red[i],   Rt[i] );
  2112.           green[i] = PROD( green[i], Gt[i] );
  2113.           blue[i]  = PROD( blue[i],  Bt[i] );
  2114.           /* Av = Af */
  2115.            }
  2116.            break;
  2117.         case GL_RGBA:
  2118.            for (i=0;i<n;i++) {
  2119.           /* Cv = CfCt */
  2120.           red[i]   = PROD( red[i],   Rt[i] );
  2121.           green[i] = PROD( green[i], Gt[i] );
  2122.           blue[i]  = PROD( blue[i],  Bt[i] );
  2123.           /* Av = AfAt */
  2124.           alpha[i] = PROD( alpha[i], At[i] );
  2125.            }
  2126.            break;
  2127.             default:
  2128.                gl_problem(ctx, "Bad format (2) in apply_texture");
  2129.                return;
  2130.      }
  2131.      break;
  2132.  
  2133.       case GL_DECAL:
  2134.          switch (format) {
  2135.             case GL_ALPHA:
  2136.             case GL_LUMINANCE:
  2137.             case GL_LUMINANCE_ALPHA:
  2138.             case GL_INTENSITY:
  2139.                /* undefined */
  2140.                break;
  2141.         case GL_RGB:
  2142.            for (i=0;i<n;i++) {
  2143.           /* Cv = Ct */
  2144.           red[i]   = Rt[i];
  2145.           green[i] = Gt[i];
  2146.           blue[i]  = Bt[i];
  2147.           /* Av = Af */
  2148.            }
  2149.            break;
  2150.         case GL_RGBA:
  2151.            for (i=0;i<n;i++) {
  2152.           /* Cv = Cf(1-At) + CtAt */
  2153.           GLint t = At[i], s = 255 - t;
  2154.           red[i]   = PROD(red[i],  s) + PROD(Rt[i],t);
  2155.           green[i] = PROD(green[i],s) + PROD(Gt[i],t);
  2156.           blue[i]  = PROD(blue[i], s) + PROD(Bt[i],t);
  2157.           /* Av = Af */
  2158.            }
  2159.            break;
  2160.             default:
  2161.                gl_problem(ctx, "Bad format (3) in apply_texture");
  2162.                return;
  2163.      }
  2164.      break;
  2165.  
  2166.       case GL_BLEND:
  2167.          Rc = (GLint) (ctx->Texture.EnvColor[0] * 255.0F);
  2168.          Gc = (GLint) (ctx->Texture.EnvColor[1] * 255.0F);
  2169.          Bc = (GLint) (ctx->Texture.EnvColor[2] * 255.0F);
  2170.          Ac = (GLint) (ctx->Texture.EnvColor[3] * 255.0F);
  2171.      switch (format) {
  2172.         case GL_ALPHA:
  2173.            for (i=0;i<n;i++) {
  2174.           /* Cv = Cf */
  2175.           /* Av = AfAt */
  2176.                   alpha[i] = PROD(alpha[i], At[i]);
  2177.            }
  2178.            break;
  2179.             case GL_LUMINANCE:
  2180.            for (i=0;i<n;i++) {
  2181.           /* Cv = Cf(1-Lt) + CcLt */
  2182.           GLint Lt = Rt[i], s = 255 - Lt;
  2183.           red[i]   = PROD(red[i],  s) + PROD(Rc,  Lt);
  2184.           green[i] = PROD(green[i],s) + PROD(Gc,Lt);
  2185.           blue[i]  = PROD(blue[i], s) + PROD(Bc, Lt);
  2186.           /* Av = Af */
  2187.            }
  2188.            break;
  2189.         case GL_LUMINANCE_ALPHA:
  2190.            for (i=0;i<n;i++) {
  2191.           /* Cv = Cf(1-Lt) + CcLt */
  2192.           GLint Lt = Rt[i], s = 255 - Lt;
  2193.           red[i]   = PROD(red[i],  s) + PROD(Rc,  Lt);
  2194.           green[i] = PROD(green[i],s) + PROD(Gc,Lt);
  2195.           blue[i]  = PROD(blue[i], s) + PROD(Bc, Lt);
  2196.           /* Av = AfAt */
  2197.           alpha[i] = PROD(alpha[i],At[i]);
  2198.            }
  2199.            break;
  2200.             case GL_INTENSITY:
  2201.            for (i=0;i<n;i++) {
  2202.           /* Cv = Cf(1-It) + CcLt */
  2203.           GLint It = Rt[i], s = 255 - It;
  2204.           red[i]   = PROD(red[i],  s) + PROD(Rc,It);
  2205.           green[i] = PROD(green[i],s) + PROD(Gc,It);
  2206.           blue[i]  = PROD(blue[i], s) + PROD(Bc,It);
  2207.                   /* Av = Af(1-It) + Ac*It */
  2208.                   alpha[i] = PROD(alpha[i],s) + PROD(Ac,It);
  2209.                }
  2210.                break;
  2211.         case GL_RGB:
  2212.            for (i=0;i<n;i++) {
  2213.           /* Cv = Cf(1-Ct) + CcCt */
  2214.           red[i]   = PROD(red[i],  (255-Rt[i])) + PROD(Rc,Rt[i]);
  2215.           green[i] = PROD(green[i],(255-Gt[i])) + PROD(Gc,Gt[i]);
  2216.           blue[i]  = PROD(blue[i], (255-Bt[i])) + PROD(Bc,Bt[i]);
  2217.           /* Av = Af */
  2218.            }
  2219.            break;
  2220.         case GL_RGBA:
  2221.            for (i=0;i<n;i++) {
  2222.           /* Cv = Cf(1-Ct) + CcCt */
  2223.           red[i]   = PROD(red[i],  (255-Rt[i])) + PROD(Rc,Rt[i]);
  2224.           green[i] = PROD(green[i],(255-Gt[i])) + PROD(Gc,Gt[i]);
  2225.           blue[i]  = PROD(blue[i], (255-Bt[i])) + PROD(Bc,Bt[i]);
  2226.           /* Av = AfAt */
  2227.           alpha[i] = PROD(alpha[i],At[i]);
  2228.            }
  2229.            break;
  2230.      }
  2231.      break;
  2232.  
  2233.       default:
  2234.          gl_problem(ctx, "Bad env mode in apply_texture");
  2235.          return;
  2236.    }
  2237. #undef PROD
  2238.  
  2239.    if (!ctx->Visual->EightBitColor) {
  2240.       /* This is a hack!  Rescale input colors from [0,255] to [0,scale]. */
  2241.       GLfloat rscale = ctx->Visual->RedScale   * (1.0F/ 255.0F);
  2242.       GLfloat gscale = ctx->Visual->GreenScale * (1.0F/ 255.0F);
  2243.       GLfloat bscale = ctx->Visual->BlueScale  * (1.0F/ 255.0F);
  2244.       GLfloat ascale = ctx->Visual->AlphaScale * (1.0F/ 255.0F);
  2245.       for (i=0;i<n;i++) {
  2246.      red[i]   = (GLint) (red[i]   * rscale);
  2247.      green[i] = (GLint) (green[i] * gscale);
  2248.      blue[i]  = (GLint) (blue[i]  * bscale);
  2249.      alpha[i] = (GLint) (alpha[i] * ascale);
  2250.       }
  2251.    }
  2252. }
  2253.  
  2254.  
  2255.  
  2256. void gl_texture_pixels( GLcontext *ctx, GLuint n,
  2257.                         const GLfloat s[], const GLfloat t[],
  2258.                         const GLfloat r[], const GLfloat lambda[],
  2259.                         GLubyte red[], GLubyte green[],
  2260.                         GLubyte blue[], GLubyte alpha[] )
  2261. {
  2262.    GLubyte tred[PB_SIZE];
  2263.    GLubyte tgreen[PB_SIZE];
  2264.    GLubyte tblue[PB_SIZE];
  2265.    GLubyte talpha[PB_SIZE];
  2266.  
  2267.    if (!ctx->Texture.Current || !ctx->Texture.Current->SampleFunc)
  2268.       return;
  2269.  
  2270.    /* Sample the texture. */
  2271.    (*ctx->Texture.Current->SampleFunc)( ctx->Texture.Current, n,
  2272.                                         s, t, r, lambda,
  2273.                                         tred, tgreen, tblue, talpha );
  2274.  
  2275.    apply_texture( ctx, n,
  2276.                   ctx->Texture.Current->Image[0]->Format,
  2277.                   ctx->Texture.EnvMode,
  2278.                   red, green, blue, alpha,
  2279.                   tred, tgreen, tblue, talpha );
  2280. }
  2281.