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