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