Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
      5  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 /**
     27  * \file texgen.c
     28  *
     29  * glTexGen-related functions
     30  */
     31 
     32 
     33 #include "main/glheader.h"
     34 #include "main/context.h"
     35 #include "main/enums.h"
     36 #include "main/macros.h"
     37 #include "main/texgen.h"
     38 #include "main/texstate.h"
     39 #include "math/m_matrix.h"
     40 #include "main/dispatch.h"
     41 
     42 
     43 /**
     44  * Return texgen state for given coordinate
     45  */
     46 static struct gl_texgen *
     47 get_texgen(struct gl_context *ctx, struct gl_texture_unit *texUnit,
     48            GLenum coord)
     49 {
     50    if (ctx->API == API_OPENGLES) {
     51       return (coord == GL_TEXTURE_GEN_STR_OES)
     52          ? &texUnit->GenS : NULL;
     53    }
     54 
     55    switch (coord) {
     56    case GL_S:
     57       return &texUnit->GenS;
     58    case GL_T:
     59       return &texUnit->GenT;
     60    case GL_R:
     61       return &texUnit->GenR;
     62    case GL_Q:
     63       return &texUnit->GenQ;
     64    default:
     65       return NULL;
     66    }
     67 }
     68 
     69 
     70 void GLAPIENTRY
     71 _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
     72 {
     73    struct gl_texture_unit *texUnit;
     74    struct gl_texgen *texgen;
     75    GET_CURRENT_CONTEXT(ctx);
     76 
     77    if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
     78       _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n",
     79                   _mesa_enum_to_string(coord),
     80                   _mesa_enum_to_string(pname),
     81                   *params,
     82 		  _mesa_enum_to_string((GLenum) (GLint) *params));
     83 
     84    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
     85       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)");
     86       return;
     87    }
     88 
     89    texUnit = _mesa_get_current_tex_unit(ctx);
     90 
     91    texgen = get_texgen(ctx, texUnit, coord);
     92    if (!texgen) {
     93       _mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)");
     94       return;
     95    }
     96 
     97    switch (pname) {
     98    case GL_TEXTURE_GEN_MODE:
     99       {
    100          GLenum mode = (GLenum) (GLint) params[0];
    101          GLbitfield bit = 0x0;
    102          if (texgen->Mode == mode)
    103             return;
    104          switch (mode) {
    105          case GL_OBJECT_LINEAR:
    106             bit = TEXGEN_OBJ_LINEAR;
    107             break;
    108          case GL_EYE_LINEAR:
    109             bit = TEXGEN_EYE_LINEAR;
    110             break;
    111          case GL_SPHERE_MAP:
    112             if (coord == GL_S || coord == GL_T)
    113                bit = TEXGEN_SPHERE_MAP;
    114             break;
    115          case GL_REFLECTION_MAP_NV:
    116             if (coord != GL_Q)
    117                bit = TEXGEN_REFLECTION_MAP_NV;
    118             break;
    119          case GL_NORMAL_MAP_NV:
    120             if (coord != GL_Q)
    121                bit = TEXGEN_NORMAL_MAP_NV;
    122             break;
    123          default:
    124             ; /* nop */
    125          }
    126          if (!bit) {
    127             _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
    128             return;
    129          }
    130          if (ctx->API != API_OPENGL_COMPAT
    131              && (bit & (TEXGEN_REFLECTION_MAP_NV | TEXGEN_NORMAL_MAP_NV)) == 0) {
    132             _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
    133             return;
    134          }
    135 
    136          FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    137          texgen->Mode = mode;
    138          texgen->_ModeBit = bit;
    139       }
    140       break;
    141 
    142    case GL_OBJECT_PLANE:
    143       {
    144          if (ctx->API != API_OPENGL_COMPAT) {
    145             _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
    146             return;
    147          }
    148          if (TEST_EQ_4V(texgen->ObjectPlane, params))
    149             return;
    150          FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    151          COPY_4FV(texgen->ObjectPlane, params);
    152       }
    153       break;
    154 
    155    case GL_EYE_PLANE:
    156       {
    157          GLfloat tmp[4];
    158 
    159          if (ctx->API != API_OPENGL_COMPAT) {
    160             _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
    161             return;
    162          }
    163 
    164          /* Transform plane equation by the inverse modelview matrix */
    165          if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
    166             _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
    167          }
    168          _mesa_transform_vector(tmp, params,
    169                                 ctx->ModelviewMatrixStack.Top->inv);
    170          if (TEST_EQ_4V(texgen->EyePlane, tmp))
    171             return;
    172          FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    173          COPY_4FV(texgen->EyePlane, tmp);
    174       }
    175       break;
    176 
    177    default:
    178       _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
    179       return;
    180    }
    181 
    182    if (ctx->Driver.TexGen)
    183       ctx->Driver.TexGen( ctx, coord, pname, params );
    184 }
    185 
    186 
    187 void GLAPIENTRY
    188 _mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params )
    189 {
    190    GLfloat p[4];
    191    p[0] = (GLfloat) params[0];
    192    if (pname == GL_TEXTURE_GEN_MODE) {
    193       p[1] = p[2] = p[3] = 0.0F;
    194    }
    195    else {
    196       p[1] = (GLfloat) params[1];
    197       p[2] = (GLfloat) params[2];
    198       p[3] = (GLfloat) params[3];
    199    }
    200    _mesa_TexGenfv(coord, pname, p);
    201 }
    202 
    203 
    204 void GLAPIENTRY
    205 _mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
    206 {
    207    GLfloat p[4];
    208    p[0] = (GLfloat) param;
    209    p[1] = p[2] = p[3] = 0.0F;
    210    _mesa_TexGenfv( coord, pname, p );
    211 }
    212 
    213 
    214 void GLAPIENTRY
    215 _es_GetTexGenfv(GLenum coord, GLenum pname, GLfloat *params)
    216 {
    217    _mesa_GetTexGenfv(GL_S, pname, params);
    218 }
    219 
    220 
    221 void GLAPIENTRY
    222 _es_TexGenf(GLenum coord, GLenum pname, GLfloat param)
    223 {
    224    if (coord != GL_TEXTURE_GEN_STR_OES) {
    225       GET_CURRENT_CONTEXT(ctx);
    226       _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx](pname)" );
    227       return;
    228    }
    229    /* set S, T, and R at the same time */
    230    _mesa_TexGenf(GL_S, pname, param);
    231    _mesa_TexGenf(GL_T, pname, param);
    232    _mesa_TexGenf(GL_R, pname, param);
    233 }
    234 
    235 
    236 void GLAPIENTRY
    237 _es_TexGenfv(GLenum coord, GLenum pname, const GLfloat *params)
    238 {
    239    if (coord != GL_TEXTURE_GEN_STR_OES) {
    240       GET_CURRENT_CONTEXT(ctx);
    241       _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx]v(pname)" );
    242       return;
    243    }
    244    /* set S, T, and R at the same time */
    245    _mesa_TexGenfv(GL_S, pname, params);
    246    _mesa_TexGenfv(GL_T, pname, params);
    247    _mesa_TexGenfv(GL_R, pname, params);
    248 }
    249 
    250 
    251 void GLAPIENTRY
    252 _mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params )
    253 {
    254    GLfloat p[4];
    255    p[0] = (GLfloat) params[0];
    256    if (pname == GL_TEXTURE_GEN_MODE) {
    257       p[1] = p[2] = p[3] = 0.0F;
    258    }
    259    else {
    260       p[1] = (GLfloat) params[1];
    261       p[2] = (GLfloat) params[2];
    262       p[3] = (GLfloat) params[3];
    263    }
    264    _mesa_TexGenfv( coord, pname, p );
    265 }
    266 
    267 
    268 void GLAPIENTRY
    269 _mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param )
    270 {
    271    GLfloat p[4];
    272    p[0] = param;
    273    p[1] = p[2] = p[3] = 0.0F;
    274    _mesa_TexGenfv(coord, pname, p);
    275 }
    276 
    277 
    278 void GLAPIENTRY
    279 _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
    280 {
    281    GLint p[4];
    282    p[0] = param;
    283    p[1] = p[2] = p[3] = 0;
    284    _mesa_TexGeniv( coord, pname, p );
    285 }
    286 
    287 
    288 
    289 void GLAPIENTRY
    290 _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
    291 {
    292    struct gl_texture_unit *texUnit;
    293    struct gl_texgen *texgen;
    294    GET_CURRENT_CONTEXT(ctx);
    295 
    296    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
    297       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)");
    298       return;
    299    }
    300 
    301    texUnit = _mesa_get_current_tex_unit(ctx);
    302 
    303    texgen = get_texgen(ctx, texUnit, coord);
    304    if (!texgen) {
    305       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)");
    306       return;
    307    }
    308 
    309    switch (pname) {
    310    case GL_TEXTURE_GEN_MODE:
    311       params[0] = ENUM_TO_DOUBLE(texgen->Mode);
    312       break;
    313    case GL_OBJECT_PLANE:
    314       COPY_4V(params, texgen->ObjectPlane);
    315       break;
    316    case GL_EYE_PLANE:
    317       COPY_4V(params, texgen->EyePlane);
    318       break;
    319    default:
    320       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
    321    }
    322 }
    323 
    324 
    325 
    326 void GLAPIENTRY
    327 _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
    328 {
    329    struct gl_texture_unit *texUnit;
    330    struct gl_texgen *texgen;
    331    GET_CURRENT_CONTEXT(ctx);
    332 
    333    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
    334       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)");
    335       return;
    336    }
    337 
    338    texUnit = _mesa_get_current_tex_unit(ctx);
    339 
    340    texgen = get_texgen(ctx, texUnit, coord);
    341    if (!texgen) {
    342       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)");
    343       return;
    344    }
    345 
    346    switch (pname) {
    347    case GL_TEXTURE_GEN_MODE:
    348       params[0] = ENUM_TO_FLOAT(texgen->Mode);
    349       break;
    350    case GL_OBJECT_PLANE:
    351       if (ctx->API != API_OPENGL_COMPAT) {
    352          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(param)" );
    353          return;
    354       }
    355       COPY_4V(params, texgen->ObjectPlane);
    356       break;
    357    case GL_EYE_PLANE:
    358       if (ctx->API != API_OPENGL_COMPAT) {
    359          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(param)" );
    360          return;
    361       }
    362       COPY_4V(params, texgen->EyePlane);
    363       break;
    364    default:
    365       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
    366    }
    367 }
    368 
    369 
    370 
    371 void GLAPIENTRY
    372 _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
    373 {
    374    struct gl_texture_unit *texUnit;
    375    struct gl_texgen *texgen;
    376    GET_CURRENT_CONTEXT(ctx);
    377 
    378    if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
    379       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)");
    380       return;
    381    }
    382 
    383    texUnit = _mesa_get_current_tex_unit(ctx);
    384 
    385    texgen = get_texgen(ctx, texUnit, coord);
    386    if (!texgen) {
    387       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)");
    388       return;
    389    }
    390 
    391    switch (pname) {
    392    case GL_TEXTURE_GEN_MODE:
    393       params[0] = texgen->Mode;
    394       break;
    395    case GL_OBJECT_PLANE:
    396       if (ctx->API != API_OPENGL_COMPAT) {
    397          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(param)" );
    398          return;
    399       }
    400       params[0] = (GLint) texgen->ObjectPlane[0];
    401       params[1] = (GLint) texgen->ObjectPlane[1];
    402       params[2] = (GLint) texgen->ObjectPlane[2];
    403       params[3] = (GLint) texgen->ObjectPlane[3];
    404       break;
    405    case GL_EYE_PLANE:
    406       if (ctx->API != API_OPENGL_COMPAT) {
    407          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(param)" );
    408          return;
    409       }
    410       params[0] = (GLint) texgen->EyePlane[0];
    411       params[1] = (GLint) texgen->EyePlane[1];
    412       params[2] = (GLint) texgen->EyePlane[2];
    413       params[3] = (GLint) texgen->EyePlane[3];
    414       break;
    415    default:
    416       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
    417    }
    418 }
    419