add FreeTexImageData hook to help single-copy texturing in drivers
[mesa.git] / src / mesa / main / texstate.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
4 *
5 * Copyright (C) 1999-2005 Brian Paul 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file texstate.c
27 *
28 * Texture state handling.
29 */
30
31 #include "glheader.h"
32 #include "colormac.h"
33 #include "colortab.h"
34 #include "context.h"
35 #include "enums.h"
36 #include "extensions.h"
37 #include "macros.h"
38 #include "nvfragprog.h"
39 #include "texobj.h"
40 #include "teximage.h"
41 #include "texstate.h"
42 #include "mtypes.h"
43 #include "math/m_xform.h"
44 #include "math/m_matrix.h"
45
46
47
48 #ifdef SPECIALCAST
49 /* Needed for an Amiga compiler */
50 #define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X))
51 #define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X))
52 #else
53 /* all other compilers */
54 #define ENUM_TO_FLOAT(X) ((GLfloat)(X))
55 #define ENUM_TO_DOUBLE(X) ((GLdouble)(X))
56 #endif
57
58 /**
59 * Default texture combine environment state. This is used to initialize
60 * a context's texture units and as the basis for converting "classic"
61 * texture environmnets to ARB_texture_env_combine style values.
62 */
63 static const struct gl_tex_env_combine_state default_combine_state = {
64 GL_MODULATE, GL_MODULATE,
65 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
66 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
67 { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA },
68 { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
69 0, 0,
70 2, 2
71 };
72
73
74 void
75 _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
76 {
77 GLuint i;
78
79 ASSERT(src);
80 ASSERT(dst);
81
82 dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
83 dst->Texture._GenFlags = src->Texture._GenFlags;
84 dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
85 dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
86 dst->Texture.SharedPalette = src->Texture.SharedPalette;
87
88 /* per-unit state */
89 for (i = 0; i < src->Const.MaxTextureUnits; i++) {
90 dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled;
91 dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode;
92 COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor);
93 dst->Texture.Unit[i].TexGenEnabled = src->Texture.Unit[i].TexGenEnabled;
94 dst->Texture.Unit[i].GenModeS = src->Texture.Unit[i].GenModeS;
95 dst->Texture.Unit[i].GenModeT = src->Texture.Unit[i].GenModeT;
96 dst->Texture.Unit[i].GenModeR = src->Texture.Unit[i].GenModeR;
97 dst->Texture.Unit[i].GenModeQ = src->Texture.Unit[i].GenModeQ;
98 dst->Texture.Unit[i]._GenBitS = src->Texture.Unit[i]._GenBitS;
99 dst->Texture.Unit[i]._GenBitT = src->Texture.Unit[i]._GenBitT;
100 dst->Texture.Unit[i]._GenBitR = src->Texture.Unit[i]._GenBitR;
101 dst->Texture.Unit[i]._GenBitQ = src->Texture.Unit[i]._GenBitQ;
102 dst->Texture.Unit[i]._GenFlags = src->Texture.Unit[i]._GenFlags;
103 COPY_4V(dst->Texture.Unit[i].ObjectPlaneS, src->Texture.Unit[i].ObjectPlaneS);
104 COPY_4V(dst->Texture.Unit[i].ObjectPlaneT, src->Texture.Unit[i].ObjectPlaneT);
105 COPY_4V(dst->Texture.Unit[i].ObjectPlaneR, src->Texture.Unit[i].ObjectPlaneR);
106 COPY_4V(dst->Texture.Unit[i].ObjectPlaneQ, src->Texture.Unit[i].ObjectPlaneQ);
107 COPY_4V(dst->Texture.Unit[i].EyePlaneS, src->Texture.Unit[i].EyePlaneS);
108 COPY_4V(dst->Texture.Unit[i].EyePlaneT, src->Texture.Unit[i].EyePlaneT);
109 COPY_4V(dst->Texture.Unit[i].EyePlaneR, src->Texture.Unit[i].EyePlaneR);
110 COPY_4V(dst->Texture.Unit[i].EyePlaneQ, src->Texture.Unit[i].EyePlaneQ);
111 dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
112
113 /* GL_EXT_texture_env_combine */
114 dst->Texture.Unit[i].Combine.ModeRGB = src->Texture.Unit[i].Combine.ModeRGB;
115 dst->Texture.Unit[i].Combine.ModeA = src->Texture.Unit[i].Combine.ModeA;
116 COPY_3V(dst->Texture.Unit[i].Combine.SourceRGB, src->Texture.Unit[i].Combine.SourceRGB);
117 COPY_3V(dst->Texture.Unit[i].Combine.SourceA, src->Texture.Unit[i].Combine.SourceA);
118 COPY_3V(dst->Texture.Unit[i].Combine.OperandRGB, src->Texture.Unit[i].Combine.OperandRGB);
119 COPY_3V(dst->Texture.Unit[i].Combine.OperandA, src->Texture.Unit[i].Combine.OperandA);
120 dst->Texture.Unit[i].Combine.ScaleShiftRGB = src->Texture.Unit[i].Combine.ScaleShiftRGB;
121 dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
122
123 /* texture object state */
124 _mesa_copy_texture_object(dst->Texture.Unit[i].Current1D,
125 src->Texture.Unit[i].Current1D);
126 _mesa_copy_texture_object(dst->Texture.Unit[i].Current2D,
127 src->Texture.Unit[i].Current2D);
128 _mesa_copy_texture_object(dst->Texture.Unit[i].Current3D,
129 src->Texture.Unit[i].Current3D);
130 _mesa_copy_texture_object(dst->Texture.Unit[i].CurrentCubeMap,
131 src->Texture.Unit[i].CurrentCubeMap);
132 _mesa_copy_texture_object(dst->Texture.Unit[i].CurrentRect,
133 src->Texture.Unit[i].CurrentRect);
134 }
135 }
136
137
138 /*
139 * For debugging
140 */
141 void
142 _mesa_print_texunit_state( GLcontext *ctx, GLuint unit )
143 {
144 const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
145 _mesa_printf("Texture Unit %d\n", unit);
146 _mesa_printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
147 _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
148 _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
149 _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
150 _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
151 _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
152 _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
153 _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
154 _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
155 _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
156 _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
157 _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
158 _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
159 _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
160 _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
161 _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
162 _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
163 _mesa_printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
164 }
165
166
167
168 /**********************************************************************/
169 /* Texture Environment */
170 /**********************************************************************/
171
172 /**
173 * Convert "classic" texture environment to ARB_texture_env_combine style
174 * environments.
175 *
176 * \param state texture_env_combine state vector to be filled-in.
177 * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
178 * \c GL_BLEND, \c GL_DECAL, etc.).
179 * \param texBaseFormat Base format of the texture associated with the
180 * texture unit.
181 */
182 static void
183 calculate_derived_texenv( struct gl_tex_env_combine_state *state,
184 GLenum mode, GLenum texBaseFormat )
185 {
186 GLenum mode_rgb;
187 GLenum mode_a;
188
189 *state = default_combine_state;
190
191 switch (texBaseFormat) {
192 case GL_ALPHA:
193 state->SourceRGB[0] = GL_PREVIOUS;
194 break;
195
196 case GL_LUMINANCE_ALPHA:
197 case GL_INTENSITY:
198 case GL_RGBA:
199 break;
200
201 case GL_LUMINANCE:
202 case GL_RGB:
203 case GL_YCBCR_MESA:
204 state->SourceA[0] = GL_PREVIOUS;
205 break;
206
207 default:
208 _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv");
209 return;
210 }
211
212 switch (mode) {
213 case GL_REPLACE:
214 case GL_MODULATE:
215 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
216 mode_a = mode;
217 break;
218
219 case GL_DECAL:
220 mode_rgb = GL_INTERPOLATE;
221 mode_a = GL_REPLACE;
222
223 state->SourceA[0] = GL_PREVIOUS;
224
225 /* Having alpha / luminance / intensity textures replace using the
226 * incoming fragment color matches the definition in NV_texture_shader.
227 * The 1.5 spec simply marks these as "undefined".
228 */
229 switch (texBaseFormat) {
230 case GL_ALPHA:
231 case GL_LUMINANCE:
232 case GL_LUMINANCE_ALPHA:
233 case GL_INTENSITY:
234 state->SourceRGB[0] = GL_PREVIOUS;
235 break;
236 case GL_RGB:
237 case GL_YCBCR_MESA:
238 mode_rgb = GL_REPLACE;
239 break;
240 case GL_RGBA:
241 state->SourceRGB[2] = GL_TEXTURE;
242 break;
243 }
244 break;
245
246 case GL_BLEND:
247 mode_rgb = GL_INTERPOLATE;
248 mode_a = GL_MODULATE;
249
250 switch (texBaseFormat) {
251 case GL_ALPHA:
252 mode_rgb = GL_REPLACE;
253 break;
254 case GL_INTENSITY:
255 mode_a = GL_INTERPOLATE;
256 state->SourceA[0] = GL_CONSTANT;
257 state->OperandA[2] = GL_SRC_ALPHA;
258 /* FALLTHROUGH */
259 case GL_LUMINANCE:
260 case GL_RGB:
261 case GL_LUMINANCE_ALPHA:
262 case GL_RGBA:
263 case GL_YCBCR_MESA:
264 state->SourceRGB[2] = GL_TEXTURE;
265 state->SourceA[2] = GL_TEXTURE;
266 state->SourceRGB[0] = GL_CONSTANT;
267 state->OperandRGB[2] = GL_SRC_COLOR;
268 break;
269 }
270 break;
271
272 case GL_ADD:
273 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
274 mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
275 break;
276
277 default:
278 _mesa_problem(NULL,
279 "Invalid texture env mode in calculate_derived_texenv");
280 return;
281 }
282
283 state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
284 ? mode_rgb : GL_REPLACE;
285 state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
286 ? mode_a : GL_REPLACE;
287 }
288
289
290 void GLAPIENTRY
291 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
292 {
293 GET_CURRENT_CONTEXT(ctx);
294 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
295 ASSERT_OUTSIDE_BEGIN_END(ctx);
296
297 #define TE_ERROR(errCode, msg, value) \
298 _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
299
300 if (target == GL_TEXTURE_ENV) {
301 switch (pname) {
302 case GL_TEXTURE_ENV_MODE:
303 {
304 const GLenum mode = (GLenum) (GLint) *param;
305 if (texUnit->EnvMode == mode)
306 return;
307 if (mode == GL_MODULATE ||
308 mode == GL_BLEND ||
309 mode == GL_DECAL ||
310 mode == GL_REPLACE ||
311 (mode == GL_ADD && ctx->Extensions.EXT_texture_env_add) ||
312 (mode == GL_COMBINE &&
313 (ctx->Extensions.EXT_texture_env_combine ||
314 ctx->Extensions.ARB_texture_env_combine))) {
315 /* legal */
316 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
317 texUnit->EnvMode = mode;
318 }
319 else {
320 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
321 return;
322 }
323 }
324 break;
325 case GL_TEXTURE_ENV_COLOR:
326 {
327 GLfloat tmp[4];
328 tmp[0] = CLAMP( param[0], 0.0F, 1.0F );
329 tmp[1] = CLAMP( param[1], 0.0F, 1.0F );
330 tmp[2] = CLAMP( param[2], 0.0F, 1.0F );
331 tmp[3] = CLAMP( param[3], 0.0F, 1.0F );
332 if (TEST_EQ_4V(tmp, texUnit->EnvColor))
333 return;
334 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
335 COPY_4FV(texUnit->EnvColor, tmp);
336 }
337 break;
338 case GL_COMBINE_RGB:
339 if (ctx->Extensions.EXT_texture_env_combine ||
340 ctx->Extensions.ARB_texture_env_combine) {
341 const GLenum mode = (GLenum) (GLint) *param;
342 if (texUnit->Combine.ModeRGB == mode)
343 return;
344 switch (mode) {
345 case GL_REPLACE:
346 case GL_MODULATE:
347 case GL_ADD:
348 case GL_ADD_SIGNED:
349 case GL_INTERPOLATE:
350 /* OK */
351 break;
352 case GL_SUBTRACT:
353 if (!ctx->Extensions.ARB_texture_env_combine) {
354 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
355 return;
356 }
357 break;
358 case GL_DOT3_RGB_EXT:
359 case GL_DOT3_RGBA_EXT:
360 if (!ctx->Extensions.EXT_texture_env_dot3) {
361 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
362 return;
363 }
364 break;
365 case GL_DOT3_RGB:
366 case GL_DOT3_RGBA:
367 if (!ctx->Extensions.ARB_texture_env_dot3) {
368 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
369 return;
370 }
371 break;
372 case GL_MODULATE_ADD_ATI:
373 case GL_MODULATE_SIGNED_ADD_ATI:
374 case GL_MODULATE_SUBTRACT_ATI:
375 if (!ctx->Extensions.ATI_texture_env_combine3) {
376 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
377 return;
378 }
379 break;
380 default:
381 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
382 return;
383 }
384 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
385 texUnit->Combine.ModeRGB = mode;
386 }
387 else {
388 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
389 return;
390 }
391 break;
392 case GL_COMBINE_ALPHA:
393 if (ctx->Extensions.EXT_texture_env_combine ||
394 ctx->Extensions.ARB_texture_env_combine) {
395 const GLenum mode = (GLenum) (GLint) *param;
396 if (texUnit->Combine.ModeA == mode)
397 return;
398 switch (mode) {
399 case GL_REPLACE:
400 case GL_MODULATE:
401 case GL_ADD:
402 case GL_ADD_SIGNED:
403 case GL_INTERPOLATE:
404 /* OK */
405 break;
406 case GL_SUBTRACT:
407 if (!ctx->Extensions.ARB_texture_env_combine) {
408 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
409 return;
410 }
411 break;
412 case GL_MODULATE_ADD_ATI:
413 case GL_MODULATE_SIGNED_ADD_ATI:
414 case GL_MODULATE_SUBTRACT_ATI:
415 if (!ctx->Extensions.ATI_texture_env_combine3) {
416 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
417 return;
418 }
419 break;
420 default:
421 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
422 return;
423 }
424 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
425 texUnit->Combine.ModeA = mode;
426 }
427 else {
428 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
429 return;
430 }
431 break;
432 case GL_SOURCE0_RGB:
433 case GL_SOURCE1_RGB:
434 case GL_SOURCE2_RGB:
435 if (ctx->Extensions.EXT_texture_env_combine ||
436 ctx->Extensions.ARB_texture_env_combine) {
437 const GLenum source = (GLenum) (GLint) *param;
438 const GLuint s = pname - GL_SOURCE0_RGB;
439 if (texUnit->Combine.SourceRGB[s] == source)
440 return;
441 if (source == GL_TEXTURE ||
442 source == GL_CONSTANT ||
443 source == GL_PRIMARY_COLOR ||
444 source == GL_PREVIOUS ||
445 (ctx->Extensions.ARB_texture_env_crossbar &&
446 source >= GL_TEXTURE0 &&
447 source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) ||
448 (ctx->Extensions.ATI_texture_env_combine3 &&
449 (source == GL_ZERO || source == GL_ONE))) {
450 /* legal */
451 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
452 texUnit->Combine.SourceRGB[s] = source;
453 }
454 else {
455 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
456 return;
457 }
458 }
459 else {
460 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
461 return;
462 }
463 break;
464 case GL_SOURCE0_ALPHA:
465 case GL_SOURCE1_ALPHA:
466 case GL_SOURCE2_ALPHA:
467 if (ctx->Extensions.EXT_texture_env_combine ||
468 ctx->Extensions.ARB_texture_env_combine) {
469 const GLenum source = (GLenum) (GLint) *param;
470 const GLuint s = pname - GL_SOURCE0_ALPHA;
471 if (texUnit->Combine.SourceA[s] == source)
472 return;
473 if (source == GL_TEXTURE ||
474 source == GL_CONSTANT ||
475 source == GL_PRIMARY_COLOR ||
476 source == GL_PREVIOUS ||
477 (ctx->Extensions.ARB_texture_env_crossbar &&
478 source >= GL_TEXTURE0 &&
479 source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) ||
480 (ctx->Extensions.ATI_texture_env_combine3 &&
481 (source == GL_ZERO || source == GL_ONE))) {
482 /* legal */
483 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
484 texUnit->Combine.SourceA[s] = source;
485 }
486 else {
487 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
488 return;
489 }
490 }
491 else {
492 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
493 return;
494 }
495 break;
496 case GL_OPERAND0_RGB:
497 case GL_OPERAND1_RGB:
498 if (ctx->Extensions.EXT_texture_env_combine ||
499 ctx->Extensions.ARB_texture_env_combine) {
500 const GLenum operand = (GLenum) (GLint) *param;
501 const GLuint s = pname - GL_OPERAND0_RGB;
502 if (texUnit->Combine.OperandRGB[s] == operand)
503 return;
504 switch (operand) {
505 case GL_SRC_COLOR:
506 case GL_ONE_MINUS_SRC_COLOR:
507 case GL_SRC_ALPHA:
508 case GL_ONE_MINUS_SRC_ALPHA:
509 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
510 texUnit->Combine.OperandRGB[s] = operand;
511 break;
512 default:
513 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
514 return;
515 }
516 }
517 else {
518 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
519 return;
520 }
521 break;
522 case GL_OPERAND0_ALPHA:
523 case GL_OPERAND1_ALPHA:
524 if (ctx->Extensions.EXT_texture_env_combine ||
525 ctx->Extensions.ARB_texture_env_combine) {
526 const GLenum operand = (GLenum) (GLint) *param;
527 if (texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] == operand)
528 return;
529 switch (operand) {
530 case GL_SRC_ALPHA:
531 case GL_ONE_MINUS_SRC_ALPHA:
532 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
533 texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] = operand;
534 break;
535 default:
536 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
537 return;
538 }
539 }
540 else {
541 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
542 return;
543 }
544 break;
545 case GL_OPERAND2_RGB:
546 if (ctx->Extensions.EXT_texture_env_combine ||
547 ctx->Extensions.ARB_texture_env_combine) {
548 const GLenum operand = (GLenum) (GLint) *param;
549 if (texUnit->Combine.OperandRGB[2] == operand)
550 return;
551 switch (operand) {
552 case GL_SRC_COLOR: /* ARB combine only */
553 case GL_ONE_MINUS_SRC_COLOR: /* ARB combine only */
554 case GL_SRC_ALPHA:
555 case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
556 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
557 texUnit->Combine.OperandRGB[2] = operand;
558 break;
559 default:
560 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
561 return;
562 }
563 }
564 else {
565 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
566 return;
567 }
568 break;
569 case GL_OPERAND2_ALPHA:
570 if (ctx->Extensions.EXT_texture_env_combine ||
571 ctx->Extensions.ARB_texture_env_combine) {
572 const GLenum operand = (GLenum) (GLint) *param;
573 if (texUnit->Combine.OperandA[2] == operand)
574 return;
575 switch (operand) {
576 case GL_SRC_ALPHA:
577 case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
578 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
579 texUnit->Combine.OperandA[2] = operand;
580 break;
581 default:
582 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
583 return;
584 }
585 }
586 else {
587 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
588 return;
589 }
590 break;
591 case GL_RGB_SCALE:
592 if (ctx->Extensions.EXT_texture_env_combine ||
593 ctx->Extensions.ARB_texture_env_combine) {
594 GLuint newshift;
595 if (*param == 1.0) {
596 newshift = 0;
597 }
598 else if (*param == 2.0) {
599 newshift = 1;
600 }
601 else if (*param == 4.0) {
602 newshift = 2;
603 }
604 else {
605 _mesa_error( ctx, GL_INVALID_VALUE,
606 "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
607 return;
608 }
609 if (texUnit->Combine.ScaleShiftRGB == newshift)
610 return;
611 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
612 texUnit->Combine.ScaleShiftRGB = newshift;
613 }
614 else {
615 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
616 return;
617 }
618 break;
619 case GL_ALPHA_SCALE:
620 if (ctx->Extensions.EXT_texture_env_combine ||
621 ctx->Extensions.ARB_texture_env_combine) {
622 GLuint newshift;
623 if (*param == 1.0) {
624 newshift = 0;
625 }
626 else if (*param == 2.0) {
627 newshift = 1;
628 }
629 else if (*param == 4.0) {
630 newshift = 2;
631 }
632 else {
633 _mesa_error( ctx, GL_INVALID_VALUE,
634 "glTexEnv(GL_ALPHA_SCALE not 1, 2 or 4)" );
635 return;
636 }
637 if (texUnit->Combine.ScaleShiftA == newshift)
638 return;
639 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
640 texUnit->Combine.ScaleShiftA = newshift;
641 }
642 else {
643 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
644 return;
645 }
646 break;
647 default:
648 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
649 return;
650 }
651 }
652 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
653 /* GL_EXT_texture_lod_bias */
654 if (!ctx->Extensions.EXT_texture_lod_bias) {
655 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
656 return;
657 }
658 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
659 if (texUnit->LodBias == param[0])
660 return;
661 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
662 texUnit->LodBias = param[0];
663 }
664 else {
665 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
666 return;
667 }
668 }
669 else if (target == GL_POINT_SPRITE_NV) {
670 /* GL_ARB_point_sprite / GL_NV_point_sprite */
671 if (!ctx->Extensions.NV_point_sprite
672 && !ctx->Extensions.ARB_point_sprite) {
673 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
674 return;
675 }
676 if (pname == GL_COORD_REPLACE_NV) {
677 const GLenum value = (GLenum) param[0];
678 if (value == GL_TRUE || value == GL_FALSE) {
679 /* It's kind of weird to set point state via glTexEnv,
680 * but that's what the spec calls for.
681 */
682 const GLboolean state = (GLboolean) value;
683 if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state)
684 return;
685 FLUSH_VERTICES(ctx, _NEW_POINT);
686 ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state;
687 }
688 else {
689 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value);
690 return;
691 }
692 }
693 else {
694 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
695 return;
696 }
697 }
698 else {
699 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target );
700 return;
701 }
702
703 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
704 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
705 _mesa_lookup_enum_by_nr(target),
706 _mesa_lookup_enum_by_nr(pname),
707 *param,
708 _mesa_lookup_enum_by_nr((GLenum) (GLint) *param));
709
710 /* Tell device driver about the new texture environment */
711 if (ctx->Driver.TexEnv) {
712 (*ctx->Driver.TexEnv)( ctx, target, pname, param );
713 }
714 }
715
716
717 void GLAPIENTRY
718 _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
719 {
720 _mesa_TexEnvfv( target, pname, &param );
721 }
722
723
724
725 void GLAPIENTRY
726 _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
727 {
728 GLfloat p[4];
729 p[0] = (GLfloat) param;
730 p[1] = p[2] = p[3] = 0.0;
731 _mesa_TexEnvfv( target, pname, p );
732 }
733
734
735 void GLAPIENTRY
736 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
737 {
738 GLfloat p[4];
739 if (pname == GL_TEXTURE_ENV_COLOR) {
740 p[0] = INT_TO_FLOAT( param[0] );
741 p[1] = INT_TO_FLOAT( param[1] );
742 p[2] = INT_TO_FLOAT( param[2] );
743 p[3] = INT_TO_FLOAT( param[3] );
744 }
745 else {
746 p[0] = (GLfloat) param[0];
747 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */
748 }
749 _mesa_TexEnvfv( target, pname, p );
750 }
751
752
753 void GLAPIENTRY
754 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
755 {
756 GET_CURRENT_CONTEXT(ctx);
757 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
758 ASSERT_OUTSIDE_BEGIN_END(ctx);
759
760 if (target == GL_TEXTURE_ENV) {
761 switch (pname) {
762 case GL_TEXTURE_ENV_MODE:
763 *params = ENUM_TO_FLOAT(texUnit->EnvMode);
764 break;
765 case GL_TEXTURE_ENV_COLOR:
766 COPY_4FV( params, texUnit->EnvColor );
767 break;
768 case GL_COMBINE_RGB:
769 if (ctx->Extensions.EXT_texture_env_combine ||
770 ctx->Extensions.ARB_texture_env_combine) {
771 *params = (GLfloat) texUnit->Combine.ModeRGB;
772 }
773 else {
774 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
775 }
776 break;
777 case GL_COMBINE_ALPHA:
778 if (ctx->Extensions.EXT_texture_env_combine ||
779 ctx->Extensions.ARB_texture_env_combine) {
780 *params = (GLfloat) texUnit->Combine.ModeA;
781 }
782 else {
783 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
784 }
785 break;
786 case GL_SOURCE0_RGB:
787 if (ctx->Extensions.EXT_texture_env_combine ||
788 ctx->Extensions.ARB_texture_env_combine) {
789 *params = (GLfloat) texUnit->Combine.SourceRGB[0];
790 }
791 else {
792 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
793 }
794 break;
795 case GL_SOURCE1_RGB:
796 if (ctx->Extensions.EXT_texture_env_combine ||
797 ctx->Extensions.ARB_texture_env_combine) {
798 *params = (GLfloat) texUnit->Combine.SourceRGB[1];
799 }
800 else {
801 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
802 }
803 break;
804 case GL_SOURCE2_RGB:
805 if (ctx->Extensions.EXT_texture_env_combine ||
806 ctx->Extensions.ARB_texture_env_combine) {
807 *params = (GLfloat) texUnit->Combine.SourceRGB[2];
808 }
809 else {
810 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
811 }
812 break;
813 case GL_SOURCE0_ALPHA:
814 if (ctx->Extensions.EXT_texture_env_combine ||
815 ctx->Extensions.ARB_texture_env_combine) {
816 *params = (GLfloat) texUnit->Combine.SourceA[0];
817 }
818 else {
819 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
820 }
821 break;
822 case GL_SOURCE1_ALPHA:
823 if (ctx->Extensions.EXT_texture_env_combine ||
824 ctx->Extensions.ARB_texture_env_combine) {
825 *params = (GLfloat) texUnit->Combine.SourceA[1];
826 }
827 else {
828 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
829 }
830 break;
831 case GL_SOURCE2_ALPHA:
832 if (ctx->Extensions.EXT_texture_env_combine ||
833 ctx->Extensions.ARB_texture_env_combine) {
834 *params = (GLfloat) texUnit->Combine.SourceA[2];
835 }
836 else {
837 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
838 }
839 break;
840 case GL_OPERAND0_RGB:
841 if (ctx->Extensions.EXT_texture_env_combine ||
842 ctx->Extensions.ARB_texture_env_combine) {
843 *params = (GLfloat) texUnit->Combine.OperandRGB[0];
844 }
845 else {
846 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
847 }
848 break;
849 case GL_OPERAND1_RGB:
850 if (ctx->Extensions.EXT_texture_env_combine ||
851 ctx->Extensions.ARB_texture_env_combine) {
852 *params = (GLfloat) texUnit->Combine.OperandRGB[1];
853 }
854 else {
855 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
856 }
857 break;
858 case GL_OPERAND2_RGB:
859 if (ctx->Extensions.EXT_texture_env_combine ||
860 ctx->Extensions.ARB_texture_env_combine) {
861 *params = (GLfloat) texUnit->Combine.OperandRGB[2];
862 }
863 else {
864 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
865 }
866 break;
867 case GL_OPERAND0_ALPHA:
868 if (ctx->Extensions.EXT_texture_env_combine ||
869 ctx->Extensions.ARB_texture_env_combine) {
870 *params = (GLfloat) texUnit->Combine.OperandA[0];
871 }
872 else {
873 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
874 }
875 break;
876 case GL_OPERAND1_ALPHA:
877 if (ctx->Extensions.EXT_texture_env_combine ||
878 ctx->Extensions.ARB_texture_env_combine) {
879 *params = (GLfloat) texUnit->Combine.OperandA[1];
880 }
881 else {
882 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
883 }
884 break;
885 case GL_OPERAND2_ALPHA:
886 if (ctx->Extensions.EXT_texture_env_combine ||
887 ctx->Extensions.ARB_texture_env_combine) {
888 *params = (GLfloat) texUnit->Combine.OperandA[2];
889 }
890 else {
891 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
892 }
893 break;
894 case GL_RGB_SCALE:
895 if (ctx->Extensions.EXT_texture_env_combine ||
896 ctx->Extensions.ARB_texture_env_combine) {
897 if (texUnit->Combine.ScaleShiftRGB == 0)
898 *params = 1.0;
899 else if (texUnit->Combine.ScaleShiftRGB == 1)
900 *params = 2.0;
901 else
902 *params = 4.0;
903 }
904 else {
905 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
906 return;
907 }
908 break;
909 case GL_ALPHA_SCALE:
910 if (ctx->Extensions.EXT_texture_env_combine ||
911 ctx->Extensions.ARB_texture_env_combine) {
912 if (texUnit->Combine.ScaleShiftA == 0)
913 *params = 1.0;
914 else if (texUnit->Combine.ScaleShiftA == 1)
915 *params = 2.0;
916 else
917 *params = 4.0;
918 }
919 else {
920 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
921 return;
922 }
923 break;
924 default:
925 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname=0x%x)", pname);
926 }
927 }
928 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
929 /* GL_EXT_texture_lod_bias */
930 if (!ctx->Extensions.EXT_texture_lod_bias) {
931 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
932 return;
933 }
934 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
935 *params = texUnit->LodBias;
936 }
937 else {
938 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
939 return;
940 }
941 }
942 else if (target == GL_POINT_SPRITE_NV) {
943 /* GL_ARB_point_sprite / GL_NV_point_sprite */
944 if (!ctx->Extensions.NV_point_sprite
945 && !ctx->Extensions.ARB_point_sprite) {
946 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
947 return;
948 }
949 if (pname == GL_COORD_REPLACE_NV) {
950 *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
951 }
952 else {
953 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
954 return;
955 }
956 }
957 else {
958 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
959 return;
960 }
961 }
962
963
964 void GLAPIENTRY
965 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
966 {
967 GET_CURRENT_CONTEXT(ctx);
968 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
969 ASSERT_OUTSIDE_BEGIN_END(ctx);
970
971 if (target == GL_TEXTURE_ENV) {
972 switch (pname) {
973 case GL_TEXTURE_ENV_MODE:
974 *params = (GLint) texUnit->EnvMode;
975 break;
976 case GL_TEXTURE_ENV_COLOR:
977 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
978 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
979 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
980 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
981 break;
982 case GL_COMBINE_RGB:
983 if (ctx->Extensions.EXT_texture_env_combine ||
984 ctx->Extensions.ARB_texture_env_combine) {
985 *params = (GLint) texUnit->Combine.ModeRGB;
986 }
987 else {
988 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
989 }
990 break;
991 case GL_COMBINE_ALPHA:
992 if (ctx->Extensions.EXT_texture_env_combine ||
993 ctx->Extensions.ARB_texture_env_combine) {
994 *params = (GLint) texUnit->Combine.ModeA;
995 }
996 else {
997 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
998 }
999 break;
1000 case GL_SOURCE0_RGB:
1001 if (ctx->Extensions.EXT_texture_env_combine ||
1002 ctx->Extensions.ARB_texture_env_combine) {
1003 *params = (GLint) texUnit->Combine.SourceRGB[0];
1004 }
1005 else {
1006 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1007 }
1008 break;
1009 case GL_SOURCE1_RGB:
1010 if (ctx->Extensions.EXT_texture_env_combine ||
1011 ctx->Extensions.ARB_texture_env_combine) {
1012 *params = (GLint) texUnit->Combine.SourceRGB[1];
1013 }
1014 else {
1015 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1016 }
1017 break;
1018 case GL_SOURCE2_RGB:
1019 if (ctx->Extensions.EXT_texture_env_combine ||
1020 ctx->Extensions.ARB_texture_env_combine) {
1021 *params = (GLint) texUnit->Combine.SourceRGB[2];
1022 }
1023 else {
1024 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1025 }
1026 break;
1027 case GL_SOURCE0_ALPHA:
1028 if (ctx->Extensions.EXT_texture_env_combine ||
1029 ctx->Extensions.ARB_texture_env_combine) {
1030 *params = (GLint) texUnit->Combine.SourceA[0];
1031 }
1032 else {
1033 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1034 }
1035 break;
1036 case GL_SOURCE1_ALPHA:
1037 if (ctx->Extensions.EXT_texture_env_combine ||
1038 ctx->Extensions.ARB_texture_env_combine) {
1039 *params = (GLint) texUnit->Combine.SourceA[1];
1040 }
1041 else {
1042 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1043 }
1044 break;
1045 case GL_SOURCE2_ALPHA:
1046 if (ctx->Extensions.EXT_texture_env_combine ||
1047 ctx->Extensions.ARB_texture_env_combine) {
1048 *params = (GLint) texUnit->Combine.SourceA[2];
1049 }
1050 else {
1051 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1052 }
1053 break;
1054 case GL_OPERAND0_RGB:
1055 if (ctx->Extensions.EXT_texture_env_combine ||
1056 ctx->Extensions.ARB_texture_env_combine) {
1057 *params = (GLint) texUnit->Combine.OperandRGB[0];
1058 }
1059 else {
1060 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1061 }
1062 break;
1063 case GL_OPERAND1_RGB:
1064 if (ctx->Extensions.EXT_texture_env_combine ||
1065 ctx->Extensions.ARB_texture_env_combine) {
1066 *params = (GLint) texUnit->Combine.OperandRGB[1];
1067 }
1068 else {
1069 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1070 }
1071 break;
1072 case GL_OPERAND2_RGB:
1073 if (ctx->Extensions.EXT_texture_env_combine ||
1074 ctx->Extensions.ARB_texture_env_combine) {
1075 *params = (GLint) texUnit->Combine.OperandRGB[2];
1076 }
1077 else {
1078 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1079 }
1080 break;
1081 case GL_OPERAND0_ALPHA:
1082 if (ctx->Extensions.EXT_texture_env_combine ||
1083 ctx->Extensions.ARB_texture_env_combine) {
1084 *params = (GLint) texUnit->Combine.OperandA[0];
1085 }
1086 else {
1087 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1088 }
1089 break;
1090 case GL_OPERAND1_ALPHA:
1091 if (ctx->Extensions.EXT_texture_env_combine ||
1092 ctx->Extensions.ARB_texture_env_combine) {
1093 *params = (GLint) texUnit->Combine.OperandA[1];
1094 }
1095 else {
1096 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1097 }
1098 break;
1099 case GL_OPERAND2_ALPHA:
1100 if (ctx->Extensions.EXT_texture_env_combine ||
1101 ctx->Extensions.ARB_texture_env_combine) {
1102 *params = (GLint) texUnit->Combine.OperandA[2];
1103 }
1104 else {
1105 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1106 }
1107 break;
1108 case GL_RGB_SCALE:
1109 if (ctx->Extensions.EXT_texture_env_combine ||
1110 ctx->Extensions.ARB_texture_env_combine) {
1111 if (texUnit->Combine.ScaleShiftRGB == 0)
1112 *params = 1;
1113 else if (texUnit->Combine.ScaleShiftRGB == 1)
1114 *params = 2;
1115 else
1116 *params = 4;
1117 }
1118 else {
1119 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1120 return;
1121 }
1122 break;
1123 case GL_ALPHA_SCALE:
1124 if (ctx->Extensions.EXT_texture_env_combine ||
1125 ctx->Extensions.ARB_texture_env_combine) {
1126 if (texUnit->Combine.ScaleShiftA == 0)
1127 *params = 1;
1128 else if (texUnit->Combine.ScaleShiftA == 1)
1129 *params = 2;
1130 else
1131 *params = 4;
1132 }
1133 else {
1134 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
1135 return;
1136 }
1137 break;
1138 default:
1139 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname=0x%x)",
1140 pname);
1141 }
1142 }
1143 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
1144 /* GL_EXT_texture_lod_bias */
1145 if (!ctx->Extensions.EXT_texture_lod_bias) {
1146 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
1147 return;
1148 }
1149 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
1150 *params = (GLint) texUnit->LodBias;
1151 }
1152 else {
1153 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
1154 return;
1155 }
1156 }
1157 else if (target == GL_POINT_SPRITE_NV) {
1158 /* GL_ARB_point_sprite / GL_NV_point_sprite */
1159 if (!ctx->Extensions.NV_point_sprite
1160 && !ctx->Extensions.ARB_point_sprite) {
1161 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
1162 return;
1163 }
1164 if (pname == GL_COORD_REPLACE_NV) {
1165 *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
1166 }
1167 else {
1168 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
1169 return;
1170 }
1171 }
1172 else {
1173 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
1174 return;
1175 }
1176 }
1177
1178
1179
1180
1181 /**********************************************************************/
1182 /* Texture Parameters */
1183 /**********************************************************************/
1184
1185 static GLboolean
1186 _mesa_validate_texture_wrap_mode(GLcontext * ctx,
1187 GLenum target, GLenum eparam)
1188 {
1189 const struct gl_extensions * const e = & ctx->Extensions;
1190
1191 if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE ||
1192 (eparam == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
1193 /* any texture target */
1194 return GL_TRUE;
1195 }
1196 else if (target != GL_TEXTURE_RECTANGLE_NV &&
1197 (eparam == GL_REPEAT ||
1198 (eparam == GL_MIRRORED_REPEAT &&
1199 e->ARB_texture_mirrored_repeat) ||
1200 (eparam == GL_MIRROR_CLAMP_EXT &&
1201 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
1202 (eparam == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
1203 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
1204 (eparam == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
1205 (e->EXT_texture_mirror_clamp)))) {
1206 /* non-rectangle texture */
1207 return GL_TRUE;
1208 }
1209
1210 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
1211 return GL_FALSE;
1212 }
1213
1214
1215 void GLAPIENTRY
1216 _mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
1217 {
1218 _mesa_TexParameterfv(target, pname, &param);
1219 }
1220
1221
1222 void GLAPIENTRY
1223 _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
1224 {
1225 GET_CURRENT_CONTEXT(ctx);
1226 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1227 GLenum eparam = (GLenum) (GLint) params[0];
1228 struct gl_texture_object *texObj;
1229 ASSERT_OUTSIDE_BEGIN_END(ctx);
1230
1231 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
1232 _mesa_debug(ctx, "glTexParameter %s %s %.1f(%s)...\n",
1233 _mesa_lookup_enum_by_nr(target),
1234 _mesa_lookup_enum_by_nr(pname),
1235 *params,
1236 _mesa_lookup_enum_by_nr(eparam));
1237
1238
1239 switch (target) {
1240 case GL_TEXTURE_1D:
1241 texObj = texUnit->Current1D;
1242 break;
1243 case GL_TEXTURE_2D:
1244 texObj = texUnit->Current2D;
1245 break;
1246 case GL_TEXTURE_3D:
1247 texObj = texUnit->Current3D;
1248 break;
1249 case GL_TEXTURE_CUBE_MAP:
1250 if (!ctx->Extensions.ARB_texture_cube_map) {
1251 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
1252 return;
1253 }
1254 texObj = texUnit->CurrentCubeMap;
1255 break;
1256 case GL_TEXTURE_RECTANGLE_NV:
1257 if (!ctx->Extensions.NV_texture_rectangle) {
1258 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
1259 return;
1260 }
1261 texObj = texUnit->CurrentRect;
1262 break;
1263 default:
1264 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
1265 return;
1266 }
1267
1268 switch (pname) {
1269 case GL_TEXTURE_MIN_FILTER:
1270 /* A small optimization */
1271 if (texObj->MinFilter == eparam)
1272 return;
1273 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
1274 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1275 texObj->MinFilter = eparam;
1276 }
1277 else if ((eparam==GL_NEAREST_MIPMAP_NEAREST ||
1278 eparam==GL_LINEAR_MIPMAP_NEAREST ||
1279 eparam==GL_NEAREST_MIPMAP_LINEAR ||
1280 eparam==GL_LINEAR_MIPMAP_LINEAR) &&
1281 texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
1282 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1283 texObj->MinFilter = eparam;
1284 }
1285 else {
1286 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
1287 return;
1288 }
1289 break;
1290 case GL_TEXTURE_MAG_FILTER:
1291 /* A small optimization */
1292 if (texObj->MagFilter == eparam)
1293 return;
1294
1295 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
1296 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1297 texObj->MagFilter = eparam;
1298 }
1299 else {
1300 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
1301 return;
1302 }
1303 break;
1304 case GL_TEXTURE_WRAP_S:
1305 if (texObj->WrapS == eparam)
1306 return;
1307 if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
1308 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1309 texObj->WrapS = eparam;
1310 }
1311 else {
1312 return;
1313 }
1314 break;
1315 case GL_TEXTURE_WRAP_T:
1316 if (texObj->WrapT == eparam)
1317 return;
1318 if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
1319 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1320 texObj->WrapT = eparam;
1321 }
1322 else {
1323 return;
1324 }
1325 break;
1326 case GL_TEXTURE_WRAP_R:
1327 if (texObj->WrapR == eparam)
1328 return;
1329 if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
1330 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1331 texObj->WrapR = eparam;
1332 }
1333 else {
1334 return;
1335 }
1336 break;
1337 case GL_TEXTURE_BORDER_COLOR:
1338 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1339 texObj->BorderColor[RCOMP] = params[0];
1340 texObj->BorderColor[GCOMP] = params[1];
1341 texObj->BorderColor[BCOMP] = params[2];
1342 texObj->BorderColor[ACOMP] = params[3];
1343 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[RCOMP], params[0]);
1344 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[GCOMP], params[1]);
1345 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[BCOMP], params[2]);
1346 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[ACOMP], params[3]);
1347 break;
1348 case GL_TEXTURE_MIN_LOD:
1349 if (texObj->MinLod == params[0])
1350 return;
1351 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1352 texObj->MinLod = params[0];
1353 break;
1354 case GL_TEXTURE_MAX_LOD:
1355 if (texObj->MaxLod == params[0])
1356 return;
1357 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1358 texObj->MaxLod = params[0];
1359 break;
1360 case GL_TEXTURE_BASE_LEVEL:
1361 if (params[0] < 0.0) {
1362 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
1363 return;
1364 }
1365 if (target == GL_TEXTURE_RECTANGLE_NV && params[0] != 0.0) {
1366 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
1367 return;
1368 }
1369 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1370 texObj->BaseLevel = (GLint) params[0];
1371 break;
1372 case GL_TEXTURE_MAX_LEVEL:
1373 if (params[0] < 0.0) {
1374 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
1375 return;
1376 }
1377 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1378 texObj->MaxLevel = (GLint) params[0];
1379 break;
1380 case GL_TEXTURE_PRIORITY:
1381 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1382 texObj->Priority = CLAMP( params[0], 0.0F, 1.0F );
1383 break;
1384 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1385 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
1386 if (params[0] < 1.0) {
1387 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
1388 return;
1389 }
1390 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1391 /* clamp to max, that's what NVIDIA does */
1392 texObj->MaxAnisotropy = MIN2(params[0],
1393 ctx->Const.MaxTextureMaxAnisotropy);
1394 }
1395 else {
1396 _mesa_error(ctx, GL_INVALID_ENUM,
1397 "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
1398 return;
1399 }
1400 break;
1401 case GL_TEXTURE_COMPARE_SGIX:
1402 if (ctx->Extensions.SGIX_shadow) {
1403 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1404 texObj->CompareFlag = params[0] ? GL_TRUE : GL_FALSE;
1405 }
1406 else {
1407 _mesa_error(ctx, GL_INVALID_ENUM,
1408 "glTexParameter(pname=GL_TEXTURE_COMPARE_SGIX)");
1409 return;
1410 }
1411 break;
1412 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
1413 if (ctx->Extensions.SGIX_shadow) {
1414 GLenum op = (GLenum) params[0];
1415 if (op == GL_TEXTURE_LEQUAL_R_SGIX ||
1416 op == GL_TEXTURE_GEQUAL_R_SGIX) {
1417 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1418 texObj->CompareOperator = op;
1419 }
1420 else {
1421 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)");
1422 }
1423 }
1424 else {
1425 _mesa_error(ctx, GL_INVALID_ENUM,
1426 "glTexParameter(pname=GL_TEXTURE_COMPARE_OPERATOR_SGIX)");
1427 return;
1428 }
1429 break;
1430 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
1431 if (ctx->Extensions.SGIX_shadow_ambient) {
1432 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1433 texObj->ShadowAmbient = CLAMP(params[0], 0.0F, 1.0F);
1434 }
1435 else {
1436 _mesa_error(ctx, GL_INVALID_ENUM,
1437 "glTexParameter(pname=GL_SHADOW_AMBIENT_SGIX)");
1438 return;
1439 }
1440 break;
1441 case GL_GENERATE_MIPMAP_SGIS:
1442 if (ctx->Extensions.SGIS_generate_mipmap) {
1443 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
1444 }
1445 else {
1446 _mesa_error(ctx, GL_INVALID_ENUM,
1447 "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
1448 return;
1449 }
1450 break;
1451 case GL_TEXTURE_COMPARE_MODE_ARB:
1452 if (ctx->Extensions.ARB_shadow) {
1453 const GLenum mode = (GLenum) params[0];
1454 if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) {
1455 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1456 texObj->CompareMode = mode;
1457 }
1458 else {
1459 _mesa_error(ctx, GL_INVALID_ENUM,
1460 "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB: 0x%x)", mode);
1461 return;
1462 }
1463 }
1464 else {
1465 _mesa_error(ctx, GL_INVALID_ENUM,
1466 "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)");
1467 return;
1468 }
1469 break;
1470 case GL_TEXTURE_COMPARE_FUNC_ARB:
1471 if (ctx->Extensions.ARB_shadow) {
1472 const GLenum func = (GLenum) params[0];
1473 if (func == GL_LEQUAL || func == GL_GEQUAL) {
1474 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1475 texObj->CompareFunc = func;
1476 }
1477 else if (ctx->Extensions.EXT_shadow_funcs &&
1478 (func == GL_EQUAL ||
1479 func == GL_NOTEQUAL ||
1480 func == GL_LESS ||
1481 func == GL_GREATER ||
1482 func == GL_ALWAYS ||
1483 func == GL_NEVER)) {
1484 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1485 texObj->CompareFunc = func;
1486 }
1487 else {
1488 _mesa_error(ctx, GL_INVALID_ENUM,
1489 "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)");
1490 return;
1491 }
1492 }
1493 else {
1494 _mesa_error(ctx, GL_INVALID_ENUM,
1495 "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)");
1496 return;
1497 }
1498 break;
1499 case GL_DEPTH_TEXTURE_MODE_ARB:
1500 if (ctx->Extensions.ARB_depth_texture) {
1501 const GLenum result = (GLenum) params[0];
1502 if (result == GL_LUMINANCE || result == GL_INTENSITY
1503 || result == GL_ALPHA) {
1504 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1505 texObj->DepthMode = result;
1506 }
1507 else {
1508 _mesa_error(ctx, GL_INVALID_ENUM,
1509 "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)");
1510 return;
1511 }
1512 }
1513 else {
1514 _mesa_error(ctx, GL_INVALID_ENUM,
1515 "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)");
1516 return;
1517 }
1518 break;
1519 case GL_TEXTURE_LOD_BIAS:
1520 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias*/
1521 if (ctx->Extensions.EXT_texture_lod_bias) {
1522 if (texObj->LodBias != params[0]) {
1523 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1524 texObj->LodBias = params[0];
1525 }
1526 }
1527 break;
1528
1529 default:
1530 _mesa_error(ctx, GL_INVALID_ENUM,
1531 "glTexParameter(pname=0x%x)", pname);
1532 return;
1533 }
1534
1535 texObj->Complete = GL_FALSE;
1536
1537 if (ctx->Driver.TexParameter) {
1538 (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params );
1539 }
1540 }
1541
1542
1543 void GLAPIENTRY
1544 _mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
1545 {
1546 GLfloat fparam[4];
1547 if (pname == GL_TEXTURE_PRIORITY)
1548 fparam[0] = INT_TO_FLOAT(param);
1549 else
1550 fparam[0] = (GLfloat) param;
1551 fparam[1] = fparam[2] = fparam[3] = 0.0;
1552 _mesa_TexParameterfv(target, pname, fparam);
1553 }
1554
1555
1556 void GLAPIENTRY
1557 _mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
1558 {
1559 GLfloat fparam[4];
1560 if (pname == GL_TEXTURE_BORDER_COLOR) {
1561 fparam[0] = INT_TO_FLOAT(params[0]);
1562 fparam[1] = INT_TO_FLOAT(params[1]);
1563 fparam[2] = INT_TO_FLOAT(params[2]);
1564 fparam[3] = INT_TO_FLOAT(params[3]);
1565 }
1566 else {
1567 if (pname == GL_TEXTURE_PRIORITY)
1568 fparam[0] = INT_TO_FLOAT(params[0]);
1569 else
1570 fparam[0] = (GLfloat) params[0];
1571 fparam[1] = fparam[2] = fparam[3] = 0.0F;
1572 }
1573 _mesa_TexParameterfv(target, pname, fparam);
1574 }
1575
1576
1577 void GLAPIENTRY
1578 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
1579 GLenum pname, GLfloat *params )
1580 {
1581 GLint iparam;
1582 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
1583 *params = (GLfloat) iparam;
1584 }
1585
1586
1587 static GLuint
1588 tex_image_dimensions(GLcontext *ctx, GLenum target)
1589 {
1590 switch (target) {
1591 case GL_TEXTURE_1D:
1592 case GL_PROXY_TEXTURE_1D:
1593 return 1;
1594 case GL_TEXTURE_2D:
1595 case GL_PROXY_TEXTURE_2D:
1596 return 2;
1597 case GL_TEXTURE_3D:
1598 case GL_PROXY_TEXTURE_3D:
1599 return 3;
1600 case GL_TEXTURE_CUBE_MAP:
1601 case GL_PROXY_TEXTURE_CUBE_MAP:
1602 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1603 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1604 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1605 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1606 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1607 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1608 return ctx->Extensions.ARB_texture_cube_map ? 2 : 0;
1609 case GL_TEXTURE_RECTANGLE_NV:
1610 case GL_PROXY_TEXTURE_RECTANGLE_NV:
1611 return ctx->Extensions.NV_texture_rectangle ? 2 : 0;
1612 default:
1613 _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()");
1614 return 0;
1615 }
1616 }
1617
1618
1619 void GLAPIENTRY
1620 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
1621 GLenum pname, GLint *params )
1622 {
1623 GET_CURRENT_CONTEXT(ctx);
1624 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1625 const struct gl_texture_image *img = NULL;
1626 GLuint dimensions;
1627 GLboolean isProxy;
1628 GLint maxLevels;
1629 ASSERT_OUTSIDE_BEGIN_END(ctx);
1630
1631 /* this will catch bad target values */
1632 dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */
1633 if (dimensions == 0) {
1634 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
1635 return;
1636 }
1637
1638 switch (target) {
1639 case GL_TEXTURE_1D:
1640 case GL_PROXY_TEXTURE_1D:
1641 case GL_TEXTURE_2D:
1642 case GL_PROXY_TEXTURE_2D:
1643 maxLevels = ctx->Const.MaxTextureLevels;
1644 break;
1645 case GL_TEXTURE_3D:
1646 case GL_PROXY_TEXTURE_3D:
1647 maxLevels = ctx->Const.Max3DTextureLevels;
1648 break;
1649 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1650 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1651 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1652 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1653 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1655 case GL_PROXY_TEXTURE_CUBE_MAP:
1656 maxLevels = ctx->Const.MaxCubeTextureLevels;
1657 break;
1658 case GL_TEXTURE_RECTANGLE_NV:
1659 case GL_PROXY_TEXTURE_RECTANGLE_NV:
1660 maxLevels = 1;
1661 break;
1662 default:
1663 _mesa_problem(ctx, "switch in _mesa_GetTexLevelParameter");
1664 return;
1665 }
1666
1667 if (level < 0 || level >= maxLevels) {
1668 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
1669 return;
1670 }
1671
1672 img = _mesa_select_tex_image(ctx, texUnit, target, level);
1673 if (!img || !img->TexFormat) {
1674 /* undefined texture image */
1675 if (pname == GL_TEXTURE_COMPONENTS)
1676 *params = 1;
1677 else
1678 *params = 0;
1679 return;
1680 }
1681
1682 isProxy = (target == GL_PROXY_TEXTURE_1D) ||
1683 (target == GL_PROXY_TEXTURE_2D) ||
1684 (target == GL_PROXY_TEXTURE_3D) ||
1685 (target == GL_PROXY_TEXTURE_CUBE_MAP) ||
1686 (target == GL_PROXY_TEXTURE_RECTANGLE_NV);
1687
1688 switch (pname) {
1689 case GL_TEXTURE_WIDTH:
1690 *params = img->Width;
1691 return;
1692 case GL_TEXTURE_HEIGHT:
1693 *params = img->Height;
1694 return;
1695 case GL_TEXTURE_DEPTH:
1696 *params = img->Depth;
1697 return;
1698 case GL_TEXTURE_INTERNAL_FORMAT:
1699 *params = img->IntFormat;
1700 return;
1701 case GL_TEXTURE_BORDER:
1702 *params = img->Border;
1703 return;
1704 case GL_TEXTURE_RED_SIZE:
1705 if (img->Format == GL_RGB || img->Format == GL_RGBA)
1706 *params = img->TexFormat->RedBits;
1707 else
1708 *params = 0;
1709 return;
1710 case GL_TEXTURE_GREEN_SIZE:
1711 if (img->Format == GL_RGB || img->Format == GL_RGBA)
1712 *params = img->TexFormat->GreenBits;
1713 else
1714 *params = 0;
1715 return;
1716 case GL_TEXTURE_BLUE_SIZE:
1717 if (img->Format == GL_RGB || img->Format == GL_RGBA)
1718 *params = img->TexFormat->BlueBits;
1719 else
1720 *params = 0;
1721 return;
1722 case GL_TEXTURE_ALPHA_SIZE:
1723 if (img->Format == GL_ALPHA || img->Format == GL_LUMINANCE_ALPHA ||
1724 img->Format == GL_RGBA)
1725 *params = img->TexFormat->AlphaBits;
1726 else
1727 *params = 0;
1728 return;
1729 case GL_TEXTURE_INTENSITY_SIZE:
1730 if (img->Format != GL_INTENSITY)
1731 *params = 0;
1732 else if (img->TexFormat->IntensityBits > 0)
1733 *params = img->TexFormat->IntensityBits;
1734 else /* intensity probably stored as rgb texture */
1735 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
1736 return;
1737 case GL_TEXTURE_LUMINANCE_SIZE:
1738 if (img->Format != GL_LUMINANCE &&
1739 img->Format != GL_LUMINANCE_ALPHA)
1740 *params = 0;
1741 else if (img->TexFormat->LuminanceBits > 0)
1742 *params = img->TexFormat->LuminanceBits;
1743 else /* luminance probably stored as rgb texture */
1744 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
1745 return;
1746 case GL_TEXTURE_INDEX_SIZE_EXT:
1747 if (img->Format == GL_COLOR_INDEX)
1748 *params = img->TexFormat->IndexBits;
1749 else
1750 *params = 0;
1751 return;
1752 case GL_DEPTH_BITS:
1753 /* XXX this isn't in the GL_SGIX_depth_texture spec
1754 * but seems appropriate.
1755 */
1756 if (ctx->Extensions.SGIX_depth_texture)
1757 *params = img->TexFormat->DepthBits;
1758 else
1759 _mesa_error(ctx, GL_INVALID_ENUM,
1760 "glGetTexLevelParameter[if]v(pname)");
1761 return;
1762
1763 /* GL_ARB_texture_compression */
1764 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1765 if (ctx->Extensions.ARB_texture_compression) {
1766 if (img->IsCompressed && !isProxy)
1767 *params = img->CompressedSize;
1768 else
1769 _mesa_error(ctx, GL_INVALID_OPERATION,
1770 "glGetTexLevelParameter[if]v(pname)");
1771 }
1772 else {
1773 _mesa_error(ctx, GL_INVALID_ENUM,
1774 "glGetTexLevelParameter[if]v(pname)");
1775 }
1776 return;
1777 case GL_TEXTURE_COMPRESSED:
1778 if (ctx->Extensions.ARB_texture_compression) {
1779 *params = (GLint) img->IsCompressed;
1780 }
1781 else {
1782 _mesa_error(ctx, GL_INVALID_ENUM,
1783 "glGetTexLevelParameter[if]v(pname)");
1784 }
1785 return;
1786
1787 /* GL_ARB_texture_float */
1788 case GL_TEXTURE_RED_TYPE_ARB:
1789 if (ctx->Extensions.ARB_texture_float) {
1790 *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE;
1791 }
1792 else {
1793 _mesa_error(ctx, GL_INVALID_ENUM,
1794 "glGetTexLevelParameter[if]v(pname)");
1795 }
1796 return;
1797 case GL_TEXTURE_GREEN_TYPE_ARB:
1798 if (ctx->Extensions.ARB_texture_float) {
1799 *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
1800 }
1801 else {
1802 _mesa_error(ctx, GL_INVALID_ENUM,
1803 "glGetTexLevelParameter[if]v(pname)");
1804 }
1805 return;
1806 case GL_TEXTURE_BLUE_TYPE_ARB:
1807 if (ctx->Extensions.ARB_texture_float) {
1808 *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
1809 }
1810 else {
1811 _mesa_error(ctx, GL_INVALID_ENUM,
1812 "glGetTexLevelParameter[if]v(pname)");
1813 }
1814 return;
1815 case GL_TEXTURE_ALPHA_TYPE_ARB:
1816 if (ctx->Extensions.ARB_texture_float) {
1817 *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
1818 }
1819 else {
1820 _mesa_error(ctx, GL_INVALID_ENUM,
1821 "glGetTexLevelParameter[if]v(pname)");
1822 }
1823 return;
1824 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1825 if (ctx->Extensions.ARB_texture_float) {
1826 *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
1827 }
1828 else {
1829 _mesa_error(ctx, GL_INVALID_ENUM,
1830 "glGetTexLevelParameter[if]v(pname)");
1831 }
1832 return;
1833 case GL_TEXTURE_INTENSITY_TYPE_ARB:
1834 if (ctx->Extensions.ARB_texture_float) {
1835 *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
1836 }
1837 else {
1838 _mesa_error(ctx, GL_INVALID_ENUM,
1839 "glGetTexLevelParameter[if]v(pname)");
1840 }
1841 return;
1842 case GL_TEXTURE_DEPTH_TYPE_ARB:
1843 if (ctx->Extensions.ARB_texture_float) {
1844 *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
1845 }
1846 else {
1847 _mesa_error(ctx, GL_INVALID_ENUM,
1848 "glGetTexLevelParameter[if]v(pname)");
1849 }
1850 return;
1851 default:
1852 _mesa_error(ctx, GL_INVALID_ENUM,
1853 "glGetTexLevelParameter[if]v(pname)");
1854 }
1855 }
1856
1857
1858
1859 void GLAPIENTRY
1860 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
1861 {
1862 GET_CURRENT_CONTEXT(ctx);
1863 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1864 struct gl_texture_object *obj;
1865 ASSERT_OUTSIDE_BEGIN_END(ctx);
1866
1867 obj = _mesa_select_tex_object(ctx, texUnit, target);
1868 if (!obj) {
1869 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
1870 return;
1871 }
1872
1873 switch (pname) {
1874 case GL_TEXTURE_MAG_FILTER:
1875 *params = ENUM_TO_FLOAT(obj->MagFilter);
1876 return;
1877 case GL_TEXTURE_MIN_FILTER:
1878 *params = ENUM_TO_FLOAT(obj->MinFilter);
1879 return;
1880 case GL_TEXTURE_WRAP_S:
1881 *params = ENUM_TO_FLOAT(obj->WrapS);
1882 return;
1883 case GL_TEXTURE_WRAP_T:
1884 *params = ENUM_TO_FLOAT(obj->WrapT);
1885 return;
1886 case GL_TEXTURE_WRAP_R:
1887 *params = ENUM_TO_FLOAT(obj->WrapR);
1888 return;
1889 case GL_TEXTURE_BORDER_COLOR:
1890 params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
1891 params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
1892 params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
1893 params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
1894 return;
1895 case GL_TEXTURE_RESIDENT:
1896 {
1897 GLboolean resident;
1898 if (ctx->Driver.IsTextureResident)
1899 resident = ctx->Driver.IsTextureResident(ctx, obj);
1900 else
1901 resident = GL_TRUE;
1902 *params = ENUM_TO_FLOAT(resident);
1903 }
1904 return;
1905 case GL_TEXTURE_PRIORITY:
1906 *params = obj->Priority;
1907 return;
1908 case GL_TEXTURE_MIN_LOD:
1909 *params = obj->MinLod;
1910 return;
1911 case GL_TEXTURE_MAX_LOD:
1912 *params = obj->MaxLod;
1913 return;
1914 case GL_TEXTURE_BASE_LEVEL:
1915 *params = (GLfloat) obj->BaseLevel;
1916 return;
1917 case GL_TEXTURE_MAX_LEVEL:
1918 *params = (GLfloat) obj->MaxLevel;
1919 return;
1920 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1921 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
1922 *params = obj->MaxAnisotropy;
1923 return;
1924 }
1925 break;
1926 case GL_TEXTURE_COMPARE_SGIX:
1927 if (ctx->Extensions.SGIX_shadow) {
1928 *params = (GLfloat) obj->CompareFlag;
1929 return;
1930 }
1931 break;
1932 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
1933 if (ctx->Extensions.SGIX_shadow) {
1934 *params = (GLfloat) obj->CompareOperator;
1935 return;
1936 }
1937 break;
1938 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
1939 if (ctx->Extensions.SGIX_shadow_ambient) {
1940 *params = obj->ShadowAmbient;
1941 return;
1942 }
1943 break;
1944 case GL_GENERATE_MIPMAP_SGIS:
1945 if (ctx->Extensions.SGIS_generate_mipmap) {
1946 *params = (GLfloat) obj->GenerateMipmap;
1947 return;
1948 }
1949 break;
1950 case GL_TEXTURE_COMPARE_MODE_ARB:
1951 if (ctx->Extensions.ARB_shadow) {
1952 *params = (GLfloat) obj->CompareMode;
1953 return;
1954 }
1955 break;
1956 case GL_TEXTURE_COMPARE_FUNC_ARB:
1957 if (ctx->Extensions.ARB_shadow) {
1958 *params = (GLfloat) obj->CompareFunc;
1959 return;
1960 }
1961 break;
1962 case GL_DEPTH_TEXTURE_MODE_ARB:
1963 if (ctx->Extensions.ARB_depth_texture) {
1964 *params = (GLfloat) obj->DepthMode;
1965 return;
1966 }
1967 break;
1968 case GL_TEXTURE_LOD_BIAS:
1969 if (ctx->Extensions.EXT_texture_lod_bias) {
1970 *params = obj->LodBias;
1971 return;
1972 }
1973 break;
1974 default:
1975 ; /* silence warnings */
1976 }
1977 /* If we get here, pname was an unrecognized enum */
1978 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
1979 pname);
1980 }
1981
1982
1983 void GLAPIENTRY
1984 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1985 {
1986 GET_CURRENT_CONTEXT(ctx);
1987 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1988 struct gl_texture_object *obj;
1989 ASSERT_OUTSIDE_BEGIN_END(ctx);
1990
1991 obj = _mesa_select_tex_object(ctx, texUnit, target);
1992 if (!obj) {
1993 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(target)");
1994 return;
1995 }
1996
1997 switch (pname) {
1998 case GL_TEXTURE_MAG_FILTER:
1999 *params = (GLint) obj->MagFilter;
2000 return;
2001 case GL_TEXTURE_MIN_FILTER:
2002 *params = (GLint) obj->MinFilter;
2003 return;
2004 case GL_TEXTURE_WRAP_S:
2005 *params = (GLint) obj->WrapS;
2006 return;
2007 case GL_TEXTURE_WRAP_T:
2008 *params = (GLint) obj->WrapT;
2009 return;
2010 case GL_TEXTURE_WRAP_R:
2011 *params = (GLint) obj->WrapR;
2012 return;
2013 case GL_TEXTURE_BORDER_COLOR:
2014 {
2015 GLfloat b[4];
2016 b[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
2017 b[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
2018 b[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
2019 b[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
2020 params[0] = FLOAT_TO_INT(b[0]);
2021 params[1] = FLOAT_TO_INT(b[1]);
2022 params[2] = FLOAT_TO_INT(b[2]);
2023 params[3] = FLOAT_TO_INT(b[3]);
2024 }
2025 return;
2026 case GL_TEXTURE_RESIDENT:
2027 {
2028 GLboolean resident;
2029 if (ctx->Driver.IsTextureResident)
2030 resident = ctx->Driver.IsTextureResident(ctx, obj);
2031 else
2032 resident = GL_TRUE;
2033 *params = (GLint) resident;
2034 }
2035 return;
2036 case GL_TEXTURE_PRIORITY:
2037 *params = FLOAT_TO_INT(obj->Priority);
2038 return;
2039 case GL_TEXTURE_MIN_LOD:
2040 *params = (GLint) obj->MinLod;
2041 return;
2042 case GL_TEXTURE_MAX_LOD:
2043 *params = (GLint) obj->MaxLod;
2044 return;
2045 case GL_TEXTURE_BASE_LEVEL:
2046 *params = obj->BaseLevel;
2047 return;
2048 case GL_TEXTURE_MAX_LEVEL:
2049 *params = obj->MaxLevel;
2050 return;
2051 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
2052 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
2053 *params = (GLint) obj->MaxAnisotropy;
2054 return;
2055 }
2056 break;
2057 case GL_TEXTURE_COMPARE_SGIX:
2058 if (ctx->Extensions.SGIX_shadow) {
2059 *params = (GLint) obj->CompareFlag;
2060 return;
2061 }
2062 break;
2063 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
2064 if (ctx->Extensions.SGIX_shadow) {
2065 *params = (GLint) obj->CompareOperator;
2066 return;
2067 }
2068 break;
2069 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
2070 if (ctx->Extensions.SGIX_shadow_ambient) {
2071 *params = (GLint) FLOAT_TO_INT(obj->ShadowAmbient);
2072 return;
2073 }
2074 break;
2075 case GL_GENERATE_MIPMAP_SGIS:
2076 if (ctx->Extensions.SGIS_generate_mipmap) {
2077 *params = (GLint) obj->GenerateMipmap;
2078 return;
2079 }
2080 break;
2081 case GL_TEXTURE_COMPARE_MODE_ARB:
2082 if (ctx->Extensions.ARB_shadow) {
2083 *params = (GLint) obj->CompareMode;
2084 return;
2085 }
2086 break;
2087 case GL_TEXTURE_COMPARE_FUNC_ARB:
2088 if (ctx->Extensions.ARB_shadow) {
2089 *params = (GLint) obj->CompareFunc;
2090 return;
2091 }
2092 break;
2093 case GL_DEPTH_TEXTURE_MODE_ARB:
2094 if (ctx->Extensions.ARB_depth_texture) {
2095 *params = (GLint) obj->DepthMode;
2096 return;
2097 }
2098 break;
2099 case GL_TEXTURE_LOD_BIAS:
2100 if (ctx->Extensions.EXT_texture_lod_bias) {
2101 *params = (GLint) obj->LodBias;
2102 return;
2103 }
2104 break;
2105 default:
2106 ; /* silence warnings */
2107 }
2108 /* If we get here, pname was an unrecognized enum */
2109 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
2110 }
2111
2112
2113
2114
2115 /**********************************************************************/
2116 /* Texture Coord Generation */
2117 /**********************************************************************/
2118
2119 #if FEATURE_texgen
2120 void GLAPIENTRY
2121 _mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
2122 {
2123 GET_CURRENT_CONTEXT(ctx);
2124 GLuint tUnit = ctx->Texture.CurrentUnit;
2125 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
2126 ASSERT_OUTSIDE_BEGIN_END(ctx);
2127
2128 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
2129 _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n",
2130 _mesa_lookup_enum_by_nr(coord),
2131 _mesa_lookup_enum_by_nr(pname),
2132 *params,
2133 _mesa_lookup_enum_by_nr((GLenum) (GLint) *params));
2134
2135 switch (coord) {
2136 case GL_S:
2137 if (pname==GL_TEXTURE_GEN_MODE) {
2138 GLenum mode = (GLenum) (GLint) *params;
2139 GLuint bits;
2140 switch (mode) {
2141 case GL_OBJECT_LINEAR:
2142 bits = TEXGEN_OBJ_LINEAR;
2143 break;
2144 case GL_EYE_LINEAR:
2145 bits = TEXGEN_EYE_LINEAR;
2146 break;
2147 case GL_REFLECTION_MAP_NV:
2148 bits = TEXGEN_REFLECTION_MAP_NV;
2149 break;
2150 case GL_NORMAL_MAP_NV:
2151 bits = TEXGEN_NORMAL_MAP_NV;
2152 break;
2153 case GL_SPHERE_MAP:
2154 bits = TEXGEN_SPHERE_MAP;
2155 break;
2156 default:
2157 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
2158 return;
2159 }
2160 if (texUnit->GenModeS == mode)
2161 return;
2162 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2163 texUnit->GenModeS = mode;
2164 texUnit->_GenBitS = bits;
2165 }
2166 else if (pname==GL_OBJECT_PLANE) {
2167 if (TEST_EQ_4V(texUnit->ObjectPlaneS, params))
2168 return;
2169 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2170 texUnit->ObjectPlaneS[0] = params[0];
2171 texUnit->ObjectPlaneS[1] = params[1];
2172 texUnit->ObjectPlaneS[2] = params[2];
2173 texUnit->ObjectPlaneS[3] = params[3];
2174 }
2175 else if (pname==GL_EYE_PLANE) {
2176 GLfloat tmp[4];
2177
2178 /* Transform plane equation by the inverse modelview matrix */
2179 if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
2180 _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
2181 }
2182 _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
2183 if (TEST_EQ_4V(texUnit->EyePlaneS, tmp))
2184 return;
2185 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2186 COPY_4FV(texUnit->EyePlaneS, tmp);
2187 }
2188 else {
2189 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
2190 return;
2191 }
2192 break;
2193 case GL_T:
2194 if (pname==GL_TEXTURE_GEN_MODE) {
2195 GLenum mode = (GLenum) (GLint) *params;
2196 GLuint bitt;
2197 switch (mode) {
2198 case GL_OBJECT_LINEAR:
2199 bitt = TEXGEN_OBJ_LINEAR;
2200 break;
2201 case GL_EYE_LINEAR:
2202 bitt = TEXGEN_EYE_LINEAR;
2203 break;
2204 case GL_REFLECTION_MAP_NV:
2205 bitt = TEXGEN_REFLECTION_MAP_NV;
2206 break;
2207 case GL_NORMAL_MAP_NV:
2208 bitt = TEXGEN_NORMAL_MAP_NV;
2209 break;
2210 case GL_SPHERE_MAP:
2211 bitt = TEXGEN_SPHERE_MAP;
2212 break;
2213 default:
2214 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
2215 return;
2216 }
2217 if (texUnit->GenModeT == mode)
2218 return;
2219 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2220 texUnit->GenModeT = mode;
2221 texUnit->_GenBitT = bitt;
2222 }
2223 else if (pname==GL_OBJECT_PLANE) {
2224 if (TEST_EQ_4V(texUnit->ObjectPlaneT, params))
2225 return;
2226 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2227 texUnit->ObjectPlaneT[0] = params[0];
2228 texUnit->ObjectPlaneT[1] = params[1];
2229 texUnit->ObjectPlaneT[2] = params[2];
2230 texUnit->ObjectPlaneT[3] = params[3];
2231 }
2232 else if (pname==GL_EYE_PLANE) {
2233 GLfloat tmp[4];
2234 /* Transform plane equation by the inverse modelview matrix */
2235 if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
2236 _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
2237 }
2238 _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
2239 if (TEST_EQ_4V(texUnit->EyePlaneT, tmp))
2240 return;
2241 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2242 COPY_4FV(texUnit->EyePlaneT, tmp);
2243 }
2244 else {
2245 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
2246 return;
2247 }
2248 break;
2249 case GL_R:
2250 if (pname==GL_TEXTURE_GEN_MODE) {
2251 GLenum mode = (GLenum) (GLint) *params;
2252 GLuint bitr;
2253 switch (mode) {
2254 case GL_OBJECT_LINEAR:
2255 bitr = TEXGEN_OBJ_LINEAR;
2256 break;
2257 case GL_REFLECTION_MAP_NV:
2258 bitr = TEXGEN_REFLECTION_MAP_NV;
2259 break;
2260 case GL_NORMAL_MAP_NV:
2261 bitr = TEXGEN_NORMAL_MAP_NV;
2262 break;
2263 case GL_EYE_LINEAR:
2264 bitr = TEXGEN_EYE_LINEAR;
2265 break;
2266 default:
2267 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
2268 return;
2269 }
2270 if (texUnit->GenModeR == mode)
2271 return;
2272 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2273 texUnit->GenModeR = mode;
2274 texUnit->_GenBitR = bitr;
2275 }
2276 else if (pname==GL_OBJECT_PLANE) {
2277 if (TEST_EQ_4V(texUnit->ObjectPlaneR, params))
2278 return;
2279 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2280 texUnit->ObjectPlaneR[0] = params[0];
2281 texUnit->ObjectPlaneR[1] = params[1];
2282 texUnit->ObjectPlaneR[2] = params[2];
2283 texUnit->ObjectPlaneR[3] = params[3];
2284 }
2285 else if (pname==GL_EYE_PLANE) {
2286 GLfloat tmp[4];
2287 /* Transform plane equation by the inverse modelview matrix */
2288 if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
2289 _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
2290 }
2291 _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
2292 if (TEST_EQ_4V(texUnit->EyePlaneR, tmp))
2293 return;
2294 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2295 COPY_4FV(texUnit->EyePlaneR, tmp);
2296 }
2297 else {
2298 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
2299 return;
2300 }
2301 break;
2302 case GL_Q:
2303 if (pname==GL_TEXTURE_GEN_MODE) {
2304 GLenum mode = (GLenum) (GLint) *params;
2305 GLuint bitq;
2306 switch (mode) {
2307 case GL_OBJECT_LINEAR:
2308 bitq = TEXGEN_OBJ_LINEAR;
2309 break;
2310 case GL_EYE_LINEAR:
2311 bitq = TEXGEN_EYE_LINEAR;
2312 break;
2313 default:
2314 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
2315 return;
2316 }
2317 if (texUnit->GenModeQ == mode)
2318 return;
2319 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2320 texUnit->GenModeQ = mode;
2321 texUnit->_GenBitQ = bitq;
2322 }
2323 else if (pname==GL_OBJECT_PLANE) {
2324 if (TEST_EQ_4V(texUnit->ObjectPlaneQ, params))
2325 return;
2326 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2327 texUnit->ObjectPlaneQ[0] = params[0];
2328 texUnit->ObjectPlaneQ[1] = params[1];
2329 texUnit->ObjectPlaneQ[2] = params[2];
2330 texUnit->ObjectPlaneQ[3] = params[3];
2331 }
2332 else if (pname==GL_EYE_PLANE) {
2333 GLfloat tmp[4];
2334 /* Transform plane equation by the inverse modelview matrix */
2335 if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) {
2336 _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
2337 }
2338 _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv );
2339 if (TEST_EQ_4V(texUnit->EyePlaneQ, tmp))
2340 return;
2341 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2342 COPY_4FV(texUnit->EyePlaneQ, tmp);
2343 }
2344 else {
2345 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
2346 return;
2347 }
2348 break;
2349 default:
2350 _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(coord)" );
2351 return;
2352 }
2353
2354 if (ctx->Driver.TexGen)
2355 ctx->Driver.TexGen( ctx, coord, pname, params );
2356 }
2357
2358
2359 void GLAPIENTRY
2360 _mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params )
2361 {
2362 GLfloat p[4];
2363 p[0] = (GLfloat) params[0];
2364 if (pname == GL_TEXTURE_GEN_MODE) {
2365 p[1] = p[2] = p[3] = 0.0F;
2366 }
2367 else {
2368 p[1] = (GLfloat) params[1];
2369 p[2] = (GLfloat) params[2];
2370 p[3] = (GLfloat) params[3];
2371 }
2372 _mesa_TexGenfv(coord, pname, p);
2373 }
2374
2375
2376 void GLAPIENTRY
2377 _mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
2378 {
2379 GLfloat p = (GLfloat) param;
2380 _mesa_TexGenfv( coord, pname, &p );
2381 }
2382
2383
2384 void GLAPIENTRY
2385 _mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params )
2386 {
2387 GLfloat p[4];
2388 p[0] = (GLfloat) params[0];
2389 if (pname == GL_TEXTURE_GEN_MODE) {
2390 p[1] = p[2] = p[3] = 0.0F;
2391 }
2392 else {
2393 p[1] = (GLfloat) params[1];
2394 p[2] = (GLfloat) params[2];
2395 p[3] = (GLfloat) params[3];
2396 }
2397 _mesa_TexGenfv( coord, pname, p );
2398 }
2399
2400
2401 void GLAPIENTRY
2402 _mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param )
2403 {
2404 _mesa_TexGenfv(coord, pname, &param);
2405 }
2406
2407
2408 void GLAPIENTRY
2409 _mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
2410 {
2411 _mesa_TexGeniv( coord, pname, &param );
2412 }
2413
2414
2415
2416 void GLAPIENTRY
2417 _mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
2418 {
2419 GET_CURRENT_CONTEXT(ctx);
2420 GLuint tUnit = ctx->Texture.CurrentUnit;
2421 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
2422 ASSERT_OUTSIDE_BEGIN_END(ctx);
2423
2424 switch (coord) {
2425 case GL_S:
2426 if (pname==GL_TEXTURE_GEN_MODE) {
2427 params[0] = ENUM_TO_DOUBLE(texUnit->GenModeS);
2428 }
2429 else if (pname==GL_OBJECT_PLANE) {
2430 COPY_4V( params, texUnit->ObjectPlaneS );
2431 }
2432 else if (pname==GL_EYE_PLANE) {
2433 COPY_4V( params, texUnit->EyePlaneS );
2434 }
2435 else {
2436 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
2437 return;
2438 }
2439 break;
2440 case GL_T:
2441 if (pname==GL_TEXTURE_GEN_MODE) {
2442 params[0] = ENUM_TO_DOUBLE(texUnit->GenModeT);
2443 }
2444 else if (pname==GL_OBJECT_PLANE) {
2445 COPY_4V( params, texUnit->ObjectPlaneT );
2446 }
2447 else if (pname==GL_EYE_PLANE) {
2448 COPY_4V( params, texUnit->EyePlaneT );
2449 }
2450 else {
2451 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
2452 return;
2453 }
2454 break;
2455 case GL_R:
2456 if (pname==GL_TEXTURE_GEN_MODE) {
2457 params[0] = ENUM_TO_DOUBLE(texUnit->GenModeR);
2458 }
2459 else if (pname==GL_OBJECT_PLANE) {
2460 COPY_4V( params, texUnit->ObjectPlaneR );
2461 }
2462 else if (pname==GL_EYE_PLANE) {
2463 COPY_4V( params, texUnit->EyePlaneR );
2464 }
2465 else {
2466 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
2467 return;
2468 }
2469 break;
2470 case GL_Q:
2471 if (pname==GL_TEXTURE_GEN_MODE) {
2472 params[0] = ENUM_TO_DOUBLE(texUnit->GenModeQ);
2473 }
2474 else if (pname==GL_OBJECT_PLANE) {
2475 COPY_4V( params, texUnit->ObjectPlaneQ );
2476 }
2477 else if (pname==GL_EYE_PLANE) {
2478 COPY_4V( params, texUnit->EyePlaneQ );
2479 }
2480 else {
2481 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
2482 return;
2483 }
2484 break;
2485 default:
2486 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)" );
2487 return;
2488 }
2489 }
2490
2491
2492
2493 void GLAPIENTRY
2494 _mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
2495 {
2496 GET_CURRENT_CONTEXT(ctx);
2497 GLuint tUnit = ctx->Texture.CurrentUnit;
2498 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
2499 ASSERT_OUTSIDE_BEGIN_END(ctx);
2500
2501 switch (coord) {
2502 case GL_S:
2503 if (pname==GL_TEXTURE_GEN_MODE) {
2504 params[0] = ENUM_TO_FLOAT(texUnit->GenModeS);
2505 }
2506 else if (pname==GL_OBJECT_PLANE) {
2507 COPY_4V( params, texUnit->ObjectPlaneS );
2508 }
2509 else if (pname==GL_EYE_PLANE) {
2510 COPY_4V( params, texUnit->EyePlaneS );
2511 }
2512 else {
2513 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
2514 return;
2515 }
2516 break;
2517 case GL_T:
2518 if (pname==GL_TEXTURE_GEN_MODE) {
2519 params[0] = ENUM_TO_FLOAT(texUnit->GenModeT);
2520 }
2521 else if (pname==GL_OBJECT_PLANE) {
2522 COPY_4V( params, texUnit->ObjectPlaneT );
2523 }
2524 else if (pname==GL_EYE_PLANE) {
2525 COPY_4V( params, texUnit->EyePlaneT );
2526 }
2527 else {
2528 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
2529 return;
2530 }
2531 break;
2532 case GL_R:
2533 if (pname==GL_TEXTURE_GEN_MODE) {
2534 params[0] = ENUM_TO_FLOAT(texUnit->GenModeR);
2535 }
2536 else if (pname==GL_OBJECT_PLANE) {
2537 COPY_4V( params, texUnit->ObjectPlaneR );
2538 }
2539 else if (pname==GL_EYE_PLANE) {
2540 COPY_4V( params, texUnit->EyePlaneR );
2541 }
2542 else {
2543 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
2544 return;
2545 }
2546 break;
2547 case GL_Q:
2548 if (pname==GL_TEXTURE_GEN_MODE) {
2549 params[0] = ENUM_TO_FLOAT(texUnit->GenModeQ);
2550 }
2551 else if (pname==GL_OBJECT_PLANE) {
2552 COPY_4V( params, texUnit->ObjectPlaneQ );
2553 }
2554 else if (pname==GL_EYE_PLANE) {
2555 COPY_4V( params, texUnit->EyePlaneQ );
2556 }
2557 else {
2558 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
2559 return;
2560 }
2561 break;
2562 default:
2563 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)" );
2564 return;
2565 }
2566 }
2567
2568
2569
2570 void GLAPIENTRY
2571 _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
2572 {
2573 GET_CURRENT_CONTEXT(ctx);
2574 GLuint tUnit = ctx->Texture.CurrentUnit;
2575 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
2576 ASSERT_OUTSIDE_BEGIN_END(ctx);
2577
2578 switch (coord) {
2579 case GL_S:
2580 if (pname==GL_TEXTURE_GEN_MODE) {
2581 params[0] = texUnit->GenModeS;
2582 }
2583 else if (pname==GL_OBJECT_PLANE) {
2584 params[0] = (GLint) texUnit->ObjectPlaneS[0];
2585 params[1] = (GLint) texUnit->ObjectPlaneS[1];
2586 params[2] = (GLint) texUnit->ObjectPlaneS[2];
2587 params[3] = (GLint) texUnit->ObjectPlaneS[3];
2588 }
2589 else if (pname==GL_EYE_PLANE) {
2590 params[0] = (GLint) texUnit->EyePlaneS[0];
2591 params[1] = (GLint) texUnit->EyePlaneS[1];
2592 params[2] = (GLint) texUnit->EyePlaneS[2];
2593 params[3] = (GLint) texUnit->EyePlaneS[3];
2594 }
2595 else {
2596 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
2597 return;
2598 }
2599 break;
2600 case GL_T:
2601 if (pname==GL_TEXTURE_GEN_MODE) {
2602 params[0] = texUnit->GenModeT;
2603 }
2604 else if (pname==GL_OBJECT_PLANE) {
2605 params[0] = (GLint) texUnit->ObjectPlaneT[0];
2606 params[1] = (GLint) texUnit->ObjectPlaneT[1];
2607 params[2] = (GLint) texUnit->ObjectPlaneT[2];
2608 params[3] = (GLint) texUnit->ObjectPlaneT[3];
2609 }
2610 else if (pname==GL_EYE_PLANE) {
2611 params[0] = (GLint) texUnit->EyePlaneT[0];
2612 params[1] = (GLint) texUnit->EyePlaneT[1];
2613 params[2] = (GLint) texUnit->EyePlaneT[2];
2614 params[3] = (GLint) texUnit->EyePlaneT[3];
2615 }
2616 else {
2617 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
2618 return;
2619 }
2620 break;
2621 case GL_R:
2622 if (pname==GL_TEXTURE_GEN_MODE) {
2623 params[0] = texUnit->GenModeR;
2624 }
2625 else if (pname==GL_OBJECT_PLANE) {
2626 params[0] = (GLint) texUnit->ObjectPlaneR[0];
2627 params[1] = (GLint) texUnit->ObjectPlaneR[1];
2628 params[2] = (GLint) texUnit->ObjectPlaneR[2];
2629 params[3] = (GLint) texUnit->ObjectPlaneR[3];
2630 }
2631 else if (pname==GL_EYE_PLANE) {
2632 params[0] = (GLint) texUnit->EyePlaneR[0];
2633 params[1] = (GLint) texUnit->EyePlaneR[1];
2634 params[2] = (GLint) texUnit->EyePlaneR[2];
2635 params[3] = (GLint) texUnit->EyePlaneR[3];
2636 }
2637 else {
2638 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
2639 return;
2640 }
2641 break;
2642 case GL_Q:
2643 if (pname==GL_TEXTURE_GEN_MODE) {
2644 params[0] = texUnit->GenModeQ;
2645 }
2646 else if (pname==GL_OBJECT_PLANE) {
2647 params[0] = (GLint) texUnit->ObjectPlaneQ[0];
2648 params[1] = (GLint) texUnit->ObjectPlaneQ[1];
2649 params[2] = (GLint) texUnit->ObjectPlaneQ[2];
2650 params[3] = (GLint) texUnit->ObjectPlaneQ[3];
2651 }
2652 else if (pname==GL_EYE_PLANE) {
2653 params[0] = (GLint) texUnit->EyePlaneQ[0];
2654 params[1] = (GLint) texUnit->EyePlaneQ[1];
2655 params[2] = (GLint) texUnit->EyePlaneQ[2];
2656 params[3] = (GLint) texUnit->EyePlaneQ[3];
2657 }
2658 else {
2659 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
2660 return;
2661 }
2662 break;
2663 default:
2664 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)" );
2665 return;
2666 }
2667 }
2668 #endif
2669
2670 /* GL_ARB_multitexture */
2671 void GLAPIENTRY
2672 _mesa_ActiveTextureARB( GLenum target )
2673 {
2674 GET_CURRENT_CONTEXT(ctx);
2675 const GLuint texUnit = target - GL_TEXTURE0;
2676 ASSERT_OUTSIDE_BEGIN_END(ctx);
2677
2678 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2679 _mesa_debug(ctx, "glActiveTexture %s\n",
2680 _mesa_lookup_enum_by_nr(target));
2681
2682 /* Cater for texture unit 0 is first, therefore use >= */
2683 if (texUnit >= ctx->Const.MaxTextureUnits) {
2684 _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(target)");
2685 return;
2686 }
2687
2688 if (ctx->Texture.CurrentUnit == texUnit)
2689 return;
2690
2691 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
2692
2693 ctx->Texture.CurrentUnit = texUnit;
2694 if (ctx->Transform.MatrixMode == GL_TEXTURE) {
2695 /* update current stack pointer */
2696 ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
2697 }
2698
2699 if (ctx->Driver.ActiveTexture) {
2700 (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit );
2701 }
2702 }
2703
2704
2705 /* GL_ARB_multitexture */
2706 void GLAPIENTRY
2707 _mesa_ClientActiveTextureARB( GLenum target )
2708 {
2709 GET_CURRENT_CONTEXT(ctx);
2710 GLuint texUnit = target - GL_TEXTURE0;
2711 ASSERT_OUTSIDE_BEGIN_END(ctx);
2712
2713 if (texUnit > ctx->Const.MaxTextureUnits) {
2714 _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(target)");
2715 return;
2716 }
2717
2718 FLUSH_VERTICES(ctx, _NEW_ARRAY);
2719 ctx->Array.ActiveTexture = texUnit;
2720 }
2721
2722
2723
2724 /**********************************************************************/
2725 /* Pixel Texgen Extensions */
2726 /**********************************************************************/
2727
2728 void GLAPIENTRY
2729 _mesa_PixelTexGenSGIX(GLenum mode)
2730 {
2731 GLenum newRgbSource, newAlphaSource;
2732 GET_CURRENT_CONTEXT(ctx);
2733 ASSERT_OUTSIDE_BEGIN_END(ctx);
2734
2735 switch (mode) {
2736 case GL_NONE:
2737 newRgbSource = GL_PIXEL_GROUP_COLOR_SGIS;
2738 newAlphaSource = GL_PIXEL_GROUP_COLOR_SGIS;
2739 break;
2740 case GL_ALPHA:
2741 newRgbSource = GL_PIXEL_GROUP_COLOR_SGIS;
2742 newAlphaSource = GL_CURRENT_RASTER_COLOR;
2743 break;
2744 case GL_RGB:
2745 newRgbSource = GL_CURRENT_RASTER_COLOR;
2746 newAlphaSource = GL_PIXEL_GROUP_COLOR_SGIS;
2747 break;
2748 case GL_RGBA:
2749 newRgbSource = GL_CURRENT_RASTER_COLOR;
2750 newAlphaSource = GL_CURRENT_RASTER_COLOR;
2751 break;
2752 default:
2753 _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenSGIX(mode)");
2754 return;
2755 }
2756
2757 if (newRgbSource == ctx->Pixel.FragmentRgbSource &&
2758 newAlphaSource == ctx->Pixel.FragmentAlphaSource)
2759 return;
2760
2761 FLUSH_VERTICES(ctx, _NEW_PIXEL);
2762 ctx->Pixel.FragmentRgbSource = newRgbSource;
2763 ctx->Pixel.FragmentAlphaSource = newAlphaSource;
2764 }
2765
2766
2767 void GLAPIENTRY
2768 _mesa_PixelTexGenParameterfSGIS(GLenum target, GLfloat value)
2769 {
2770 _mesa_PixelTexGenParameteriSGIS(target, (GLint) value);
2771 }
2772
2773
2774 void GLAPIENTRY
2775 _mesa_PixelTexGenParameterfvSGIS(GLenum target, const GLfloat *value)
2776 {
2777 _mesa_PixelTexGenParameteriSGIS(target, (GLint) *value);
2778 }
2779
2780
2781 void GLAPIENTRY
2782 _mesa_PixelTexGenParameteriSGIS(GLenum target, GLint value)
2783 {
2784 GET_CURRENT_CONTEXT(ctx);
2785 ASSERT_OUTSIDE_BEGIN_END(ctx);
2786
2787 if (value != GL_CURRENT_RASTER_COLOR && value != GL_PIXEL_GROUP_COLOR_SGIS) {
2788 _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenParameterSGIS(value)");
2789 return;
2790 }
2791
2792 switch (target) {
2793 case GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS:
2794 if (ctx->Pixel.FragmentRgbSource == (GLenum) value)
2795 return;
2796 FLUSH_VERTICES(ctx, _NEW_PIXEL);
2797 ctx->Pixel.FragmentRgbSource = (GLenum) value;
2798 break;
2799 case GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS:
2800 if (ctx->Pixel.FragmentAlphaSource == (GLenum) value)
2801 return;
2802 FLUSH_VERTICES(ctx, _NEW_PIXEL);
2803 ctx->Pixel.FragmentAlphaSource = (GLenum) value;
2804 break;
2805 default:
2806 _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenParameterSGIS(target)");
2807 return;
2808 }
2809 }
2810
2811
2812 void GLAPIENTRY
2813 _mesa_PixelTexGenParameterivSGIS(GLenum target, const GLint *value)
2814 {
2815 _mesa_PixelTexGenParameteriSGIS(target, *value);
2816 }
2817
2818
2819 void GLAPIENTRY
2820 _mesa_GetPixelTexGenParameterfvSGIS(GLenum target, GLfloat *value)
2821 {
2822 GET_CURRENT_CONTEXT(ctx);
2823 ASSERT_OUTSIDE_BEGIN_END(ctx);
2824
2825 if (target == GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS) {
2826 *value = (GLfloat) ctx->Pixel.FragmentRgbSource;
2827 }
2828 else if (target == GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS) {
2829 *value = (GLfloat) ctx->Pixel.FragmentAlphaSource;
2830 }
2831 else {
2832 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterfvSGIS(target)");
2833 }
2834 }
2835
2836
2837 void GLAPIENTRY
2838 _mesa_GetPixelTexGenParameterivSGIS(GLenum target, GLint *value)
2839 {
2840 GET_CURRENT_CONTEXT(ctx);
2841 ASSERT_OUTSIDE_BEGIN_END(ctx);
2842
2843 if (target == GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS) {
2844 *value = (GLint) ctx->Pixel.FragmentRgbSource;
2845 }
2846 else if (target == GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS) {
2847 *value = (GLint) ctx->Pixel.FragmentAlphaSource;
2848 }
2849 else {
2850 _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterivSGIS(target)");
2851 }
2852 }
2853
2854
2855
2856 /**********************************************************************/
2857 /***** State management *****/
2858 /**********************************************************************/
2859
2860
2861 /**
2862 * \note This routine refers to derived texture attribute values to
2863 * compute the ENABLE_TEXMAT flags, but is only called on
2864 * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
2865 * flags are updated by _mesa_update_textures(), below.
2866 *
2867 * \param ctx GL context.
2868 */
2869 static void
2870 update_texture_matrices( GLcontext *ctx )
2871 {
2872 GLuint i;
2873
2874 ctx->Texture._TexMatEnabled = 0;
2875
2876 for (i=0; i < ctx->Const.MaxTextureUnits; i++) {
2877 if (ctx->TextureMatrixStack[i].Top->flags & MAT_DIRTY) {
2878 _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
2879
2880 if (ctx->Texture.Unit[i]._ReallyEnabled &&
2881 ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
2882 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
2883
2884 if (ctx->Driver.TextureMatrix)
2885 ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
2886 }
2887 }
2888 }
2889
2890
2891
2892
2893 /**
2894 * \note This routine refers to derived texture matrix values to
2895 * compute the ENABLE_TEXMAT flags, but is only called on
2896 * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
2897 * flags are updated by _mesa_update_texture_matrices, above.
2898 *
2899 * \param ctx GL context.
2900 */
2901 static void
2902 update_texture_state( GLcontext *ctx )
2903 {
2904 GLuint unit;
2905
2906 ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are
2907 * actual changes.
2908 */
2909
2910 ctx->Texture._EnabledUnits = 0;
2911 ctx->Texture._GenFlags = 0;
2912 ctx->Texture._TexMatEnabled = 0;
2913 ctx->Texture._TexGenEnabled = 0;
2914
2915 /* Update texture unit state.
2916 * XXX this loop should probably be broken into separate loops for
2917 * texture coord units and texture image units.
2918 */
2919 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
2920 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
2921 GLuint enableBits;
2922
2923 texUnit->_Current = NULL;
2924 texUnit->_ReallyEnabled = 0;
2925 texUnit->_GenFlags = 0;
2926
2927 /* Get the bitmask of texture enables */
2928 if (ctx->FragmentProgram._Enabled) {
2929 enableBits = ctx->FragmentProgram.Current->TexturesUsed[unit];
2930 }
2931 else {
2932 if (!texUnit->Enabled)
2933 continue;
2934 enableBits = texUnit->Enabled;
2935 }
2936
2937 /* Look for the highest-priority texture target that's enabled and
2938 * complete. That's the one we'll use for texturing. If we're using
2939 * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
2940 */
2941 if (enableBits & TEXTURE_CUBE_BIT) {
2942 struct gl_texture_object *texObj = texUnit->CurrentCubeMap;
2943 if (!texObj->Complete) {
2944 _mesa_test_texobj_completeness(ctx, texObj);
2945 }
2946 if (texObj->Complete) {
2947 texUnit->_ReallyEnabled = TEXTURE_CUBE_BIT;
2948 texUnit->_Current = texObj;
2949 }
2950 }
2951
2952 if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_3D_BIT)) {
2953 struct gl_texture_object *texObj = texUnit->Current3D;
2954 if (!texObj->Complete) {
2955 _mesa_test_texobj_completeness(ctx, texObj);
2956 }
2957 if (texObj->Complete) {
2958 texUnit->_ReallyEnabled = TEXTURE_3D_BIT;
2959 texUnit->_Current = texObj;
2960 }
2961 }
2962
2963 if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_RECT_BIT)) {
2964 struct gl_texture_object *texObj = texUnit->CurrentRect;
2965 if (!texObj->Complete) {
2966 _mesa_test_texobj_completeness(ctx, texObj);
2967 }
2968 if (texObj->Complete) {
2969 texUnit->_ReallyEnabled = TEXTURE_RECT_BIT;
2970 texUnit->_Current = texObj;
2971 }
2972 }
2973
2974 if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_2D_BIT)) {
2975 struct gl_texture_object *texObj = texUnit->Current2D;
2976 if (!texObj->Complete) {
2977 _mesa_test_texobj_completeness(ctx, texObj);
2978 }
2979 if (texObj->Complete) {
2980 texUnit->_ReallyEnabled = TEXTURE_2D_BIT;
2981 texUnit->_Current = texObj;
2982 }
2983 }
2984
2985 if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_1D_BIT)) {
2986 struct gl_texture_object *texObj = texUnit->Current1D;
2987 if (!texObj->Complete) {
2988 _mesa_test_texobj_completeness(ctx, texObj);
2989 }
2990 if (texObj->Complete) {
2991 texUnit->_ReallyEnabled = TEXTURE_1D_BIT;
2992 texUnit->_Current = texObj;
2993 }
2994 }
2995
2996 if (!texUnit->_ReallyEnabled) {
2997 continue;
2998 }
2999
3000 if (texUnit->_ReallyEnabled)
3001 ctx->Texture._EnabledUnits |= (1 << unit);
3002
3003 if (texUnit->EnvMode == GL_COMBINE) {
3004 texUnit->_CurrentCombine = & texUnit->Combine;
3005 }
3006 else {
3007 GLenum format = texUnit->_Current->Image[0][0]->Format;
3008 if (format == GL_COLOR_INDEX) {
3009 format = GL_RGBA; /* a bit of a hack */
3010 }
3011 else if (format == GL_DEPTH_COMPONENT) {
3012 format = texUnit->_Current->DepthMode;
3013 }
3014 calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
3015 texUnit->_CurrentCombine = & texUnit->_EnvMode;
3016 }
3017
3018 switch (texUnit->_CurrentCombine->ModeRGB) {
3019 case GL_REPLACE:
3020 texUnit->_CurrentCombine->_NumArgsRGB = 1;
3021 break;
3022 case GL_MODULATE:
3023 case GL_ADD:
3024 case GL_ADD_SIGNED:
3025 case GL_SUBTRACT:
3026 case GL_DOT3_RGB:
3027 case GL_DOT3_RGBA:
3028 case GL_DOT3_RGB_EXT:
3029 case GL_DOT3_RGBA_EXT:
3030 texUnit->_CurrentCombine->_NumArgsRGB = 2;
3031 break;
3032 case GL_INTERPOLATE:
3033 case GL_MODULATE_ADD_ATI:
3034 case GL_MODULATE_SIGNED_ADD_ATI:
3035 case GL_MODULATE_SUBTRACT_ATI:
3036 texUnit->_CurrentCombine->_NumArgsRGB = 3;
3037 break;
3038 default:
3039 texUnit->_CurrentCombine->_NumArgsRGB = 0;
3040 _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
3041 return;
3042 }
3043
3044 switch (texUnit->_CurrentCombine->ModeA) {
3045 case GL_REPLACE:
3046 texUnit->_CurrentCombine->_NumArgsA = 1;
3047 break;
3048 case GL_MODULATE:
3049 case GL_ADD:
3050 case GL_ADD_SIGNED:
3051 case GL_SUBTRACT:
3052 texUnit->_CurrentCombine->_NumArgsA = 2;
3053 break;
3054 case GL_INTERPOLATE:
3055 case GL_MODULATE_ADD_ATI:
3056 case GL_MODULATE_SIGNED_ADD_ATI:
3057 case GL_MODULATE_SUBTRACT_ATI:
3058 texUnit->_CurrentCombine->_NumArgsA = 3;
3059 break;
3060 default:
3061 texUnit->_CurrentCombine->_NumArgsA = 0;
3062 _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
3063 break;
3064 }
3065
3066 if (texUnit->TexGenEnabled) {
3067 if (texUnit->TexGenEnabled & S_BIT) {
3068 texUnit->_GenFlags |= texUnit->_GenBitS;
3069 }
3070 if (texUnit->TexGenEnabled & T_BIT) {
3071 texUnit->_GenFlags |= texUnit->_GenBitT;
3072 }
3073 if (texUnit->TexGenEnabled & Q_BIT) {
3074 texUnit->_GenFlags |= texUnit->_GenBitQ;
3075 }
3076 if (texUnit->TexGenEnabled & R_BIT) {
3077 texUnit->_GenFlags |= texUnit->_GenBitR;
3078 }
3079
3080 ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
3081 ctx->Texture._GenFlags |= texUnit->_GenFlags;
3082 }
3083
3084 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
3085 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
3086 }
3087
3088 ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
3089 /* Fragment programs may need texture coordinates but not the
3090 * corresponding texture images.
3091 */
3092 if (ctx->FragmentProgram._Enabled) {
3093 ctx->Texture._EnabledCoordUnits |=
3094 (ctx->FragmentProgram.Current->InputsRead >> FRAG_ATTRIB_TEX0);
3095 }
3096 }
3097
3098
3099 void _mesa_update_texture( GLcontext *ctx, GLuint new_state )
3100 {
3101 if (new_state & _NEW_TEXTURE_MATRIX)
3102 update_texture_matrices( ctx );
3103
3104 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
3105 update_texture_state( ctx );
3106 }
3107
3108 /**********************************************************************/
3109 /***** Initialization *****/
3110 /**********************************************************************/
3111
3112 /**
3113 * Allocate the proxy textures for the given context.
3114 *
3115 * \param ctx the context to allocate proxies for.
3116 *
3117 * \return GL_TRUE on success, or GL_FALSE on failure
3118 *
3119 * If run out of memory part way through the allocations, clean up and return
3120 * GL_FALSE.
3121 */
3122 static GLboolean
3123 alloc_proxy_textures( GLcontext *ctx )
3124 {
3125 ctx->Texture.Proxy1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
3126 if (!ctx->Texture.Proxy1D)
3127 goto cleanup;
3128
3129 ctx->Texture.Proxy2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
3130 if (!ctx->Texture.Proxy2D)
3131 goto cleanup;
3132
3133 ctx->Texture.Proxy3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
3134 if (!ctx->Texture.Proxy3D)
3135 goto cleanup;
3136
3137 ctx->Texture.ProxyCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
3138 if (!ctx->Texture.ProxyCubeMap)
3139 goto cleanup;
3140
3141 ctx->Texture.ProxyRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
3142 if (!ctx->Texture.ProxyRect)
3143 goto cleanup;
3144
3145 return GL_TRUE;
3146
3147 cleanup:
3148 if (ctx->Texture.Proxy1D)
3149 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D);
3150 if (ctx->Texture.Proxy2D)
3151 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D);
3152 if (ctx->Texture.Proxy3D)
3153 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D);
3154 if (ctx->Texture.ProxyCubeMap)
3155 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap);
3156 if (ctx->Texture.ProxyRect)
3157 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect);
3158 return GL_FALSE;
3159 }
3160
3161
3162 /**
3163 * Initialize a texture unit.
3164 *
3165 * \param ctx GL context.
3166 * \param unit texture unit number to be initialized.
3167 */
3168 static void
3169 init_texture_unit( GLcontext *ctx, GLuint unit )
3170 {
3171 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
3172
3173 texUnit->EnvMode = GL_MODULATE;
3174 ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
3175
3176 texUnit->Combine = default_combine_state;
3177 texUnit->_EnvMode = default_combine_state;
3178 texUnit->_CurrentCombine = & texUnit->_EnvMode;
3179
3180 texUnit->TexGenEnabled = 0;
3181 texUnit->GenModeS = GL_EYE_LINEAR;
3182 texUnit->GenModeT = GL_EYE_LINEAR;
3183 texUnit->GenModeR = GL_EYE_LINEAR;
3184 texUnit->GenModeQ = GL_EYE_LINEAR;
3185 texUnit->_GenBitS = TEXGEN_EYE_LINEAR;
3186 texUnit->_GenBitT = TEXGEN_EYE_LINEAR;
3187 texUnit->_GenBitR = TEXGEN_EYE_LINEAR;
3188 texUnit->_GenBitQ = TEXGEN_EYE_LINEAR;
3189
3190 /* Yes, these plane coefficients are correct! */
3191 ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 );
3192 ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 );
3193 ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 );
3194 ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 );
3195 ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 );
3196 ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 );
3197 ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
3198 ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
3199
3200 texUnit->Current1D = ctx->Shared->Default1D;
3201 texUnit->Current2D = ctx->Shared->Default2D;
3202 texUnit->Current3D = ctx->Shared->Default3D;
3203 texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
3204 texUnit->CurrentRect = ctx->Shared->DefaultRect;
3205 }
3206
3207
3208 GLboolean _mesa_init_texture( GLcontext * ctx )
3209 {
3210 int i;
3211
3212 assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
3213 assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
3214
3215 /* Effectively bind the default textures to all texture units */
3216 ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS;
3217 ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS;
3218 ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS;
3219 ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS;
3220 ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS;
3221
3222 /* Texture group */
3223 ctx->Texture.CurrentUnit = 0; /* multitexture */
3224 ctx->Texture._EnabledUnits = 0;
3225 for (i=0; i<MAX_TEXTURE_UNITS; i++)
3226 init_texture_unit( ctx, i );
3227 ctx->Texture.SharedPalette = GL_FALSE;
3228 _mesa_init_colortable(&ctx->Texture.Palette);
3229
3230 /* Allocate proxy textures */
3231 if (!alloc_proxy_textures( ctx ))
3232 return GL_FALSE;
3233
3234 return GL_TRUE;
3235 }
3236
3237 void _mesa_free_texture_data( GLcontext *ctx )
3238 {
3239 int i;
3240
3241 /* Free proxy texture objects */
3242 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D );
3243 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D );
3244 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D );
3245 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap );
3246 (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect );
3247
3248 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
3249 _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
3250 }