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