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