mesa: add new signed rgba texture format
[mesa.git] / src / mesa / main / texgen.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.5
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 "math/m_matrix.h"
39
40
41 /**
42 * Return texgen state for given coordinate
43 */
44 static struct gl_texgen *
45 get_texgen(struct gl_texture_unit *texUnit, GLenum coord)
46 {
47 switch (coord) {
48 case GL_S:
49 return &texUnit->GenS;
50 case GL_T:
51 return &texUnit->GenT;
52 case GL_R:
53 return &texUnit->GenR;
54 case GL_Q:
55 return &texUnit->GenQ;
56 default:
57 return NULL;
58 }
59 }
60
61
62 void GLAPIENTRY
63 _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
64 {
65 struct gl_texture_unit *texUnit;
66 struct gl_texgen *texgen;
67 GET_CURRENT_CONTEXT(ctx);
68 ASSERT_OUTSIDE_BEGIN_END(ctx);
69
70 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
71 _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n",
72 _mesa_lookup_enum_by_nr(coord),
73 _mesa_lookup_enum_by_nr(pname),
74 *params,
75 _mesa_lookup_enum_by_nr((GLenum) (GLint) *params));
76
77 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
78 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)");
79 return;
80 }
81
82 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
83
84 texgen = get_texgen(texUnit, coord);
85 if (!texgen) {
86 _mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)");
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 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
124 texgen->Mode = mode;
125 texgen->_ModeBit = bit;
126 }
127 break;
128
129 case GL_OBJECT_PLANE:
130 {
131 if (TEST_EQ_4V(texgen->ObjectPlane, params))
132 return;
133 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
134 COPY_4FV(texgen->ObjectPlane, params);
135 }
136 break;
137
138 case GL_EYE_PLANE:
139 {
140 GLfloat tmp[4];
141 /* Transform plane equation by the inverse modelview matrix */
142 if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
143 _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
144 }
145 _mesa_transform_vector(tmp, params,
146 ctx->ModelviewMatrixStack.Top->inv);
147 if (TEST_EQ_4V(texgen->EyePlane, tmp))
148 return;
149 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
150 COPY_4FV(texgen->EyePlane, tmp);
151 }
152 break;
153
154 default:
155 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
156 return;
157 }
158
159 if (ctx->Driver.TexGen)
160 ctx->Driver.TexGen( ctx, coord, pname, params );
161 }
162
163
164 void GLAPIENTRY
165 _mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params )
166 {
167 GLfloat p[4];
168 p[0] = (GLfloat) params[0];
169 if (pname == GL_TEXTURE_GEN_MODE) {
170 p[1] = p[2] = p[3] = 0.0F;
171 }
172 else {
173 p[1] = (GLfloat) params[1];
174 p[2] = (GLfloat) params[2];
175 p[3] = (GLfloat) params[3];
176 }
177 _mesa_TexGenfv(coord, pname, p);
178 }
179
180
181 void GLAPIENTRY
182 _mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
183 {
184 GLfloat p = (GLfloat) param;
185 _mesa_TexGenfv( coord, pname, &p );
186 }
187
188
189 void GLAPIENTRY
190 _mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params )
191 {
192 GLfloat p[4];
193 p[0] = (GLfloat) params[0];
194 if (pname == GL_TEXTURE_GEN_MODE) {
195 p[1] = p[2] = p[3] = 0.0F;
196 }
197 else {
198 p[1] = (GLfloat) params[1];
199 p[2] = (GLfloat) params[2];
200 p[3] = (GLfloat) params[3];
201 }
202 _mesa_TexGenfv( coord, pname, p );
203 }
204
205
206 void GLAPIENTRY
207 _mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param )
208 {
209 _mesa_TexGenfv(coord, pname, &param);
210 }
211
212
213 void GLAPIENTRY
214 _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
215 {
216 _mesa_TexGeniv( coord, pname, &param );
217 }
218
219
220
221 void GLAPIENTRY
222 _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
223 {
224 struct gl_texture_unit *texUnit;
225 struct gl_texgen *texgen;
226 GET_CURRENT_CONTEXT(ctx);
227 ASSERT_OUTSIDE_BEGIN_END(ctx);
228
229 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
230 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)");
231 return;
232 }
233
234 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
235
236 texgen = get_texgen(texUnit, coord);
237 if (!texgen) {
238 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)");
239 return;
240 }
241
242 switch (pname) {
243 case GL_TEXTURE_GEN_MODE:
244 params[0] = ENUM_TO_DOUBLE(texgen->Mode);
245 break;
246 case GL_OBJECT_PLANE:
247 COPY_4V(params, texgen->ObjectPlane);
248 break;
249 case GL_EYE_PLANE:
250 COPY_4V(params, texgen->EyePlane);
251 break;
252 default:
253 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
254 }
255 }
256
257
258
259 void GLAPIENTRY
260 _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
261 {
262 struct gl_texture_unit *texUnit;
263 struct gl_texgen *texgen;
264 GET_CURRENT_CONTEXT(ctx);
265 ASSERT_OUTSIDE_BEGIN_END(ctx);
266
267 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
268 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)");
269 return;
270 }
271
272 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
273
274 texgen = get_texgen(texUnit, coord);
275 if (!texgen) {
276 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)");
277 return;
278 }
279
280 switch (pname) {
281 case GL_TEXTURE_GEN_MODE:
282 params[0] = ENUM_TO_FLOAT(texgen->Mode);
283 break;
284 case GL_OBJECT_PLANE:
285 COPY_4V(params, texgen->ObjectPlane);
286 break;
287 case GL_EYE_PLANE:
288 COPY_4V(params, texgen->EyePlane);
289 break;
290 default:
291 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
292 }
293 }
294
295
296
297 void GLAPIENTRY
298 _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
299 {
300 struct gl_texture_unit *texUnit;
301 struct gl_texgen *texgen;
302 GET_CURRENT_CONTEXT(ctx);
303 ASSERT_OUTSIDE_BEGIN_END(ctx);
304
305 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
306 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)");
307 return;
308 }
309
310 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
311
312 texgen = get_texgen(texUnit, coord);
313 if (!texgen) {
314 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)");
315 return;
316 }
317
318 switch (pname) {
319 case GL_TEXTURE_GEN_MODE:
320 params[0] = texgen->Mode;
321 break;
322 case GL_OBJECT_PLANE:
323 params[0] = (GLint) texgen->ObjectPlane[0];
324 params[1] = (GLint) texgen->ObjectPlane[1];
325 params[2] = (GLint) texgen->ObjectPlane[2];
326 params[3] = (GLint) texgen->ObjectPlane[3];
327 break;
328 case GL_EYE_PLANE:
329 params[0] = (GLint) texgen->EyePlane[0];
330 params[1] = (GLint) texgen->EyePlane[1];
331 params[2] = (GLint) texgen->EyePlane[2];
332 params[3] = (GLint) texgen->EyePlane[3];
333 break;
334 default:
335 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
336 }
337 }
338
339