texgen.c revision b8e80941
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 41 42/** 43 * Return texgen state for given coordinate 44 */ 45static struct gl_texgen * 46get_texgen(struct gl_context *ctx, struct gl_fixedfunc_texture_unit *texUnit, 47 GLenum coord) 48{ 49 if (ctx->API == API_OPENGLES) { 50 return (coord == GL_TEXTURE_GEN_STR_OES) 51 ? &texUnit->GenS : NULL; 52 } 53 54 switch (coord) { 55 case GL_S: 56 return &texUnit->GenS; 57 case GL_T: 58 return &texUnit->GenT; 59 case GL_R: 60 return &texUnit->GenR; 61 case GL_Q: 62 return &texUnit->GenQ; 63 default: 64 return NULL; 65 } 66} 67 68 69void GLAPIENTRY 70_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params ) 71{ 72 struct gl_fixedfunc_texture_unit *texUnit; 73 struct gl_texgen *texgen; 74 GET_CURRENT_CONTEXT(ctx); 75 76 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) 77 _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n", 78 _mesa_enum_to_string(coord), 79 _mesa_enum_to_string(pname), 80 *params, 81 _mesa_enum_to_string((GLenum) (GLint) *params)); 82 83 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { 84 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)"); 85 return; 86 } 87 88 texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx); 89 90 texgen = get_texgen(ctx, texUnit, coord); 91 if (!texgen) { 92 _mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)"); 93 return; 94 } 95 96 switch (pname) { 97 case GL_TEXTURE_GEN_MODE: 98 { 99 GLenum mode = (GLenum) (GLint) params[0]; 100 GLbitfield bit = 0x0; 101 if (texgen->Mode == mode) 102 return; 103 switch (mode) { 104 case GL_OBJECT_LINEAR: 105 bit = TEXGEN_OBJ_LINEAR; 106 break; 107 case GL_EYE_LINEAR: 108 bit = TEXGEN_EYE_LINEAR; 109 break; 110 case GL_SPHERE_MAP: 111 if (coord == GL_S || coord == GL_T) 112 bit = TEXGEN_SPHERE_MAP; 113 break; 114 case GL_REFLECTION_MAP_NV: 115 if (coord != GL_Q) 116 bit = TEXGEN_REFLECTION_MAP_NV; 117 break; 118 case GL_NORMAL_MAP_NV: 119 if (coord != GL_Q) 120 bit = TEXGEN_NORMAL_MAP_NV; 121 break; 122 default: 123 ; /* nop */ 124 } 125 if (!bit) { 126 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 127 return; 128 } 129 if (ctx->API != API_OPENGL_COMPAT 130 && (bit & (TEXGEN_REFLECTION_MAP_NV | TEXGEN_NORMAL_MAP_NV)) == 0) { 131 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 132 return; 133 } 134 135 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 136 texgen->Mode = mode; 137 texgen->_ModeBit = bit; 138 } 139 break; 140 141 case GL_OBJECT_PLANE: 142 { 143 if (ctx->API != API_OPENGL_COMPAT) { 144 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 145 return; 146 } 147 if (TEST_EQ_4V(texgen->ObjectPlane, params)) 148 return; 149 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 150 COPY_4FV(texgen->ObjectPlane, params); 151 } 152 break; 153 154 case GL_EYE_PLANE: 155 { 156 GLfloat tmp[4]; 157 158 if (ctx->API != API_OPENGL_COMPAT) { 159 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 160 return; 161 } 162 163 /* Transform plane equation by the inverse modelview matrix */ 164 if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { 165 _math_matrix_analyse(ctx->ModelviewMatrixStack.Top); 166 } 167 _mesa_transform_vector(tmp, params, 168 ctx->ModelviewMatrixStack.Top->inv); 169 if (TEST_EQ_4V(texgen->EyePlane, tmp)) 170 return; 171 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE); 172 COPY_4FV(texgen->EyePlane, tmp); 173 } 174 break; 175 176 default: 177 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); 178 return; 179 } 180 181 if (ctx->Driver.TexGen) 182 ctx->Driver.TexGen( ctx, coord, pname, params ); 183} 184 185 186void GLAPIENTRY 187_mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params ) 188{ 189 GLfloat p[4]; 190 p[0] = (GLfloat) params[0]; 191 if (pname == GL_TEXTURE_GEN_MODE) { 192 p[1] = p[2] = p[3] = 0.0F; 193 } 194 else { 195 p[1] = (GLfloat) params[1]; 196 p[2] = (GLfloat) params[2]; 197 p[3] = (GLfloat) params[3]; 198 } 199 _mesa_TexGenfv(coord, pname, p); 200} 201 202 203void GLAPIENTRY 204_mesa_TexGend(GLenum coord, GLenum pname, GLdouble param ) 205{ 206 GLfloat p[4]; 207 p[0] = (GLfloat) param; 208 p[1] = p[2] = p[3] = 0.0F; 209 _mesa_TexGenfv( coord, pname, p ); 210} 211 212 213void GLAPIENTRY 214_es_GetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) 215{ 216 _mesa_GetTexGenfv(GL_S, pname, params); 217} 218 219 220void GLAPIENTRY 221_es_TexGenf(GLenum coord, GLenum pname, GLfloat param) 222{ 223 if (coord != GL_TEXTURE_GEN_STR_OES) { 224 GET_CURRENT_CONTEXT(ctx); 225 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx](pname)" ); 226 return; 227 } 228 /* set S, T, and R at the same time */ 229 _mesa_TexGenf(GL_S, pname, param); 230 _mesa_TexGenf(GL_T, pname, param); 231 _mesa_TexGenf(GL_R, pname, param); 232} 233 234 235void GLAPIENTRY 236_es_TexGenfv(GLenum coord, GLenum pname, const GLfloat *params) 237{ 238 if (coord != GL_TEXTURE_GEN_STR_OES) { 239 GET_CURRENT_CONTEXT(ctx); 240 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx]v(pname)" ); 241 return; 242 } 243 /* set S, T, and R at the same time */ 244 _mesa_TexGenfv(GL_S, pname, params); 245 _mesa_TexGenfv(GL_T, pname, params); 246 _mesa_TexGenfv(GL_R, pname, params); 247} 248 249 250void GLAPIENTRY 251_mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params ) 252{ 253 GLfloat p[4]; 254 p[0] = (GLfloat) params[0]; 255 if (pname == GL_TEXTURE_GEN_MODE) { 256 p[1] = p[2] = p[3] = 0.0F; 257 } 258 else { 259 p[1] = (GLfloat) params[1]; 260 p[2] = (GLfloat) params[2]; 261 p[3] = (GLfloat) params[3]; 262 } 263 _mesa_TexGenfv( coord, pname, p ); 264} 265 266 267void GLAPIENTRY 268_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param ) 269{ 270 GLfloat p[4]; 271 p[0] = param; 272 p[1] = p[2] = p[3] = 0.0F; 273 _mesa_TexGenfv(coord, pname, p); 274} 275 276 277void GLAPIENTRY 278_mesa_TexGeni( GLenum coord, GLenum pname, GLint param ) 279{ 280 GLint p[4]; 281 p[0] = param; 282 p[1] = p[2] = p[3] = 0; 283 _mesa_TexGeniv( coord, pname, p ); 284} 285 286 287 288void GLAPIENTRY 289_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params ) 290{ 291 struct gl_fixedfunc_texture_unit *texUnit; 292 struct gl_texgen *texgen; 293 GET_CURRENT_CONTEXT(ctx); 294 295 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { 296 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)"); 297 return; 298 } 299 300 texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx); 301 302 texgen = get_texgen(ctx, texUnit, coord); 303 if (!texgen) { 304 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)"); 305 return; 306 } 307 308 switch (pname) { 309 case GL_TEXTURE_GEN_MODE: 310 params[0] = ENUM_TO_DOUBLE(texgen->Mode); 311 break; 312 case GL_OBJECT_PLANE: 313 COPY_4V(params, texgen->ObjectPlane); 314 break; 315 case GL_EYE_PLANE: 316 COPY_4V(params, texgen->EyePlane); 317 break; 318 default: 319 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); 320 } 321} 322 323 324 325void GLAPIENTRY 326_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ) 327{ 328 struct gl_fixedfunc_texture_unit *texUnit; 329 struct gl_texgen *texgen; 330 GET_CURRENT_CONTEXT(ctx); 331 332 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { 333 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)"); 334 return; 335 } 336 337 texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx); 338 339 texgen = get_texgen(ctx, texUnit, coord); 340 if (!texgen) { 341 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)"); 342 return; 343 } 344 345 switch (pname) { 346 case GL_TEXTURE_GEN_MODE: 347 params[0] = ENUM_TO_FLOAT(texgen->Mode); 348 break; 349 case GL_OBJECT_PLANE: 350 if (ctx->API != API_OPENGL_COMPAT) { 351 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(param)" ); 352 return; 353 } 354 COPY_4V(params, texgen->ObjectPlane); 355 break; 356 case GL_EYE_PLANE: 357 if (ctx->API != API_OPENGL_COMPAT) { 358 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(param)" ); 359 return; 360 } 361 COPY_4V(params, texgen->EyePlane); 362 break; 363 default: 364 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); 365 } 366} 367 368 369 370void GLAPIENTRY 371_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params ) 372{ 373 struct gl_fixedfunc_texture_unit *texUnit; 374 struct gl_texgen *texgen; 375 GET_CURRENT_CONTEXT(ctx); 376 377 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { 378 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)"); 379 return; 380 } 381 382 texUnit = _mesa_get_current_fixedfunc_tex_unit(ctx); 383 384 texgen = get_texgen(ctx, texUnit, coord); 385 if (!texgen) { 386 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)"); 387 return; 388 } 389 390 switch (pname) { 391 case GL_TEXTURE_GEN_MODE: 392 params[0] = texgen->Mode; 393 break; 394 case GL_OBJECT_PLANE: 395 if (ctx->API != API_OPENGL_COMPAT) { 396 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(param)" ); 397 return; 398 } 399 params[0] = (GLint) texgen->ObjectPlane[0]; 400 params[1] = (GLint) texgen->ObjectPlane[1]; 401 params[2] = (GLint) texgen->ObjectPlane[2]; 402 params[3] = (GLint) texgen->ObjectPlane[3]; 403 break; 404 case GL_EYE_PLANE: 405 if (ctx->API != API_OPENGL_COMPAT) { 406 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(param)" ); 407 return; 408 } 409 params[0] = (GLint) texgen->EyePlane[0]; 410 params[1] = (GLint) texgen->EyePlane[1]; 411 params[2] = (GLint) texgen->EyePlane[2]; 412 params[3] = (GLint) texgen->EyePlane[3]; 413 break; 414 default: 415 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); 416 } 417} 418