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