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 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 */
185 static void
gettexgendv(GLuint texunitIndex,GLenum coord,GLenum pname,GLdouble * params,const char * caller)186 gettexgendv( 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 */
218 static void
gettexgenfv(GLenum texunitIndex,GLenum coord,GLenum pname,GLfloat * params,const char * caller)219 gettexgenfv( 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 */
259 static void
gettexgeniv(GLenum texunitIndex,GLenum coord,GLenum pname,GLint * params,const char * caller)260 gettexgeniv( 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
305 void GLAPIENTRY
_mesa_TexGenfv(GLenum coord,GLenum pname,const GLfloat * params)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
313 void GLAPIENTRY
_mesa_MultiTexGenfvEXT(GLenum texunit,GLenum coord,GLenum pname,const GLfloat * params)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
320 void GLAPIENTRY
_mesa_TexGeniv(GLenum coord,GLenum pname,const GLint * params)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
337 void GLAPIENTRY
_mesa_MultiTexGenivEXT(GLenum texunit,GLenum coord,GLenum pname,const GLint * params)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
354 void GLAPIENTRY
_mesa_TexGend(GLenum coord,GLenum pname,GLdouble param)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
365 void GLAPIENTRY
_mesa_MultiTexGendEXT(GLenum texunit,GLenum coord,GLenum pname,GLdouble param)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
374 void GLAPIENTRY
_es_GetTexGenfv(GLenum coord,GLenum pname,GLfloat * params)375 _es_GetTexGenfv(GLenum coord, GLenum pname, GLfloat *params)
376 {
377 _mesa_GetTexGenfv(GL_S, pname, params);
378 }
379
380
381 void GLAPIENTRY
_es_TexGenf(GLenum coord,GLenum pname,GLfloat param)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
396 void GLAPIENTRY
_es_TexGenfv(GLenum coord,GLenum pname,const GLfloat * params)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
411 void GLAPIENTRY
_mesa_TexGendv(GLenum coord,GLenum pname,const GLdouble * params)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
429 void GLAPIENTRY
_mesa_MultiTexGendvEXT(GLenum texunit,GLenum coord,GLenum pname,const GLdouble * params)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
446 void GLAPIENTRY
_mesa_TexGenf(GLenum coord,GLenum pname,GLfloat param)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
457 void GLAPIENTRY
_mesa_MultiTexGenfEXT(GLenum texunit,GLenum coord,GLenum pname,GLfloat param)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
467 void GLAPIENTRY
_mesa_TexGeni(GLenum coord,GLenum pname,GLint param)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
477 void GLAPIENTRY
_mesa_MultiTexGeniEXT(GLenum texunit,GLenum coord,GLenum pname,GLint param)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
487 void GLAPIENTRY
_mesa_GetTexGendv(GLenum coord,GLenum pname,GLdouble * params)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
495 void GLAPIENTRY
_mesa_GetMultiTexGendvEXT(GLenum texunit,GLenum coord,GLenum pname,GLdouble * params)496 _mesa_GetMultiTexGendvEXT( GLenum texunit, GLenum coord, GLenum pname, GLdouble *params )
497 {
498 gettexgendv(texunit - GL_TEXTURE0, coord, pname, params, "glGetMultiTexGendvEXT");
499 }
500
501
502 void GLAPIENTRY
_mesa_GetTexGenfv(GLenum coord,GLenum pname,GLfloat * params)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
510 void GLAPIENTRY
_mesa_GetMultiTexGenfvEXT(GLenum texunit,GLenum coord,GLenum pname,GLfloat * params)511 _mesa_GetMultiTexGenfvEXT( GLenum texunit, GLenum coord, GLenum pname, GLfloat *params )
512 {
513 gettexgenfv(texunit - GL_TEXTURE0, coord, pname, params, "glGetMultiTexGenfvEXT");
514 }
515
516
517 void GLAPIENTRY
_mesa_GetTexGeniv(GLenum coord,GLenum pname,GLint * params)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
525 void GLAPIENTRY
_mesa_GetMultiTexGenivEXT(GLenum texunit,GLenum coord,GLenum pname,GLint * params)526 _mesa_GetMultiTexGenivEXT( GLenum texunit, GLenum coord, GLenum pname, GLint *params )
527 {
528 gettexgeniv(texunit - GL_TEXTURE0, coord, pname, params, "glGetTexGenivEXT");
529 }
530