• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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