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, GLuint texunitIndex, GLenum coord, const char* caller) 47{ 48 struct gl_fixedfunc_texture_unit* texUnit; 49 if (texunitIndex >= ctx->Const.MaxTextureCoordUnits) { 50 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unit=%d)", caller, texunitIndex); 51 return NULL; 52 } 53 54 texUnit = _mesa_get_fixedfunc_tex_unit(ctx, texunitIndex); 55 56 if (ctx->API == API_OPENGLES) { 57 return (coord == GL_TEXTURE_GEN_STR_OES) 58 ? &texUnit->GenS : NULL; 59 } 60 61 switch (coord) { 62 case GL_S: 63 return &texUnit->GenS; 64 case GL_T: 65 return &texUnit->GenT; 66 case GL_R: 67 return &texUnit->GenR; 68 case GL_Q: 69 return &texUnit->GenQ; 70 default: 71 return NULL; 72 } 73} 74 75 76/* Helper for glTexGenfv and glMultiTexGenfvEXT functions */ 77static void 78texgenfv( GLuint texunitIndex, GLenum coord, GLenum pname, 79 const GLfloat *params, const char* caller ) 80{ 81 struct gl_texgen *texgen; 82 GET_CURRENT_CONTEXT(ctx); 83 84 texgen = get_texgen(ctx, texunitIndex, coord, caller); 85 if (!texgen) { 86 _mesa_error(ctx, GL_INVALID_ENUM, "%s(coord)", caller); 87 return; 88 } 89 90 struct gl_fixedfunc_texture_unit *unit = &ctx->Texture.FixedFuncUnit[texunitIndex]; 91 int index = coord == GL_TEXTURE_GEN_STR_OES ? 0 : (coord - GL_S); 92 93 switch (pname) { 94 case GL_TEXTURE_GEN_MODE: 95 { 96 GLenum mode = (GLenum) (GLint) params[0]; 97 GLbitfield bit = 0x0; 98 if (texgen->Mode == mode) 99 return; 100 switch (mode) { 101 case GL_OBJECT_LINEAR: 102 bit = TEXGEN_OBJ_LINEAR; 103 break; 104 case GL_EYE_LINEAR: 105 bit = TEXGEN_EYE_LINEAR; 106 break; 107 case GL_SPHERE_MAP: 108 if (coord == GL_S || coord == GL_T) 109 bit = TEXGEN_SPHERE_MAP; 110 break; 111 case GL_REFLECTION_MAP_NV: 112 if (coord != GL_Q) 113 bit = TEXGEN_REFLECTION_MAP_NV; 114 break; 115 case GL_NORMAL_MAP_NV: 116 if (coord != GL_Q) 117 bit = TEXGEN_NORMAL_MAP_NV; 118 break; 119 default: 120 ; /* nop */ 121 } 122 if (!bit) { 123 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 124 return; 125 } 126 if (ctx->API != API_OPENGL_COMPAT 127 && (bit & (TEXGEN_REFLECTION_MAP_NV | TEXGEN_NORMAL_MAP_NV)) == 0) { 128 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 129 return; 130 } 131 132 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE | _NEW_FF_VERT_PROGRAM, 133 GL_TEXTURE_BIT); 134 texgen->Mode = mode; 135 texgen->_ModeBit = bit; 136 } 137 break; 138 139 case GL_OBJECT_PLANE: 140 { 141 if (ctx->API != API_OPENGL_COMPAT) { 142 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 143 return; 144 } 145 if (TEST_EQ_4V(unit->ObjectPlane[index], params)) 146 return; 147 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 148 COPY_4FV(unit->ObjectPlane[index], params); 149 } 150 break; 151 152 case GL_EYE_PLANE: 153 { 154 GLfloat tmp[4]; 155 156 if (ctx->API != API_OPENGL_COMPAT) { 157 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); 158 return; 159 } 160 161 /* Transform plane equation by the inverse modelview matrix */ 162 if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { 163 _math_matrix_analyse(ctx->ModelviewMatrixStack.Top); 164 } 165 _mesa_transform_vector(tmp, params, 166 ctx->ModelviewMatrixStack.Top->inv); 167 if (TEST_EQ_4V(unit->EyePlane[index], tmp)) 168 return; 169 FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE, GL_TEXTURE_BIT); 170 COPY_4FV(unit->EyePlane[index], tmp); 171 } 172 break; 173 174 default: 175 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); 176 return; 177 } 178 179 if (ctx->Driver.TexGen) 180 ctx->Driver.TexGen( ctx, coord, pname, params ); 181} 182 183 184/* Helper for glGetTexGendv / glGetMultiTexGendvEXT */ 185static void 186gettexgendv( GLuint texunitIndex, GLenum coord, GLenum pname, 187 GLdouble *params, const char* caller) 188{ 189 struct gl_texgen *texgen; 190 GET_CURRENT_CONTEXT(ctx); 191 192 texgen = get_texgen(ctx, texunitIndex, coord, caller); 193 if (!texgen) { 194 _mesa_error(ctx, GL_INVALID_ENUM, "%s(coord)", caller); 195 return; 196 } 197 198 struct gl_fixedfunc_texture_unit *unit = &ctx->Texture.FixedFuncUnit[texunitIndex]; 199 int index = coord == GL_TEXTURE_GEN_STR_OES ? 0 : (coord - GL_S); 200 201 switch (pname) { 202 case GL_TEXTURE_GEN_MODE: 203 params[0] = ENUM_TO_DOUBLE(texgen->Mode); 204 break; 205 case GL_OBJECT_PLANE: 206 COPY_4V(params, unit->ObjectPlane[index]); 207 break; 208 case GL_EYE_PLANE: 209 COPY_4V(params, unit->EyePlane[index]); 210 break; 211 default: 212 _mesa_error( ctx, GL_INVALID_ENUM, "%s(pname)", caller ); 213 } 214} 215 216 217/* Helper for glGetTexGenfv / glGetMultiTexGenfvEXT */ 218static void 219gettexgenfv( GLenum texunitIndex, GLenum coord, GLenum pname, 220 GLfloat *params, const char* caller ) 221{ 222 struct gl_texgen *texgen; 223 GET_CURRENT_CONTEXT(ctx); 224 225 texgen = get_texgen(ctx, texunitIndex, coord, caller); 226 if (!texgen) { 227 _mesa_error(ctx, GL_INVALID_ENUM, "%s(coord)", caller); 228 return; 229 } 230 231 struct gl_fixedfunc_texture_unit *unit = &ctx->Texture.FixedFuncUnit[texunitIndex]; 232 int index = coord == GL_TEXTURE_GEN_STR_OES ? 0 : (coord - GL_S); 233 234 switch (pname) { 235 case GL_TEXTURE_GEN_MODE: 236 params[0] = ENUM_TO_FLOAT(texgen->Mode); 237 break; 238 case GL_OBJECT_PLANE: 239 if (ctx->API != API_OPENGL_COMPAT) { 240 _mesa_error( ctx, GL_INVALID_ENUM, "%s(param)", caller ); 241 return; 242 } 243 COPY_4V(params, unit->ObjectPlane[index]); 244 break; 245 case GL_EYE_PLANE: 246 if (ctx->API != API_OPENGL_COMPAT) { 247 _mesa_error( ctx, GL_INVALID_ENUM, "%s(param)", caller ); 248 return; 249 } 250 COPY_4V(params, unit->EyePlane[index]); 251 break; 252 default: 253 _mesa_error( ctx, GL_INVALID_ENUM, "%s(pname)", caller ); 254 } 255} 256 257 258/* Helper for glGetTexGeniv / glGetMultiTexGenivEXT */ 259static void 260gettexgeniv( GLenum texunitIndex, GLenum coord, GLenum pname, 261 GLint *params, const char* caller) 262{ 263 struct gl_texgen *texgen; 264 GET_CURRENT_CONTEXT(ctx); 265 266 texgen = get_texgen(ctx, texunitIndex, coord, caller); 267 if (!texgen) { 268 _mesa_error(ctx, GL_INVALID_ENUM, "%s(coord)", caller); 269 return; 270 } 271 272 struct gl_fixedfunc_texture_unit *unit = &ctx->Texture.FixedFuncUnit[texunitIndex]; 273 int index = coord == GL_TEXTURE_GEN_STR_OES ? 0 : (coord - GL_S); 274 275 switch (pname) { 276 case GL_TEXTURE_GEN_MODE: 277 params[0] = texgen->Mode; 278 break; 279 case GL_OBJECT_PLANE: 280 if (ctx->API != API_OPENGL_COMPAT) { 281 _mesa_error( ctx, GL_INVALID_ENUM, "%s(param)" , caller); 282 return; 283 } 284 params[0] = (GLint) unit->ObjectPlane[index][0]; 285 params[1] = (GLint) unit->ObjectPlane[index][1]; 286 params[2] = (GLint) unit->ObjectPlane[index][2]; 287 params[3] = (GLint) unit->ObjectPlane[index][3]; 288 break; 289 case GL_EYE_PLANE: 290 if (ctx->API != API_OPENGL_COMPAT) { 291 _mesa_error( ctx, GL_INVALID_ENUM, "%s(param)" , caller); 292 return; 293 } 294 params[0] = (GLint) unit->EyePlane[index][0]; 295 params[1] = (GLint) unit->EyePlane[index][1]; 296 params[2] = (GLint) unit->EyePlane[index][2]; 297 params[3] = (GLint) unit->EyePlane[index][3]; 298 break; 299 default: 300 _mesa_error( ctx, GL_INVALID_ENUM, "%s(pname)" , caller); 301 } 302} 303 304 305void GLAPIENTRY 306_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params ) 307{ 308 GET_CURRENT_CONTEXT(ctx); 309 texgenfv(ctx->Texture.CurrentUnit, coord, pname, params, "glTexGenfv"); 310} 311 312 313void GLAPIENTRY 314_mesa_MultiTexGenfvEXT( GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params ) 315{ 316 texgenfv(texunit - GL_TEXTURE0, coord, pname, params, "glMultiTexGenfvEXT"); 317} 318 319 320void GLAPIENTRY 321_mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params ) 322{ 323 GET_CURRENT_CONTEXT(ctx); 324 GLfloat p[4]; 325 p[0] = (GLfloat) params[0]; 326 if (pname == GL_TEXTURE_GEN_MODE) { 327 p[1] = p[2] = p[3] = 0.0F; 328 } 329 else { 330 p[1] = (GLfloat) params[1]; 331 p[2] = (GLfloat) params[2]; 332 p[3] = (GLfloat) params[3]; 333 } 334 texgenfv(ctx->Texture.CurrentUnit, coord, pname, p, "glTexGeniv"); 335} 336 337void GLAPIENTRY 338_mesa_MultiTexGenivEXT(GLenum texunit, GLenum coord, GLenum pname, const GLint *params ) 339{ 340 GLfloat p[4]; 341 p[0] = (GLfloat) params[0]; 342 if (pname == GL_TEXTURE_GEN_MODE) { 343 p[1] = p[2] = p[3] = 0.0F; 344 } 345 else { 346 p[1] = (GLfloat) params[1]; 347 p[2] = (GLfloat) params[2]; 348 p[3] = (GLfloat) params[3]; 349 } 350 texgenfv(texunit - GL_TEXTURE0, coord, pname, p, "glMultiTexGenivEXT"); 351} 352 353 354void GLAPIENTRY 355_mesa_TexGend(GLenum coord, GLenum pname, GLdouble param ) 356{ 357 GET_CURRENT_CONTEXT(ctx); 358 GLfloat p[4]; 359 p[0] = (GLfloat) param; 360 p[1] = p[2] = p[3] = 0.0F; 361 texgenfv(ctx->Texture.CurrentUnit, coord, pname, p, "glTexGend"); 362} 363 364 365void GLAPIENTRY 366_mesa_MultiTexGendEXT(GLenum texunit, GLenum coord, GLenum pname, GLdouble param ) 367{ 368 GLfloat p[4]; 369 p[0] = (GLfloat) param; 370 p[1] = p[2] = p[3] = 0.0F; 371 texgenfv(texunit - GL_TEXTURE0, coord, pname, p, "glMultiTexGendEXT"); 372} 373 374void GLAPIENTRY 375_es_GetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) 376{ 377 _mesa_GetTexGenfv(GL_S, pname, params); 378} 379 380 381void GLAPIENTRY 382_es_TexGenf(GLenum coord, GLenum pname, GLfloat param) 383{ 384 if (coord != GL_TEXTURE_GEN_STR_OES) { 385 GET_CURRENT_CONTEXT(ctx); 386 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx](pname)" ); 387 return; 388 } 389 /* set S, T, and R at the same time */ 390 _mesa_TexGenf(GL_S, pname, param); 391 _mesa_TexGenf(GL_T, pname, param); 392 _mesa_TexGenf(GL_R, pname, param); 393} 394 395 396void GLAPIENTRY 397_es_TexGenfv(GLenum coord, GLenum pname, const GLfloat *params) 398{ 399 if (coord != GL_TEXTURE_GEN_STR_OES) { 400 GET_CURRENT_CONTEXT(ctx); 401 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx]v(pname)" ); 402 return; 403 } 404 /* set S, T, and R at the same time */ 405 _mesa_TexGenfv(GL_S, pname, params); 406 _mesa_TexGenfv(GL_T, pname, params); 407 _mesa_TexGenfv(GL_R, pname, params); 408} 409 410 411void GLAPIENTRY 412_mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params ) 413{ 414 GET_CURRENT_CONTEXT(ctx); 415 GLfloat p[4]; 416 p[0] = (GLfloat) params[0]; 417 if (pname == GL_TEXTURE_GEN_MODE) { 418 p[1] = p[2] = p[3] = 0.0F; 419 } 420 else { 421 p[1] = (GLfloat) params[1]; 422 p[2] = (GLfloat) params[2]; 423 p[3] = (GLfloat) params[3]; 424 } 425 texgenfv(ctx->Texture.CurrentUnit, coord, pname, p, "glTexGendv"); 426} 427 428 429void GLAPIENTRY 430_mesa_MultiTexGendvEXT(GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params ) 431{ 432 GLfloat p[4]; 433 p[0] = (GLfloat) params[0]; 434 if (pname == GL_TEXTURE_GEN_MODE) { 435 p[1] = p[2] = p[3] = 0.0F; 436 } 437 else { 438 p[1] = (GLfloat) params[1]; 439 p[2] = (GLfloat) params[2]; 440 p[3] = (GLfloat) params[3]; 441 } 442 texgenfv(texunit - GL_TEXTURE0, coord, pname, p, "glMultiTexGendvEXT"); 443} 444 445 446void GLAPIENTRY 447_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param ) 448{ 449 GET_CURRENT_CONTEXT(ctx); 450 GLfloat p[4]; 451 p[0] = param; 452 p[1] = p[2] = p[3] = 0.0F; 453 texgenfv(ctx->Texture.CurrentUnit, coord, pname, p, "glTexGenf"); 454} 455 456 457void GLAPIENTRY 458_mesa_MultiTexGenfEXT( GLenum texunit, GLenum coord, GLenum pname, GLfloat param ) 459{ 460 GLfloat p[4]; 461 p[0] = param; 462 p[1] = p[2] = p[3] = 0.0F; 463 texgenfv(texunit - GL_TEXTURE0, coord, pname, p, "glMultiTexGenfEXT"); 464} 465 466 467void GLAPIENTRY 468_mesa_TexGeni( GLenum coord, GLenum pname, GLint param ) 469{ 470 GLint p[4]; 471 p[0] = param; 472 p[1] = p[2] = p[3] = 0; 473 _mesa_TexGeniv( coord, pname, p ); 474} 475 476 477void GLAPIENTRY 478_mesa_MultiTexGeniEXT( GLenum texunit, GLenum coord, GLenum pname, GLint param ) 479{ 480 GLint p[4]; 481 p[0] = param; 482 p[1] = p[2] = p[3] = 0; 483 _mesa_MultiTexGenivEXT( texunit, coord, pname, p ); 484} 485 486 487void GLAPIENTRY 488_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params ) 489{ 490 GET_CURRENT_CONTEXT(ctx); 491 gettexgendv(ctx->Texture.CurrentUnit, coord, pname, params, "glGetTexGendv"); 492} 493 494 495void GLAPIENTRY 496_mesa_GetMultiTexGendvEXT( GLenum texunit, GLenum coord, GLenum pname, GLdouble *params ) 497{ 498 gettexgendv(texunit - GL_TEXTURE0, coord, pname, params, "glGetMultiTexGendvEXT"); 499} 500 501 502void GLAPIENTRY 503_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ) 504{ 505 GET_CURRENT_CONTEXT(ctx); 506 gettexgenfv(ctx->Texture.CurrentUnit, coord, pname, params, "glGetTexGenfv"); 507} 508 509 510void GLAPIENTRY 511_mesa_GetMultiTexGenfvEXT( GLenum texunit, GLenum coord, GLenum pname, GLfloat *params ) 512{ 513 gettexgenfv(texunit - GL_TEXTURE0, coord, pname, params, "glGetMultiTexGenfvEXT"); 514} 515 516 517void GLAPIENTRY 518_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params ) 519{ 520 GET_CURRENT_CONTEXT(ctx); 521 gettexgeniv(ctx->Texture.CurrentUnit, coord, pname, params, "glGetTexGeniv"); 522} 523 524 525void GLAPIENTRY 526_mesa_GetMultiTexGenivEXT( GLenum texunit, GLenum coord, GLenum pname, GLint *params ) 527{ 528 gettexgeniv(texunit - GL_TEXTURE0, coord, pname, params, "glGetTexGenivEXT"); 529} 530