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