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