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 #include "main/dispatch.h"
41
42
43 /**
44 * Return texgen state for given coordinate
45 */
46 static struct gl_texgen *
get_texgen(struct gl_context * ctx,struct gl_texture_unit * texUnit,GLenum coord)47 get_texgen(struct gl_context *ctx, struct gl_texture_unit *texUnit,
48 GLenum coord)
49 {
50 if (ctx->API == API_OPENGLES) {
51 return (coord == GL_TEXTURE_GEN_STR_OES)
52 ? &texUnit->GenS : NULL;
53 }
54
55 switch (coord) {
56 case GL_S:
57 return &texUnit->GenS;
58 case GL_T:
59 return &texUnit->GenT;
60 case GL_R:
61 return &texUnit->GenR;
62 case GL_Q:
63 return &texUnit->GenQ;
64 default:
65 return NULL;
66 }
67 }
68
69
70 void GLAPIENTRY
_mesa_TexGenfv(GLenum coord,GLenum pname,const GLfloat * params)71 _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
72 {
73 struct gl_texture_unit *texUnit;
74 struct gl_texgen *texgen;
75 GET_CURRENT_CONTEXT(ctx);
76
77 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
78 _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n",
79 _mesa_enum_to_string(coord),
80 _mesa_enum_to_string(pname),
81 *params,
82 _mesa_enum_to_string((GLenum) (GLint) *params));
83
84 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
85 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)");
86 return;
87 }
88
89 texUnit = _mesa_get_current_tex_unit(ctx);
90
91 texgen = get_texgen(ctx, texUnit, coord);
92 if (!texgen) {
93 _mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)");
94 return;
95 }
96
97 switch (pname) {
98 case GL_TEXTURE_GEN_MODE:
99 {
100 GLenum mode = (GLenum) (GLint) params[0];
101 GLbitfield bit = 0x0;
102 if (texgen->Mode == mode)
103 return;
104 switch (mode) {
105 case GL_OBJECT_LINEAR:
106 bit = TEXGEN_OBJ_LINEAR;
107 break;
108 case GL_EYE_LINEAR:
109 bit = TEXGEN_EYE_LINEAR;
110 break;
111 case GL_SPHERE_MAP:
112 if (coord == GL_S || coord == GL_T)
113 bit = TEXGEN_SPHERE_MAP;
114 break;
115 case GL_REFLECTION_MAP_NV:
116 if (coord != GL_Q)
117 bit = TEXGEN_REFLECTION_MAP_NV;
118 break;
119 case GL_NORMAL_MAP_NV:
120 if (coord != GL_Q)
121 bit = TEXGEN_NORMAL_MAP_NV;
122 break;
123 default:
124 ; /* nop */
125 }
126 if (!bit) {
127 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
128 return;
129 }
130 if (ctx->API != API_OPENGL_COMPAT
131 && (bit & (TEXGEN_REFLECTION_MAP_NV | TEXGEN_NORMAL_MAP_NV)) == 0) {
132 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
133 return;
134 }
135
136 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
137 texgen->Mode = mode;
138 texgen->_ModeBit = bit;
139 }
140 break;
141
142 case GL_OBJECT_PLANE:
143 {
144 if (ctx->API != API_OPENGL_COMPAT) {
145 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
146 return;
147 }
148 if (TEST_EQ_4V(texgen->ObjectPlane, params))
149 return;
150 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
151 COPY_4FV(texgen->ObjectPlane, params);
152 }
153 break;
154
155 case GL_EYE_PLANE:
156 {
157 GLfloat tmp[4];
158
159 if (ctx->API != API_OPENGL_COMPAT) {
160 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
161 return;
162 }
163
164 /* Transform plane equation by the inverse modelview matrix */
165 if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
166 _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
167 }
168 _mesa_transform_vector(tmp, params,
169 ctx->ModelviewMatrixStack.Top->inv);
170 if (TEST_EQ_4V(texgen->EyePlane, tmp))
171 return;
172 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
173 COPY_4FV(texgen->EyePlane, tmp);
174 }
175 break;
176
177 default:
178 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
179 return;
180 }
181
182 if (ctx->Driver.TexGen)
183 ctx->Driver.TexGen( ctx, coord, pname, params );
184 }
185
186
187 void GLAPIENTRY
_mesa_TexGeniv(GLenum coord,GLenum pname,const GLint * params)188 _mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params )
189 {
190 GLfloat p[4];
191 p[0] = (GLfloat) params[0];
192 if (pname == GL_TEXTURE_GEN_MODE) {
193 p[1] = p[2] = p[3] = 0.0F;
194 }
195 else {
196 p[1] = (GLfloat) params[1];
197 p[2] = (GLfloat) params[2];
198 p[3] = (GLfloat) params[3];
199 }
200 _mesa_TexGenfv(coord, pname, p);
201 }
202
203
204 void GLAPIENTRY
_mesa_TexGend(GLenum coord,GLenum pname,GLdouble param)205 _mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
206 {
207 GLfloat p[4];
208 p[0] = (GLfloat) param;
209 p[1] = p[2] = p[3] = 0.0F;
210 _mesa_TexGenfv( coord, pname, p );
211 }
212
213
214 void GLAPIENTRY
_es_GetTexGenfv(GLenum coord,GLenum pname,GLfloat * params)215 _es_GetTexGenfv(GLenum coord, GLenum pname, GLfloat *params)
216 {
217 _mesa_GetTexGenfv(GL_S, pname, params);
218 }
219
220
221 void GLAPIENTRY
_es_TexGenf(GLenum coord,GLenum pname,GLfloat param)222 _es_TexGenf(GLenum coord, GLenum pname, GLfloat param)
223 {
224 if (coord != GL_TEXTURE_GEN_STR_OES) {
225 GET_CURRENT_CONTEXT(ctx);
226 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx](pname)" );
227 return;
228 }
229 /* set S, T, and R at the same time */
230 _mesa_TexGenf(GL_S, pname, param);
231 _mesa_TexGenf(GL_T, pname, param);
232 _mesa_TexGenf(GL_R, pname, param);
233 }
234
235
236 void GLAPIENTRY
_es_TexGenfv(GLenum coord,GLenum pname,const GLfloat * params)237 _es_TexGenfv(GLenum coord, GLenum pname, const GLfloat *params)
238 {
239 if (coord != GL_TEXTURE_GEN_STR_OES) {
240 GET_CURRENT_CONTEXT(ctx);
241 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGen[fx]v(pname)" );
242 return;
243 }
244 /* set S, T, and R at the same time */
245 _mesa_TexGenfv(GL_S, pname, params);
246 _mesa_TexGenfv(GL_T, pname, params);
247 _mesa_TexGenfv(GL_R, pname, params);
248 }
249
250
251 void GLAPIENTRY
_mesa_TexGendv(GLenum coord,GLenum pname,const GLdouble * params)252 _mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params )
253 {
254 GLfloat p[4];
255 p[0] = (GLfloat) params[0];
256 if (pname == GL_TEXTURE_GEN_MODE) {
257 p[1] = p[2] = p[3] = 0.0F;
258 }
259 else {
260 p[1] = (GLfloat) params[1];
261 p[2] = (GLfloat) params[2];
262 p[3] = (GLfloat) params[3];
263 }
264 _mesa_TexGenfv( coord, pname, p );
265 }
266
267
268 void GLAPIENTRY
_mesa_TexGenf(GLenum coord,GLenum pname,GLfloat param)269 _mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param )
270 {
271 GLfloat p[4];
272 p[0] = param;
273 p[1] = p[2] = p[3] = 0.0F;
274 _mesa_TexGenfv(coord, pname, p);
275 }
276
277
278 void GLAPIENTRY
_mesa_TexGeni(GLenum coord,GLenum pname,GLint param)279 _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
280 {
281 GLint p[4];
282 p[0] = param;
283 p[1] = p[2] = p[3] = 0;
284 _mesa_TexGeniv( coord, pname, p );
285 }
286
287
288
289 void GLAPIENTRY
_mesa_GetTexGendv(GLenum coord,GLenum pname,GLdouble * params)290 _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
291 {
292 struct gl_texture_unit *texUnit;
293 struct gl_texgen *texgen;
294 GET_CURRENT_CONTEXT(ctx);
295
296 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
297 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)");
298 return;
299 }
300
301 texUnit = _mesa_get_current_tex_unit(ctx);
302
303 texgen = get_texgen(ctx, texUnit, coord);
304 if (!texgen) {
305 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)");
306 return;
307 }
308
309 switch (pname) {
310 case GL_TEXTURE_GEN_MODE:
311 params[0] = ENUM_TO_DOUBLE(texgen->Mode);
312 break;
313 case GL_OBJECT_PLANE:
314 COPY_4V(params, texgen->ObjectPlane);
315 break;
316 case GL_EYE_PLANE:
317 COPY_4V(params, texgen->EyePlane);
318 break;
319 default:
320 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
321 }
322 }
323
324
325
326 void GLAPIENTRY
_mesa_GetTexGenfv(GLenum coord,GLenum pname,GLfloat * params)327 _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
328 {
329 struct gl_texture_unit *texUnit;
330 struct gl_texgen *texgen;
331 GET_CURRENT_CONTEXT(ctx);
332
333 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
334 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)");
335 return;
336 }
337
338 texUnit = _mesa_get_current_tex_unit(ctx);
339
340 texgen = get_texgen(ctx, texUnit, coord);
341 if (!texgen) {
342 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)");
343 return;
344 }
345
346 switch (pname) {
347 case GL_TEXTURE_GEN_MODE:
348 params[0] = ENUM_TO_FLOAT(texgen->Mode);
349 break;
350 case GL_OBJECT_PLANE:
351 if (ctx->API != API_OPENGL_COMPAT) {
352 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(param)" );
353 return;
354 }
355 COPY_4V(params, texgen->ObjectPlane);
356 break;
357 case GL_EYE_PLANE:
358 if (ctx->API != API_OPENGL_COMPAT) {
359 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(param)" );
360 return;
361 }
362 COPY_4V(params, texgen->EyePlane);
363 break;
364 default:
365 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
366 }
367 }
368
369
370
371 void GLAPIENTRY
_mesa_GetTexGeniv(GLenum coord,GLenum pname,GLint * params)372 _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
373 {
374 struct gl_texture_unit *texUnit;
375 struct gl_texgen *texgen;
376 GET_CURRENT_CONTEXT(ctx);
377
378 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
379 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)");
380 return;
381 }
382
383 texUnit = _mesa_get_current_tex_unit(ctx);
384
385 texgen = get_texgen(ctx, texUnit, coord);
386 if (!texgen) {
387 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)");
388 return;
389 }
390
391 switch (pname) {
392 case GL_TEXTURE_GEN_MODE:
393 params[0] = texgen->Mode;
394 break;
395 case GL_OBJECT_PLANE:
396 if (ctx->API != API_OPENGL_COMPAT) {
397 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(param)" );
398 return;
399 }
400 params[0] = (GLint) texgen->ObjectPlane[0];
401 params[1] = (GLint) texgen->ObjectPlane[1];
402 params[2] = (GLint) texgen->ObjectPlane[2];
403 params[3] = (GLint) texgen->ObjectPlane[3];
404 break;
405 case GL_EYE_PLANE:
406 if (ctx->API != API_OPENGL_COMPAT) {
407 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(param)" );
408 return;
409 }
410 params[0] = (GLint) texgen->EyePlane[0];
411 params[1] = (GLint) texgen->EyePlane[1];
412 params[2] = (GLint) texgen->EyePlane[2];
413 params[3] = (GLint) texgen->EyePlane[3];
414 break;
415 default:
416 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
417 }
418 }
419