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