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