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