head	3.31;
access;
symbols
	merge-1:3.28.2.2
	autoconf:3.28.0.4
	experimental-1:3.28.0.2
	mesa-3-1-with-kw3:3.18
	mesa-3-1-prior-to-kw3:3.17;
locks; strict;
comment	@ * @;


3.31
date	99.08.02.19.07.00;	author brianp;	state Exp;
branches;
next	3.30;

3.30
date	99.08.02.18.59.06;	author brianp;	state Exp;
branches;
next	3.29;

3.29
date	99.07.12.12.05.25;	author keithw;	state Exp;
branches;
next	3.28;

3.28
date	99.05.17.21.24.32;	author brianp;	state Exp;
branches
	3.28.2.1;
next	3.27;

3.27
date	99.05.06.16.53.59;	author brianp;	state Exp;
branches;
next	3.26;

3.26
date	99.05.02.00.59.24;	author keithw;	state Exp;
branches;
next	3.25;

3.25
date	99.04.21.13.01.01;	author brianp;	state Exp;
branches;
next	3.24;

3.24
date	99.04.18.15.45.49;	author keithw;	state Exp;
branches;
next	3.23;

3.23
date	99.04.03.16.23.40;	author brianp;	state Exp;
branches;
next	3.22;

3.22
date	99.03.31.20.18.40;	author keithw;	state Exp;
branches;
next	3.21;

3.21
date	99.03.20.18.58.12;	author brianp;	state Exp;
branches;
next	3.20;

3.20
date	99.03.20.02.56.31;	author brianp;	state Exp;
branches;
next	3.19;

3.19
date	99.02.27.17.46.56;	author brianp;	state Exp;
branches;
next	3.18;

3.18
date	99.02.25.14.12.32;	author keithw;	state Exp;
branches;
next	3.17;

3.17
date	99.02.24.22.48.07;	author jens;	state Exp;
branches;
next	3.16;

3.16
date	99.02.14.03.46.34;	author brianp;	state Exp;
branches;
next	3.15;

3.15
date	99.01.19.02.14.08;	author brianp;	state Exp;
branches;
next	3.14;

3.14
date	99.01.16.16.50.05;	author brianp;	state Exp;
branches;
next	3.13;

3.13
date	98.11.29.21.49.10;	author brianp;	state Exp;
branches;
next	3.12;

3.12
date	98.11.19.03.07.36;	author brianp;	state Exp;
branches;
next	3.11;

3.11
date	98.11.17.01.52.47;	author brianp;	state Exp;
branches;
next	3.10;

3.10
date	98.11.08.22.34.07;	author brianp;	state Exp;
branches;
next	3.9;

3.9
date	98.10.23.00.36.38;	author brianp;	state Exp;
branches;
next	3.8;

3.8
date	98.06.11.02.04.41;	author brianp;	state Exp;
branches;
next	3.7;

3.7
date	98.03.28.03.58.16;	author brianp;	state Exp;
branches;
next	3.6;

3.6
date	98.03.27.04.26.44;	author brianp;	state Exp;
branches;
next	3.5;

3.5
date	98.03.15.18.12.37;	author brianp;	state Exp;
branches;
next	3.4;

3.4
date	98.03.01.20.19.26;	author brianp;	state Exp;
branches;
next	3.3;

3.3
date	98.02.20.04.53.37;	author brianp;	state Exp;
branches;
next	3.2;

3.2
date	98.02.03.04.27.54;	author brianp;	state Exp;
branches;
next	3.1;

3.1
date	98.02.01.19.39.09;	author brianp;	state Exp;
branches;
next	3.0;

3.0
date	98.01.31.21.04.38;	author brianp;	state Exp;
branches;
next	;

3.28.2.1
date	99.05.21.21.29.27;	author keithw;	state Exp;
branches;
next	3.28.2.2;

3.28.2.2
date	99.06.06.22.35.55;	author keithw;	state Exp;
branches;
next	;


desc
@texture mapping functions
@


3.31
log
@cleaned-up comments
@
text
@/* $Id: texture.c,v 3.30 1999/08/02 18:59:06 brianp Exp $ */

/*
 * Mesa 3-D graphics library
 * Version:  3.1
 * 
 * Copyright (C) 1999  Brian Paul   All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "context.h"
#include "macros.h"
#include "mmath.h"
#include "pb.h"
#include "texture.h"
#include "types.h"
#include "xform.h"
#ifdef XFree86Server
#include "GL/xf86glx.h"
#endif
#endif


/***********************************************************************
 * Automatic texture coordinate generation (texgen) code.
 */

static GLuint all_bits[5] = {
   0,
   VEC_SIZE_1,
   VEC_SIZE_2,
   VEC_SIZE_3,
   VEC_SIZE_4,
};


static texgen_func texgen_generic_tab[4];
static texgen_func texgen_reflection_map_nv_tab[4];
static texgen_func texgen_normal_map_nv_tab[4];
static texgen_func texgen_sphere_map_tab[4];


typedef void (*build_m_func)(GLfloat f[][3],
			     GLfloat m[],
			     const GLvector3f *normals, 
			     const GLvector4f *coord_vec, 
			     const GLuint flags[],
			     const GLubyte cullmask[] );


typedef void (*build_f_func)( GLfloat *f, 
			      GLuint fstride,
			      const GLvector3f *normal_vec,
			      const GLvector4f *coord_vec, 
			      const GLuint flags[],
			      const GLubyte cullmask[] );


/* KW: compacted vs. coindexed normals don't bring any performance
 *     gains to texture generation, but it is still necessary to cope
 *     with the two different formats.
 */
#define TAG(x)           x
#define FIRST_NORMAL     normals->start
#define NEXT_NORMAL      STRIDE_F(normal, normals->stride)
#define LOCAL_VARS
#define CHECK            
#define IDX              0
#include "texgen_tmp.h"


#define TAG(x)           x##_compacted
#define FIRST_NORMAL     normals->start
#define NEXT_NORMAL      ((flags[i]&VERT_NORM) ? (normal=first_normal[i]) : (normal))
#define CHECK            
#define IDX              2
#define LOCAL_VARS        \
   GLfloat (*first_normal)[3] = (GLfloat (*)[3]) FIRST_NORMAL;

#include "texgen_tmp.h"

#define TAG(x)           x##_masked
#define FIRST_NORMAL     normals->start
#define NEXT_NORMAL      STRIDE_F(normal, normals->stride)
#define LOCAL_VARS       
#define CHECK            if (cullmask[i])
#define IDX              1
#include "texgen_tmp.h"

#define TAG(x)           x##_compacted_masked
#define FIRST_NORMAL     normals->start
#define NEXT_NORMAL      ((flags[i]&VERT_NORM) ? normal=first_normal[i] : 0)
#define CHECK            if (cullmask[i])
#define IDX              3
#define LOCAL_VARS       \
   GLfloat (*first_normal)[3] = (GLfloat (*)[3]) FIRST_NORMAL;

#include "texgen_tmp.h"


/*
 * End texgen code
 ***********************************************************************
 */



/*
 * One time inits for texture mapping.
 * Called by one_time_init() in context.c
 */
void gl_init_texture( void )
{
   init_texgen();
   init_texgen_compacted();
   init_texgen_masked();
   init_texgen_compacted_masked();
}


/*
 * After state changes to texturing we call this function to update
 * intermediate and derived state.
 * Called by gl_update_state().
 */
void gl_update_texture_unit( GLcontext *ctx, struct gl_texture_unit *texUnit )
{
   (void) ctx;

   if ((texUnit->Enabled & TEXTURE0_3D) && texUnit->CurrentD[3]->Complete) {
      texUnit->ReallyEnabled = TEXTURE0_3D;
      texUnit->Current = texUnit->CurrentD[3];
      texUnit->CurrentDimension = 3;
   }
   else if ((texUnit->Enabled & TEXTURE0_2D) && texUnit->CurrentD[2]->Complete) {
      texUnit->ReallyEnabled = TEXTURE0_2D;
      texUnit->Current = texUnit->CurrentD[2];
      texUnit->CurrentDimension = 2;
   }
   else if ((texUnit->Enabled & TEXTURE0_1D) && texUnit->CurrentD[1]->Complete) {
      texUnit->ReallyEnabled = TEXTURE0_1D;
      texUnit->Current = texUnit->CurrentD[1];
      texUnit->CurrentDimension = 1;
   }
   else {
      if (MESA_VERBOSE & VERBOSE_TEXTURE) {
	 switch (texUnit->Enabled) {
	 case TEXTURE0_3D:
	    fprintf(stderr, "Using incomplete 3d texture %u\n",
		    texUnit->CurrentD[3]->Name);
	    break;
	 case TEXTURE0_2D:
	    fprintf(stderr, "Using incomplete 2d texture %u\n",
		    texUnit->CurrentD[2]->Name);
	    break;
	 case TEXTURE0_1D:
	    fprintf(stderr, "Using incomplete 1d texture %u\n",
		    texUnit->CurrentD[1]->Name);
	    break;
	 default:
	    fprintf(stderr, "Bad value for texUnit->Enabled %x\n",
		    texUnit->Enabled);
	    break;
	 }	 
      }

      texUnit->ReallyEnabled = 0;
      texUnit->Current = NULL;
      texUnit->CurrentDimension = 0;
      return;
   }

   texUnit->GenFlags = 0;

   if (texUnit->TexGenEnabled) {
      GLuint sz = 0;

      if (texUnit->TexGenEnabled & S_BIT) {
         sz = 1;
         texUnit->GenFlags |= texUnit->GenBitS;
      }
      if (texUnit->TexGenEnabled & T_BIT) {
         sz = 2;
         texUnit->GenFlags |= texUnit->GenBitT;
      }
      if (texUnit->TexGenEnabled & Q_BIT) {
         sz = 3;
         texUnit->GenFlags |= texUnit->GenBitQ;
      }
      if (texUnit->TexGenEnabled & R_BIT) {
         sz = 4;
         texUnit->GenFlags |= texUnit->GenBitR;
      }
   
      texUnit->TexgenSize = sz;
      texUnit->Holes = (all_bits[sz] & ~texUnit->TexGenEnabled);
      texUnit->func = texgen_generic_tab;

      if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
	 if (texUnit->GenFlags == TEXGEN_REFLECTION_MAP_NV) {
	    texUnit->func = texgen_reflection_map_nv_tab;
	 }
	 else if (texUnit->GenFlags == TEXGEN_NORMAL_MAP_NV) {
	    texUnit->func = texgen_normal_map_nv_tab;
	 }
      }
      else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) && 
	       texUnit->GenFlags == TEXGEN_SPHERE_MAP) {
	 texUnit->func = texgen_sphere_map_tab;
      }
   }
}



/*
 * Paletted texture sampling.
 * Input:  tObj - the texture object
 *         index - the palette index (8-bit only)
 * Output:  red, green, blue, alpha - the texel color
 */
static void palette_sample(const struct gl_texture_object *tObj,
                           GLubyte index, GLubyte rgba[4] )
{
   GLcontext *ctx = gl_get_current_context();  /* THIS IS A HACK */
   GLint i = index;
   const GLubyte *palette;

   if (ctx->Texture.SharedPalette) {
      palette = ctx->Texture.Palette;
   }
   else {
      palette = tObj->Palette;
   }

   switch (tObj->PaletteFormat) {
      case GL_ALPHA:
         rgba[ACOMP] = tObj->Palette[index];
         return;
      case GL_LUMINANCE:
      case GL_INTENSITY:
         rgba[RCOMP] = palette[index];
         return;
      case GL_LUMINANCE_ALPHA:
         rgba[RCOMP] = palette[(index << 1) + 0];
         rgba[ACOMP] = palette[(index << 1) + 1];
         return;
      case GL_RGB:
         rgba[RCOMP] = palette[index * 3 + 0];
         rgba[GCOMP] = palette[index * 3 + 1];
         rgba[BCOMP] = palette[index * 3 + 2];
         return;
      case GL_RGBA:
         rgba[RCOMP] = palette[(i << 2) + 0];
         rgba[GCOMP] = palette[(i << 2) + 1];
         rgba[BCOMP] = palette[(i << 2) + 2];
         rgba[ACOMP] = palette[(i << 2) + 3];
         return;
      default:
         gl_problem(NULL, "Bad palette format in palette_sample");
   }
}




/**********************************************************************/
/*                    1-D Texture Sampling Functions                  */
/**********************************************************************/


/*
 * Return the fractional part of x.
 */
#define frac(x) ((GLfloat)(x)-floor((GLfloat)x))



/*
 * Given 1-D texture image and an (i) texel column coordinate, return the
 * texel color.
 */
static void get_1d_texel( const struct gl_texture_object *tObj,
                          const struct gl_texture_image *img, GLint i,
                          GLubyte rgba[4] )
{
   GLubyte *texel;

#ifdef DEBUG
   GLint width = img->Width;
   if (i<0 || i>=width)  abort();
#endif

   switch (img->Format) {
      case GL_COLOR_INDEX:
         {
            GLubyte index = img->Data[i];
            palette_sample(tObj, index, rgba);
            return;
         }
      case GL_ALPHA:
         rgba[ACOMP] = img->Data[ i ];
         return;
      case GL_LUMINANCE:
      case GL_INTENSITY:
         rgba[RCOMP] = img->Data[ i ];
         return;
      case GL_LUMINANCE_ALPHA:
         texel = img->Data + i * 2;
         rgba[RCOMP] = texel[0];
         rgba[ACOMP] = texel[1];
         return;
      case GL_RGB:
         texel = img->Data + i * 3;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         return;
      case GL_RGBA:
         texel = img->Data + i * 4;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         rgba[ACOMP] = texel[3];
         return;
      default:
         gl_problem(NULL, "Bad format in get_1d_texel");
         return;
   }
}



/*
 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
 */
static void sample_1d_nearest( const struct gl_texture_object *tObj,
                               const struct gl_texture_image *img,
                               GLfloat s, GLubyte rgba[4] )
{
   GLint width = img->Width2;  /* without border, power of two */
   GLint i;
   GLubyte *texel;

   /* Clamp/Repeat S and convert to integer texel coordinate */
   if (tObj->WrapS==GL_REPEAT) {
      /* s limited to [0,1) */
      /* i limited to [0,width-1] */
      i = (GLint) (s * width);
      if (s<0.0F)  i -= 1;
      i &= (width-1);
   }
   else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
      GLfloat min = 1.0F / (2.0F * width);
      GLfloat max = 1.0F - min;
      if (s < min)
         i = 0;
      else if (s > max)
         i = width-1;
      else
         i = (GLint) (s * width);
   }
   else {
      ASSERT(tObj->WrapS==GL_CLAMP);
      /* s limited to [0,1] */
      /* i limited to [0,width-1] */
      if (s<=0.0F)       i = 0;
      else if (s>=1.0F)  i = width-1;
      else               i = (GLint) (s * width);
   }

   /* skip over the border, if any */
   i += img->Border;

   /* Get the texel */
   switch (img->Format) {
      case GL_COLOR_INDEX:
         {
            GLubyte index = img->Data[i];
            palette_sample(tObj, index, rgba );
            return;
         }
      case GL_ALPHA:
         rgba[ACOMP] = img->Data[i];
         return;
      case GL_LUMINANCE:
      case GL_INTENSITY:
         rgba[RCOMP] = img->Data[i];
         return;
      case GL_LUMINANCE_ALPHA:
         texel = img->Data + i * 2;
         rgba[RCOMP] = texel[0];
         rgba[ACOMP] = texel[1];
         return;
      case GL_RGB:
         texel = img->Data + i * 3;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         return;
      case GL_RGBA:
         texel = img->Data + i * 4;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         rgba[ACOMP] = texel[3];
         return;
      default:
         gl_problem(NULL, "Bad format in sample_1d_nearest");
   }
}



/*
 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
 */
static void sample_1d_linear( const struct gl_texture_object *tObj,
                              const struct gl_texture_image *img,
                              GLfloat s,
                              GLubyte rgba[4] )
{
   GLint width = img->Width2;
   GLint i0, i1;
   GLfloat u;
   GLint i0border = 0, i1border = 0;

   if (tObj->WrapS==GL_REPEAT) {
      u = s * width - 0.5F;
      i0 = ((GLint) floor(u)) & (width - 1);
      i1 = i0 + 1;
      if (i1 >= width)
         i1 = 0;
   }
   else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
      u = s * width - 0.5F;
      i0 = (GLint) floor(u);
      i1 = i0 + 1;
      if (i0 < 0)
         i0 = 0;
      else if (i0 >= width)
         i0 = width - 1;
      if (i1 < 0)
         i1 = 0;
      else if (i1 >= width)
         i1 = width - 1;
   }
   else {
      ASSERT(tObj->WrapS==GL_CLAMP);
      if (s < 0.0)
         s = 0.0;
      else if (s > 1.0)
         s = 1.0;
      u = s * width - 0.5F;
      i0 = (GLint) floor(u);
      i1 = i0 + 1;
      i0border = (i0<0) | (i0>=width);
      i1border = (i1<0) | (i1>=width);
   }

   if (img->Border) {
      i0 += img->Border;
      i1 += img->Border;
      if (tObj->WrapS != GL_CLAMP)
         i0border = i1border = 0;
   }
   else {
      i0 &= (width-1);
   }

   {
      GLfloat a = frac(u);

      GLint w0 = (GLint) ((1.0F-a) * 256.0F);
      GLint w1 = (GLint) (      a  * 256.0F);

      GLubyte t0[4], t1[4];  /* texels */

      if (i0border) {
         t0[RCOMP] = tObj->BorderColor[0];
         t0[GCOMP] = tObj->BorderColor[1];
         t0[BCOMP] = tObj->BorderColor[2];
         t0[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_1d_texel( tObj, img, i0, t0 );
      }
      if (i1border) {
         t1[RCOMP] = tObj->BorderColor[0];
         t1[GCOMP] = tObj->BorderColor[1];
         t1[BCOMP] = tObj->BorderColor[2];
         t1[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_1d_texel( tObj, img, i1, t1 );
      }

      rgba[0] = (w0 * t0[0] + w1 * t1[0]) >> 8;
      rgba[1] = (w0 * t0[1] + w1 * t1[1]) >> 8;
      rgba[2] = (w0 * t0[2] + w1 * t1[2]) >> 8;
      rgba[3] = (w0 * t0[3] + w1 * t1[3]) >> 8;
   }
}


static void
sample_1d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
                                  GLfloat s, GLfloat lambda,
                                  GLubyte rgba[4] )
{
   GLint level;
   if (lambda <= 0.5F)
      lambda = 0.0F;
   else if (lambda > tObj->M + 0.4999F)
      lambda = tObj->M + 0.4999F;
   level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
   if (level > tObj->P)
      level = tObj->P;

   sample_1d_nearest( tObj, tObj->Image[level], s, rgba );
}


static void
sample_1d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
                                 GLfloat s, GLfloat lambda,
                                 GLubyte rgba[4] )
{
   GLint level;
   if (lambda <= 0.5F)
      lambda = 0.0F;
   else if (lambda > tObj->M + 0.4999F)
      lambda = tObj->M + 0.4999F;
   level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
   if (level > tObj->P)
      level = tObj->P;

   sample_1d_linear( tObj, tObj->Image[level], s, rgba );
}



static void
sample_1d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
                                 GLfloat s, GLfloat lambda,
                                 GLubyte rgba[4] )
{
   GLint level;
   if (lambda < 0.0F)
      lambda = 0.0F;
   else if (lambda > tObj->M)
      lambda = tObj->M;
   level = (GLint) (tObj->BaseLevel + lambda);

   if (level >= tObj->P) {
      sample_1d_nearest( tObj, tObj->Image[tObj->P], s, rgba );
   }
   else {
      GLubyte t0[4], t1[4];
      GLfloat f = frac(lambda);
      sample_1d_nearest( tObj, tObj->Image[level  ], s, t0 );
      sample_1d_nearest( tObj, tObj->Image[level+1], s, t1 );
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
      rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
      rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
      rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
   }
}



static void
sample_1d_linear_mipmap_linear( const struct gl_texture_object *tObj,
                                GLfloat s, GLfloat lambda,
                                GLubyte rgba[4] )
{
   GLint level;
   if (lambda < 0.0F)
      lambda = 0.0F;
   else if (lambda > tObj->M)
      lambda = tObj->M;
   level = (GLint) (tObj->BaseLevel + lambda);

   if (level >= tObj->P) {
      sample_1d_linear( tObj, tObj->Image[tObj->P], s, rgba );
   }
   else {
      GLubyte t0[4], t1[4];
      GLfloat f = frac(lambda);
      sample_1d_linear( tObj, tObj->Image[level  ], s, t0 );
      sample_1d_linear( tObj, tObj->Image[level+1], s, t1 );
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
      rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
      rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
      rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
   }
}



static void sample_nearest_1d( const struct gl_texture_object *tObj, GLuint n,
                               const GLfloat s[], const GLfloat t[],
                               const GLfloat u[], const GLfloat lambda[],
                               GLubyte rgba[][4] )
{
   GLuint i;
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
   (void) t;
   (void) u;
   (void) lambda;
   for (i=0;i<n;i++) {
      sample_1d_nearest( tObj, image, s[i], rgba[i] );
   }
}



static void sample_linear_1d( const struct gl_texture_object *tObj, GLuint n,
                              const GLfloat s[], const GLfloat t[],
                              const GLfloat u[], const GLfloat lambda[],
                              GLubyte rgba[][4] )
{
   GLuint i;
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
   (void) t;
   (void) u;
   (void) lambda;
   for (i=0;i<n;i++) {
      sample_1d_linear( tObj, image, s[i], rgba[i] );
   }
}


/*
 * Given an (s) texture coordinate and lambda (level of detail) value,
 * return a texture sample.
 *
 */
static void sample_lambda_1d( const struct gl_texture_object *tObj, GLuint n,
                              const GLfloat s[], const GLfloat t[],
                              const GLfloat u[], const GLfloat lambda[],
                              GLubyte rgba[][4] )
{
   GLuint i;

   (void) t;
   (void) u;

   for (i=0;i<n;i++) {
      if (lambda[i] > tObj->MinMagThresh) {
         /* minification */
         switch (tObj->MinFilter) {
            case GL_NEAREST:
               sample_1d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
               break;
            case GL_LINEAR:
               sample_1d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
               break;
            case GL_NEAREST_MIPMAP_NEAREST:
               sample_1d_nearest_mipmap_nearest( tObj, lambda[i], s[i], rgba[i] );
               break;
            case GL_LINEAR_MIPMAP_NEAREST:
               sample_1d_linear_mipmap_nearest( tObj, s[i], lambda[i], rgba[i] );
               break;
            case GL_NEAREST_MIPMAP_LINEAR:
               sample_1d_nearest_mipmap_linear( tObj, s[i], lambda[i], rgba[i] );
               break;
            case GL_LINEAR_MIPMAP_LINEAR:
               sample_1d_linear_mipmap_linear( tObj, s[i], lambda[i], rgba[i] );
               break;
            default:
               gl_problem(NULL, "Bad min filter in sample_1d_texture");
               return;
         }
      }
      else {
         /* magnification */
         switch (tObj->MagFilter) {
            case GL_NEAREST:
               sample_1d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
               break;
            case GL_LINEAR:
               sample_1d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
               break;
            default:
               gl_problem(NULL, "Bad mag filter in sample_1d_texture");
               return;
         }
      }
   }
}




/**********************************************************************/
/*                    2-D Texture Sampling Functions                  */
/**********************************************************************/


/*
 * Given a texture image and an (i,j) integer texel coordinate, return the
 * texel color.
 */
static void get_2d_texel( const struct gl_texture_object *tObj,
                          const struct gl_texture_image *img, GLint i, GLint j,
                          GLubyte rgba[4] )
{
   GLint width = img->Width;    /* includes border */
   GLubyte *texel;

#ifdef DEBUG
   GLint height = img->Height;  /* includes border */
   if (i<0 || i>=width)  abort();
   if (j<0 || j>=height)  abort();
#endif

   switch (img->Format) {
      case GL_COLOR_INDEX:
         {
            GLubyte index = img->Data[ width *j + i ];
            palette_sample(tObj, index, rgba );
            return;
         }
      case GL_ALPHA:
         rgba[ACOMP] = img->Data[ width * j + i ];
         return;
      case GL_LUMINANCE:
      case GL_INTENSITY:
         rgba[RCOMP] = img->Data[ width * j + i ];
         return;
      case GL_LUMINANCE_ALPHA:
         texel = img->Data + (width * j + i) * 2;
         rgba[RCOMP] = texel[0];
         rgba[ACOMP] = texel[1];
         return;
      case GL_RGB:
         texel = img->Data + (width * j + i) * 3;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         return;
      case GL_RGBA:
         texel = img->Data + (width * j + i) * 4;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         rgba[ACOMP] = texel[3];
         return;
      default:
         gl_problem(NULL, "Bad format in get_2d_texel");
   }
}



/*
 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
 */
static void sample_2d_nearest( const struct gl_texture_object *tObj,
                               const struct gl_texture_image *img,
                               GLfloat s, GLfloat t,
                               GLubyte rgba[] )
{
   GLint imgWidth = img->Width;  /* includes border */
   GLint width = img->Width2;    /* without border, power of two */
   GLint height = img->Height2;  /* without border, power of two */
   GLint i, j;
   GLubyte *texel;

   /* Clamp/Repeat S and convert to integer texel coordinate */
   if (tObj->WrapS==GL_REPEAT) {
      /* s limited to [0,1) */
      /* i limited to [0,width-1] */
      i = (GLint) (s * width);
      if (s<0.0F)  i -= 1;
      i &= (width-1);
   }
   else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
      GLfloat min = 1.0F / (2.0F * width);
      GLfloat max = 1.0F - min;
      if (s < min)
         i = 0;
      else if (s > max)
         i = width-1;
      else
         i = (GLint) (s * width);
   }
   else {
      ASSERT(tObj->WrapS==GL_CLAMP);
      /* s limited to [0,1] */
      /* i limited to [0,width-1] */
      if (s<=0.0F)      i = 0;
      else if (s>=1.0F) i = width-1;
      else              i = (GLint) (s * width);
   }

   /* Clamp/Repeat T and convert to integer texel coordinate */
   if (tObj->WrapT==GL_REPEAT) {
      /* t limited to [0,1) */
      /* j limited to [0,height-1] */
      j = (GLint) (t * height);
      if (t<0.0F)  j -= 1;
      j &= (height-1);
   }
   else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
      GLfloat min = 1.0F / (2.0F * height);
      GLfloat max = 1.0F - min;
      if (t < min)
         j = 0;
      else if (t > max)
         j = height-1;
      else
         j = (GLint) (t * height);
   }
   else {
      ASSERT(tObj->WrapT==GL_CLAMP);
      /* t limited to [0,1] */
      /* j limited to [0,height-1] */
      if (t<=0.0F)      j = 0;
      else if (t>=1.0F) j = height-1;
      else              j = (GLint) (t * height);
   }

   /* skip over the border, if any */
   i += img->Border;
   j += img->Border;

   switch (img->Format) {
      case GL_COLOR_INDEX:
         {
            GLubyte index = img->Data[ j * imgWidth + i ];
            palette_sample(tObj, index, rgba);
            return;
         }
      case GL_ALPHA:
         rgba[ACOMP] = img->Data[ j * imgWidth + i ];
         return;
      case GL_LUMINANCE:
      case GL_INTENSITY:
         rgba[RCOMP] = img->Data[ j * imgWidth + i ];
         return;
      case GL_LUMINANCE_ALPHA:
         texel = img->Data + ((j * imgWidth + i) << 1);
         rgba[RCOMP] = texel[0];
         rgba[ACOMP] = texel[1];
         return;
      case GL_RGB:
         texel = img->Data + (j * imgWidth + i) * 3;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         return;
      case GL_RGBA:
         texel = img->Data + ((j * imgWidth + i) << 2);
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         rgba[ACOMP] = texel[3];
         return;
      default:
         gl_problem(NULL, "Bad format in sample_2d_nearest");
   }
}



/*
 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
 * New sampling code contributed by Lynn Quam <quam@@ai.sri.com>.
 */
static void sample_2d_linear( const struct gl_texture_object *tObj,
                              const struct gl_texture_image *img,
                              GLfloat s, GLfloat t,
                              GLubyte rgba[] )
{
   GLint width = img->Width2;
   GLint height = img->Height2;
   GLint i0, j0, i1, j1;
   GLint i0border = 0;
   GLint i1border = 0;
   GLint j0border = 0;
   GLint j1border = 0;
   GLfloat u, v;

   if (tObj->WrapS==GL_REPEAT) {
      u = s * width - 0.5F;
      i0 = ((GLint) floor(u)) & (width - 1);
      i1 = i0 + 1;
      if (i1 >= width)
         i1 = 0;
   }
   else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
      u = s * width - 0.5F;
      i0 = (GLint) floor(u);
      i1 = i0 + 1;
      if (i0 < 0)
         i0 = 0;
      else if (i0 >= width)
         i0 = width - 1;
      if (i1 < 0)
         i1 = 0;
      else if (i1 >= width)
         i1 = width - 1;
   }
   else {
      ASSERT(tObj->WrapS==GL_CLAMP);
      if (s < 0.0)
         s = 0.0;
      else if (s > 1.0)
         s = 1.0;
      u = s * width - 0.5F;
      i0 = (GLint) floor(u);
      i1 = i0 + 1;
      i0border = (i0<0) | (i0>=width);
      i1border = (i1<0) | (i1>=width);
   }

   if (tObj->WrapT==GL_REPEAT) {
      v = t * height - 0.5F;
      j0 = ((GLint) floor(v)) & (height - 1);
      j1 = (j0 + 1);
      if (j1 >= height)
         j1 = 0;
   }
   else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
      v = t * height - 0.5F;
      j0 = (GLint) floor(v);
      j1 = j0 + 1;
      if (j0 < 0)
         j0 = 0;
      else if (j0 >= height)
         j0 = height-1;
      if (j1 < 0)
         j1 = 0;
      else if (j1 >= height)
         j1 = height-1;
   }
   else {
      ASSERT(tObj->WrapT==GL_CLAMP);
      if (t < 0.0)
         t = 0.0;
      else if (t > 1.0)
         t = 1.0;
      v = t * height - 0.5F;
      j0 = (GLint) floor(v);
      j1 = j0 + 1;
      j0border = (j0<0) | (j0>=height);
      j1border = (j1<0) | (j1>=height);
   }

   if (img->Border) {
      i0 += img->Border;
      i1 += img->Border;
      j0 += img->Border;
      j1 += img->Border;
      if (tObj->WrapS != GL_CLAMP)
         i0border = i1border = 0;
      if (tObj->WrapT != GL_CLAMP)
         j0border = j1border = 0;
   }

   {
      GLfloat a = frac(u);
      GLfloat b = frac(v);

      GLint w00 = (GLint) ((1.0F-a)*(1.0F-b) * 256.0F);
      GLint w10 = (GLint) (      a *(1.0F-b) * 256.0F);
      GLint w01 = (GLint) ((1.0F-a)*      b  * 256.0F);
      GLint w11 = (GLint) (      a *      b  * 256.0F);

      GLubyte t00[4];
      GLubyte t10[4];
      GLubyte t01[4];
      GLubyte t11[4];

      if (i0border | j0border) {
         t00[RCOMP] = tObj->BorderColor[0];
         t00[GCOMP] = tObj->BorderColor[1];
         t00[BCOMP] = tObj->BorderColor[2];
         t00[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_2d_texel( tObj, img, i0, j0, t00 );
      }
      if (i1border | j0border) {
         t10[RCOMP] = tObj->BorderColor[0];
         t10[GCOMP] = tObj->BorderColor[1];
         t10[BCOMP] = tObj->BorderColor[2];
         t10[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_2d_texel( tObj, img, i1, j0, t10 );
      }
      if (i0border | j1border) {
         t01[RCOMP] = tObj->BorderColor[0];
         t01[GCOMP] = tObj->BorderColor[1];
         t01[BCOMP] = tObj->BorderColor[2];
         t01[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_2d_texel( tObj, img, i0, j1, t01 );
      }
      if (i1border | j1border) {
         t11[RCOMP] = tObj->BorderColor[0];
         t11[GCOMP] = tObj->BorderColor[1];
         t11[BCOMP] = tObj->BorderColor[2];
         t11[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_2d_texel( tObj, img, i1, j1, t11 );
      }

      rgba[0] = (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]) >> 8;
      rgba[1] = (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]) >> 8;
      rgba[2] = (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]) >> 8;
      rgba[3] = (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]) >> 8;
   }
}



static void
sample_2d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
                                  GLfloat s, GLfloat t, GLfloat lambda,
                                  GLubyte rgba[4] )
{
   GLint level;
   if (lambda <= 0.5F)
      lambda = 0.0F;
   else if (lambda > tObj->M + 0.4999F)
      lambda = tObj->M + 0.4999F;
   level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
   if (level > tObj->P)
      level = tObj->P;

   sample_2d_nearest( tObj, tObj->Image[level], s, t, rgba );
}



static void
sample_2d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
                                 GLfloat s, GLfloat t, GLfloat lambda,
                                 GLubyte rgba[4] )
{
   GLint level;
   if (lambda <= 0.5F)
      lambda = 0.0F;
   else if (lambda > tObj->M + 0.4999F)
      lambda = tObj->M + 0.4999F;
   level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
   if (level > tObj->P)
      level = tObj->P;

   sample_2d_linear( tObj, tObj->Image[level], s, t, rgba );
}



static void
sample_2d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
                                 GLfloat s, GLfloat t, GLfloat lambda,
                                 GLubyte rgba[4] )
{
   GLint level;
   if (lambda < 0.0F)
      lambda = 0.0F;
   else if (lambda > tObj->M)
      lambda = tObj->M;
   level = (GLint) (tObj->BaseLevel + lambda);

   if (level >= tObj->P) {
      sample_2d_nearest( tObj, tObj->Image[tObj->P], s, t, rgba );
   }
   else {
      GLubyte t0[4], t1[4];  /* texels */
      GLfloat f = frac(lambda);
      sample_2d_nearest( tObj, tObj->Image[level  ], s, t, t0 );
      sample_2d_nearest( tObj, tObj->Image[level+1], s, t, t1 );
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
      rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
      rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
      rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
   }
}



static void
sample_2d_linear_mipmap_linear( const struct gl_texture_object *tObj,
                                GLfloat s, GLfloat t, GLfloat lambda,
                                GLubyte rgba[4] )
{
   GLint level;
   if (lambda < 0.0F)
      lambda = 0.0F;
   else if (lambda > tObj->M)
      lambda = tObj->M;
   level = (GLint) (tObj->BaseLevel + lambda);

   if (level >= tObj->P) {
      sample_2d_linear( tObj, tObj->Image[tObj->P], s, t, rgba );
   }
   else {
      GLubyte t0[4], t1[4];  /* texels */
      GLfloat f = frac(lambda);
      sample_2d_linear( tObj, tObj->Image[level  ], s, t, t0 );
      sample_2d_linear( tObj, tObj->Image[level+1], s, t, t1 );
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
      rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
      rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
      rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
   }
}



static void sample_nearest_2d( const struct gl_texture_object *tObj, GLuint n,
                               const GLfloat s[], const GLfloat t[],
                               const GLfloat u[], const GLfloat lambda[],
                               GLubyte rgba[][4] )
{
   GLuint i;
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
   (void) u;
   (void) lambda;
   for (i=0;i<n;i++) {
      sample_2d_nearest( tObj, image, s[i], t[i], rgba[i] );
   }
}



static void sample_linear_2d( const struct gl_texture_object *tObj, GLuint n,
                              const GLfloat s[], const GLfloat t[],
                              const GLfloat u[], const GLfloat lambda[],
                              GLubyte rgba[][4] )
{
   GLuint i;
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
   (void) u;
   (void) lambda;
   for (i=0;i<n;i++) {
      sample_2d_linear( tObj, image, s[i], t[i], rgba[i] );
   }
}


/*
 * Given an (s,t) texture coordinate and lambda (level of detail) value,
 * return a texture sample.
 */
static void sample_lambda_2d( const struct gl_texture_object *tObj,
                              GLuint n,
                              const GLfloat s[], const GLfloat t[],
                              const GLfloat u[], const GLfloat lambda[],
                              GLubyte rgba[][4] )
{
   GLuint i;
   (void) u;
   for (i=0;i<n;i++) {
      if (lambda[i] > tObj->MinMagThresh) {
         /* minification */
         switch (tObj->MinFilter) {
            case GL_NEAREST:
               sample_2d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
               break;
            case GL_LINEAR:
               sample_2d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
               break;
            case GL_NEAREST_MIPMAP_NEAREST:
               sample_2d_nearest_mipmap_nearest( tObj, s[i], t[i], lambda[i], rgba[i] );
               break;
            case GL_LINEAR_MIPMAP_NEAREST:
               sample_2d_linear_mipmap_nearest( tObj, s[i], t[i], lambda[i], rgba[i] );
               break;
            case GL_NEAREST_MIPMAP_LINEAR:
               sample_2d_nearest_mipmap_linear( tObj, s[i], t[i], lambda[i], rgba[i] );
               break;
            case GL_LINEAR_MIPMAP_LINEAR:
               sample_2d_linear_mipmap_linear( tObj, s[i], t[i], lambda[i], rgba[i] );
               break;
            default:
               gl_problem(NULL, "Bad min filter in sample_2d_texture");
               return;
         }
      }
      else {
         /* magnification */
         switch (tObj->MagFilter) {
            case GL_NEAREST:
               sample_2d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
               break;
            case GL_LINEAR:
               sample_2d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
               break;
            default:
               gl_problem(NULL, "Bad mag filter in sample_2d_texture");
         }
      }
   }
}


/*
 * Optimized 2-D texture sampling:
 *    S and T wrap mode == GL_REPEAT
 *    GL_NEAREST min/mag filter
 *    No border
 *    Format = GL_RGB
 */
static void opt_sample_rgb_2d( const struct gl_texture_object *tObj,
                               GLuint n, const GLfloat s[], const GLfloat t[],
                               const GLfloat u[], const GLfloat lambda[],
                               GLubyte rgba[][4] )
{
   const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
   const GLfloat width = img->Width, height = img->Height;
   const GLint colMask = width-1, rowMask = height-1;
   const GLint shift = img->WidthLog2;
   GLuint k;
   (void) u;
   (void) lambda;
   ASSERT(tObj->WrapS==GL_REPEAT);
   ASSERT(tObj->WrapT==GL_REPEAT);
   ASSERT(tObj->MinFilter==GL_NEAREST);
   ASSERT(tObj->MagFilter==GL_NEAREST);
   ASSERT(img->Border==0);
   ASSERT(img->Format==GL_RGB);

   /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
   for (k=0;k<n;k++) {
      GLint i = (GLint) ((s[k] + 10000.0) * width) & colMask;
      GLint j = (GLint) ((t[k] + 10000.0) * height) & rowMask;
      GLint pos = (j << shift) | i;
      GLubyte *texel = img->Data + pos + pos + pos;  /* pos*3 */
      rgba[k][RCOMP] = texel[0];
      rgba[k][GCOMP] = texel[1];
      rgba[k][BCOMP] = texel[2];
   }
}


/*
 * Optimized 2-D texture sampling:
 *    S and T wrap mode == GL_REPEAT
 *    GL_NEAREST min/mag filter
 *    No border
 *    Format = GL_RGBA
 */
static void opt_sample_rgba_2d( const struct gl_texture_object *tObj,
                                GLuint n, const GLfloat s[], const GLfloat t[],
                                const GLfloat u[], const GLfloat lambda[],
                                GLubyte rgba[][4] )
{
   const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
   const GLfloat width = img->Width, height = img->Height;
   const GLint colMask = width-1, rowMask = height-1;
   const GLint shift = img->WidthLog2;
   GLuint k;
   (void) u;
   (void) lambda;
   ASSERT(tObj->WrapS==GL_REPEAT);
   ASSERT(tObj->WrapT==GL_REPEAT);
   ASSERT(tObj->MinFilter==GL_NEAREST);
   ASSERT(tObj->MagFilter==GL_NEAREST);
   ASSERT(img->Border==0);
   ASSERT(img->Format==GL_RGBA);

   /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
   for (k=0;k<n;k++) {
      GLint i = (GLint) ((s[k] + 10000.0) * width) & colMask;
      GLint j = (GLint) ((t[k] + 10000.0) * height) & rowMask;
      GLint pos = (j << shift) | i;
      GLubyte *texel = img->Data + (pos << 2);    /* pos*4 */
      rgba[k][RCOMP] = texel[0];
      rgba[k][GCOMP] = texel[1];
      rgba[k][BCOMP] = texel[2];
      rgba[k][ACOMP] = texel[3];
   }
}



/**********************************************************************/
/*                    3-D Texture Sampling Functions                  */
/**********************************************************************/

/*
 * Given a texture image and an (i,j,k) integer texel coordinate, return the
 * texel color.
 */
static void get_3d_texel( const struct gl_texture_object *tObj,
                          const struct gl_texture_image *img,
                          GLint i, GLint j, GLint k,
                          GLubyte rgba[4] )
{
   GLint width = img->Width;    /* includes border */
   GLint height = img->Height;  /* includes border */
   GLint depth = img->Depth;    /* includes border */
   GLint rectarea;              /* = width * heigth */
   GLubyte *texel;

   rectarea = width*height;

#ifdef DEBUG
   if (i<0 || i>=width)  abort();
   if (j<0 || j>=height)  abort();
   if (k<0 || k>=depth)  abort();
#else
   (void) depth;
#endif

   switch (img->Format) {
      case GL_COLOR_INDEX:
         {
            GLubyte index = img->Data[ rectarea * k +  width * j + i ];
            palette_sample(tObj, index, rgba );
            return;
         }
      case GL_ALPHA:
         rgba[ACOMP] = img->Data[ rectarea * k +  width * j + i ];
         return;
      case GL_LUMINANCE:
      case GL_INTENSITY:
         rgba[RCOMP] = img->Data[ rectarea * k +  width * j + i ];
         return;
      case GL_LUMINANCE_ALPHA:
         texel = img->Data + ( rectarea * k + width * j + i) * 2;
         rgba[RCOMP] = texel[0];
         rgba[ACOMP] = texel[1];
         return;
      case GL_RGB:
         texel = img->Data + (rectarea * k + width * j + i) * 3;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         return;
      case GL_RGBA:
         texel = img->Data + (rectarea * k + width * j + i) * 4;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         rgba[ACOMP] = texel[3];
         return;
      default:
         gl_problem(NULL, "Bad format in get_3d_texel");
   }
}


/*
 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
 */
static void sample_3d_nearest( const struct gl_texture_object *tObj,
                               const struct gl_texture_image *img,
                               GLfloat s, GLfloat t, GLfloat r,
                               GLubyte rgba[4] )
{
   GLint imgWidth = img->Width;   /* includes border, if any */
   GLint imgHeight = img->Height; /* includes border, if any */
   GLint width = img->Width2;     /* without border, power of two */
   GLint height = img->Height2;   /* without border, power of two */
   GLint depth = img->Depth2;     /* without border, power of two */
   GLint rectarea;                /* = width * height */
   GLint i, j, k;
   GLubyte *texel;

   rectarea = imgWidth * imgHeight;

   /* Clamp/Repeat S and convert to integer texel coordinate */
   if (tObj->WrapS==GL_REPEAT) {
      /* s limited to [0,1) */
      /* i limited to [0,width-1] */
      i = (GLint) (s * width);
      if (s<0.0F)  i -= 1;
      i &= (width-1);
   }
   else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
      GLfloat min = 1.0F / (2.0F * width);
      GLfloat max = 1.0F - min;
      if (s < min)
         i = 0;
      else if (s > max)
         i = width-1;
      else
         i = (GLint) (s * width);
   }
   else {
      ASSERT(tObj->WrapS==GL_CLAMP);
      /* s limited to [0,1] */
      /* i limited to [0,width-1] */
      if (s<=0.0F)      i = 0;
      else if (s>=1.0F) i = width-1;
      else              i = (GLint) (s * width);
   }

   /* Clamp/Repeat T and convert to integer texel coordinate */
   if (tObj->WrapT==GL_REPEAT) {
      /* t limited to [0,1) */
      /* j limited to [0,height-1] */
      j = (GLint) (t * height);
      if (t<0.0F)  j -= 1;
      j &= (height-1);
   }
   else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
      GLfloat min = 1.0F / (2.0F * height);
      GLfloat max = 1.0F - min;
      if (t < min)
         j = 0;
      else if (t > max)
         j = height-1;
      else
         j = (GLint) (t * height);
   }
   else {
      ASSERT(tObj->WrapT==GL_CLAMP);
      /* t limited to [0,1] */
      /* j limited to [0,height-1] */
      if (t<=0.0F)      j = 0;
      else if (t>=1.0F) j = height-1;
      else              j = (GLint) (t * height);
   }

   /* Clamp/Repeat R and convert to integer texel coordinate */
   if (tObj->WrapR==GL_REPEAT) {
      /* r limited to [0,1) */
      /* k limited to [0,depth-1] */
      k = (GLint) (r * depth);
      if (r<0.0F)  k -= 1;
      k &= (depth-1);
   }
   else if (tObj->WrapR==GL_CLAMP_TO_EDGE) {
      GLfloat min = 1.0F / (2.0F * depth);
      GLfloat max = 1.0F - min;
      if (r < min)
         k = 0;
      else if (r > max)
         k = depth-1;
      else
         k = (GLint) (t * depth);
   }
   else {
      ASSERT(tObj->WrapR==GL_CLAMP);
      /* r limited to [0,1] */
      /* k limited to [0,depth-1] */
      if (r<=0.0F)      k = 0;
      else if (r>=1.0F) k = depth-1;
      else              k = (GLint) (r * depth);
   }

   switch (tObj->Image[0]->Format) {
      case GL_COLOR_INDEX:
         {
            GLubyte index = img->Data[ rectarea * k + j * imgWidth + i ];
            palette_sample(tObj, index, rgba );
            return;
         }
      case GL_ALPHA:
         rgba[ACOMP] = img->Data[ rectarea * k + j * imgWidth + i ];
         return;
      case GL_LUMINANCE:
      case GL_INTENSITY:
         rgba[RCOMP] = img->Data[ rectarea * k + j * imgWidth + i ];
         return;
      case GL_LUMINANCE_ALPHA:
         texel = img->Data + ((rectarea * k + j * imgWidth + i) << 1);
         rgba[RCOMP] = texel[0];
         rgba[ACOMP] = texel[1];
         return;
      case GL_RGB:
         texel = img->Data + ( rectarea * k + j * imgWidth + i) * 3;
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         return;
      case GL_RGBA:
         texel = img->Data + ((rectarea * k + j * imgWidth + i) << 2);
         rgba[RCOMP] = texel[0];
         rgba[GCOMP] = texel[1];
         rgba[BCOMP] = texel[2];
         rgba[ACOMP] = texel[3];
         return;
      default:
         gl_problem(NULL, "Bad format in sample_3d_nearest");
   }
}


/*
 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
 */
static void sample_3d_linear( const struct gl_texture_object *tObj,
                              const struct gl_texture_image *img,
                              GLfloat s, GLfloat t, GLfloat r,
                              GLubyte rgba[4] )
{
   GLint width = img->Width2;
   GLint height = img->Height2;
   GLint depth = img->Depth2;
   GLint i0, j0, k0, i1, j1, k1;
   GLint i0border = 0, j0border = 0, k0border = 0;
   GLint i1border = 0, j1border = 0, k1border = 0;
   GLfloat u, v, w;

   if (tObj->WrapS==GL_REPEAT) {
      u = s * width - 0.5F;
      i0 = ((GLint) floor(u)) & (width - 1);
      i1 = i0 + 1;
      if (i1 >= width)
         i1 = 0;
   }
   else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
      u = s * width - 0.5F;
      i0 = (GLint) floor(u);
      i1 = i0 + 1;
      if (i0 < 0)
         i0 = 0;
      else if (i0 >= width)
         i0 = width - 1;
      if (i1 < 0)
         i1 = 0;
      else if (i1 >= width)
         i1 = width - 1;
   }
   else {
      ASSERT(tObj->WrapS==GL_CLAMP);
      if (s < 0.0)
         s = 0.0;
      else if (s > 1.0)
         s = 1.0;
      u = s * width - 0.5F;
      i0 = (GLint) floor(u);
      i1 = i0 + 1;
      i0border = (i0<0) | (i0>=width);
      i1border = (i1<0) | (i1>=width);
   }

   if (tObj->WrapT==GL_REPEAT) {
      v = t * height - 0.5F;
      j0 = ((GLint) floor(v)) & (height - 1);
      j1 = (j0 + 1);
      if (j1 >= height)
         j1 = 0;
   }
   else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
      v = t * height - 0.5F;
      j0 = (GLint) floor(v);
      j1 = j0 + 1;
      if (j0 < 0)
         j0 = 0;
      else if (j0 >= height)
         j0 = height-1;
      if (j1 < 0)
         j1 = 0;
      else if (j1 >= height)
         j1 = height-1;
   }
   else {
      ASSERT(tObj->WrapT==GL_CLAMP);
      if (t < 0.0)
         t = 0.0;
      else if (t > 1.0)
         t = 1.0;
      v = t * height - 0.5F;
      j0 = (GLint) floor(v);
      j1 = j0 + 1;
      j0border = (j0<0) | (j0>=height);
      j1border = (j1<0) | (j1>=height);
   }

   if (tObj->WrapR==GL_REPEAT) {
      w = r * depth - 0.5F;
      k0 = ((GLint) floor(w)) & (depth - 1);
      k1 = (k0 + 1);
      if (k1 >= depth)
         k1 = 0;
   }
   else if (tObj->WrapR==GL_CLAMP_TO_EDGE) {
      w = r * depth - 0.5F;
      k0 = (GLint) floor(w);
      k1 = k0 + 1;
      if (k0 < 0)
         k0 = 0;
      else if (k0 >= depth)
         k0 = depth-1;
      if (k1 < 0)
         k1 = 0;
      else if (k1 >= depth)
         k1 = depth-1;
   }
   else {
      ASSERT(tObj->WrapR==GL_CLAMP);
      if (r < 0.0)
         r = 0.0;
      else if (r > 1.0)
         r = 1.0;
      w = r * depth - 0.5F;
      k0 = (GLint) floor(w);
      k1 = k0 + 1;
      k0border = (k0<0) | (k0>=depth);
      k1border = (k1<0) | (k1>=depth);
   }

   if (img->Border) {
      i0 += img->Border;
      i1 += img->Border;
      j0 += img->Border;
      j1 += img->Border;
      k0 += img->Border;
      k1 += img->Border;
      if (tObj->WrapS != GL_CLAMP)
         i0border = i1border = 0;
      if (tObj->WrapT != GL_CLAMP)
         j0border = j1border = 0;
      if (tObj->WrapR != GL_CLAMP)
         k0border = k1border = 0;
   }
   else {
      i0 &= (width-1);
      j0 &= (height-1);
      k0 &= (depth-1);
   }

   {
      GLfloat a = frac(u);
      GLfloat b = frac(v);
      GLfloat c = frac(w);

      GLint w000 = (GLint) ((1.0F-a)*(1.0F-b) * (1.0F-c) * 256.0F);
      GLint w100 = (GLint) (      a *(1.0F-b) * (1.0F-c) * 256.0F);
      GLint w010 = (GLint) ((1.0F-a)*      b  * (1.0F-c) * 256.0F);
      GLint w110 = (GLint) (      a *      b  * (1.0F-c) * 256.0F);
      GLint w001 = (GLint) ((1.0F-a)*(1.0F-b) * c * 256.0F);
      GLint w101 = (GLint) (      a *(1.0F-b) * c * 256.0F);
      GLint w011 = (GLint) ((1.0F-a)*      b  * c * 256.0F);
      GLint w111 = (GLint) (      a *      b  * c * 256.0F);


      GLubyte t000[4], t010[4], t001[4], t011[4];      /* texels */
      GLubyte t100[4], t110[4], t101[4], t111[4];

      if (k0border | i0border | j0border ) {
         t000[RCOMP] = tObj->BorderColor[0];
         t000[GCOMP] = tObj->BorderColor[1];
         t000[BCOMP] = tObj->BorderColor[2];
         t000[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i0, j0, k0, t000 );
      }
      if (k0border | i1border | j0border) {
         t100[RCOMP] = tObj->BorderColor[0];
         t100[GCOMP] = tObj->BorderColor[1];
         t100[BCOMP] = tObj->BorderColor[2];
         t100[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i1, j0, k0, t100 );
      }
      if (k0border | i0border | j1border) {
         t010[RCOMP] = tObj->BorderColor[0];
         t010[GCOMP] = tObj->BorderColor[1];
         t010[BCOMP] = tObj->BorderColor[2];
         t010[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i0, j1, k0, t010 );
      }
      if (k0border | i1border | j1border) {
         t110[RCOMP] = tObj->BorderColor[0];
         t110[GCOMP] = tObj->BorderColor[1];
         t110[BCOMP] = tObj->BorderColor[2];
         t110[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i1, j1, k0, t110 );
      }

      if (k1border | i0border | j0border ) {
         t001[RCOMP] = tObj->BorderColor[0];
         t001[GCOMP] = tObj->BorderColor[1];
         t001[BCOMP] = tObj->BorderColor[2];
         t001[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i0, j0, k1, t001 );
      }
      if (k1border | i1border | j0border) {
         t101[RCOMP] = tObj->BorderColor[0];
         t101[GCOMP] = tObj->BorderColor[1];
         t101[BCOMP] = tObj->BorderColor[2];
         t101[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i1, j0, k1, t101 );
      }
      if (k1border | i0border | j1border) {
         t011[RCOMP] = tObj->BorderColor[0];
         t011[GCOMP] = tObj->BorderColor[1];
         t011[BCOMP] = tObj->BorderColor[2];
         t011[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i0, j1, k1, t011 );
      }
      if (k1border | i1border | j1border) {
         t111[RCOMP] = tObj->BorderColor[0];
         t111[GCOMP] = tObj->BorderColor[1];
         t111[BCOMP] = tObj->BorderColor[2];
         t111[ACOMP] = tObj->BorderColor[3];
      }
      else {
         get_3d_texel( tObj, img, i1, j1, k1, t111 );
      }

      rgba[0] = (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
                 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0]  )
                >> 8;
      rgba[1] = (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
                 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
                >> 8;
      rgba[2] = (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
                 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
                >> 8;
      rgba[3] = (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
                 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
                >> 8;
   }
}



static void
sample_3d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
                                  GLfloat s, GLfloat t, GLfloat r,
                                  GLfloat lambda, GLubyte rgba[4] )
{
   GLint level;
   if (lambda <= 0.5F)
      lambda = 0.0F;
   else if (lambda > tObj->M + 0.4999F)
      lambda = tObj->M + 0.4999F;
   level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
   if (level > tObj->P)
      level = tObj->P;

   sample_3d_nearest( tObj, tObj->Image[level], s, t, r, rgba );
}


static void
sample_3d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
                                 GLfloat s, GLfloat t, GLfloat r,
                                 GLfloat lambda, GLubyte rgba[4] )
{
   GLint level;
   if (lambda <= 0.5F)
      lambda = 0.0F;
   else if (lambda > tObj->M + 0.4999F)
      lambda = tObj->M + 0.4999F;
   level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
   if (level > tObj->P)
      level = tObj->P;

   sample_3d_linear( tObj, tObj->Image[level], s, t, r, rgba );
}


static void
sample_3d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
                                 GLfloat s, GLfloat t, GLfloat r,
                                 GLfloat lambda, GLubyte rgba[4] )
{
   GLint level;
   if (lambda < 0.0F)
      lambda = 0.0F;
   else if (lambda > tObj->M)
      lambda = tObj->M;
   level = (GLint) (tObj->BaseLevel + lambda);

   if (level >= tObj->P) {
      sample_3d_nearest( tObj, tObj->Image[tObj->P], s, t, r, rgba );
   }
   else {
      GLubyte t0[4], t1[4];  /* texels */
      GLfloat f = frac(lambda);
      sample_3d_nearest( tObj, tObj->Image[level  ], s, t, r, t0 );
      sample_3d_nearest( tObj, tObj->Image[level+1], s, t, r, t1 );
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
      rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
      rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
      rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
   }
}


static void
sample_3d_linear_mipmap_linear( const struct gl_texture_object *tObj,
                                GLfloat s, GLfloat t, GLfloat r,
                                GLfloat lambda, GLubyte rgba[4] )
{
   GLint level;
   if (lambda < 0.0F)
      lambda = 0.0F;
   else if (lambda > tObj->M)
      lambda = tObj->M;
   level = (GLint) (tObj->BaseLevel + lambda);

   if (level >= tObj->P) {
      sample_3d_linear( tObj, tObj->Image[tObj->P], s, t, r, rgba );
   }
   else {
      GLubyte t0[4], t1[4];  /* texels */
      GLfloat f = frac(lambda);
      sample_3d_linear( tObj, tObj->Image[level  ], s, t, r, t0 );
      sample_3d_linear( tObj, tObj->Image[level+1], s, t, r, t1 );
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
      rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
      rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
      rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
   }
}


static void sample_nearest_3d( const struct gl_texture_object *tObj, GLuint n,
                               const GLfloat s[], const GLfloat t[],
                               const GLfloat u[], const GLfloat lambda[],
                               GLubyte rgba[][4] )
{
   GLuint i;
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
   (void) lambda;
   for (i=0;i<n;i++) {
      sample_3d_nearest( tObj, image, s[i], t[i], u[i], rgba[i] );
   }
}



static void sample_linear_3d( const struct gl_texture_object *tObj, GLuint n,
                              const GLfloat s[], const GLfloat t[],
                              const GLfloat u[], const GLfloat lambda[],
                              GLubyte rgba[][4] )
{
   GLuint i;
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
   (void) lambda;
   for (i=0;i<n;i++) {
      sample_3d_linear( tObj, image, s[i], t[i], u[i], rgba[i] );
   }
}


/*
 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
 * return a texture sample.
 */
static void sample_lambda_3d( const struct gl_texture_object *tObj, GLuint n,
                              const GLfloat s[], const GLfloat t[],
                              const GLfloat u[], const GLfloat lambda[],
                              GLubyte rgba[][4] )
{
   GLuint i;

   for (i=0;i<n;i++) {

      if (lambda[i] > tObj->MinMagThresh) {
         /* minification */
         switch (tObj->MinFilter) {
            case GL_NEAREST:
               sample_3d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
               break;
            case GL_LINEAR:
               sample_3d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
               break;
            case GL_NEAREST_MIPMAP_NEAREST:
               sample_3d_nearest_mipmap_nearest( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
               break;
            case GL_LINEAR_MIPMAP_NEAREST:
               sample_3d_linear_mipmap_nearest( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
               break;
            case GL_NEAREST_MIPMAP_LINEAR:
               sample_3d_nearest_mipmap_linear( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
               break;
            case GL_LINEAR_MIPMAP_LINEAR:
               sample_3d_linear_mipmap_linear( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
               break;
            default:
               gl_problem(NULL, "Bad min filterin sample_3d_texture");
         }
      }
      else {
         /* magnification */
         switch (tObj->MagFilter) {
            case GL_NEAREST:
               sample_3d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
               break;
            case GL_LINEAR:
               sample_3d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
               break;
            default:
               gl_problem(NULL, "Bad mag filter in sample_3d_texture");
         }
      }
   }
}



/**********************************************************************/
/*                       Texture Sampling Setup                       */
/**********************************************************************/


/*
 * Setup the texture sampling function for this texture object.
 */
void gl_set_texture_sampler( struct gl_texture_object *t )
{
   if (!t->Complete) {
      t->SampleFunc = NULL;
   }
   else {
      GLboolean needLambda = (t->MinFilter != t->MagFilter);

      if (needLambda) {
         /* Compute min/mag filter threshold */
         if (t->MagFilter==GL_LINEAR
             && (t->MinFilter==GL_NEAREST_MIPMAP_NEAREST ||
                 t->MinFilter==GL_LINEAR_MIPMAP_NEAREST)) {
            t->MinMagThresh = 0.5F;
         }
         else {
            t->MinMagThresh = 0.0F;
         }
      }

      switch (t->Dimensions) {
         case 1:
            if (needLambda) {
               t->SampleFunc = sample_lambda_1d;
            }
            else if (t->MinFilter==GL_LINEAR) {
               t->SampleFunc = sample_linear_1d;
            }
            else {
               ASSERT(t->MinFilter==GL_NEAREST);
               t->SampleFunc = sample_nearest_1d;
            }
            break;
         case 2:
            if (needLambda) {
               t->SampleFunc = sample_lambda_2d;
            }
            else if (t->MinFilter==GL_LINEAR) {
               t->SampleFunc = sample_linear_2d;
            }
            else {
               ASSERT(t->MinFilter==GL_NEAREST);
               if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
                   && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGB) {
                  t->SampleFunc = opt_sample_rgb_2d;
               }
               else if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
                   && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGBA) {
                  t->SampleFunc = opt_sample_rgba_2d;
               }
               else
                  t->SampleFunc = sample_nearest_2d;
            }
            break;
         case 3:
            if (needLambda) {
               t->SampleFunc = sample_lambda_3d;
            }
            else if (t->MinFilter==GL_LINEAR) {
               t->SampleFunc = sample_linear_3d;
            }
            else {
               ASSERT(t->MinFilter==GL_NEAREST);
               t->SampleFunc = sample_nearest_3d;
            }
            break;
         default:
            gl_problem(NULL, "invalid dimensions in gl_set_texture_sampler");
      }
   }
}



/**********************************************************************/
/*                      Texture Application                           */
/**********************************************************************/


/*
 * Combine incoming fragment color with texel color to produce output color.
 * Input:  textureUnit - pointer to texture unit to apply
 *         format - base internal texture format
 *         n - number of fragments
 *         texels - array of texel colors
 * InOut:  rgba - incoming fragment colors modified by texel colors
 *                according to the texture environment mode.
 */
static void apply_texture( const GLcontext *ctx,
                           const struct gl_texture_unit *texUnit,
                           GLuint n,
                           GLubyte rgba[][4], CONST GLubyte texel[][4] )
{
   GLuint i;
   GLint Rc, Gc, Bc, Ac;
   GLenum format;

   ASSERT(texUnit);
   ASSERT(texUnit->Current);
   ASSERT(texUnit->Current->Image[0]);

   format = texUnit->Current->Image[0]->Format;

/*
 * Use (A*(B+1)) >> 8 as a fast approximation of (A*B)/255 for A
 * and B in [0,255]
 */
#define PROD(A,B)   (((GLint)(A) * ((GLint)(B)+1)) >> 8)

   if (format==GL_COLOR_INDEX) {
      format = GL_RGBA;  /* XXXX a hack! */
   }

   switch (texUnit->EnvMode) {
      case GL_REPLACE:
	 switch (format) {
	    case GL_ALPHA:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf */
                  /* Av = At */
                  rgba[i][ACOMP] = texel[i][ACOMP];
	       }
	       break;
	    case GL_LUMINANCE:
	       for (i=0;i<n;i++) {
		  /* Cv = Lt */
                  GLint Lt = texel[i][RCOMP];
                  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
                  /* Av = Af */
	       }
	       break;
	    case GL_LUMINANCE_ALPHA:
	       for (i=0;i<n;i++) {
                  GLint Lt = texel[i][RCOMP];
		  /* Cv = Lt */
		  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
		  /* Av = At */
		  rgba[i][ACOMP] = texel[i][ACOMP];
	       }
	       break;
	    case GL_INTENSITY:
	       for (i=0;i<n;i++) {
		  /* Cv = It */
                  GLint It = texel[i][RCOMP];
                  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
                  /* Av = It */
                  rgba[i][ACOMP] = It;
	       }
	       break;
	    case GL_RGB:
	       for (i=0;i<n;i++) {
		  /* Cv = Ct */
		  rgba[i][RCOMP] = texel[i][RCOMP];
		  rgba[i][GCOMP] = texel[i][GCOMP];
		  rgba[i][BCOMP] = texel[i][BCOMP];
		  /* Av = Af */
	       }
	       break;
	    case GL_RGBA:
	       for (i=0;i<n;i++) {
		  /* Cv = Ct */
		  rgba[i][RCOMP] = texel[i][RCOMP];
		  rgba[i][GCOMP] = texel[i][GCOMP];
		  rgba[i][BCOMP] = texel[i][BCOMP];
		  /* Av = At */
		  rgba[i][ACOMP] = texel[i][ACOMP];
	       }
	       break;
            default:
               gl_problem(ctx, "Bad format in apply_texture");
               return;
	 }
	 break;

      case GL_MODULATE:
         switch (format) {
	    case GL_ALPHA:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf */
		  /* Av = AfAt */
		  rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
	       }
	       break;
	    case GL_LUMINANCE:
	       for (i=0;i<n;i++) {
		  /* Cv = LtCf */
                  GLint Lt = texel[i][RCOMP];
		  rgba[i][RCOMP] = PROD( rgba[i][RCOMP], Lt );
		  rgba[i][GCOMP] = PROD( rgba[i][GCOMP], Lt );
		  rgba[i][BCOMP] = PROD( rgba[i][BCOMP], Lt );
		  /* Av = Af */
	       }
	       break;
	    case GL_LUMINANCE_ALPHA:
	       for (i=0;i<n;i++) {
		  /* Cv = CfLt */
                  GLint Lt = texel[i][RCOMP];
		  rgba[i][RCOMP] = PROD( rgba[i][RCOMP], Lt );
		  rgba[i][GCOMP] = PROD( rgba[i][GCOMP], Lt );
		  rgba[i][BCOMP] = PROD( rgba[i][BCOMP], Lt );
		  /* Av = AfAt */
		  rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
	       }
	       break;
	    case GL_INTENSITY:
	       for (i=0;i<n;i++) {
		  /* Cv = CfIt */
                  GLint It = texel[i][RCOMP];
		  rgba[i][RCOMP] = PROD( rgba[i][RCOMP], It );
		  rgba[i][GCOMP] = PROD( rgba[i][GCOMP], It );
		  rgba[i][BCOMP] = PROD( rgba[i][BCOMP], It );
		  /* Av = AfIt */
		  rgba[i][ACOMP] = PROD( rgba[i][ACOMP], It );
	       }
	       break;
	    case GL_RGB:
	       for (i=0;i<n;i++) {
		  /* Cv = CfCt */
		  rgba[i][RCOMP] = PROD( rgba[i][RCOMP], texel[i][RCOMP] );
		  rgba[i][GCOMP] = PROD( rgba[i][GCOMP], texel[i][GCOMP] );
		  rgba[i][BCOMP] = PROD( rgba[i][BCOMP], texel[i][BCOMP] );
		  /* Av = Af */
	       }
	       break;
	    case GL_RGBA:
	       for (i=0;i<n;i++) {
		  /* Cv = CfCt */
		  rgba[i][RCOMP] = PROD( rgba[i][RCOMP], texel[i][RCOMP] );
		  rgba[i][GCOMP] = PROD( rgba[i][GCOMP], texel[i][GCOMP] );
		  rgba[i][BCOMP] = PROD( rgba[i][BCOMP], texel[i][BCOMP] );
		  /* Av = AfAt */
		  rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
	       }
	       break;
            default:
               gl_problem(ctx, "Bad format (2) in apply_texture");
               return;
	 }
	 break;

      case GL_DECAL:
         switch (format) {
            case GL_ALPHA:
            case GL_LUMINANCE:
            case GL_LUMINANCE_ALPHA:
            case GL_INTENSITY:
               /* undefined */
               break;
	    case GL_RGB:
	       for (i=0;i<n;i++) {
		  /* Cv = Ct */
		  rgba[i][RCOMP] = texel[i][RCOMP];
		  rgba[i][GCOMP] = texel[i][GCOMP];
		  rgba[i][BCOMP] = texel[i][BCOMP];
		  /* Av = Af */
	       }
	       break;
	    case GL_RGBA:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf(1-At) + CtAt */
		  GLint t = texel[i][ACOMP], s = 255 - t;
		  rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(texel[i][RCOMP],t);
		  rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(texel[i][GCOMP],t);
		  rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(texel[i][BCOMP],t);
		  /* Av = Af */
	       }
	       break;
            default:
               gl_problem(ctx, "Bad format (3) in apply_texture");
               return;
	 }
	 break;

      case GL_BLEND:
         Rc = (GLint) (texUnit->EnvColor[0] * 255.0F);
         Gc = (GLint) (texUnit->EnvColor[1] * 255.0F);
         Bc = (GLint) (texUnit->EnvColor[2] * 255.0F);
         Ac = (GLint) (texUnit->EnvColor[3] * 255.0F);
	 switch (format) {
	    case GL_ALPHA:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf */
		  /* Av = AfAt */
                  rgba[i][ACOMP] = PROD(rgba[i][ACOMP], texel[i][ACOMP]);
	       }
	       break;
            case GL_LUMINANCE:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf(1-Lt) + CcLt */
		  GLint Lt = texel[i][RCOMP], s = 255 - Lt;
		  rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, Lt);
		  rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, Lt);
		  rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, Lt);
		  /* Av = Af */
	       }
	       break;
	    case GL_LUMINANCE_ALPHA:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf(1-Lt) + CcLt */
		  GLint Lt = texel[i][RCOMP], s = 255 - Lt;
		  rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, Lt);
		  rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, Lt);
		  rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, Lt);
		  /* Av = AfAt */
		  rgba[i][ACOMP] = PROD(rgba[i][ACOMP],texel[i][ACOMP]);
	       }
	       break;
            case GL_INTENSITY:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf(1-It) + CcLt */
		  GLint It = texel[i][RCOMP], s = 255 - It;
		  rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, It);
		  rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, It);
		  rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, It);
                  /* Av = Af(1-It) + Ac*It */
                  rgba[i][ACOMP] = PROD(rgba[i][ACOMP], s) + PROD(Ac, It);
               }
               break;
	    case GL_RGB:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf(1-Ct) + CcCt */
		  rgba[i][RCOMP] = PROD(rgba[i][RCOMP], (255-texel[i][RCOMP])) + PROD(Rc,texel[i][RCOMP]);
		  rgba[i][GCOMP] = PROD(rgba[i][GCOMP], (255-texel[i][GCOMP])) + PROD(Gc,texel[i][GCOMP]);
		  rgba[i][BCOMP] = PROD(rgba[i][BCOMP], (255-texel[i][BCOMP])) + PROD(Bc,texel[i][BCOMP]);
		  /* Av = Af */
	       }
	       break;
	    case GL_RGBA:
	       for (i=0;i<n;i++) {
		  /* Cv = Cf(1-Ct) + CcCt */
		  rgba[i][RCOMP] = PROD(rgba[i][RCOMP], (255-texel[i][RCOMP])) + PROD(Rc,texel[i][RCOMP]);
		  rgba[i][GCOMP] = PROD(rgba[i][GCOMP], (255-texel[i][GCOMP])) + PROD(Gc,texel[i][GCOMP]);
		  rgba[i][BCOMP] = PROD(rgba[i][BCOMP], (255-texel[i][BCOMP])) + PROD(Bc,texel[i][BCOMP]);
		  /* Av = AfAt */
		  rgba[i][ACOMP] = PROD(rgba[i][ACOMP],texel[i][ACOMP]);
	       }
	       break;
            default:
               gl_problem(ctx, "Bad format (4) in apply_texture");
               return;
	 }
	 break;

      default:
         gl_problem(ctx, "Bad env mode in apply_texture");
         return;
   }
#undef PROD
}



/*
 * Apply a unit of texture mapping to the incoming fragments.
 */
void gl_texture_pixels( GLcontext *ctx, GLuint texUnit, GLuint n,
                        const GLfloat s[], const GLfloat t[],
                        const GLfloat r[], GLfloat lambda[],
                        GLubyte rgba[][4] )
{
   GLuint mask = (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D) << (texUnit * 4);
   if (ctx->Texture.Enabled & mask) {
      const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
      if (textureUnit->Current && textureUnit->Current->SampleFunc) {

         GLubyte texel[PB_SIZE][4];

         if (textureUnit->Current->MinLod != -1000.0
             || textureUnit->Current->MaxLod != 1000.0) {
            /* apply LOD clamping to lambda */
            GLfloat min = textureUnit->Current->MinLod;
            GLfloat max = textureUnit->Current->MaxLod;
            GLuint i;
            for (i=0;i<n;i++) {
               GLfloat l = lambda[i];
               lambda[i] = CLAMP(l, min, max);
            }
         }

         /* Sample the texture. */
         (*textureUnit->Current->SampleFunc)( textureUnit->Current, n,
                                             s, t, r, lambda, texel );

         apply_texture( ctx, textureUnit, n, 
			rgba, (const GLubyte (*)[4])texel );
      }
   }
}
@


3.30
log
@texUnit->GenFlags was never disabled (epajarre@@koti.tpo.fi)
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.29 1999/07/12 12:05:25 keithw Exp $ */
d47 4
a64 10
/*
 * Perform automatic texture coordinate generation.
 * Input:  ctx - the context
 *         n - number of texture coordinates to generate
 *         obj - array of vertexes in object coordinate system
 *         objStride - stride (in floats) between object coords (usually 4)
 *         eye - array of vertexes in eye coordinate system
 *         normal - array of normal vectores in eye coordinate system
 * Output:  texcoord - array of resuling texture coordinates
 */
a81 1

d124 6
d131 4
d143 6
@


3.29
log
@merge from experimental branch upto merge-1 tag
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.28.2.2 1999/06/06 22:35:55 keithw Exp $ */
a159 1

d187 3
a189 2
   if (texUnit->TexGenEnabled) 
   {
a190 1
      texUnit->GenFlags = 0;
d192 16
a207 4
      if (texUnit->TexGenEnabled&S_BIT) sz=1, texUnit->GenFlags|=texUnit->GenBitS;
      if (texUnit->TexGenEnabled&T_BIT) sz=2, texUnit->GenFlags|=texUnit->GenBitT;
      if (texUnit->TexGenEnabled&Q_BIT) sz=3, texUnit->GenFlags|=texUnit->GenBitQ;
      if (texUnit->TexGenEnabled&R_BIT) sz=4, texUnit->GenFlags|=texUnit->GenBitR;
d213 2
a214 4
      if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) 
      {
	 if (texUnit->GenFlags == TEXGEN_REFLECTION_MAP_NV)
	 {
d217 1
a217 2
	 else if (texUnit->GenFlags == TEXGEN_NORMAL_MAP_NV)
	 {
d222 1
a222 2
	       texUnit->GenFlags == TEXGEN_SPHERE_MAP)
      {
@


3.28
log
@fixed problems with GL_CLAMP and GL_LINEAR filtering
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.27 1999/05/06 16:53:59 brianp Exp $ */
a141 2
   GLuint sz = 0;

a142 1
   texUnit->GenFlags = 0;
d144 1
a144 1
   if ((texUnit->Enabled & TEXTURE0_3D) && texUnit->Current3D->Complete) {
d146 2
a147 1
      texUnit->Current = texUnit->Current3D;
d149 1
a149 1
   else if ((texUnit->Enabled & TEXTURE0_2D) && texUnit->Current2D->Complete) {
d151 2
a152 1
      texUnit->Current = texUnit->Current2D;
d154 1
a154 1
   else if ((texUnit->Enabled & TEXTURE0_1D) && texUnit->Current1D->Complete) {
d156 2
a157 1
      texUnit->Current = texUnit->Current1D;
d165 1
a165 1
		    texUnit->Current3D->Name);
d169 1
a169 1
		    texUnit->Current2D->Name);
d173 1
a173 1
		    texUnit->Current1D->Name);
d184 1
d188 9
a196 4
   if (texUnit->TexGenEnabled&S_BIT) sz=1, texUnit->GenFlags|=texUnit->GenBitS;
   if (texUnit->TexGenEnabled&T_BIT) sz=2, texUnit->GenFlags|=texUnit->GenBitT;
   if (texUnit->TexGenEnabled&Q_BIT) sz=3, texUnit->GenFlags|=texUnit->GenBitQ;
   if (texUnit->TexGenEnabled&R_BIT) sz=4, texUnit->GenFlags|=texUnit->GenBitR;
d198 3
a200 3
   texUnit->TexgenSize = sz;
   texUnit->Holes = (all_bits[sz] & ~texUnit->TexGenEnabled);
   texUnit->func = texgen_generic_tab;
d202 1
a202 3
   if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) 
   {
      if (texUnit->GenFlags == TEXGEN_REFLECTION_MAP_NV)
d204 8
a211 1
	 texUnit->func = texgen_reflection_map_nv_tab;
d213 2
a214 1
      else if (texUnit->GenFlags == TEXGEN_NORMAL_MAP_NV)
d216 1
a216 1
	 texUnit->func = texgen_normal_map_nv_tab;
a218 5
   else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) && 
	    texUnit->GenFlags == TEXGEN_SPHERE_MAP)
   {
      texUnit->func = texgen_sphere_map_tab;
   }
a222 1

d2310 2
a2311 1
         apply_texture( ctx, textureUnit, n, rgba, texel );
@


3.28.2.1
log
@Quake3 inspired optimizations
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.28 1999/05/17 21:24:32 brianp Exp $ */
d142 2
d145 1
d187 4
a190 9
   if (texUnit->TexGenEnabled) 
   {
      GLuint sz = 0;
      texUnit->GenFlags = 0;

      if (texUnit->TexGenEnabled&S_BIT) sz=1, texUnit->GenFlags|=texUnit->GenBitS;
      if (texUnit->TexGenEnabled&T_BIT) sz=2, texUnit->GenFlags|=texUnit->GenBitT;
      if (texUnit->TexGenEnabled&Q_BIT) sz=3, texUnit->GenFlags|=texUnit->GenBitQ;
      if (texUnit->TexGenEnabled&R_BIT) sz=4, texUnit->GenFlags|=texUnit->GenBitR;
d192 3
a194 3
      texUnit->TexgenSize = sz;
      texUnit->Holes = (all_bits[sz] & ~texUnit->TexGenEnabled);
      texUnit->func = texgen_generic_tab;
d196 3
a198 1
      if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) 
d200 1
a200 8
	 if (texUnit->GenFlags == TEXGEN_REFLECTION_MAP_NV)
	 {
	    texUnit->func = texgen_reflection_map_nv_tab;
	 }
	 else if (texUnit->GenFlags == TEXGEN_NORMAL_MAP_NV)
	 {
	    texUnit->func = texgen_normal_map_nv_tab;
	 }
d202 1
a202 2
      else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) && 
	       texUnit->GenFlags == TEXGEN_SPHERE_MAP)
d204 1
a204 1
	 texUnit->func = texgen_sphere_map_tab;
d207 5
d216 1
d2304 1
a2304 2
         apply_texture( ctx, textureUnit, n, 
			rgba, (const GLubyte (*)[4])texel );
@


3.28.2.2
log
@some trial assembly, made newer code active by default
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.28.2.1 1999/05/21 21:29:27 keithw Exp $ */
d144 1
a144 1
   if ((texUnit->Enabled & TEXTURE0_3D) && texUnit->CurrentD[3]->Complete) {
d146 1
a146 2
      texUnit->Current = texUnit->CurrentD[3];
      texUnit->CurrentDimension = 3;
d148 1
a148 1
   else if ((texUnit->Enabled & TEXTURE0_2D) && texUnit->CurrentD[2]->Complete) {
d150 1
a150 2
      texUnit->Current = texUnit->CurrentD[2];
      texUnit->CurrentDimension = 2;
d152 1
a152 1
   else if ((texUnit->Enabled & TEXTURE0_1D) && texUnit->CurrentD[1]->Complete) {
d154 1
a154 2
      texUnit->Current = texUnit->CurrentD[1];
      texUnit->CurrentDimension = 1;
d162 1
a162 1
		    texUnit->CurrentD[3]->Name);
d166 1
a166 1
		    texUnit->CurrentD[2]->Name);
d170 1
a170 1
		    texUnit->CurrentD[1]->Name);
a180 1
      texUnit->CurrentDimension = 0;
@


3.27
log
@minor printf changes
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.26 1999/05/02 00:59:24 keithw Exp $ */
d427 1
a427 1
   GLint i0border, i1border;
a428 1
   u = s * width;
d430 5
a434 3
      i0 = ((GLint) floor(u - 0.5F)) & (width - 1);
      i1 = (i0 + 1) & (width-1);
      i0border = i1border = 0;
d437 4
a440 3
      GLfloat min = 1.0F / (2.0F * width);
      GLfloat max = 1.0F - min;
      if (s < min)
d442 5
a446 6
      else if (s > max)
         i0 = width-1;
      else
         i0 = (GLint) (u - 0.5F);
      i1 = i0 + 1;
      if (i1 >= width)
a447 1
      i0border = i1border = 0;
d451 6
a456 3
      if (u < 0.0F)  u = 0.0F;
      else if (u > width)  u = width;
      i0 = (GLint) floor(u - 0.5F);
d473 1
a473 1
      GLfloat a = frac(u - 0.5F);
a886 1
   u = s * width - 0.5f;
d888 1
d890 1
a890 1
      i1 = (i0 + 1);
d895 1
d898 1
a898 1
      if (i0<0)
d900 3
a902 4
      else if
         (i0>=width)
         i0 = width-1;
      if (i1<0)
d904 2
a905 2
      else if (i1>=width)
         i1 = width-1;
d909 5
a919 1
   v = t * height - 0.5f;
d921 1
d924 2
a925 1
      if (j1 >= height) j1 = 0;
d928 1
d931 1
a931 1
      if (j0<0)
d933 1
a933 1
      else if (j0>=height)
d935 1
a935 1
      if (j1<0)
d937 1
a937 1
      else if (j1>=height)
d942 5
d1210 1
d1228 2
d1233 1
d1235 2
a1236 2
      GLint i = (GLint) (s[k] * width) & colMask;
      GLint j = (GLint) (t[k] * height) & rowMask;
d1249 1
a1264 1

d1267 2
d1272 1
d1274 2
a1275 2
      GLint i = (GLint) (s[k] * width) & colMask;
      GLint j = (GLint) (t[k] * height) & rowMask;
a1507 1
   u = s * width - 0.5f;
d1509 1
d1511 1
a1511 1
      i1 = (i0 + 1);
d1516 1
d1519 1
a1519 1
      if (i0<0)
d1521 3
a1523 4
      else if
         (i0>=width)
         i0 = width-1;
      if (i1<0)
d1525 2
a1526 2
      else if (i1>=width)
         i1 = width-1;
d1530 5
a1540 1
   v = t * height - 0.5f;
d1542 1
d1545 2
a1546 1
      if (j1 >= height) j1 = 0;
d1549 1
d1552 1
a1552 1
      if (j0<0)
d1554 1
a1554 1
      else if (j0>=height)
d1556 1
a1556 1
      if (j1<0)
d1558 1
a1558 1
      else if (j1>=height)
d1563 5
a1573 1
   w = r * depth - 0.5F;
d1575 1
d1582 1
d1585 1
a1585 1
      if (k0<0)
d1587 1
a1587 2
      else if
         (k0>=depth)
d1589 1
a1589 1
      if (k1<0)
d1591 1
a1591 1
      else if (k1>=depth)
d1596 5
@


3.26
log
@FX polygon offset and debugging changes
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.25 1999/04/21 13:01:01 brianp Exp $ */
d164 1
a164 1
	    fprintf(stderr, "Using incomplete 3d texture %d\n",
d168 1
a168 1
	    fprintf(stderr, "Using incomplete 2d texture %d\n",
d172 1
a172 1
	    fprintf(stderr, "Using incomplete 1d texture %d\n",
@


3.25
log
@fixed float/int confusion in sample_2d_linear()
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.24 1999/04/18 15:45:49 keithw Exp $ */
d33 1
d160 22
@


3.24
log
@texture state bug fix
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.23 1999/04/03 16:23:40 brianp Exp $ */
a472 1
      /* MMX */
d977 4
a980 7
      /* XXX this mix of floating point and integer math probably isn't
       * too efficient.
       */
      rgba[0] = (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0] + 0.002);
      rgba[1] = (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1] + 0.002);
      rgba[2] = (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2] + 0.002);
      rgba[3] = (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3] + 0.001);
a1656 1
      /* MMX */
@


3.23
log
@change in border handling for GL_CLAMP mode
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.22 1999/03/31 20:18:40 keithw Exp $ */
d146 2
a147 2
   if (texUnit->Enabled & TEXTURE0_3D && texUnit->Current3D->Complete) {
      texUnit->ReallyEnabled |= TEXTURE0_3D;
d150 2
a151 2
   else if (texUnit->Enabled & TEXTURE0_2D && texUnit->Current2D->Complete) {
      texUnit->ReallyEnabled |= TEXTURE0_2D;
d154 2
a155 2
   else if (texUnit->Enabled & TEXTURE0_1D && texUnit->Current1D->Complete) {
      texUnit->ReallyEnabled |= TEXTURE0_1D;
d159 1
@


3.22
log
@Compiled vertex arrays
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.21 1999/03/20 18:58:12 brianp Exp $ */
d438 2
a439 1
      i0border = i1border = 0;
d920 4
a923 2
      i0border = i1border = 0;
      j0border = j1border = 0;
d1555 6
a1560 3
      i0border = i1border = 0;
      j0border = j1border = 0;
      k0border = k1border = 0;
@


3.21
log
@fixed IRIX compiler warnings
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.20 1999/03/20 02:56:31 brianp Exp $ */
d142 1
d144 1
d146 16
a161 1
   texUnit->GenFlags = 0;
d189 1
@


3.20
log
@fixed border color bugs in sample_3d_linear()
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.19 1999/02/27 17:46:56 brianp Exp $ */
d131 1
a131 1
void gl_init_texture()
d142 2
@


3.19
log
@fixed bugs in sample_3d_linear()
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.18 1999/02/25 14:12:32 keithw Exp $ */
d1570 4
a1573 4
         t010[RCOMP] = tObj->BorderColor[0];
         t010[GCOMP] = tObj->BorderColor[1];
         t010[BCOMP] = tObj->BorderColor[2];
         t010[ACOMP] = tObj->BorderColor[3];
d1579 4
a1582 4
         t001[RCOMP] = tObj->BorderColor[0];
         t001[GCOMP] = tObj->BorderColor[1];
         t001[BCOMP] = tObj->BorderColor[2];
         t001[ACOMP] = tObj->BorderColor[3];
d1588 4
a1591 4
         t011[RCOMP] = tObj->BorderColor[0];
         t011[GCOMP] = tObj->BorderColor[1];
         t011[BCOMP] = tObj->BorderColor[2];
         t011[ACOMP] = tObj->BorderColor[3];
d1598 4
a1601 4
         t100[RCOMP] = tObj->BorderColor[0];
         t100[GCOMP] = tObj->BorderColor[1];
         t100[BCOMP] = tObj->BorderColor[2];
         t100[ACOMP] = tObj->BorderColor[3];
d1607 4
a1610 4
         t110[RCOMP] = tObj->BorderColor[0];
         t110[GCOMP] = tObj->BorderColor[1];
         t110[BCOMP] = tObj->BorderColor[2];
         t110[ACOMP] = tObj->BorderColor[3];
d1616 4
a1619 4
         t101[RCOMP] = tObj->BorderColor[0];
         t101[GCOMP] = tObj->BorderColor[1];
         t101[BCOMP] = tObj->BorderColor[2];
         t101[ACOMP] = tObj->BorderColor[3];
d1649 1
@


3.18
log
@Merged in kw3 patch
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.17 1999/02/24 22:48:07 jens Exp $ */
d1439 2
a1440 1
   GLint i0border, j0border, k0border, i1border, j1border, k1border;
d1443 1
a1443 1
   u = s * width;
d1445 4
a1448 3
      i0 = ((GLint) floor(u - 0.5F)) & (width - 1);
      i1 = (i0 + 1) & (width-1);
      i0border = i1border = 0;
d1451 3
a1453 3
      GLfloat min = 1.0F / (2.0F * width);
      GLfloat max = 1.0F - min;
      if (s < min)
d1455 2
a1456 1
      else if (s > max)
d1458 4
a1461 6
      else
         i0 = (GLint) (u - 0.5F);
      i1 = i0 + 1;
      if (i1 >= width)
         i1 = width - 1;
      i0border = i1border = 0;
d1465 1
a1465 3
      if (u < 0.0F)  u = 0.0F;
      else if (u > width)  u = width;
      i0 = (GLint) floor(u - 0.5F);
d1471 1
a1471 1
   v = t * height;
d1473 3
a1475 3
      j0 = ((GLint) floor(v - 0.5F)) & (height - 1);
      j1 = (j0 + 1) & (height-1);
      j0border = j1border = 0;
d1478 3
a1480 3
      GLfloat min = 1.0F / (2.0F * height);
      GLfloat max = 1.0F - min;
      if (t < min)
d1482 1
a1482 1
      else if (t > max)
d1484 4
a1487 6
      else
         j0 = (GLint) (v - 0.5F);
      j1 = j0 + 1;
      if (j1 >= height)
         j1 = height - 1;
      j0border = j1border = 0;
d1491 1
a1491 3
      if (v < 0.0F)  v = 0.0F;
      else if (v > height)  v = height;
      j0 = (GLint) floor(v - 0.5F);
d1497 1
a1497 1
   w = r * depth;
d1499 4
a1502 3
      k0 = ((GLint) floor(w - 0.5F)) & (depth - 1);
      k1 = (k0 + 1) & (depth-1);
      k0border = k1border = 0;
d1505 3
a1507 3
      GLfloat min = 1.0F / (2.0F * depth);
      GLfloat max = 1.0F - min;
      if (r < min)
d1509 2
a1510 1
      else if (r > max)
d1512 4
a1515 6
      else
         k0 = (GLint) (w - 0.5F);
      k1 = k0 + 1;
      if (k1 >= depth)
         k1 = depth - 1;
      k0border = k1border = 0;
d1519 1
a1519 3
      if (r < 0.0F)  r = 0.0F;
      else if (r > depth)  r = depth;
      k0 = (GLint) floor(r - 0.5F);
d1543 3
a1545 3
      GLfloat a = frac(u - 0.5F);
      GLfloat b = frac(v - 0.5F);
      GLfloat c = frac(w - 0.5F);
d1548 6
a1553 6
      GLint w010 = (GLint) (      a *(1.0F-b) * (1.0F-c) * 256.0F);
      GLint w001 = (GLint) ((1.0F-a)*      b  * (1.0F-c) * 256.0F);
      GLint w011 = (GLint) (      a *      b  * (1.0F-c) * 256.0F);
      GLint w100 = (GLint) ((1.0F-a)*(1.0F-b) * c * 256.0F);
      GLint w110 = (GLint) (      a *(1.0F-b) * c * 256.0F);
      GLint w101 = (GLint) ((1.0F-a)*      b  * c * 256.0F);
d1576 1
a1576 1
         get_3d_texel( tObj, img, i1, j0, k0, t010 );
d1585 1
a1585 1
         get_3d_texel( tObj, img, i0, j1, k0, t001 );
d1594 1
a1594 1
         get_3d_texel( tObj, img, i1, j1, k0, t011 );
d1604 1
a1604 1
         get_3d_texel( tObj, img, i0, j0, k1, t100 );
d1613 1
a1613 1
         get_3d_texel( tObj, img, i1, j0, k1, t110 );
d1622 1
a1622 1
         get_3d_texel( tObj, img, i0, j1, k1, t101 );
@


3.17
log
@Added header file to get XMesa to compile standalone and inside XFree86
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.16 1999/02/14 03:46:34 brianp Exp $ */
a27 56
/*
 * $Log: texture.c,v $
 * Revision 3.16  1999/02/14 03:46:34  brianp
 * new copyright
 *
 * Revision 3.15  1999/01/19 02:14:08  brianp
 * fixed some typos in texture sampling code
 *
 * Revision 3.14  1999/01/16 16:50:05  brianp
 * new sample_2d_linear() code (Lynn Quam  quam@@ai.sri.com)
 *
 * Revision 3.13  1998/11/29 21:49:10  brianp
 * gl_texgen() now takes objStride
 *
 * Revision 3.12  1998/11/19 03:07:36  brianp
 * use floating point math in sample_2d_linear()
 *
 * Revision 3.11  1998/11/17 01:52:47  brianp
 * implemented GL_NV_texgen_reflection extension (MJK)
 *
 * Revision 3.10  1998/11/08 22:34:07  brianp
 * renamed texture sets to texture units
 *
 * Revision 3.9  1998/10/23 00:36:38  brianp
 * fixed GL_CLAMP_TO_EDGE texture sample bug (Petri Nordlund)
 *
 * Revision 3.8  1998/06/11 02:04:41  brianp
 * fixed texture clamp problem when coord==1 (bad sampling)
 *
 * Revision 3.7  1998/03/28 03:58:16  brianp
 * added CONST macro to fix IRIX compilation problems
 *
 * Revision 3.6  1998/03/27 04:26:44  brianp
 * fixed G++ warnings
 *
 * Revision 3.5  1998/03/15 18:12:37  brianp
 * fixed sampling bug when filter=NEAREST and wrap=CLAMP
 *
 * Revision 3.4  1998/03/01 20:19:26  brianp
 * fixed a few sampling functions to prevent access of missing mipmap levels
 *
 * Revision 3.3  1998/02/20 04:53:37  brianp
 * implemented GL_SGIS_multitexture
 *
 * Revision 3.2  1998/02/03 04:27:54  brianp
 * added texture lod clamping
 *
 * Revision 3.1  1998/02/01 19:39:09  brianp
 * added GL_CLAMP_TO_EDGE texture wrap mode
 *
 * Revision 3.0  1998/01/31 21:04:38  brianp
 * initial rev
 *
 */


d39 1
d46 13
a69 7
void gl_texgen( GLcontext *ctx, GLint n,
                const GLfloat *obj, GLuint objStride,
		CONST GLfloat eye[][4],
                CONST GLfloat normal[][3], GLfloat texcoord[][4],
                GLuint textureUnit)
{
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[textureUnit];
d71 58
a128 26
   /* special case: S and T sphere mapping */
   if (texUnit->TexGenEnabled==(S_BIT|T_BIT)
       && texUnit->GenModeS==GL_SPHERE_MAP
       && texUnit->GenModeT==GL_SPHERE_MAP) {
      GLint i;
      for (i=0;i<n;i++) {
         GLfloat u[3], two_nu, m, fx, fy, fz;
         COPY_3V( u, eye[i] );
         NORMALIZE_3FV( u );
         two_nu = 2.0F * DOT3(normal[i],u);
         fx = u[0] - normal[i][0] * two_nu;
         fy = u[1] - normal[i][1] * two_nu;
         fz = u[2] - normal[i][2] * two_nu;
         m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0F)*(fz+1.0F) );
         if (m==0.0F) {
            texcoord[i][0] = 0.5F;
            texcoord[i][1] = 0.5F;
         }
         else {
            GLfloat mInv = 1.0F / m;
            texcoord[i][0] = fx * mInv + 0.5F;
            texcoord[i][1] = fy * mInv + 0.5F;
         }
      }
      return;
   }
a129 30
   if (texUnit->TexGenEnabled==(S_BIT|T_BIT|R_BIT)) {
      /* special case: S, T, and R reflection mapping */
      if (texUnit->GenModeS==GL_REFLECTION_MAP_NV
          && texUnit->GenModeT==GL_REFLECTION_MAP_NV
          && texUnit->GenModeR==GL_REFLECTION_MAP_NV) {
         GLint i;
         for (i=0;i<n;i++) {
            GLfloat u[3], two_nu;
            COPY_3V( u, eye[i] );
            NORMALIZE_3FV( u );
            two_nu = 2.0F * DOT3(normal[i],u);
            texcoord[i][0] = u[0] - normal[i][0] * two_nu;
            texcoord[i][1] = u[1] - normal[i][1] * two_nu;
            texcoord[i][2] = u[2] - normal[i][2] * two_nu;
         }
         return;
      }
      /* special case: S, T, and R normal mapping */
      if (texUnit->GenModeS==GL_NORMAL_MAP_NV
          && texUnit->GenModeT==GL_NORMAL_MAP_NV
          && texUnit->GenModeR==GL_NORMAL_MAP_NV) {
         GLint i;
         for (i=0;i<n;i++) {
            texcoord[i][0] = normal[i][0];
            texcoord[i][1] = normal[i][1];
            texcoord[i][2] = normal[i][2];
         }
         return;
      }
   }
d131 7
a137 54
   /* general solution */
   if (texUnit->TexGenEnabled & S_BIT) {
      GLint i;
      switch (texUnit->GenModeS) {
         case GL_OBJECT_LINEAR:
            {
               const GLfloat *objPtr = obj;
               for (i=0;i<n;i++, objPtr += objStride) {
                  texcoord[i][0] = DOT4( objPtr, texUnit->ObjectPlaneS );
               }
            }
            break;
         case GL_EYE_LINEAR:
            for (i=0;i<n;i++) {
               texcoord[i][0] = DOT4( eye[i], texUnit->EyePlaneS );
            }
            break;
         case GL_SPHERE_MAP:
            for (i=0;i<n;i++) {
               GLfloat u[3], two_nu, m, fx, fy, fz;
               COPY_3V( u, eye[i] );
               NORMALIZE_3FV( u );
               two_nu = 2.0*DOT3(normal[i],u);
               fx = u[0] - normal[i][0] * two_nu;
               fy = u[1] - normal[i][1] * two_nu;
               fz = u[2] - normal[i][2] * two_nu;
               m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
               if (m==0.0F) {
                  texcoord[i][0] = 0.5F;
               }
               else {
                  texcoord[i][0] = fx / m + 0.5F;
               }
            }
            break;
         case GL_REFLECTION_MAP_NV:
            for (i=0;i<n;i++) {
               GLfloat u[3], two_nu;
               COPY_3V( u, eye[i] );
               NORMALIZE_3FV( u );
               two_nu = 2.0*DOT3(normal[i],u);
               texcoord[i][0] = u[0] - normal[i][0] * two_nu;
            }
            break;
         case GL_NORMAL_MAP_NV:
            for (i=0;i<n;i++) {
               texcoord[i][0] = normal[i][0];
            }
            break;
         default:
            gl_problem(ctx, "Bad S texgen");
            return;
      }
   }
d139 4
a142 53
   if (texUnit->TexGenEnabled & T_BIT) {
      GLint i;
      switch (texUnit->GenModeT) {
         case GL_OBJECT_LINEAR:
            {
               const GLfloat *objPtr = obj;
               for (i=0;i<n;i++, objPtr += objStride) {
                  texcoord[i][1] = DOT4( objPtr, texUnit->ObjectPlaneT );
               }
            }
            break;
         case GL_EYE_LINEAR:
            for (i=0;i<n;i++) {
               texcoord[i][1] = DOT4( eye[i], texUnit->EyePlaneT );
            }
            break;
         case GL_SPHERE_MAP:
            for (i=0;i<n;i++) {
               GLfloat u[3], two_nu, m, fx, fy, fz;
               COPY_3V( u, eye[i] );
               NORMALIZE_3FV( u );
               two_nu = 2.0*DOT3(normal[i],u);
               fx = u[0] - normal[i][0] * two_nu;
               fy = u[1] - normal[i][1] * two_nu;
               fz = u[2] - normal[i][2] * two_nu;
               m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
               if (m==0.0F) {
                  texcoord[i][1] = 0.5F;
               }
               else {
                  texcoord[i][1] = fy / m + 0.5F;
               }
            }
            break;
         case GL_REFLECTION_MAP_NV:
            for (i=0;i<n;i++) {
               GLfloat u[3], two_nu;
               COPY_3V( u, eye[i] );
               NORMALIZE_3FV( u );
               two_nu = 2.0*DOT3(normal[i],u);
               texcoord[i][1] = u[1] - normal[i][1] * two_nu;
            }
            break;
         case GL_NORMAL_MAP_NV:
            for (i=0;i<n;i++) {
               texcoord[i][1] = normal[i][1];
            }
            break;
         default:
            gl_problem(ctx, "Bad T texgen");
            return;
      }
   }
d144 18
a161 33
   if (texUnit->TexGenEnabled & R_BIT) {
      GLint i;
      switch (texUnit->GenModeR) {
         case GL_OBJECT_LINEAR:
            {
               const GLfloat *objPtr = obj;
               for (i=0;i<n;i++, objPtr += objStride) {
                  texcoord[i][2] = DOT4( objPtr, texUnit->ObjectPlaneR );
               }
            }
            break;
         case GL_EYE_LINEAR:
            for (i=0;i<n;i++) {
               texcoord[i][2] = DOT4( eye[i], texUnit->EyePlaneR );
            }
            break;
         case GL_REFLECTION_MAP_NV:
            for (i=0;i<n;i++) {
               GLfloat u[3], two_nu;
               COPY_3V( u, eye[i] );
               NORMALIZE_3FV( u );
               two_nu = 2.0*DOT3(normal[i],u);
               texcoord[i][2] = u[1] - normal[i][2] * two_nu;
            }
            break;
         case GL_NORMAL_MAP_NV:
            for (i=0;i<n;i++) {
               texcoord[i][2] = normal[i][2];
            }
            break;
         default:
            gl_problem(ctx, "Bad R texgen");
            return;
d164 4
a167 21

   if (texUnit->TexGenEnabled & Q_BIT) {
      GLint i;
      switch (texUnit->GenModeQ) {
         case GL_OBJECT_LINEAR:
            {
               const GLfloat *objPtr = obj;
               for (i=0;i<n;i++, objPtr += objStride) {
                  texcoord[i][3] = DOT4( objPtr, texUnit->ObjectPlaneQ );
               }
            }
            break;
         case GL_EYE_LINEAR:
            for (i=0;i<n;i++) {
               texcoord[i][3] = DOT4( eye[i], texUnit->EyePlaneQ );
            }
            break;
         default:
            gl_problem(ctx, "Bad Q texgen");
            return;
      }
@


3.16
log
@new copyright
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.15 1999/01/19 02:14:08 brianp Exp brianp $ */
d30 3
d95 3
@


3.15
log
@fixed some typos in texture sampling code
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.14 1999/01/16 16:50:05 brianp Exp brianp $ */
d6 19
a24 15
 * Copyright (C) 1995-1999  Brian Paul
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
d30 3
@


3.14
log
@new sample_2d_linear() code (Lynn Quam  quam@@ai.sri.com)
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.13 1998/11/29 21:49:10 brianp Exp brianp $ */
d26 3
d517 1
a517 1
         rgba[RCOMP] = texel[1];
d523 1
a523 1
         rgba[RCOMP] = texel[1];
d680 1
a680 1
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
d709 1
a709 1
      rgba[RCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
@


3.13
log
@gl_texgen() now takes objStride
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.12 1998/11/19 03:07:36 brianp Exp $ */
d6 1
a6 1
 * Copyright (C) 1995-1998  Brian Paul
d26 3
d546 1
a546 1
      i0 = ((GLint) floor(u - 0.5F)) % width;
d983 1
d993 4
a996 1
   GLint i0border, j0border, i1border, j1border;
d999 1
a999 1
   u = s * width;
d1001 4
a1004 3
      i0 = ((GLint) floor(u - 0.5F)) % width;
      i1 = (i0 + 1) & (width-1);
      i0border = i1border = 0;
d1007 3
a1009 3
      GLfloat min = 1.0F / (2.0F * width);
      GLfloat max = 1.0F - min;
      if (s < min)
d1011 2
a1012 1
      else if (s > max)
d1014 4
a1017 6
      else
         i0 = (GLint) (u - 0.5F);
      i1 = i0 + 1;
      if (i1 >= width)
         i1 = width - 1;
      i0border = i1border = 0;
d1021 1
a1021 3
      if (u < 0.0F)  u = 0.0F;
      else if (u > width)  u = width;
      i0 = (GLint) floor(u - 0.5F);
d1027 1
a1027 1
   v = t * height;
d1029 3
a1031 3
      j0 = ((GLint) floor(v - 0.5F)) % height;
      j1 = (j0 + 1) & (height-1);
      j0border = j1border = 0;
d1034 3
a1036 3
      GLfloat min = 1.0F / (2.0F * height);
      GLfloat max = 1.0F - min;
      if (t < min)
d1038 1
a1038 1
      else if (t > max)
d1040 4
a1043 6
      else
         j0 = (GLint) (v - 0.5F);
      j1 = j0 + 1;
      if (j1 >= height)
         j1 = height - 1;
      j0border = j1border = 0;
d1047 1
a1047 3
      if (v < 0.0F)  v = 0.0F;
      else if (v > height)  v = height;
      j0 = (GLint) floor(v - 0.5F );
a1060 4
   else {
      i0 &= (width-1);
      j0 &= (height-1);
   }
d1063 7
a1069 6
      GLfloat a = frac(u - 0.5F);
      GLfloat b = frac(v - 0.5F);
      GLfloat w00 = (1.0F-a)*(1.0F-b);
      GLfloat w10 =       a *(1.0F-b);
      GLfloat w01 = (1.0F-a)*      b ;
      GLfloat w11 =       a *      b ;
d1603 1
a1603 1
      i0 = ((GLint) floor(u - 0.5F)) % width;
d1633 1
a1633 1
      j0 = ((GLint) floor(v - 0.5F)) % height;
d1663 1
a1663 1
      k0 = ((GLint) floor(w - 0.5F)) % depth;
@


3.12
log
@use floating point math in sample_2d_linear()
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.11 1998/11/17 01:52:47 brianp Exp brianp $ */
d26 3
d88 1
d94 3
a96 2
                GLfloat obj[][4], GLfloat eye[][4],
                GLfloat normal[][3], GLfloat texcoord[][4],
d164 5
a168 2
            for (i=0;i<n;i++) {
               texcoord[i][0] = DOT4( obj[i], texUnit->ObjectPlaneS );
d218 5
a222 2
            for (i=0;i<n;i++) {
               texcoord[i][1] = DOT4( obj[i], texUnit->ObjectPlaneT );
d272 5
a276 2
            for (i=0;i<n;i++) {
               texcoord[i][2] = DOT4( obj[i], texUnit->ObjectPlaneR );
d308 5
a312 2
            for (i=0;i<n;i++) {
               texcoord[i][3] = DOT4( obj[i], texUnit->ObjectPlaneQ );
@


3.11
log
@implemented GL_NV_texgen_reflection extension (MJK)
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.10 1998/11/08 22:34:07 brianp Exp brianp $ */
d26 3
d1051 4
a1054 5

      GLint w00 = (GLint) ((1.0F-a)*(1.0F-b) * 256.0F);
      GLint w10 = (GLint) (      a *(1.0F-b) * 256.0F);
      GLint w01 = (GLint) ((1.0F-a)*      b  * 256.0F);
      GLint w11 = (GLint) (      a *      b  * 256.0F);
d1098 7
a1104 5
      /* MMX */
      rgba[0] = (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]) >> 8;
      rgba[1] = (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]) >> 8;
      rgba[2] = (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]) >> 8;
      rgba[3] = (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]) >> 8;
@


3.10
log
@renamed texture sets to texture units
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.9 1998/10/23 00:36:38 brianp Exp brianp $ */
d26 3
d120 31
d183 14
d234 14
d265 14
@


3.9
log
@fixed GL_CLAMP_TO_EDGE texture sample bug (Petri Nordlund)
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.8 1998/06/11 02:04:41 brianp Exp brianp $ */
d26 3
d86 1
a86 1
                GLuint textureSet)
d88 1
a88 1
   struct gl_texture_set *texSet = &ctx->Texture.Set[textureSet];
d91 3
a93 3
   if (texSet->TexGenEnabled==(S_BIT|T_BIT)
       && texSet->GenModeS==GL_SPHERE_MAP
       && texSet->GenModeT==GL_SPHERE_MAP) {
d118 1
a118 1
   if (texSet->TexGenEnabled & S_BIT) {
d120 1
a120 1
      switch (texSet->GenModeS) {
d123 1
a123 1
               texcoord[i][0] = DOT4( obj[i], texSet->ObjectPlaneS );
d128 1
a128 1
               texcoord[i][0] = DOT4( eye[i], texSet->EyePlaneS );
d155 1
a155 1
   if (texSet->TexGenEnabled & T_BIT) {
d157 1
a157 1
      switch (texSet->GenModeT) {
d160 1
a160 1
               texcoord[i][1] = DOT4( obj[i], texSet->ObjectPlaneT );
d165 1
a165 1
               texcoord[i][1] = DOT4( eye[i], texSet->EyePlaneT );
d192 1
a192 1
   if (texSet->TexGenEnabled & R_BIT) {
d194 1
a194 1
      switch (texSet->GenModeR) {
d197 1
a197 1
               texcoord[i][2] = DOT4( obj[i], texSet->ObjectPlaneR );
d202 1
a202 1
               texcoord[i][2] = DOT4( eye[i], texSet->EyePlaneR );
d211 1
a211 1
   if (texSet->TexGenEnabled & Q_BIT) {
d213 1
a213 1
      switch (texSet->GenModeQ) {
d216 1
a216 1
               texcoord[i][3] = DOT4( obj[i], texSet->ObjectPlaneQ );
d221 1
a221 1
               texcoord[i][3] = DOT4( eye[i], texSet->EyePlaneQ );
d1988 1
a1988 1
 * Input:  textureSet - pointer to texture set/stage to apply
d1996 1
a1996 1
                           const struct gl_texture_set *texSet,
d2004 3
a2006 3
   ASSERT(texSet);
   ASSERT(texSet->Current);
   ASSERT(texSet->Current->Image[0]);
d2008 1
a2008 1
   format = texSet->Current->Image[0]->Format;
d2020 1
a2020 1
   switch (texSet->EnvMode) {
d2181 4
a2184 4
         Rc = (GLint) (texSet->EnvColor[0] * 255.0F);
         Gc = (GLint) (texSet->EnvColor[1] * 255.0F);
         Bc = (GLint) (texSet->EnvColor[2] * 255.0F);
         Ac = (GLint) (texSet->EnvColor[3] * 255.0F);
d2260 1
a2260 1
 * Apply a stage/set of texture mapping to the incoming fragments.
d2262 1
a2262 1
void gl_texture_pixels( GLcontext *ctx, GLuint texSet, GLuint n,
d2267 1
a2267 1
   GLuint mask = (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D) << (texSet * 4);
d2269 2
a2270 2
      const struct gl_texture_set *textureSet = &ctx->Texture.Set[texSet];
      if (textureSet->Current && textureSet->Current->SampleFunc) {
d2274 2
a2275 2
         if (textureSet->Current->MinLod != -1000.0
             || textureSet->Current->MaxLod != 1000.0) {
d2277 2
a2278 2
            GLfloat min = textureSet->Current->MinLod;
            GLfloat max = textureSet->Current->MaxLod;
d2287 1
a2287 1
         (*textureSet->Current->SampleFunc)( textureSet->Current, n,
d2290 1
a2290 1
         apply_texture( ctx, textureSet, n, rgba, texel );
@


3.8
log
@fixed texture clamp problem when coord==1 (bad sampling)
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.7 1998/03/28 03:58:16 brianp Exp brianp $ */
d5 1
a5 1
 * Version:  3.0
d26 3
d456 1
a456 1
         i0 = (GLint) (s * width);
d907 1
a907 1
         i0 = (GLint) (s * width);
d937 1
a937 1
         j0 = (GLint) (t * height);
d1222 3
a1224 3
   GLfloat width = img->Width, height = img->Height;
   GLint colMask = img->Width-1, rowMask = img->Height-1;
   GLint shift = img->WidthLog2;
d1257 3
a1259 3
   GLfloat width = img->Width, height = img->Height;
   GLint colMask = img->Width-1, rowMask = img->Height-1;
   GLint shift = img->WidthLog2;
d1517 1
a1517 1
         i0 = (GLint) (s * width);
d1547 1
a1547 1
         j0 = (GLint) (t * height);
d1577 1
a1577 1
         k0 = (GLint) (r * depth);
@


3.7
log
@added CONST macro to fix IRIX compilation problems
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.6 1998/03/27 04:26:44 brianp Exp brianp $ */
d26 3
d378 2
a379 2
      if (s<0.0F)        i = 0;
      else if (s>1.0F)   i = width-1;
d802 1
a802 1
      else if (s>1.0F)  i = width-1;
d829 1
a829 1
      else if (t>1.0F)  j = height-1;
d1388 2
a1389 2
      if (s<0.0F)       i = 0;
      else if (s>1.0F)  i = width-1;
d1415 2
a1416 2
      if (t<0.0F)       j = 0;
      else if (t>1.0F)  j = height-1;
d1442 2
a1443 2
      if (r<0.0F)       k = 0;
      else if (r>1.0F)  k = depth-1;
@


3.6
log
@fixed G++ warnings
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.5 1998/03/15 18:12:37 brianp Exp brianp $ */
d26 3
a308 1
         return;
d1302 2
d1989 1
a1989 1
                           GLubyte rgba[][4], const GLubyte texel[][4] )
@


3.5
log
@fixed sampling bug when filter=NEAREST and wrap=CLAMP
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.4 1998/03/01 20:19:26 brianp Exp brianp $ */
d26 3
d566 4
a569 4
      rgba[RCOMP] = (1.0F-f) * t0[RCOMP] + f * t1[RCOMP];
      rgba[RCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
      rgba[BCOMP] = (1.0F-f) * t0[BCOMP] + f * t1[BCOMP];
      rgba[ACOMP] = (1.0F-f) * t0[ACOMP] + f * t1[ACOMP];
d595 4
a598 4
      rgba[RCOMP] = (1.0F-f) * t0[RCOMP] + f * t1[RCOMP];
      rgba[RCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
      rgba[BCOMP] = (1.0F-f) * t0[BCOMP] + f * t1[BCOMP];
      rgba[ACOMP] = (1.0F-f) * t0[ACOMP] + f * t1[ACOMP];
d611 3
d628 3
d649 3
d1077 4
a1080 4
      rgba[RCOMP] = (1.0F-f) * t0[RCOMP] + f * t1[RCOMP];
      rgba[GCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
      rgba[BCOMP] = (1.0F-f) * t0[BCOMP] + f * t1[BCOMP];
      rgba[ACOMP] = (1.0F-f) * t0[ACOMP] + f * t1[ACOMP];
d1106 4
a1109 4
      rgba[RCOMP] = (1.0F-f) * t0[RCOMP] + f * t1[RCOMP];
      rgba[GCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
      rgba[BCOMP] = (1.0F-f) * t0[BCOMP] + f * t1[BCOMP];
      rgba[ACOMP] = (1.0F-f) * t0[ACOMP] + f * t1[ACOMP];
d1122 2
d1138 2
d1157 1
d1210 1
a1210 1
                               const GLfloat u[], const GLfloat lamda[],
d1218 2
a1219 1

d1245 1
a1245 1
                                const GLfloat u[], const GLfloat lamda[],
d1253 2
d1765 4
a1768 4
      rgba[RCOMP] = (1.0F-f) * t0[RCOMP] + f * t1[RCOMP];
      rgba[GCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
      rgba[BCOMP] = (1.0F-f) * t0[BCOMP] + f * t1[BCOMP];
      rgba[ACOMP] = (1.0F-f) * t0[ACOMP] + f * t1[ACOMP];
d1793 4
a1796 4
      rgba[RCOMP] = (1.0F-f) * t0[RCOMP] + f * t1[RCOMP];
      rgba[GCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
      rgba[BCOMP] = (1.0F-f) * t0[BCOMP] + f * t1[BCOMP];
      rgba[ACOMP] = (1.0F-f) * t0[ACOMP] + f * t1[ACOMP];
d1808 1
d1823 1
@


3.4
log
@fixed a few sampling functions to prevent access of missing mipmap levels
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.3 1998/02/20 04:53:37 brianp Exp brianp $ */
d26 3
d367 1
d452 3
d781 1
d808 1
d894 3
d924 3
d1358 1
d1385 1
d1412 1
d1494 3
d1524 3
d1554 4
a1557 1
      k0 = (GLint) floor(v - 0.5F);
@


3.3
log
@implemented GL_SGIS_multitexture
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.2 1998/02/03 04:27:54 brianp Exp brianp $ */
d26 3
d510 2
d528 2
d1003 2
d1022 2
d1673 2
d1691 2
@


3.2
log
@added texture lod clamping
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.1 1998/02/01 19:39:09 brianp Exp brianp $ */
d26 3
d64 2
a65 1
                GLfloat normal[][3], GLfloat texcoord[][4] )
d67 2
d70 3
a72 3
   if (ctx->Texture.TexGenEnabled==(S_BIT|T_BIT)
       && ctx->Texture.GenModeS==GL_SPHERE_MAP
       && ctx->Texture.GenModeT==GL_SPHERE_MAP) {
d97 1
a97 1
   if (ctx->Texture.TexGenEnabled & S_BIT) {
d99 1
a99 1
      switch (ctx->Texture.GenModeS) {
d102 1
a102 1
               texcoord[i][0] = DOT4( obj[i], ctx->Texture.ObjectPlaneS );
d107 1
a107 1
               texcoord[i][0] = DOT4( eye[i], ctx->Texture.EyePlaneS );
d134 1
a134 1
   if (ctx->Texture.TexGenEnabled & T_BIT) {
d136 1
a136 1
      switch (ctx->Texture.GenModeT) {
d139 1
a139 1
               texcoord[i][1] = DOT4( obj[i], ctx->Texture.ObjectPlaneT );
d144 1
a144 1
               texcoord[i][1] = DOT4( eye[i], ctx->Texture.EyePlaneT );
d171 1
a171 1
   if (ctx->Texture.TexGenEnabled & R_BIT) {
d173 1
a173 1
      switch (ctx->Texture.GenModeR) {
d176 1
a176 1
               texcoord[i][2] = DOT4( obj[i], ctx->Texture.ObjectPlaneR );
d181 1
a181 1
               texcoord[i][2] = DOT4( eye[i], ctx->Texture.EyePlaneR );
d190 1
a190 1
   if (ctx->Texture.TexGenEnabled & Q_BIT) {
d192 1
a192 1
      switch (ctx->Texture.GenModeQ) {
d195 1
a195 1
               texcoord[i][3] = DOT4( obj[i], ctx->Texture.ObjectPlaneQ );
d200 1
a200 1
               texcoord[i][3] = DOT4( eye[i], ctx->Texture.EyePlaneQ );
d1911 1
a1911 1
 * Input:  n - number of fragments
d1913 1
a1913 1
 *         env_mode - texture environment mode
d1918 3
a1920 2
static void apply_texture( GLcontext *ctx,
                           GLuint n, GLint format, GLenum env_mode,
d1925 7
d1943 1
a1943 1
   switch (env_mode) {
d2104 4
a2107 4
         Rc = (GLint) (ctx->Texture.EnvColor[0] * 255.0F);
         Gc = (GLint) (ctx->Texture.EnvColor[1] * 255.0F);
         Bc = (GLint) (ctx->Texture.EnvColor[2] * 255.0F);
         Ac = (GLint) (ctx->Texture.EnvColor[3] * 255.0F);
d2167 3
d2182 4
a2185 1
void gl_texture_pixels( GLcontext *ctx, GLuint n,
d2190 18
a2207 1
   GLubyte texel[PB_SIZE][4];
d2209 3
a2211 2
   if (!ctx->Texture.Current || !ctx->Texture.Current->SampleFunc)
      return;
d2213 1
a2213 9
   if (ctx->Texture.Current->MinLod != -1000.0
       || ctx->Texture.Current->MaxLod != 1000.0) {
      /* apply LOD clamping to lambda */
      GLfloat min = ctx->Texture.Current->MinLod;
      GLfloat max = ctx->Texture.Current->MaxLod;
      GLuint i;
      for (i=0;i<n;i++) {
         GLfloat l = lambda[i];
         lambda[i] = CLAMP(l, min, max);
a2215 9

   /* Sample the texture. */
   (*ctx->Texture.Current->SampleFunc)( ctx->Texture.Current, n,
                                        s, t, r, lambda, texel );

   apply_texture( ctx, n,
                  ctx->Texture.Current->Image[0]->Format,
                  ctx->Texture.EnvMode,
                  rgba, texel );
@


3.1
log
@added GL_CLAMP_TO_EDGE texture wrap mode
@
text
@d1 1
a1 1
/* $Id: texture.c,v 3.0 1998/01/31 21:04:38 brianp Exp brianp $ */
d26 3
d307 1
a307 1
         rgba[RCOMP] = texel[1];
d313 1
a313 1
         rgba[RCOMP] = texel[1];
d496 6
a501 10
   if (lambda<=0.5F) {
      level = 0;
   }
   else {
      GLint widthlog2 = tObj->Image[0]->WidthLog2;
      level = (GLint) (lambda + 0.499999F);
      if (level>widthlog2 ) {
         level = widthlog2;
      }
   }
d512 6
a517 10
   if (lambda<=0.5F) {
      level = 0;
   }
   else {
      GLint widthlog2 = tObj->Image[0]->WidthLog2;
      level = (GLint) (lambda + 0.499999F);
      if (level>widthlog2 ) {
         level = widthlog2;
      }
   }
d528 6
a533 1
   GLint max = tObj->Image[0]->MaxLog2;
d535 2
a536 2
   if (lambda>=max) {
      sample_1d_nearest( tObj, tObj->Image[max], s, rgba );
d541 2
a542 4
      GLint level = (GLint) (lambda + 1.0F);
      level = CLAMP( level, 1, max );
      sample_1d_nearest( tObj, tObj->Image[level-1], s, t0 );
      sample_1d_nearest( tObj, tObj->Image[level  ], s, t1 );
d557 6
a562 1
   GLint max = tObj->Image[0]->MaxLog2;
d564 2
a565 2
   if (lambda>=max) {
      sample_1d_linear( tObj, tObj->Image[max], s, rgba );
d570 2
a571 4
      GLint level = (GLint) (lambda + 1.0F);
      level = CLAMP( level, 1, max );
      sample_1d_linear( tObj, tObj->Image[level-1], s, t0 );
      sample_1d_linear( tObj, tObj->Image[level  ], s, t1 );
d587 1
d589 1
a589 1
      sample_1d_nearest( tObj, tObj->Image[0], s[i], rgba[i] );
d601 1
d603 1
a603 1
      sample_1d_linear( tObj, tObj->Image[0], s[i], rgba[i] );
d625 1
a625 1
               sample_1d_nearest( tObj, tObj->Image[0], s[i], rgba[i] );
d628 1
a628 1
               sample_1d_linear( tObj, tObj->Image[0], s[i], rgba[i] );
d651 1
a651 1
               sample_1d_nearest( tObj, tObj->Image[0], s[i], rgba[i] );
d654 1
a654 1
               sample_1d_linear( tObj, tObj->Image[0], s[i], rgba[i] );
d711 1
a711 1
         rgba[RCOMP] = texel[1];
d717 1
a717 1
         rgba[RCOMP] = texel[1];
d820 1
a820 1
         rgba[RCOMP] = texel[1];
d826 1
a826 1
         rgba[RCOMP] = texel[1];
d985 6
a990 10
   if (lambda<=0.5F) {
      level = 0;
   }
   else {
      GLint max = tObj->Image[0]->MaxLog2;
      level = (GLint) (lambda + 0.499999F);
      if (level>max) {
         level = max;
      }
   }
d1002 6
a1007 10
   if (lambda<=0.5F) {
      level = 0;
   }
   else {
      GLint max = tObj->Image[0]->MaxLog2;
      level = (GLint) (lambda + 0.499999F);
      if (level>max) {
         level = max;
      }
   }
d1018 6
a1023 1
   GLint max = tObj->Image[0]->MaxLog2;
d1025 2
a1026 2
   if (lambda>=max) {
      sample_2d_nearest( tObj, tObj->Image[max], s, t, rgba );
d1031 2
a1032 4
      GLint level = (GLint) (lambda + 1.0F);
      level = CLAMP( level, 1, max );
      sample_2d_nearest( tObj, tObj->Image[level-1], s, t, t0 );
      sample_2d_nearest( tObj, tObj->Image[level  ], s, t, t1 );
d1034 1
a1034 1
      rgba[RCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
d1047 6
a1052 1
   GLint max = tObj->Image[0]->MaxLog2;
d1054 2
a1055 2
   if (lambda>=max) {
      sample_2d_linear( tObj, tObj->Image[max], s, t, rgba );
d1060 2
a1061 4
      GLint level = (GLint) (lambda + 1.0F);
      level = CLAMP( level, 1, max );
      sample_2d_linear( tObj, tObj->Image[level-1], s, t, t0 );
      sample_2d_linear( tObj, tObj->Image[level  ], s, t, t1 );
d1063 1
a1063 1
      rgba[RCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
d1077 1
d1079 1
a1079 1
      sample_2d_nearest( tObj, tObj->Image[0], s[i], t[i], rgba[i] );
d1091 1
d1093 1
a1093 1
      sample_2d_linear( tObj, tObj->Image[0], s[i], t[i], rgba[i] );
d1114 1
a1114 1
               sample_2d_nearest( tObj, tObj->Image[0], s[i], t[i], rgba[i] );
d1117 1
a1117 1
               sample_2d_linear( tObj, tObj->Image[0], s[i], t[i], rgba[i] );
d1140 1
a1140 1
               sample_2d_nearest( tObj, tObj->Image[0], s[i], t[i], rgba[i] );
d1143 1
a1143 1
               sample_2d_linear( tObj, tObj->Image[0], s[i], t[i], rgba[i] );
d1164 1
a1164 1
   const struct gl_texture_image *img = tObj->Image[0];
d1198 1
a1198 1
   const struct gl_texture_image *img = tObj->Image[0];
d1272 1
a1272 1
         rgba[RCOMP] = texel[1];
d1278 1
a1278 1
         rgba[RCOMP] = texel[1];
d1407 1
a1407 1
         rgba[RCOMP] = texel[1];
d1413 1
a1413 1
         rgba[RCOMP] = texel[1];
d1651 6
a1656 10
   if (lambda<=0.5F) {
      level = 0;
   }
   else {
      GLint widthlog2 = tObj->Image[0]->WidthLog2;
      level = (GLint) (lambda + 0.499999F);
      if (level>widthlog2 ) {
         level = widthlog2;
      }
   }
d1667 6
a1672 10
   if (lambda<=0.5F) {
      level = 0;
   }
   else {
      GLint widthlog2 = tObj->Image[0]->WidthLog2;
      level = (GLint) (lambda + 0.499999F);
      if (level>widthlog2 ) {
         level = widthlog2;
      }
   }
d1682 6
a1687 1
   GLint max = tObj->Image[0]->MaxLog2;
d1689 2
a1690 2
   if (lambda>=max) {
      sample_3d_nearest( tObj, tObj->Image[max], s, t, r, rgba );
d1695 2
a1696 4
      GLint level = (GLint) (lambda + 1.0F);
      level = CLAMP( level, 1, max );
      sample_3d_nearest( tObj, tObj->Image[level-1], s, t, r, t0 );
      sample_3d_nearest( tObj, tObj->Image[level  ], s, t, r, t1 );
d1698 1
a1698 1
      rgba[RCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
d1710 6
a1715 1
   GLint max = tObj->Image[0]->MaxLog2;
d1717 2
a1718 3
   if (lambda>=max) {
      sample_3d_linear( tObj, tObj->Image[max],
                        s, t, r, rgba );
d1723 2
a1724 4
      GLint level = (GLint) (lambda + 1.0F);
      level = CLAMP( level, 1, max );
      sample_3d_linear( tObj, tObj->Image[level-1], s, t, r, t0 );
      sample_3d_linear( tObj, tObj->Image[level  ], s, t, r, t1 );
d1726 1
a1726 1
      rgba[RCOMP] = (1.0F-f) * t0[GCOMP] + f * t1[GCOMP];
d1739 1
d1741 1
a1741 1
      sample_3d_nearest( tObj, tObj->Image[0], s[i], t[i], u[i], rgba[i] );
d1753 1
d1755 1
a1755 1
      sample_3d_linear( tObj, tObj->Image[0], s[i], t[i], u[i], rgba[i] );
d1777 1
a1777 1
               sample_3d_nearest( tObj, tObj->Image[0], s[i], t[i], u[i], rgba[i] );
d1780 1
a1780 1
               sample_3d_linear( tObj, tObj->Image[0], s[i], t[i], u[i], rgba[i] );
d1802 1
a1802 1
               sample_3d_nearest( tObj, tObj->Image[0], s[i], t[i], u[i], rgba[i] );
d1805 1
a1805 1
               sample_3d_linear( tObj, tObj->Image[0], s[i], t[i], u[i], rgba[i] );
d1808 1
a1808 1
               gl_problem(NULL, "Bad mag filterin sample_3d_texture");
d2167 1
a2167 1
                        const GLfloat r[], const GLfloat lambda[],
d2174 12
@


3.0
log
@initial rev
@
text
@d1 1
a1 1
/* $Id$ */
d25 4
a28 1
 * $Log$
d341 10
d421 14
d747 10
d773 10
d854 14
d881 14
d1312 10
d1338 10
d1364 10
d1441 14
d1468 14
d1493 14
@
