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