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