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