texgen.c revision f329adfa497b6b2e0a125ab98a38c656a017270d
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 ASSERT(coord == GL_TEXTURE_GEN_STR_OES); 224 _mesa_GetTexGenfv(GL_S, pname, params); 225} 226 227 228void GLAPIENTRY 229_es_TexGenf(GLenum coord, GLenum pname, GLfloat param) 230{ 231 if (coord != GL_TEXTURE_GEN_STR_OES) { 232 GET_CURRENT_CONTEXT(ctx); 233 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx](pname)" ); 234 return; 235 } 236 /* set S, T, and R at the same time */ 237 _mesa_TexGenf(GL_S, pname, param); 238 _mesa_TexGenf(GL_T, pname, param); 239 _mesa_TexGenf(GL_R, pname, param); 240} 241 242 243void GLAPIENTRY 244_es_TexGenfv(GLenum coord, GLenum pname, const GLfloat *params) 245{ 246 if (coord != GL_TEXTURE_GEN_STR_OES) { 247 GET_CURRENT_CONTEXT(ctx); 248 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx]v(pname)" ); 249 return; 250 } 251 /* set S, T, and R at the same time */ 252 _mesa_TexGenfv(GL_S, pname, params); 253 _mesa_TexGenfv(GL_T, pname, params); 254 _mesa_TexGenfv(GL_R, pname, params); 255} 256 257#endif 258 259static void GLAPIENTRY 260_mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params ) 261{ 262 GLfloat p[4]; 263 p[0] = (GLfloat) params[0]; 264 if (pname == GL_TEXTURE_GEN_MODE) { 265 p[1] = p[2] = p[3] = 0.0F; 266 } 267 else { 268 p[1] = (GLfloat) params[1]; 269 p[2] = (GLfloat) params[2]; 270 p[3] = (GLfloat) params[3]; 271 } 272 _mesa_TexGenfv( coord, pname, p ); 273} 274 275 276void GLAPIENTRY 277_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param ) 278{ 279 GLfloat p[4]; 280 p[0] = param; 281 p[1] = p[2] = p[3] = 0.0F; 282 _mesa_TexGenfv(coord, pname, p); 283} 284 285 286void GLAPIENTRY 287_mesa_TexGeni( GLenum coord, GLenum pname, GLint param ) 288{ 289 GLint p[4]; 290 p[0] = param; 291 p[1] = p[2] = p[3] = 0; 292 _mesa_TexGeniv( coord, pname, p ); 293} 294 295 296 297static void GLAPIENTRY 298_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params ) 299{ 300 struct gl_texture_unit *texUnit; 301 struct gl_texgen *texgen; 302 GET_CURRENT_CONTEXT(ctx); 303 ASSERT_OUTSIDE_BEGIN_END(ctx); 304 305 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { 306 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)"); 307 return; 308 } 309 310 texUnit = _mesa_get_current_tex_unit(ctx); 311 312 texgen = get_texgen(ctx, texUnit, coord); 313 if (!texgen) { 314 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)"); 315 return; 316 } 317 318 switch (pname) { 319 case GL_TEXTURE_GEN_MODE: 320 params[0] = ENUM_TO_DOUBLE(texgen->Mode); 321 break; 322 case GL_OBJECT_PLANE: 323 COPY_4V(params, texgen->ObjectPlane); 324 break; 325 case GL_EYE_PLANE: 326 COPY_4V(params, texgen->EyePlane); 327 break; 328 default: 329 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); 330 } 331} 332 333 334 335void GLAPIENTRY 336_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ) 337{ 338 struct gl_texture_unit *texUnit; 339 struct gl_texgen *texgen; 340 GET_CURRENT_CONTEXT(ctx); 341 ASSERT_OUTSIDE_BEGIN_END(ctx); 342 343 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { 344 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)"); 345 return; 346 } 347 348 texUnit = _mesa_get_current_tex_unit(ctx); 349 350 texgen = get_texgen(ctx, texUnit, coord); 351 if (!texgen) { 352 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)"); 353 return; 354 } 355 356 switch (pname) { 357 case GL_TEXTURE_GEN_MODE: 358 params[0] = ENUM_TO_FLOAT(texgen->Mode); 359 break; 360 case GL_OBJECT_PLANE: 361 COPY_4V(params, texgen->ObjectPlane); 362 break; 363 case GL_EYE_PLANE: 364 COPY_4V(params, texgen->EyePlane); 365 break; 366 default: 367 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); 368 } 369} 370 371 372 373static void GLAPIENTRY 374_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params ) 375{ 376 struct gl_texture_unit *texUnit; 377 struct gl_texgen *texgen; 378 GET_CURRENT_CONTEXT(ctx); 379 ASSERT_OUTSIDE_BEGIN_END(ctx); 380 381 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { 382 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)"); 383 return; 384 } 385 386 texUnit = _mesa_get_current_tex_unit(ctx); 387 388 texgen = get_texgen(ctx, texUnit, coord); 389 if (!texgen) { 390 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)"); 391 return; 392 } 393 394 switch (pname) { 395 case GL_TEXTURE_GEN_MODE: 396 params[0] = texgen->Mode; 397 break; 398 case GL_OBJECT_PLANE: 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 params[0] = (GLint) texgen->EyePlane[0]; 406 params[1] = (GLint) texgen->EyePlane[1]; 407 params[2] = (GLint) texgen->EyePlane[2]; 408 params[3] = (GLint) texgen->EyePlane[3]; 409 break; 410 default: 411 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); 412 } 413} 414 415 416void 417_mesa_init_texgen_dispatch(struct _glapi_table *disp) 418{ 419 SET_GetTexGendv(disp, _mesa_GetTexGendv); 420 SET_GetTexGenfv(disp, _mesa_GetTexGenfv); 421 SET_GetTexGeniv(disp, _mesa_GetTexGeniv); 422 SET_TexGend(disp, _mesa_TexGend); 423 SET_TexGendv(disp, _mesa_TexGendv); 424 SET_TexGenf(disp, _mesa_TexGenf); 425 SET_TexGenfv(disp, _mesa_TexGenfv); 426 SET_TexGeni(disp, _mesa_TexGeni); 427 SET_TexGeniv(disp, _mesa_TexGeniv); 428} 429 430 431#endif /* FEATURE_texgen */ 432