home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / texture.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  49KB  |  1,837 lines

  1. /* texture.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: texture.c,v 1.23 1996/02/02 23:22:32 brianp Exp $
  26.  
  27. $Log: texture.c,v $
  28.  * Revision 1.23  1996/02/02  23:22:32  brianp
  29.  * check that width and height = 2^k+2*border per Frederic Devernay
  30.  *
  31.  * Revision 1.22  1995/11/22  13:38:01  brianp
  32.  * removed texcoord clamping optimization
  33.  *
  34.  * Revision 1.21  1995/11/13  21:45:53  brianp
  35.  * fixed bug in texture border logic
  36.  * added F suffix to many constants
  37.  *
  38.  * Revision 1.20  1995/11/09  16:57:52  brianp
  39.  * fixed bugs in apply_texture for GL_BLEND per Johan Nouvel
  40.  *
  41.  * Revision 1.19  1995/11/03  17:39:30  brianp
  42.  * removed unused variable, added casts for C++ compilation
  43.  *
  44.  * Revision 1.18  1995/10/14  17:42:45  brianp
  45.  * compile glTexEnv, glTexParameter, and glTexGen into display lists
  46.  *
  47.  * Revision 1.17  1995/08/31  21:28:59  brianp
  48.  * new TexGenEnabled bitfield
  49.  * fixed a bug in spherical normal generation
  50.  *
  51.  * Revision 1.16  1995/07/24  20:35:40  brianp
  52.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  53.  *
  54.  * Revision 1.15  1995/07/20  15:36:06  brianp
  55.  * added casts to PROD macro to suppress warnings with Sun's cc
  56.  *
  57.  * Revision 1.14  1995/06/12  15:43:06  brianp
  58.  * changed color arrays to GLubyte
  59.  *
  60.  * Revision 1.13  1995/05/30  15:41:23  brianp
  61.  * fixed GL_LUMINANCE bug in unpack_texture()
  62.  *
  63.  * Revision 1.12  1995/05/30  15:11:13  brianp
  64.  * added more error checking to glGetTexLevelParamater[fi]v()
  65.  * added glGetTexImage() stub
  66.  *
  67.  * Revision 1.11  1995/05/29  21:23:38  brianp
  68.  * added glGetTexEnv*(), glGetTexGen*(), glGetTex[Level]Parameter*() functions
  69.  *
  70.  * Revision 1.10  1995/05/22  21:02:41  brianp
  71.  * Release 1.2
  72.  *
  73.  * Revision 1.9  1995/05/18  14:46:51  brianp
  74.  * fixed texture DeleteFlag bug
  75.  *
  76.  * Revision 1.8  1995/05/16  14:09:44  brianp
  77.  * more data types supported by glTexImage1/2D()
  78.  *
  79.  * Revision 1.7  1995/05/15  16:09:41  brianp
  80.  * store textures as GLubytes instead of GLfloats
  81.  * implemented GL_MODULATE, GL_DECAL, GL_BLEND and GL_REPLACE_EXT modes
  82.  * save 1D and 2D textures in display lists
  83.  *
  84.  * Revision 1.6  1995/03/17  20:14:50  brianp
  85.  * small bug fixes
  86.  *
  87.  * Revision 1.5  1995/03/10  15:19:23  brianp
  88.  * added divide by zero check to gl_texgen
  89.  *
  90.  * Revision 1.4  1995/03/09  21:33:12  brianp
  91.  * removed #include stdio.h
  92.  *
  93.  * Revision 1.3  1995/03/04  19:29:44  brianp
  94.  * 1.1 beta revision
  95.  *
  96.  * Revision 1.2  1995/03/02  19:11:30  brianp
  97.  * modified gl_texgen and gl_texture_span_1d
  98.  *
  99.  * Revision 1.1  1995/02/24  14:28:31  brianp
  100.  * Initial revision
  101.  *
  102.  */
  103.  
  104.  
  105. #include <math.h>
  106. #include <stdio.h>
  107. #include <stdlib.h>
  108. #include <string.h>
  109. #include "context.h"
  110. #include "list.h"
  111. #include "macros.h"
  112. #include "pb.h"
  113.  
  114.  
  115. #ifndef NULL
  116. #  define NULL 0
  117. #endif
  118.  
  119.  
  120.  
  121. /**********************************************************************/
  122. /*                       Texture Environment                          */
  123. /**********************************************************************/
  124.  
  125.  
  126.  
  127. void gl_texenv( GLenum target, GLenum pname, const GLfloat *param )
  128. {
  129.    if (INSIDE_BEGIN_END) {
  130.       gl_error( GL_INVALID_OPERATION, "glTexEnv" );
  131.       return;
  132.    }
  133.  
  134.    if (target!=GL_TEXTURE_ENV) {
  135.       gl_error( GL_INVALID_ENUM, "glTexEnv(target)" );
  136.       return;
  137.    }
  138.  
  139.    if (pname==GL_TEXTURE_ENV_MODE) {
  140.       GLenum mode = (GLenum) (GLint) *param;
  141.       switch (mode) {
  142.      case GL_MODULATE:
  143.      case GL_BLEND:
  144.      case GL_DECAL:
  145.      case GL_REPLACE_EXT:
  146.         CC.Texture.EnvMode = mode;
  147.         break;
  148.      default:
  149.         gl_error( GL_INVALID_ENUM, "glTexEnv(param)" );
  150.         return;
  151.       }
  152.    }
  153.    else if (pname==GL_TEXTURE_ENV_COLOR) {
  154.       CC.Texture.EnvColor[0] = CLAMP( param[0], 0.0, 1.0 );
  155.       CC.Texture.EnvColor[1] = CLAMP( param[1], 0.0, 1.0 );
  156.       CC.Texture.EnvColor[2] = CLAMP( param[2], 0.0, 1.0 );
  157.       CC.Texture.EnvColor[3] = CLAMP( param[3], 0.0, 1.0 );
  158.    }
  159.    else {
  160.       gl_error( GL_INVALID_ENUM, "glTexEnv(pname)" );
  161.       return;
  162.    }
  163. }
  164.  
  165.  
  166.  
  167. void glTexEnvf( GLenum target, GLenum pname, GLfloat param )
  168. {
  169.    if (CC.CompileFlag) {
  170.       gl_save_texenv( target, pname, ¶m );
  171.    }
  172.    if (CC.ExecuteFlag) {
  173.       gl_texenv( target, pname, ¶m );
  174.    }
  175. }
  176.  
  177.  
  178.  
  179. void glTexEnvi( GLenum target, GLenum pname, GLint param )
  180. {
  181.    GLfloat p = (GLfloat) param;
  182.    if (CC.CompileFlag) {
  183.       gl_save_texenv( target, pname, &p );
  184.    }
  185.    if (CC.ExecuteFlag) {
  186.       gl_texenv( target, pname, &p );
  187.    }
  188. }
  189.  
  190.  
  191.  
  192. void glTexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
  193. {
  194.    if (CC.CompileFlag) {
  195.       gl_save_texenv( target, pname, param );
  196.    }
  197.    if (CC.ExecuteFlag) {
  198.       gl_texenv( target, pname, param );
  199.    }
  200. }
  201.  
  202.  
  203.  
  204. void glTexEnviv( GLenum target, GLenum pname, const GLint *param )
  205. {
  206.    GLfloat p[4];
  207.    p[0] = INT_TO_FLOAT( param[0] );
  208.    p[1] = INT_TO_FLOAT( param[1] );
  209.    p[2] = INT_TO_FLOAT( param[2] );
  210.    p[3] = INT_TO_FLOAT( param[3] );
  211.    if (CC.CompileFlag) {
  212.       gl_save_texenv( target, pname, p );
  213.    }
  214.    if (CC.ExecuteFlag) {
  215.       gl_texenv( target, pname, p );
  216.    }
  217. }
  218.  
  219.  
  220.  
  221.  
  222. void glGetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
  223. {
  224.    if (target!=GL_TEXTURE_ENV) {
  225.       gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  226.       return;
  227.    }
  228.    switch (pname) {
  229.       case GL_TEXTURE_ENV_MODE:
  230.          *params = (GLfloat) CC.Texture.EnvMode;
  231.      break;
  232.       case GL_TEXTURE_ENV_COLOR:
  233.      COPY_4V( params, CC.Texture.EnvColor );
  234.      break;
  235.       default:
  236.          gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  237.    }
  238. }
  239.  
  240.  
  241. void glGetTexEnviv( GLenum target, GLenum pname, GLint *params )
  242. {
  243.    if (target!=GL_TEXTURE_ENV) {
  244.       gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
  245.       return;
  246.    }
  247.    switch (pname) {
  248.       case GL_TEXTURE_ENV_MODE:
  249.          *params = (GLint) CC.Texture.EnvMode;
  250.      break;
  251.       case GL_TEXTURE_ENV_COLOR:
  252.      params[0] = FLOAT_TO_INT( CC.Texture.EnvColor[0] );
  253.      params[1] = FLOAT_TO_INT( CC.Texture.EnvColor[1] );
  254.      params[2] = FLOAT_TO_INT( CC.Texture.EnvColor[2] );
  255.      params[3] = FLOAT_TO_INT( CC.Texture.EnvColor[3] );
  256.      break;
  257.       default:
  258.          gl_error( GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
  259.    }
  260. }
  261.  
  262.  
  263.  
  264.  
  265. /**********************************************************************/
  266. /*                       Texture Parameters                           */
  267. /**********************************************************************/
  268.  
  269.  
  270. void gl_texparameter( GLenum target, GLenum pname, const GLfloat *params )
  271. {
  272.    GLenum eparam = (GLenum) (GLint) params[0];
  273.  
  274.    if (target==GL_TEXTURE_1D) {
  275.       switch (pname) {
  276.      case GL_TEXTURE_MIN_FILTER:
  277.         if (eparam==GL_NEAREST || eparam==GL_LINEAR
  278.         || eparam==GL_NEAREST_MIPMAP_NEAREST
  279.         || eparam==GL_LINEAR_MIPMAP_NEAREST
  280.         || eparam==GL_NEAREST_MIPMAP_LINEAR
  281.         || eparam==GL_LINEAR_MIPMAP_LINEAR) {
  282.            CC.Texture.MinFilter1D = eparam;
  283.         }
  284.         else {
  285.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  286.         }
  287.         break;
  288.      case GL_TEXTURE_MAG_FILTER:
  289.         if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
  290.            CC.Texture.MagFilter1D = eparam;
  291.         }
  292.         else {
  293.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  294.         }
  295.         break;
  296.      case GL_TEXTURE_WRAP_S:
  297.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  298.            CC.Texture.WrapS1D = eparam;
  299.         }
  300.         else {
  301.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  302.         }
  303.         break;
  304.      case GL_TEXTURE_WRAP_T:
  305.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  306.            CC.Texture.WrapT1D = eparam;
  307.         }
  308.         else {
  309.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  310.         }
  311.         break;
  312.          case GL_TEXTURE_BORDER_COLOR:
  313.             CC.Texture.BorderColor[0] = CLAMP( params[0], 0.0, 1.0 );
  314.             CC.Texture.BorderColor[1] = CLAMP( params[1], 0.0, 1.0 );
  315.             CC.Texture.BorderColor[2] = CLAMP( params[2], 0.0, 1.0 );
  316.             CC.Texture.BorderColor[3] = CLAMP( params[3], 0.0, 1.0 );
  317.             break;
  318.      default:
  319.         gl_error( GL_INVALID_ENUM, "glTexParameter(pname)" );
  320.       }
  321.    }
  322.    else if (target==GL_TEXTURE_2D) {
  323.       switch (pname) {
  324.      case GL_TEXTURE_MIN_FILTER:
  325.         if (eparam==GL_NEAREST || eparam==GL_LINEAR
  326.         || eparam==GL_NEAREST_MIPMAP_NEAREST
  327.         || eparam==GL_LINEAR_MIPMAP_NEAREST
  328.         || eparam==GL_NEAREST_MIPMAP_LINEAR
  329.         || eparam==GL_LINEAR_MIPMAP_LINEAR) {
  330.            CC.Texture.MinFilter2D = eparam;
  331.         }
  332.         else {
  333.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  334.         }
  335.         break;
  336.      case GL_TEXTURE_MAG_FILTER:
  337.         if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
  338.            CC.Texture.MagFilter2D = eparam;
  339.         }
  340.         else {
  341.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  342.         }
  343.         break;
  344.      case GL_TEXTURE_WRAP_S:
  345.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  346.            CC.Texture.WrapS2D = eparam;
  347.         }
  348.         else {
  349.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  350.         }
  351.         break;
  352.      case GL_TEXTURE_WRAP_T:
  353.         if (eparam==GL_CLAMP || eparam==GL_REPEAT) {
  354.            CC.Texture.WrapT2D = eparam;
  355.         }
  356.         else {
  357.            gl_error( GL_INVALID_VALUE, "glTexParameter(param)" );
  358.         }
  359.         break;
  360.          case GL_TEXTURE_BORDER_COLOR:
  361.             CC.Texture.BorderColor[0] = CLAMP( params[0], 0.0, 1.0 );
  362.             CC.Texture.BorderColor[1] = CLAMP( params[1], 0.0, 1.0 );
  363.             CC.Texture.BorderColor[2] = CLAMP( params[2], 0.0, 1.0 );
  364.             CC.Texture.BorderColor[3] = CLAMP( params[3], 0.0, 1.0 );
  365.             break;
  366.      default:
  367.         gl_error( GL_INVALID_ENUM, "glTexParameter(pname)" );
  368.       }
  369.    }
  370.    else {
  371.       gl_error( GL_INVALID_ENUM, "glTexParameter(target)" );
  372.    }
  373. }
  374.  
  375.  
  376.  
  377. void glTexParameterf( GLenum target, GLenum pname, GLfloat param )
  378. {
  379.    if (CC.CompileFlag) {
  380.       gl_save_texparameter( target, pname, ¶m );
  381.    }
  382.    if (CC.ExecuteFlag) {
  383.       gl_texparameter( target, pname, ¶m );
  384.    }
  385. }
  386.  
  387.  
  388.  
  389. void glTexParameteri( GLenum target, GLenum pname, GLint param )
  390. {
  391.    GLfloat fparam = param;
  392.    if (CC.CompileFlag) {
  393.       gl_save_texparameter( target, pname, &fparam );
  394.    }
  395.    if (CC.ExecuteFlag) {
  396.       gl_texparameter( target, pname, &fparam );
  397.    }
  398. }
  399.  
  400.  
  401.  
  402. void glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
  403. {
  404.    if (CC.CompileFlag) {
  405.       gl_save_texparameter( target, pname, params );
  406.    }
  407.    if (CC.ExecuteFlag) {
  408.       gl_texparameter( target, pname, params );
  409.    }
  410. }
  411.  
  412.  
  413.  
  414. void glTexParameteriv( GLenum target, GLenum pname, const GLint *params )
  415. {
  416.    GLfloat p[4];
  417.    if (pname==GL_TEXTURE_BORDER_COLOR) {
  418.       p[0] = INT_TO_FLOAT( params[0] );
  419.       p[1] = INT_TO_FLOAT( params[1] );
  420.       p[2] = INT_TO_FLOAT( params[2] );
  421.       p[3] = INT_TO_FLOAT( params[3] );
  422.    }
  423.    else {
  424.       p[0] = (GLfloat) params[0];
  425.       p[1] = (GLfloat) params[1];
  426.       p[2] = (GLfloat) params[2];
  427.       p[3] = (GLfloat) params[3];
  428.    }
  429.    if (CC.CompileFlag) {
  430.       gl_save_texparameter( target, pname, p );
  431.    }
  432.    if (CC.ExecuteFlag) {
  433.       gl_texparameter( target, pname, p );
  434.    }
  435. }
  436.  
  437.  
  438. void glGetTexLevelParameterfv( GLenum target, GLint level,
  439.                    GLenum pname, GLfloat *params )
  440. {
  441.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  442.       gl_error( GL_INVALID_VALUE, "glGetTexLevelParameterfv" );
  443.       return;
  444.    }
  445.  
  446.    switch (target) {
  447.       case GL_TEXTURE_1D:
  448.          switch (pname) {
  449.         case GL_TEXTURE_WIDTH:
  450.            *params = (GLfloat) CC.TextureWidth1D[level];
  451.            break;
  452.         case GL_TEXTURE_COMPONENTS:
  453.            *params = (GLfloat) CC.TextureComponents1D[level];
  454.            break;
  455.         case GL_TEXTURE_BORDER:
  456.            *params = (GLfloat) CC.TextureBorder1D[level];
  457.            break;
  458.         default:
  459.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameterfv(pname)" );
  460.      }
  461.      break;
  462.       case GL_TEXTURE_2D:
  463.      switch (pname) {
  464.         case GL_TEXTURE_WIDTH:
  465.            *params = (GLfloat) CC.TextureWidth2D[level];
  466.            break;
  467.         case GL_TEXTURE_HEIGHT:
  468.            *params = (GLfloat) CC.TextureHeight2D[level];
  469.            break;
  470.         case GL_TEXTURE_COMPONENTS:
  471.            *params = (GLfloat) CC.TextureComponents2D[level];
  472.            break;
  473.         case GL_TEXTURE_BORDER:
  474.            *params = (GLfloat) CC.TextureBorder2D[level];
  475.            break;
  476.         default:
  477.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameterfv(pname)" );
  478.      }
  479.      break;
  480.      default:
  481.      gl_error( GL_INVALID_ENUM, "glGetTexLevelParameterfv(target)" );
  482.    }     
  483. }
  484.  
  485.  
  486. void glGetTexLevelParameteriv( GLenum target, GLint level,
  487.                    GLenum pname, GLint *params )
  488. {
  489.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  490.       gl_error( GL_INVALID_VALUE, "glGetTexLevelParameteriv" );
  491.       return;
  492.    }
  493.  
  494.    switch (target) {
  495.       case GL_TEXTURE_1D:
  496.          switch (pname) {
  497.         case GL_TEXTURE_WIDTH:
  498.            *params = CC.TextureWidth1D[level];
  499.            break;
  500.         case GL_TEXTURE_COMPONENTS:
  501.            *params = CC.TextureComponents1D[level];
  502.            break;
  503.         case GL_TEXTURE_BORDER:
  504.            *params = CC.TextureBorder1D[level];
  505.            break;
  506.         default:
  507.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameteriv(pname)" );
  508.      }
  509.      break;
  510.       case GL_TEXTURE_2D:
  511.      switch (pname) {
  512.         case GL_TEXTURE_WIDTH:
  513.            *params = CC.TextureWidth2D[level];
  514.            break;
  515.         case GL_TEXTURE_HEIGHT:
  516.            *params = CC.TextureHeight2D[level];
  517.            break;
  518.         case GL_TEXTURE_COMPONENTS:
  519.            *params = CC.TextureComponents2D[level];
  520.            break;
  521.         case GL_TEXTURE_BORDER:
  522.            *params = CC.TextureBorder2D[level];
  523.            break;
  524.         default:
  525.            gl_error( GL_INVALID_ENUM, "glGetTexLevelParameteriv(pname)" );
  526.      }
  527.      break;
  528.      default:
  529.      gl_error( GL_INVALID_ENUM, "glGetTexLevelParameteriv(target)" );
  530.    }     
  531. }
  532.  
  533.  
  534.  
  535. void glGetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
  536. {
  537.    switch (target) {
  538.       case GL_TEXTURE_1D:
  539.          switch (pname) {
  540.         case GL_TEXTURE_MAG_FILTER:
  541.            *params = (GLfloat) CC.Texture.MagFilter1D;
  542.            break;
  543.         case GL_TEXTURE_MIN_FILTER:
  544.            *params = (GLfloat) CC.Texture.MinFilter1D;
  545.            break;
  546.         case GL_TEXTURE_WRAP_S:
  547.            *params = (GLfloat) CC.Texture.WrapS1D;
  548.            break;
  549.         case GL_TEXTURE_WRAP_T:
  550.            *params = (GLfloat) CC.Texture.WrapT1D;
  551.            break;
  552.         case GL_TEXTURE_BORDER_COLOR:
  553.            COPY_4V( params, CC.Texture.BorderColor );
  554.            break;
  555.         default:
  556.            gl_error( GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
  557.      }
  558.          break;
  559.       case GL_TEXTURE_2D:
  560.          switch (pname) {
  561.         case GL_TEXTURE_MAG_FILTER:
  562.            *params = (GLfloat) CC.Texture.MagFilter2D;
  563.            break;
  564.         case GL_TEXTURE_MIN_FILTER:
  565.            *params = (GLfloat) CC.Texture.MinFilter2D;
  566.            break;
  567.         case GL_TEXTURE_WRAP_S:
  568.            *params = (GLfloat) CC.Texture.WrapS2D;
  569.            break;
  570.         case GL_TEXTURE_WRAP_T:
  571.            *params = (GLfloat) CC.Texture.WrapT2D;
  572.            break;
  573.         case GL_TEXTURE_BORDER_COLOR:
  574.            COPY_4V( params, CC.Texture.BorderColor );
  575.            break;
  576.         default:
  577.            gl_error( GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
  578.      }
  579.      break;
  580.       default:
  581.          gl_error( GL_INVALID_ENUM, "glGetTexParameterfv(target)" );
  582.    }
  583. }
  584.  
  585.  
  586. void glGetTexParameteriv( GLenum target, GLenum pname, GLint *params )
  587. {
  588.    switch (target) {
  589.       case GL_TEXTURE_1D:
  590.          switch (pname) {
  591.         case GL_TEXTURE_MAG_FILTER:
  592.            *params = (GLint) CC.Texture.MagFilter1D;
  593.            break;
  594.         case GL_TEXTURE_MIN_FILTER:
  595.            *params = (GLint) CC.Texture.MinFilter1D;
  596.            break;
  597.         case GL_TEXTURE_WRAP_S:
  598.            *params = (GLint) CC.Texture.WrapS1D;
  599.            break;
  600.         case GL_TEXTURE_WRAP_T:
  601.            *params = (GLint) CC.Texture.WrapT1D;
  602.            break;
  603.         case GL_TEXTURE_BORDER_COLOR:
  604.            params[0] = FLOAT_TO_INT( CC.Texture.BorderColor[0] );
  605.            params[1] = FLOAT_TO_INT( CC.Texture.BorderColor[1] );
  606.            params[2] = FLOAT_TO_INT( CC.Texture.BorderColor[2] );
  607.            params[3] = FLOAT_TO_INT( CC.Texture.BorderColor[3] );
  608.            break;
  609.         default:
  610.            gl_error( GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
  611.      }
  612.          break;
  613.       case GL_TEXTURE_2D:
  614.          switch (pname) {
  615.         case GL_TEXTURE_MAG_FILTER:
  616.            *params = (GLint) CC.Texture.MagFilter2D;
  617.            break;
  618.         case GL_TEXTURE_MIN_FILTER:
  619.            *params = (GLint) CC.Texture.MinFilter2D;
  620.            break;
  621.         case GL_TEXTURE_WRAP_S:
  622.            *params = (GLint) CC.Texture.WrapS2D;
  623.            break;
  624.         case GL_TEXTURE_WRAP_T:
  625.            *params = (GLint) CC.Texture.WrapT2D;
  626.            break;
  627.         case GL_TEXTURE_BORDER_COLOR:
  628.            params[0] = FLOAT_TO_INT( CC.Texture.BorderColor[0] );
  629.            params[1] = FLOAT_TO_INT( CC.Texture.BorderColor[1] );
  630.            params[2] = FLOAT_TO_INT( CC.Texture.BorderColor[2] );
  631.            params[3] = FLOAT_TO_INT( CC.Texture.BorderColor[3] );
  632.            break;
  633.         default:
  634.            gl_error( GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
  635.      }
  636.      break;
  637.       default:
  638.          gl_error( GL_INVALID_ENUM, "glGetTexParameteriv(target)" );
  639.    }
  640. }
  641.  
  642.  
  643.  
  644.  
  645. /**********************************************************************/
  646. /*                    Texture Coord Generation                        */
  647. /**********************************************************************/
  648.  
  649.  
  650. void gl_texgen( GLenum coord, GLenum pname, const GLfloat *params )
  651. {
  652.    if (INSIDE_BEGIN_END) {
  653.       gl_error( GL_INVALID_OPERATION, "glTexGenfv" );
  654.       return;
  655.    }
  656.  
  657.    switch( coord ) {
  658.       case GL_S:
  659.          if (pname==GL_TEXTURE_GEN_MODE) {
  660.         GLenum mode = (GLenum) (GLint) *params;
  661.         if (mode==GL_OBJECT_LINEAR ||
  662.         mode==GL_EYE_LINEAR ||
  663.         mode==GL_SPHERE_MAP) {
  664.            CC.Texture.GenModeS = mode;
  665.         }
  666.         else {
  667.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  668.            return;
  669.         }
  670.      }
  671.      else if (pname==GL_OBJECT_PLANE) {
  672.         CC.Texture.ObjectPlaneS[0] = params[0];
  673.         CC.Texture.ObjectPlaneS[1] = params[1];
  674.         CC.Texture.ObjectPlaneS[2] = params[2];
  675.         CC.Texture.ObjectPlaneS[3] = params[3];
  676.      }
  677.      else if (pname==GL_EYE_PLANE) {
  678.         /* TODO:  xform plane by modelview??? */
  679.         CC.Texture.EyePlaneS[0] = params[0];
  680.         CC.Texture.EyePlaneS[1] = params[1];
  681.         CC.Texture.EyePlaneS[2] = params[2];
  682.         CC.Texture.EyePlaneS[3] = params[3];
  683.      }
  684.      else {
  685.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  686.         return;
  687.      }
  688.      break;
  689.       case GL_T:
  690.          if (pname==GL_TEXTURE_GEN_MODE) {
  691.         GLenum mode = (GLenum) (GLint) *params;
  692.         if (mode==GL_OBJECT_LINEAR ||
  693.         mode==GL_EYE_LINEAR ||
  694.         mode==GL_SPHERE_MAP) {
  695.            CC.Texture.GenModeT = mode;
  696.         }
  697.         else {
  698.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  699.            return;
  700.         }
  701.      }
  702.      else if (pname==GL_OBJECT_PLANE) {
  703.         CC.Texture.ObjectPlaneT[0] = params[0];
  704.         CC.Texture.ObjectPlaneT[1] = params[1];
  705.         CC.Texture.ObjectPlaneT[2] = params[2];
  706.         CC.Texture.ObjectPlaneT[3] = params[3];
  707.      }
  708.      else if (pname==GL_EYE_PLANE) {
  709.         CC.Texture.EyePlaneT[0] = params[0];
  710.         CC.Texture.EyePlaneT[1] = params[1];
  711.         CC.Texture.EyePlaneT[2] = params[2];
  712.         CC.Texture.EyePlaneT[3] = params[3];
  713.      }
  714.      else {
  715.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  716.         return;
  717.      }
  718.      break;
  719.       case GL_R:
  720.          if (pname==GL_TEXTURE_GEN_MODE) {
  721.         GLenum mode = (GLenum) (GLint) *params;
  722.         if (mode==GL_OBJECT_LINEAR ||
  723.         mode==GL_EYE_LINEAR) {
  724.            CC.Texture.GenModeR = mode;
  725.         }
  726.         else {
  727.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  728.            return;
  729.         }
  730.      }
  731.      else if (pname==GL_OBJECT_PLANE) {
  732.         CC.Texture.ObjectPlaneR[0] = params[0];
  733.         CC.Texture.ObjectPlaneR[1] = params[1];
  734.         CC.Texture.ObjectPlaneR[2] = params[2];
  735.         CC.Texture.ObjectPlaneR[3] = params[3];
  736.      }
  737.      else if (pname==GL_EYE_PLANE) {
  738.         CC.Texture.EyePlaneR[0] = params[0];
  739.         CC.Texture.EyePlaneR[1] = params[1];
  740.         CC.Texture.EyePlaneR[2] = params[2];
  741.         CC.Texture.EyePlaneR[3] = params[3];
  742.      }
  743.      else {
  744.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  745.         return;
  746.      }
  747.      break;
  748.       case GL_Q:
  749.          if (pname==GL_TEXTURE_GEN_MODE) {
  750.         GLenum mode = (GLenum) (GLint) *params;
  751.         if (mode==GL_OBJECT_LINEAR ||
  752.         mode==GL_EYE_LINEAR) {
  753.            CC.Texture.GenModeQ = mode;
  754.         }
  755.         else {
  756.            gl_error( GL_INVALID_ENUM, "glTexGenfv(param)" );
  757.            return;
  758.         }
  759.      }
  760.      else if (pname==GL_OBJECT_PLANE) {
  761.         CC.Texture.ObjectPlaneQ[0] = params[0];
  762.         CC.Texture.ObjectPlaneQ[1] = params[1];
  763.         CC.Texture.ObjectPlaneQ[2] = params[2];
  764.         CC.Texture.ObjectPlaneQ[3] = params[3];
  765.      }
  766.      else if (pname==GL_EYE_PLANE) {
  767.         CC.Texture.EyePlaneQ[0] = params[0];
  768.         CC.Texture.EyePlaneQ[1] = params[1];
  769.         CC.Texture.EyePlaneQ[2] = params[2];
  770.         CC.Texture.EyePlaneQ[3] = params[3];
  771.      }
  772.      else {
  773.         gl_error( GL_INVALID_ENUM, "glTexGenfv(pname)" );
  774.         return;
  775.      }
  776.      break;
  777.       default:
  778.          gl_error( GL_INVALID_ENUM, "glTexGenfv(coord)" );
  779.      return;
  780.    }
  781.  
  782.    CC.NewState = GL_TRUE;
  783. }
  784.  
  785.  
  786.  
  787. void glTexGend( GLenum coord, GLenum pname, GLdouble param )
  788. {
  789.    GLfloat p = (GLfloat) param;
  790.    if (CC.CompileFlag) {
  791.       gl_save_texgen( coord, pname, &p );
  792.    }
  793.    if (CC.ExecuteFlag) {
  794.       gl_texgen( coord, pname, &p );
  795.    }
  796. }
  797.  
  798.  
  799. void glTexGenf( GLenum coord, GLenum pname, GLfloat param )
  800. {
  801.    if (CC.CompileFlag) {
  802.       gl_save_texgen( coord, pname, ¶m );
  803.    }
  804.    if (CC.ExecuteFlag) {
  805.       gl_texgen( coord, pname, ¶m );
  806.    }
  807. }
  808.  
  809.  
  810. void glTexGeni( GLenum coord, GLenum pname, GLint param )
  811. {
  812.    GLfloat p = (GLfloat) param;
  813.    if (CC.CompileFlag) {
  814.       gl_save_texgen( coord, pname, &p );
  815.    }
  816.    if (CC.ExecuteFlag) {
  817.       gl_texgen( coord, pname, &p );
  818.    }
  819. }
  820.  
  821.  
  822. void glTexGendv( GLenum coord, GLenum pname, const GLdouble *params )
  823. {
  824.    GLfloat p[4];
  825.    p[0] = params[0];
  826.    p[1] = params[1];
  827.    p[2] = params[2];
  828.    p[3] = params[3];
  829.    if (CC.CompileFlag) {
  830.       gl_save_texgen( coord, pname, p );
  831.    }
  832.    if (CC.ExecuteFlag) {
  833.       gl_texgen( coord, pname, p );
  834.    }
  835. }
  836.  
  837.  
  838. void glTexGeniv( GLenum coord, GLenum pname, const GLint *params )
  839. {
  840.    GLfloat p[4];
  841.    p[0] = params[0];
  842.    p[1] = params[1];
  843.    p[2] = params[2];
  844.    p[3] = params[3];
  845.    if (CC.CompileFlag) {
  846.       gl_save_texgen( coord, pname, p );
  847.    }
  848.    if (CC.ExecuteFlag) {
  849.       gl_texgen( coord, pname, p );
  850.    }
  851. }
  852.  
  853.  
  854. void glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
  855. {
  856.    if (CC.CompileFlag) {
  857.       gl_save_texgen( coord, pname, params );
  858.    }
  859.    if (CC.ExecuteFlag) {
  860.       gl_texgen( coord, pname, params );
  861.    }
  862. }
  863.  
  864.  
  865. void glGetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
  866. {
  867.    /* TODO */
  868. }
  869.  
  870. void glGetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
  871. {
  872.    /* TODO */
  873. }
  874.  
  875. void glGetTexGeniv( GLenum coord, GLenum pname, GLint *params )
  876. {
  877.    /* TODO */
  878. }
  879.  
  880.  
  881.  
  882. /*
  883.  * Perform automatic texture coordinate generation.
  884.  * Input:  obj - vertex in object coordinate system
  885.  *         eye - vertex in eye coordinate system
  886.  *         normal - normal vector in eye coordinate system
  887.  * Output:  texcoord - the resuling texture coordinate, if TexGen enabled.
  888.  */
  889. void gl_do_texgen( const GLfloat obj[4],
  890.                    const GLfloat eye[4],
  891.                    const GLfloat normal[3],
  892.                    GLfloat texcoord[4] )
  893. {
  894.    GLfloat u[3], two_nn, m, fx, fy, fz;
  895.  
  896.    if (CC.Texture.TexGenEnabled & S_BIT) {
  897.       switch( CC.Texture.GenModeS) {
  898.      case GL_OBJECT_LINEAR:
  899.             texcoord[0] = DOT4( obj, CC.Texture.ObjectPlaneS );
  900.         break;
  901.      case GL_EYE_LINEAR:
  902.         texcoord[0] = DOT4( eye, CC.Texture.EyePlaneS );
  903.         break;
  904.      case GL_SPHERE_MAP:
  905.             COPY_3V( u, eye );
  906.             NORMALIZE_3V( u );
  907.         two_nn = 2.0*DOT3(normal,normal);
  908.         fx = u[0] - two_nn * u[0];
  909.         fy = u[1] - two_nn * u[1];
  910.         fz = u[2] - two_nn * u[2];
  911.         m = 2.0 * sqrt( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  912.         if (m==0.0) {
  913.            texcoord[0] = 0.0;
  914.         }
  915.         else {
  916.            texcoord[0] = fx / m + 0.5;
  917.         }
  918.         break;
  919.       }
  920.    }
  921.  
  922.    if (CC.Texture.TexGenEnabled & T_BIT) {
  923.       switch( CC.Texture.GenModeT) {
  924.      case GL_OBJECT_LINEAR:
  925.         texcoord[1] = DOT4( obj, CC.Texture.ObjectPlaneT );
  926.         break;
  927.      case GL_EYE_LINEAR:
  928.         texcoord[1] = DOT4( eye, CC.Texture.EyePlaneT );
  929.         break;
  930.      case GL_SPHERE_MAP:
  931.         /* TODO: safe to assume that m and fy valid from above??? */
  932.         if (m==0.0) {
  933.            texcoord[1] = 0.0;
  934.         }
  935.         else {
  936.            texcoord[1] = fy / m + 0.5;
  937.         }
  938.         break;
  939.       }
  940.    }
  941.  
  942.    if (CC.Texture.TexGenEnabled & R_BIT) {
  943.       switch( CC.Texture.GenModeR) {
  944.      case GL_OBJECT_LINEAR:
  945.         texcoord[2] = DOT4( obj, CC.Texture.ObjectPlaneR );
  946.         break;
  947.      case GL_EYE_LINEAR:
  948.         texcoord[2] = DOT4( eye, CC.Texture.EyePlaneR );
  949.         break;
  950.       }
  951.    }
  952.  
  953.    if (CC.Texture.TexGenEnabled & Q_BIT) {
  954.       switch( CC.Texture.GenModeQ) {
  955.      case GL_OBJECT_LINEAR:
  956.         texcoord[3] = DOT4( obj, CC.Texture.ObjectPlaneQ );
  957.         break;
  958.      case GL_EYE_LINEAR:
  959.         texcoord[3] = DOT4( eye, CC.Texture.EyePlaneQ );
  960.         break;
  961.       }
  962.    }
  963. }
  964.  
  965.  
  966.  
  967. /**********************************************************************/
  968. /*                           Texture Image                            */
  969. /**********************************************************************/
  970.  
  971.  
  972. /*
  973.  * Convert the texture image given to glTexImage1D or glTexImage2D into
  974.  * an array of GLubytes.
  975.  * Return:  address of texture image or NULL if error.
  976.  */
  977. static GLubyte *unpack_texture( GLint components, GLsizei width, GLsizei height,
  978.                     GLenum format, GLenum type, const GLvoid *pixels )
  979. {
  980.    GLboolean rflag, gflag, bflag, aflag, lflag;
  981.    GLuint elements;
  982.    GLuint i, row;
  983.    GLubyte *texture, *texptr;
  984.    GLboolean scale_or_bias;
  985.  
  986.    scale_or_bias = CC.Pixel.RedScale  !=1.0F || CC.Pixel.RedBias  !=0.0F
  987.                 || CC.Pixel.GreenScale!=1.0F || CC.Pixel.GreenBias!=0.0F
  988.         || CC.Pixel.BlueScale !=1.0F || CC.Pixel.BlueBias !=0.0F
  989.         || CC.Pixel.AlphaScale!=1.0F || CC.Pixel.AlphaBias!=0.0F;
  990.  
  991.    switch (format) {
  992.       case GL_COLOR_INDEX:
  993.          elements = 1;
  994.      rflag = gflag = bflag = aflag = lflag = GL_FALSE;
  995.      break;
  996.       case GL_RED:
  997.      elements = 1;
  998.      rflag = GL_TRUE;
  999.      gflag = bflag = aflag = lflag = GL_FALSE;
  1000.      break;
  1001.       case GL_GREEN:
  1002.      elements = 1;
  1003.      gflag = GL_TRUE;
  1004.      rflag = bflag = aflag = lflag = GL_FALSE;
  1005.      break;
  1006.       case GL_BLUE:
  1007.      elements = 1;
  1008.      bflag = GL_TRUE;
  1009.      rflag = gflag = aflag = lflag = GL_FALSE;
  1010.      break;
  1011.       case GL_ALPHA:
  1012.      elements = 1;
  1013.      aflag = GL_TRUE;
  1014.      rflag = gflag = bflag = lflag = GL_FALSE;
  1015.      break;
  1016.       case GL_RGB:
  1017.          elements = 3;
  1018.      rflag = gflag = bflag = GL_TRUE;
  1019.      aflag = lflag = GL_FALSE;
  1020.      break;
  1021.       case GL_RGBA:
  1022.          elements = 4;
  1023.      rflag = gflag = bflag = aflag = GL_TRUE;
  1024.      lflag = GL_FALSE;
  1025.      break;
  1026.       case GL_LUMINANCE:
  1027.          elements = 1;
  1028.      rflag = gflag = bflag = aflag = GL_FALSE;
  1029.      lflag = GL_TRUE;
  1030.      break;
  1031.       case GL_LUMINANCE_ALPHA:
  1032.          elements = 2;
  1033.      lflag = aflag = GL_TRUE;
  1034.      rflag = gflag = bflag = GL_FALSE;
  1035.          break;
  1036.       default:
  1037.          gl_error( GL_INVALID_ENUM, "glTexImage1/2D(format)" );
  1038.      return NULL;
  1039.    }
  1040.  
  1041.    /* Allocate texture memory */
  1042.    texture = (GLubyte *) malloc( width * height * components );
  1043.    if (!texture) {
  1044.       gl_error( GL_OUT_OF_MEMORY, "glTexImage1/2D" );
  1045.       return NULL;
  1046.    }
  1047.    texptr = texture;
  1048.  
  1049.    /* TODO: obey glPixelStore parameters! */
  1050.  
  1051.    /* Build texture map image row by row */
  1052.    for (row=0;row<height;row++) {
  1053.       if (type==GL_UNSIGNED_BYTE && format==GL_RGB && components==3
  1054.       && !scale_or_bias) {
  1055.      /*
  1056.       * A frequent and simple case
  1057.       */
  1058.      GLubyte *src = (GLubyte *) pixels + row * width * 3;
  1059.      MEMCPY( texptr, src, 3*width );
  1060.      texptr += 3*width;
  1061.       }
  1062.       else if (type==GL_UNSIGNED_BYTE && format==GL_RGBA && components==4
  1063.       && !scale_or_bias) {
  1064.      /*
  1065.       * Another frequent and simple case
  1066.       */
  1067.      GLubyte *src = (GLubyte *) pixels + row * width * 4;
  1068.      MEMCPY( texptr, src, 4*width );
  1069.      texptr += 4*width;
  1070.       }
  1071.       else {
  1072.      /*
  1073.       * General solution
  1074.       */
  1075.      GLfloat red[MAX_TEXTURE_SIZE], green[MAX_TEXTURE_SIZE];
  1076.      GLfloat blue[MAX_TEXTURE_SIZE], alpha[MAX_TEXTURE_SIZE];
  1077.  
  1078.      switch (type) {
  1079.         case GL_UNSIGNED_BYTE:
  1080.            {
  1081.           GLubyte *src = (GLubyte *) pixels + row * width * elements;
  1082.           for (i=0;i<width;i++) {
  1083.              if (lflag) {
  1084.             red[i] = green[i] = blue[i] = UBYTE_TO_FLOAT(*src++);
  1085.              }
  1086.              else {
  1087.             red[i]   = rflag ? UBYTE_TO_FLOAT(*src++) : 0.0F;
  1088.             green[i] = gflag ? UBYTE_TO_FLOAT(*src++) : 0.0F;
  1089.             blue[i]  = bflag ? UBYTE_TO_FLOAT(*src++) : 0.0F;
  1090.              }
  1091.              alpha[i] = aflag ? UBYTE_TO_FLOAT(*src++) : 1.0F;
  1092.           }
  1093.            }
  1094.            break;
  1095.         case GL_BYTE:
  1096.            {
  1097.           GLbyte *src = (GLbyte *) pixels + row * width * elements;
  1098.           for (i=0;i<width;i++) {
  1099.              if (lflag) {
  1100.             red[i] = green[i] = blue[i] = BYTE_TO_FLOAT(*src++);
  1101.              }
  1102.              else {
  1103.             red[i]   = rflag ? BYTE_TO_FLOAT(*src++) : 0.0F;
  1104.             green[i] = gflag ? BYTE_TO_FLOAT(*src++) : 0.0F;
  1105.             blue[i]  = bflag ? BYTE_TO_FLOAT(*src++) : 0.0F;
  1106.              }
  1107.              alpha[i] = aflag ? BYTE_TO_FLOAT(*src++) : 1.0F;
  1108.           }
  1109.            }
  1110.            break;
  1111.         case GL_UNSIGNED_SHORT:
  1112.            {
  1113.           GLushort *src = (GLushort *) pixels + row * width * elements;
  1114.           for (i=0;i<width;i++) {
  1115.              if (lflag) {
  1116.             red[i] = green[i] = blue[i] = USHORT_TO_FLOAT(*src++);
  1117.              }
  1118.              else {
  1119.             red[i]   = rflag ? USHORT_TO_FLOAT(*src++) : 0.0F;
  1120.             green[i] = gflag ? USHORT_TO_FLOAT(*src++) : 0.0F;
  1121.             blue[i]  = bflag ? USHORT_TO_FLOAT(*src++) : 0.0F;
  1122.              }
  1123.              alpha[i] = aflag ? USHORT_TO_FLOAT(*src++) : 1.0F;
  1124.           }
  1125.            }
  1126.            break;
  1127.         case GL_SHORT:
  1128.            {
  1129.           GLshort *src = (GLshort *) pixels + row * width * elements;
  1130.           for (i=0;i<width;i++) {
  1131.              if (lflag) {
  1132.             red[i] = green[i] = blue[i] = SHORT_TO_FLOAT(*src++);
  1133.              }
  1134.              else {
  1135.             red[i]   = rflag ? SHORT_TO_FLOAT(*src++) : 0.0F;
  1136.             green[i] = gflag ? SHORT_TO_FLOAT(*src++) : 0.0F;
  1137.             blue[i]  = bflag ? SHORT_TO_FLOAT(*src++) : 0.0F;
  1138.              }
  1139.              alpha[i] = aflag ? SHORT_TO_FLOAT(*src++) : 1.0F;
  1140.           }
  1141.            }
  1142.            break;
  1143.         /*TODO: implement rest of data types */
  1144.         case GL_FLOAT:
  1145.            {
  1146.           GLfloat *src = (GLfloat *) pixels + row * width * elements;
  1147.           for (i=0;i<width;i++) {
  1148.              if (lflag) {
  1149.             red[i] = green[i] = blue[i] = *src++;
  1150.              }
  1151.              else {
  1152.             red[i]   = rflag ? *src++ : 0.0F;
  1153.             green[i] = gflag ? *src++ : 0.0F;
  1154.             blue[i]  = bflag ? *src++ : 0.0F;
  1155.              }
  1156.              alpha[i] = aflag ? *src++ : 1.0F;
  1157.           }
  1158.            }
  1159.            break;
  1160.         default:
  1161.            gl_error( GL_INVALID_ENUM, "glTexImage1/2D(type)" );
  1162.      } /* switch */
  1163.  
  1164.      /* apply scale and/or bias */
  1165.      if (scale_or_bias) {
  1166.         for (i=0;i<width;i++) {
  1167.            register GLfloat r, g, b, a;
  1168.            r = red[i]   * CC.Pixel.RedScale   + CC.Pixel.RedBias;
  1169.            g = green[i] * CC.Pixel.GreenScale + CC.Pixel.GreenBias;
  1170.            b = blue[i]  * CC.Pixel.BlueScale  + CC.Pixel.BlueBias;
  1171.            a = alpha[i] * CC.Pixel.AlphaScale + CC.Pixel.AlphaBias;
  1172.            red[i]   = CLAMP( r, 0.0F, 1.0F );
  1173.            green[i] = CLAMP( g, 0.0F, 1.0F );
  1174.            blue[i]  = CLAMP( b, 0.0F, 1.0F );
  1175.            alpha[i] = CLAMP( a, 0.0F, 1.0F );
  1176.         }
  1177.      }
  1178.  
  1179.      /* save 8-bit components */
  1180.      switch (components) {
  1181.         case 1:  /* red */
  1182.            for (i=0;i<width;i++) {
  1183.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1184.            }
  1185.            break;
  1186.         case 2:  /* red, alpha */
  1187.            for (i=0;i<width;i++) {
  1188.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1189.           *texptr++ = (GLubyte) (GLint) (alpha[i] * 255.0F);
  1190.            }
  1191.            break;
  1192.         case 3:  /* red, green, blue */
  1193.            for (i=0;i<width;i++) {
  1194.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1195.           *texptr++ = (GLubyte) (GLint) (green[i] * 255.0F);
  1196.           *texptr++ = (GLubyte) (GLint) (blue[i] * 255.0F);
  1197.            }
  1198.            break;
  1199.         case 4:  /* red, green, blue, alpha */
  1200.            for (i=0;i<width;i++) {
  1201.           *texptr++ = (GLubyte) (GLint) (red[i] * 255.0F);
  1202.           *texptr++ = (GLubyte) (GLint) (green[i] * 255.0F);
  1203.           *texptr++ = (GLubyte) (GLint) (blue[i] * 255.0F);
  1204.           *texptr++ = (GLubyte) (GLint) (alpha[i] * 255.0F);
  1205.            }
  1206.            break;
  1207.      } /* switch components */
  1208.  
  1209.       } /* general solution */
  1210.  
  1211.    } /* for row */
  1212.  
  1213.    return texture;
  1214. }
  1215.  
  1216.  
  1217. void gl_teximage1d( GLint level, GLint components,
  1218.             GLsizei width, GLint border,
  1219.             const GLubyte *pixels )
  1220. {
  1221.    /* check if we can delete the current image */
  1222.    if (CC.TextureImage1D[level] && CC.TextureImage1DDeleteFlag[level]) {
  1223.       free( CC.TextureImage1D[level] );
  1224.    }
  1225.  
  1226.    CC.TextureComponents1D[level] = components;
  1227.    CC.TextureWidth1D[level] = width + border;
  1228.    CC.TextureBorder1D[level] = border;
  1229.    CC.TextureImage1D[level] = (GLubyte *) pixels;
  1230. }
  1231.  
  1232.  
  1233.  
  1234. void glTexImage1D( GLenum target, GLint level, GLint components,
  1235.            GLsizei width, GLint border, GLenum format,
  1236.            GLenum type, const GLvoid *pixels )
  1237. {
  1238.    GLubyte *texture;
  1239.  
  1240.    if (INSIDE_BEGIN_END) {
  1241.       gl_error( GL_INVALID_OPERATION, "glTexImage1D" );
  1242.       return;
  1243.    }
  1244.    if (target!=GL_TEXTURE_1D) {
  1245.       gl_error( GL_INVALID_ENUM, "glTexImage1D" );
  1246.       return;
  1247.    }
  1248.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  1249.       gl_error( GL_INVALID_VALUE, "glTexImage1D(level)" );
  1250.       return;
  1251.    }
  1252.    if (components<0 || components>4) {
  1253.       gl_error( GL_INVALID_VALUE, "glTexImage1D(components)" );
  1254.       return;
  1255.    }
  1256.    if (width<=2*border || width>2+MAX_TEXTURE_SIZE) {
  1257.       gl_error( GL_INVALID_VALUE, "glTexImage1D(width)" );
  1258.       return;
  1259.    }
  1260.    if (border!=0 && border!=1) {
  1261.       gl_error( GL_INVALID_VALUE, "glTexImage1D(border)" );
  1262.       return;
  1263.    }
  1264.    {
  1265.       GLint i, w;
  1266.       w = width - 2*border;
  1267.       i = 1;
  1268.       while ( w > i ) {
  1269.          i *= 2;
  1270.       }
  1271.       if (w != i) {
  1272.          gl_error( GL_INVALID_VALUE, "glTexImage1D(width != 2^k + 2*border))");
  1273.          return;
  1274.       }
  1275.    }
  1276.  
  1277.    /* Convert texture image to GLubytes */
  1278.    texture = unpack_texture( components, width+border, 1,
  1279.                              format, type, pixels );
  1280.    if (!texture) {
  1281.       return;
  1282.    }
  1283.  
  1284.    /* install the texture */
  1285.    if (CC.ExecuteFlag) {
  1286.       gl_teximage1d( level, components, width, border, texture );
  1287.    }
  1288.    if (CC.CompileFlag) {
  1289.       gl_save_teximage1d( level, components, width, border, texture );
  1290.       /* Mark the image as don't delete, it'll get deleted if/when the */
  1291.       /* display list is deallocated. */
  1292.       CC.TextureImage1DDeleteFlag[level] = GL_FALSE;
  1293.    }
  1294.    else {
  1295.       /* Mark this image as deletable because it's not in a display list. */
  1296.       CC.TextureImage1DDeleteFlag[level] = GL_TRUE;
  1297.    }
  1298. }
  1299.  
  1300.  
  1301.  
  1302. void gl_teximage2d( GLint level, GLint components,
  1303.             GLsizei width, GLsizei height, GLint border,
  1304.             const GLubyte *pixels )
  1305. {
  1306.    /* check if we can delete the current image */
  1307.    if (CC.TextureImage2D[level] && CC.TextureImage2DDeleteFlag[level]) {
  1308.       free( CC.TextureImage2D[level] );
  1309.    }
  1310.  
  1311.    CC.TextureComponents2D[level] = components;
  1312.    CC.TextureWidth2D[level] = width + border;
  1313.    CC.TextureHeight2D[level] = height + border;
  1314.    CC.TextureBorder2D[level] = border;
  1315.    CC.TextureImage2D[level] = (GLubyte *) pixels;
  1316. }
  1317.  
  1318.  
  1319.  
  1320. void glTexImage2D( GLenum target, GLint level, GLint components,
  1321.            GLsizei width, GLsizei height, GLint border,
  1322.            GLenum format, GLenum type, const GLvoid *pixels )
  1323. {
  1324.    GLubyte *texture;
  1325.  
  1326.    if (INSIDE_BEGIN_END) {
  1327.       gl_error( GL_INVALID_OPERATION, "glTexImage2D" );
  1328.       return;
  1329.    }
  1330.    if (target!=GL_TEXTURE_2D) {
  1331.       gl_error( GL_INVALID_ENUM, "glTexImage2D(target)" );
  1332.       return;
  1333.    }
  1334.    if (level<0 || level>=MAX_TEXTURE_LEVELS) {
  1335.       gl_error( GL_INVALID_VALUE, "glTexImage2D(level)" );
  1336.       return;
  1337.    }
  1338.    if (components<0 || components>4) {
  1339.       gl_error( GL_INVALID_VALUE, "glTexImage2D(components)" );
  1340.       return;
  1341.    }
  1342.    if (width<=2*border || width>2+MAX_TEXTURE_SIZE) {
  1343.       gl_error( GL_INVALID_VALUE, "glTexImage2D(width)" );
  1344.       return;
  1345.    }
  1346.    if (height<=2*border || height>2+MAX_TEXTURE_SIZE) {
  1347.       gl_error( GL_INVALID_VALUE, "glTexImage2D(height)" );
  1348.       return;
  1349.    }
  1350.    if (border!=0 && border!=1) {
  1351.       gl_error( GL_INVALID_VALUE, "glTexImage2D(border)" );
  1352.       return;
  1353.    }
  1354.    {
  1355.       GLint i, w;
  1356.       w = width - 2*border;
  1357.       i = 1;
  1358.       while ( w > i ) {
  1359.          i *= 2;
  1360.       }
  1361.       if (w != i) {
  1362.          gl_error(GL_INVALID_VALUE, "glTexImage2D(width != 2^k + 2*border))");
  1363.          return;
  1364.       }
  1365.    }
  1366.    {
  1367.       GLint i, h;
  1368.       h = height - 2*border;
  1369.       i = 1;
  1370.       while ( h > i ) {
  1371.          i *= 2;
  1372.       }
  1373.       if (h != i) {
  1374.          gl_error(GL_INVALID_VALUE, "glTexImage2D(height != 2^k + 2*border))");
  1375.          return;
  1376.       }
  1377.    }
  1378.  
  1379.    /* Convert texture image to GLubytes */
  1380.    texture = unpack_texture( components, width+border, height+border,
  1381.                              format, type, pixels );
  1382.    if (!texture) {
  1383.       return;
  1384.    }
  1385.  
  1386.    /* install the texture */
  1387.    if (CC.ExecuteFlag) {
  1388.       gl_teximage2d( level, components, width, height, border, texture );
  1389.    }
  1390.    if (CC.CompileFlag) {
  1391.       gl_save_teximage2d( level, components, width, height, border, texture );
  1392.       /* Mark the image as don't delete, it'll get deleted if/when the */
  1393.       /* display list is deallocated. */
  1394.       CC.TextureImage2DDeleteFlag[level] = GL_FALSE;
  1395.    }
  1396.    else {
  1397.       /* Mark this image as deletable because it's not in a display list. */
  1398.       CC.TextureImage2DDeleteFlag[level] = GL_TRUE;
  1399.    }
  1400. }
  1401.  
  1402.  
  1403.  
  1404. void glGetTexImage( GLenum target, GLint level, GLenum format,
  1405.             GLenum type, GLvoid *pixels )
  1406. {
  1407.    /* TODO */
  1408. }
  1409.  
  1410.  
  1411.  
  1412.  
  1413. /**********************************************************************/
  1414. /*                   Perform Texture Mapping                          */
  1415. /**********************************************************************/
  1416.  
  1417.  
  1418.  
  1419. /*
  1420.  * Combine incoming fragment color with texel color to produce output color.
  1421.  */
  1422. static void apply_texture( GLuint n, GLint components,
  1423.      GLubyte red[], GLubyte green[], GLubyte blue[], GLubyte alpha[],
  1424.      GLubyte tred[], GLubyte tgreen[], GLubyte tblue[], GLubyte talpha[] )
  1425. {
  1426.    register GLuint i;
  1427.    GLint envred, envgreen, envblue;
  1428.  
  1429.    /* Texture environment color */
  1430.    envred   = (GLint) (CC.Texture.EnvColor[0] * 255.0F);
  1431.    envgreen = (GLint) (CC.Texture.EnvColor[1] * 255.0F);
  1432.    envblue  = (GLint) (CC.Texture.EnvColor[2] * 255.0F);
  1433.  
  1434.    if (CC.RedScale!=255.0) {
  1435.       /* This is a hack!  Rescale input colors from [0,scale] to [0,255]. */
  1436.       GLfloat rscale = 255.0 / CC.RedScale;
  1437.       GLfloat gscale = 255.0 / CC.GreenScale;
  1438.       GLfloat bscale = 255.0 / CC.BlueScale;
  1439.       GLfloat ascale = 255.0 / CC.AlphaScale;
  1440.       for (i=0;i<n;i++) {
  1441.      red[i]   = (GLint) (red[i]   * rscale);
  1442.      green[i] = (GLint) (green[i] * gscale);
  1443.      blue[i]  = (GLint) (blue[i]  * bscale);
  1444.      alpha[i] = (GLint) (alpha[i] * ascale);
  1445.       }
  1446.    }
  1447.  
  1448. /*
  1449.  * Use (A*(B+1)) >> 8 as a fast approximation of (A*B)/255 for A and B in [0,255]
  1450.  */
  1451. #define PROD(A,B)   (((GLint)(A) * (GLint)(B)+1) >> 8)
  1452.  
  1453.    switch (CC.Texture.EnvMode) {
  1454.       case GL_MODULATE:
  1455.          switch (components) {
  1456.         case 1:  /* luminance */
  1457.            for (i=0;i<n;i++) {
  1458.           /* Cv = LtCf */
  1459.           red[i]   = PROD( tred[i], red[i] );
  1460.           green[i] = PROD( tred[i], green[i] );
  1461.           blue[i]  = PROD( tred[i], blue[i] );
  1462.           /* Av = Af */
  1463.            }
  1464.            break;
  1465.         case 2: /* luminance, alpha */
  1466.            for (i=0;i<n;i++) {
  1467.           /* Cv = LtCf */
  1468.           red[i]   = PROD( tred[i], red[i] );
  1469.           green[i] = PROD( tred[i], green[i] );
  1470.           blue[i]  = PROD( tred[i], blue[i] );
  1471.           /* Av = AtAf */
  1472.           alpha[i] = PROD( talpha[i], alpha[i] );
  1473.            }
  1474.            break;
  1475.         case 3: /* rgb */
  1476.            for (i=0;i<n;i++) {
  1477.           /* Cv = CtCf */
  1478.           red[i]   = PROD( tred[i],   red[i] );
  1479.           green[i] = PROD( tgreen[i], green[i] );
  1480.           blue[i]  = PROD( tblue[i],  blue[i] );
  1481.           /* Av = Af */
  1482.            }
  1483.            break;
  1484.         case 4: /* rgb, alpha */
  1485.            for (i=0;i<n;i++) {
  1486.           /* Cv = CtCf */
  1487.           red[i]   = PROD( tred[i],   red[i] );
  1488.           green[i] = PROD( tgreen[i], green[i] );
  1489.           blue[i]  = PROD( tblue[i],  blue[i] );
  1490.           /* Av = AtAf */
  1491.           alpha[i] = PROD( talpha[i], alpha[i] );
  1492.            }
  1493.            break;
  1494.      } /* components */
  1495.      break;
  1496.       case GL_DECAL:
  1497.          switch (components) {
  1498.         case 3:
  1499.            for (i=0;i<n;i++) {
  1500.           /* Cv = Ct */
  1501.           red[i]   = tred[i];
  1502.           green[i] = tgreen[i];
  1503.           blue[i]  = tblue[i];
  1504.           /* Av = Af */
  1505.            }
  1506.            break;
  1507.         case 4:
  1508.            for (i=0;i<n;i++) {
  1509.           /* Cv = (1-At)Cf + AtCt */
  1510.           GLint t = talpha[i], s = 255 - t;
  1511.           red[i]   = PROD(s,red[i])   + PROD(t,tred[i]);
  1512.           green[i] = PROD(s,green[i]) + PROD(t,tgreen[i]);
  1513.           blue[i]  = PROD(s,blue[i])  + PROD(t,tblue[i]);
  1514.           /* Av = Af */
  1515.            }
  1516.            break;
  1517.      }
  1518.      break;
  1519.       case GL_BLEND:
  1520.      switch (components) {
  1521.         case 1:
  1522.            for (i=0;i<n;i++) {
  1523.           /* Cv = (1-Lt)Cf + LtCc */
  1524.           GLint t = tred[i], s = 255 - t;
  1525.           red[i]   = PROD(s,red[i])   + PROD(t,envred);
  1526.           green[i] = PROD(s,green[i]) + PROD(t,envgreen);
  1527.           blue[i]  = PROD(s,blue[i])  + PROD(t,envblue);
  1528.           /* Av = Af */
  1529.            }
  1530.            break;
  1531.         case 2:
  1532.            for (i=0;i<n;i++) {
  1533.           /* Cv = (1-Lt)Cf + LtCc */
  1534.           GLint t = tred[i], s = 255 - t;
  1535.           red[i]   = PROD(s,red[i])   + PROD(t,envred);
  1536.           green[i] = PROD(s,green[i]) + PROD(t,envgreen);
  1537.           blue[i]  = PROD(s,blue[i])  + PROD(t,envblue);
  1538.           /* Av = AtAf */
  1539.           alpha[i] = PROD(talpha[i], alpha[i]);
  1540.            }
  1541.            break;
  1542.         case 3:
  1543.            for (i=0;i<n;i++) {
  1544.           /* Cv = (1-Ct)Cf + CtCc */
  1545.           red[i]   = PROD((255-tred[i]),  red[i]  ) + PROD(tred[i],  envred  );
  1546.           green[i] = PROD((255-tgreen[i]),green[i]) + PROD(tgreen[i],envgreen);
  1547.           blue[i]  = PROD((255-tblue[i]), blue[i] ) + PROD(tblue[i], envblue );
  1548.           /* Av = Af */
  1549.            }
  1550.            break;
  1551.         case 4:
  1552.            for (i=0;i<n;i++) {
  1553.           /* Cv = (1-Ct)Cf + CtCc */
  1554.           red[i]   = PROD((255-tred[i]),  red[i]  ) + PROD(tred[i],  envred  );
  1555.           green[i] = PROD((255-tgreen[i]),green[i]) + PROD(tgreen[i],envgreen);
  1556.           blue[i]  = PROD((255-tblue[i]), blue[i] ) + PROD(tblue[i], envblue );
  1557.           /* Av = AtAf */
  1558.           alpha[i] = PROD(talpha[i], alpha[i]);
  1559.            }
  1560.            break;
  1561.      }
  1562.      break;
  1563.       case GL_REPLACE_EXT:
  1564.      switch (components) {
  1565.         case 1:
  1566.            for (i=0;i<n;i++) {
  1567.           /* Cv = Lt */
  1568.           red[i] = green[i] = blue[i] = tred[i];
  1569.           /* Av = Af */
  1570.            }
  1571.            break;
  1572.         case 2:
  1573.            for (i=0;i<n;i++) {
  1574.           /* Cv = Lt */
  1575.           red[i] = green[i] = blue[i] = tred[i];
  1576.           /* Av = At */
  1577.           alpha[i] = talpha[i];
  1578.            }
  1579.            break;
  1580.         case 3:
  1581.            for (i=0;i<n;i++) {
  1582.           /* Cv = Ct */
  1583.           red[i]   = tred[i];
  1584.           green[i] = tgreen[i];
  1585.           blue[i]  = tblue[i];
  1586.           /* Av = Af */
  1587.            }
  1588.            break;
  1589.         case 4:
  1590.            for (i=0;i<n;i++) {
  1591.           /* Cv = Ct */
  1592.           red[i]   = tred[i];
  1593.           green[i] = tgreen[i];
  1594.           blue[i]  = tblue[i];
  1595.           /* Av = At */
  1596.           alpha[i] = talpha[i];
  1597.            }
  1598.            break;
  1599.      }
  1600.      break;
  1601.    }
  1602. #undef PROD
  1603.  
  1604.    if (CC.RedScale!=255.0) {
  1605.       /* This is a hack!  Rescale input colors from [0,255] to [0,scale]. */
  1606.       GLfloat rscale = CC.RedScale   / 255.0;
  1607.       GLfloat gscale = CC.GreenScale / 255.0;
  1608.       GLfloat bscale = CC.BlueScale  / 255.0;
  1609.       GLfloat ascale = CC.AlphaScale / 255.0;
  1610.       for (i=0;i<n;i++) {
  1611.      red[i]   = (GLint) (red[i]   * rscale);
  1612.      green[i] = (GLint) (green[i] * gscale);
  1613.      blue[i]  = (GLint) (blue[i]  * bscale);
  1614.      alpha[i] = (GLint) (alpha[i] * ascale);
  1615.       }
  1616.    }
  1617.  
  1618.  
  1619. }
  1620.  
  1621.  
  1622. /*
  1623.  * Apply the 1-D texture to an array of pixels.
  1624.  */
  1625. void gl_texture_pixels_1d( GLuint n, GLfloat s[], 
  1626.                GLubyte red[], GLubyte green[],
  1627.                GLubyte blue[], GLubyte alpha[] )
  1628. {
  1629.    GLubyte tred[PB_SIZE], tgreen[PB_SIZE];
  1630.    GLubyte tblue[PB_SIZE], talpha[PB_SIZE];
  1631.    GLint alpha_offset;
  1632.    GLuint level;
  1633.    GLuint i;
  1634.  
  1635.    level = 0;
  1636.  
  1637.    if (!CC.TextureImage1D[level]) {
  1638.       /* no texture image */
  1639.       return;
  1640.    }
  1641.  
  1642.    /* alpha_offset = offset of the alpha value in the texel of a texture image */
  1643.    if (CC.TextureComponents1D[level]==2) {
  1644.       alpha_offset = 1;
  1645.    }
  1646.    else if (CC.TextureComponents1D[level]==4) {
  1647.       alpha_offset = 3;
  1648.    }
  1649.    else {
  1650.       alpha_offset = 0;
  1651.    }
  1652.  
  1653.    /*
  1654.     * Compute texel colors.
  1655.     */
  1656.    for (i=0;i<n;i++) {
  1657.       GLfloat ss;
  1658.       GLboolean border;
  1659.  
  1660.       border = GL_FALSE;   /* Use border pixel color? */
  1661.  
  1662.       /* S COORDINATE */
  1663.       if (CC.Texture.WrapS1D==GL_REPEAT) {
  1664.          ss = s[i];
  1665.          while (ss<0.0F)  ss += 1.0F;
  1666.          while (ss>1.0F)  ss -= 1.0F;
  1667. /*     ss = s[i] - (GLfloat) (GLint) s[i];*/
  1668.       }
  1669.       else {
  1670.      /* GL_CLAMP */
  1671.      if (s[i]<0.0F || s[i]>1.0F) {
  1672.         if (CC.TextureBorder1D[level]) {
  1673.            /* use border texel */
  1674.            border = GL_TRUE;
  1675.         }
  1676.         else {
  1677.            /* use border color */
  1678.            ss = (s[i]<0.0F) ? 0.0F : 1.0F;
  1679.         }
  1680.      }
  1681.      else {
  1682.         ss = s[i];
  1683.      }
  1684.       }
  1685.  
  1686.       if (border) {
  1687.      tred[i]   = (GLint) (CC.Texture.BorderColor[0] * 255.0F);
  1688.      tgreen[i] = (GLint) (CC.Texture.BorderColor[1] * 255.0F);
  1689.      tblue[i]  = (GLint) (CC.Texture.BorderColor[2] * 255.0F);
  1690.      talpha[i] = (GLint) (CC.Texture.BorderColor[3] * 255.0F);
  1691.       }
  1692.       else {
  1693.      GLuint x, p;
  1694.      if (ss<1.0F) {
  1695.         x = (GLuint) (CC.TextureWidth1D[level] * ss);
  1696.      }
  1697.      else {
  1698.         x = CC.TextureWidth1D[level]-1;
  1699.      }
  1700.  
  1701.      p = CC.TextureComponents1D[level] * x;
  1702.      tred[i]   = CC.TextureImage1D[level][p];
  1703.      tgreen[i] = CC.TextureImage1D[level][p+1];
  1704.      tblue[i]  = CC.TextureImage1D[level][p+2];
  1705.      talpha[i] = CC.TextureImage1D[level][p+alpha_offset];
  1706.       }
  1707.    }
  1708.  
  1709.    apply_texture( n, CC.TextureComponents1D[level],
  1710.           red, green, blue, alpha, tred, tgreen, tblue, talpha );
  1711. }
  1712.  
  1713.  
  1714.  
  1715. /*
  1716.  * Apply the 2-D texture to an array of pixels.
  1717.  */
  1718. void gl_texture_pixels_2d( GLuint n,
  1719.                GLfloat s[], GLfloat t[],
  1720.                GLubyte red[], GLubyte green[],
  1721.                GLubyte blue[], GLubyte alpha[] )
  1722. {
  1723.    GLubyte tred[PB_SIZE], tgreen[PB_SIZE];
  1724.    GLubyte tblue[PB_SIZE], talpha[PB_SIZE];
  1725.    GLint alpha_offset;
  1726.    GLuint level;
  1727.    GLuint i;
  1728.  
  1729.    level = 0;
  1730.  
  1731.    if (!CC.TextureImage2D[level]) {
  1732.       /* no texture image */
  1733.       return;
  1734.    }
  1735.  
  1736.    /* alpha_offset = offset of the alpha value in the texel of a texture image */
  1737.    if (CC.TextureComponents2D[level]==2) {
  1738.       alpha_offset = 1;
  1739.    }
  1740.    else if (CC.TextureComponents2D[level]==4) {
  1741.       alpha_offset = 3;
  1742.    }
  1743.    else {
  1744.       alpha_offset = 0;
  1745.    }
  1746.  
  1747.    /*
  1748.     * Compute texel colors.
  1749.     */
  1750.    for (i=0;i<n;i++) {
  1751.       GLfloat ss, tt;
  1752.       GLboolean border;
  1753.  
  1754.       border = GL_FALSE;   /* Use border pixel color? */
  1755.  
  1756.       /* S COORDINATE */
  1757.       if (CC.Texture.WrapS2D==GL_REPEAT) {
  1758.          ss = s[i];
  1759.          while (ss<0.0F)  ss += 1.0F;
  1760.          while (ss>1.0F)  ss -= 1.0F;
  1761. /*         ss = s[i] - (GLfloat) (GLint) s[i];*/
  1762.       }
  1763.       else {
  1764.      /* GL_CLAMP */
  1765.      if (s[i]<0.0F || s[i]>1.0F) {
  1766.         if (CC.TextureBorder2D[level]) {
  1767.            /* use border texel */
  1768.            border = GL_TRUE;
  1769.         }
  1770.         else {
  1771.            /* use border color */
  1772.            ss = (s[i]<0.0F) ? 0.0F : 1.0F;
  1773.         }
  1774.      }
  1775.      else {
  1776.         ss = s[i];
  1777.      }
  1778.       }
  1779.  
  1780.       /* T COORDINATE */
  1781.       if (CC.Texture.WrapT2D==GL_REPEAT) {
  1782.          tt = t[i];
  1783.          while (tt<0.0F)  tt += 1.0F;
  1784.          while (tt>1.0F)  tt -= 1.0F;
  1785. /*         tt = t[i] - (GLfloat) (GLint) t[i];*/
  1786.       }
  1787.       else {
  1788.      /* GL_CLAMP */
  1789.      if (t[i]<0.0F || t[i]>1.0F) {
  1790.         if (CC.TextureBorder2D[level]) {
  1791.            /* use border texel */
  1792.            border = GL_TRUE;
  1793.         }
  1794.         else {
  1795.            /* use border color */
  1796.            tt = (t[i]<0.0F) ? 0.0F : 1.0F;
  1797.         }
  1798.      }
  1799.      else {
  1800.         tt = t[i];
  1801.      }
  1802.       }
  1803.  
  1804.       if (border) {
  1805.      tred[i]   = (GLint) (CC.Texture.BorderColor[0] * 255.0F);
  1806.      tgreen[i] = (GLint) (CC.Texture.BorderColor[1] * 255.0F);
  1807.      tblue[i]  = (GLint) (CC.Texture.BorderColor[2] * 255.0F);
  1808.      talpha[i] = (GLint) (CC.Texture.BorderColor[3] * 255.0F);
  1809.       }
  1810.       else {
  1811.      GLuint x, y, p;
  1812.      if (ss<1.0F) {
  1813.         x = (GLuint) (CC.TextureWidth2D[level] * ss);
  1814.      }
  1815.      else {
  1816.         x = CC.TextureWidth2D[level]-1;
  1817.      }
  1818.      if (tt<1.0F) {
  1819.         y = (GLuint) (CC.TextureHeight2D[level] * tt);
  1820.      }
  1821.      else {
  1822.         y = CC.TextureHeight2D[level]-1;
  1823.      }      
  1824.  
  1825.      p = CC.TextureComponents2D[level] * (CC.TextureWidth2D[level] * y + x);
  1826.      tred[i]   = CC.TextureImage2D[level][p];
  1827.      tgreen[i] = CC.TextureImage2D[level][p+1];
  1828.      tblue[i]  = CC.TextureImage2D[level][p+2];
  1829.      talpha[i] = CC.TextureImage2D[level][p+alpha_offset];
  1830.       }
  1831.    }
  1832.  
  1833.    apply_texture( n, CC.TextureComponents2D[level],
  1834.           red, green, blue, alpha, tred, tgreen, tblue, talpha );
  1835. }
  1836.  
  1837.