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 */ 50static struct gl_texgen * 51get_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 74void 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 192static 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 209static 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 220void GLAPIENTRY 221_es_GetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) 222{ 223 _mesa_GetTexGenfv(GL_S, pname, params); 224} 225 226 227void 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 242void 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 258static 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 275void 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 285void 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 296static 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 334void 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 380void 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 431void 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