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