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