texparam.c revision baeefef2c0445bfd717a3086fdd9b5bd5d9cb675
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.5
4 *
5 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/**
27 * \file texparam.c
28 *
29 * glTexParameter-related functions
30 */
31
32
33#include "main/glheader.h"
34#include "main/colormac.h"
35#include "main/context.h"
36#include "main/enums.h"
37#include "main/formats.h"
38#include "main/macros.h"
39#include "main/mfeatures.h"
40#include "main/mtypes.h"
41#include "main/state.h"
42#include "main/texcompress.h"
43#include "main/texparam.h"
44#include "main/teximage.h"
45#include "main/texstate.h"
46#include "program/prog_instruction.h"
47
48
49/**
50 * Check if a coordinate wrap mode is supported for the texture target.
51 * \return GL_TRUE if legal, GL_FALSE otherwise
52 */
53static GLboolean
54validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap)
55{
56   const struct gl_extensions * const e = & ctx->Extensions;
57
58   if (wrap == GL_CLAMP || wrap == GL_CLAMP_TO_EDGE ||
59       (wrap == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
60      /* any texture target */
61      return GL_TRUE;
62   }
63   else if (target != GL_TEXTURE_RECTANGLE_NV &&
64	    (wrap == GL_REPEAT ||
65	     (wrap == GL_MIRRORED_REPEAT &&
66	      e->ARB_texture_mirrored_repeat) ||
67	     (wrap == GL_MIRROR_CLAMP_EXT &&
68	      (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
69	     (wrap == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
70	      (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
71	     (wrap == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
72	      (e->EXT_texture_mirror_clamp)))) {
73      /* non-rectangle texture */
74      return GL_TRUE;
75   }
76
77   _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", wrap );
78   return GL_FALSE;
79}
80
81
82/**
83 * Get current texture object for given target.
84 * Return NULL if any error (and record the error).
85 * Note that this is different from _mesa_select_tex_object() in that proxy
86 * targets are not accepted.
87 * Only the glGetTexLevelParameter() functions accept proxy targets.
88 */
89static struct gl_texture_object *
90get_texobj(struct gl_context *ctx, GLenum target, GLboolean get)
91{
92   struct gl_texture_unit *texUnit;
93
94   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
95      _mesa_error(ctx, GL_INVALID_OPERATION,
96                  "gl%sTexParameter(current unit)", get ? "Get" : "");
97      return NULL;
98   }
99
100   texUnit = _mesa_get_current_tex_unit(ctx);
101
102   switch (target) {
103   case GL_TEXTURE_1D:
104      return texUnit->CurrentTex[TEXTURE_1D_INDEX];
105   case GL_TEXTURE_2D:
106      return texUnit->CurrentTex[TEXTURE_2D_INDEX];
107   case GL_TEXTURE_3D:
108      return texUnit->CurrentTex[TEXTURE_3D_INDEX];
109   case GL_TEXTURE_CUBE_MAP:
110      if (ctx->Extensions.ARB_texture_cube_map) {
111         return texUnit->CurrentTex[TEXTURE_CUBE_INDEX];
112      }
113      break;
114   case GL_TEXTURE_RECTANGLE_NV:
115      if (ctx->Extensions.NV_texture_rectangle) {
116         return texUnit->CurrentTex[TEXTURE_RECT_INDEX];
117      }
118      break;
119   case GL_TEXTURE_1D_ARRAY_EXT:
120      if (ctx->Extensions.MESA_texture_array ||
121          ctx->Extensions.EXT_texture_array) {
122         return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX];
123      }
124      break;
125   case GL_TEXTURE_2D_ARRAY_EXT:
126      if (ctx->Extensions.MESA_texture_array ||
127          ctx->Extensions.EXT_texture_array) {
128         return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX];
129      }
130      break;
131   default:
132      ;
133   }
134
135   _mesa_error(ctx, GL_INVALID_ENUM,
136                  "gl%sTexParameter(target)", get ? "Get" : "");
137   return NULL;
138}
139
140
141/**
142 * Convert GL_RED/GREEN/BLUE/ALPHA/ZERO/ONE to SWIZZLE_X/Y/Z/W/ZERO/ONE.
143 * \return -1 if error.
144 */
145static GLint
146comp_to_swizzle(GLenum comp)
147{
148   switch (comp) {
149   case GL_RED:
150      return SWIZZLE_X;
151   case GL_GREEN:
152      return SWIZZLE_Y;
153   case GL_BLUE:
154      return SWIZZLE_Z;
155   case GL_ALPHA:
156      return SWIZZLE_W;
157   case GL_ZERO:
158      return SWIZZLE_ZERO;
159   case GL_ONE:
160      return SWIZZLE_ONE;
161   default:
162      return -1;
163   }
164}
165
166
167static void
168set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
169{
170   ASSERT(comp < 4);
171   ASSERT(swz <= SWIZZLE_NIL);
172   {
173      GLuint mask = 0x7 << (3 * comp);
174      GLuint s = (*swizzle & ~mask) | (swz << (3 * comp));
175      *swizzle = s;
176   }
177}
178
179
180/**
181 * This is called just prior to changing any texture object state which
182 * will not effect texture completeness.
183 */
184static INLINE void
185flush(struct gl_context *ctx)
186{
187   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
188}
189
190
191/**
192 * This is called just prior to changing any texture object state which
193 * can effect texture completeness (texture base level, max level,
194 * minification filter).
195 * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE
196 * state flag and then mark the texture object as 'incomplete' so that any
197 * per-texture derived state gets recomputed.
198 */
199static INLINE void
200incomplete(struct gl_context *ctx, struct gl_texture_object *texObj)
201{
202   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
203   texObj->_Complete = GL_FALSE;
204}
205
206
207/**
208 * Set an integer-valued texture parameter
209 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
210 */
211static GLboolean
212set_tex_parameteri(struct gl_context *ctx,
213                   struct gl_texture_object *texObj,
214                   GLenum pname, const GLint *params)
215{
216   switch (pname) {
217   case GL_TEXTURE_MIN_FILTER:
218      if (texObj->Sampler.MinFilter == params[0])
219         return GL_FALSE;
220      switch (params[0]) {
221      case GL_NEAREST:
222      case GL_LINEAR:
223         incomplete(ctx, texObj);
224         texObj->Sampler.MinFilter = params[0];
225         return GL_TRUE;
226      case GL_NEAREST_MIPMAP_NEAREST:
227      case GL_LINEAR_MIPMAP_NEAREST:
228      case GL_NEAREST_MIPMAP_LINEAR:
229      case GL_LINEAR_MIPMAP_LINEAR:
230         if (texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
231            incomplete(ctx, texObj);
232            texObj->Sampler.MinFilter = params[0];
233            return GL_TRUE;
234         }
235         /* fall-through */
236      default:
237         goto invalid_param;
238      }
239      return GL_FALSE;
240
241   case GL_TEXTURE_MAG_FILTER:
242      if (texObj->Sampler.MagFilter == params[0])
243         return GL_FALSE;
244      switch (params[0]) {
245      case GL_NEAREST:
246      case GL_LINEAR:
247         flush(ctx); /* does not effect completeness */
248         texObj->Sampler.MagFilter = params[0];
249         return GL_TRUE;
250      default:
251         goto invalid_param;
252      }
253      return GL_FALSE;
254
255   case GL_TEXTURE_WRAP_S:
256      if (texObj->Sampler.WrapS == params[0])
257         return GL_FALSE;
258      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
259         flush(ctx);
260         texObj->Sampler.WrapS = params[0];
261         return GL_TRUE;
262      }
263      return GL_FALSE;
264
265   case GL_TEXTURE_WRAP_T:
266      if (texObj->Sampler.WrapT == params[0])
267         return GL_FALSE;
268      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
269         flush(ctx);
270         texObj->Sampler.WrapT = params[0];
271         return GL_TRUE;
272      }
273      return GL_FALSE;
274
275   case GL_TEXTURE_WRAP_R:
276      if (texObj->Sampler.WrapR == params[0])
277         return GL_FALSE;
278      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
279         flush(ctx);
280         texObj->Sampler.WrapR = params[0];
281         return GL_TRUE;
282      }
283      return GL_FALSE;
284
285   case GL_TEXTURE_BASE_LEVEL:
286      if (texObj->BaseLevel == params[0])
287         return GL_FALSE;
288      if (params[0] < 0 ||
289          (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
290         _mesa_error(ctx, GL_INVALID_VALUE,
291                     "glTexParameter(param=%d)", params[0]);
292         return GL_FALSE;
293      }
294      incomplete(ctx, texObj);
295      texObj->BaseLevel = params[0];
296      return GL_TRUE;
297
298   case GL_TEXTURE_MAX_LEVEL:
299      if (texObj->MaxLevel == params[0])
300         return GL_FALSE;
301      if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
302         _mesa_error(ctx, GL_INVALID_OPERATION,
303                     "glTexParameter(param=%d)", params[0]);
304         return GL_FALSE;
305      }
306      incomplete(ctx, texObj);
307      texObj->MaxLevel = params[0];
308      return GL_TRUE;
309
310   case GL_GENERATE_MIPMAP_SGIS:
311      if (texObj->GenerateMipmap != params[0]) {
312         /* no flush() */
313	 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
314	 return GL_TRUE;
315      }
316      return GL_FALSE;
317
318   case GL_TEXTURE_COMPARE_MODE_ARB:
319      if (ctx->Extensions.ARB_shadow) {
320         if (texObj->Sampler.CompareMode == params[0])
321            return GL_FALSE;
322         if (params[0] == GL_NONE ||
323             params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
324            flush(ctx);
325            texObj->Sampler.CompareMode = params[0];
326            return GL_TRUE;
327         }
328         goto invalid_param;
329      }
330      goto invalid_pname;
331
332   case GL_TEXTURE_COMPARE_FUNC_ARB:
333      if (ctx->Extensions.ARB_shadow) {
334         if (texObj->Sampler.CompareFunc == params[0])
335            return GL_FALSE;
336         switch (params[0]) {
337         case GL_LEQUAL:
338         case GL_GEQUAL:
339            flush(ctx);
340            texObj->Sampler.CompareFunc = params[0];
341            return GL_TRUE;
342         case GL_EQUAL:
343         case GL_NOTEQUAL:
344         case GL_LESS:
345         case GL_GREATER:
346         case GL_ALWAYS:
347         case GL_NEVER:
348            if (ctx->Extensions.EXT_shadow_funcs) {
349               flush(ctx);
350               texObj->Sampler.CompareFunc = params[0];
351               return GL_TRUE;
352            }
353            /* fall-through */
354         default:
355            goto invalid_param;
356         }
357      }
358      goto invalid_pname;
359
360   case GL_DEPTH_TEXTURE_MODE_ARB:
361      if (ctx->Extensions.ARB_depth_texture) {
362         if (texObj->Sampler.DepthMode == params[0])
363            return GL_FALSE;
364         if (params[0] == GL_LUMINANCE ||
365             params[0] == GL_INTENSITY ||
366             params[0] == GL_ALPHA ||
367             (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
368            flush(ctx);
369            texObj->Sampler.DepthMode = params[0];
370            return GL_TRUE;
371         }
372         goto invalid_param;
373      }
374      goto invalid_pname;
375
376#if FEATURE_OES_draw_texture
377   case GL_TEXTURE_CROP_RECT_OES:
378      texObj->CropRect[0] = params[0];
379      texObj->CropRect[1] = params[1];
380      texObj->CropRect[2] = params[2];
381      texObj->CropRect[3] = params[3];
382      return GL_TRUE;
383#endif
384
385   case GL_TEXTURE_SWIZZLE_R_EXT:
386   case GL_TEXTURE_SWIZZLE_G_EXT:
387   case GL_TEXTURE_SWIZZLE_B_EXT:
388   case GL_TEXTURE_SWIZZLE_A_EXT:
389      if (ctx->Extensions.EXT_texture_swizzle) {
390         const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
391         const GLint swz = comp_to_swizzle(params[0]);
392         if (swz < 0) {
393            _mesa_error(ctx, GL_INVALID_OPERATION,
394                        "glTexParameter(swizzle 0x%x)", params[0]);
395            return GL_FALSE;
396         }
397         ASSERT(comp < 4);
398         if (swz >= 0) {
399            flush(ctx);
400            texObj->Swizzle[comp] = params[0];
401            set_swizzle_component(&texObj->_Swizzle, comp, swz);
402            return GL_TRUE;
403         }
404      }
405      goto invalid_pname;
406
407   case GL_TEXTURE_SWIZZLE_RGBA_EXT:
408      if (ctx->Extensions.EXT_texture_swizzle) {
409         GLuint comp;
410         flush(ctx);
411         for (comp = 0; comp < 4; comp++) {
412            const GLint swz = comp_to_swizzle(params[comp]);
413            if (swz >= 0) {
414               texObj->Swizzle[comp] = params[comp];
415               set_swizzle_component(&texObj->_Swizzle, comp, swz);
416            }
417            else {
418               _mesa_error(ctx, GL_INVALID_OPERATION,
419                           "glTexParameter(swizzle 0x%x)", params[comp]);
420               return GL_FALSE;
421            }
422         }
423         return GL_TRUE;
424      }
425      goto invalid_pname;
426
427   case GL_TEXTURE_SRGB_DECODE_EXT:
428      if (ctx->Extensions.EXT_texture_sRGB_decode) {
429	 GLenum decode = params[0];
430	 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
431	    if (texObj->Sampler.sRGBDecode != decode) {
432	       flush(ctx);
433	       texObj->Sampler.sRGBDecode = decode;
434	    }
435	    return GL_TRUE;
436	 }
437      }
438      goto invalid_pname;
439
440   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
441      if (ctx->Extensions.AMD_seamless_cubemap_per_texture) {
442         GLenum param = params[0];
443         if (param != GL_TRUE && param != GL_FALSE) {
444            goto invalid_param;
445         }
446         if (param != texObj->Sampler.CubeMapSeamless) {
447            flush(ctx);
448            texObj->Sampler.CubeMapSeamless = param;
449         }
450         return GL_TRUE;
451      }
452      goto invalid_pname;
453
454   default:
455      goto invalid_pname;
456   }
457
458invalid_pname:
459   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
460               _mesa_lookup_enum_by_nr(pname));
461   return GL_FALSE;
462
463invalid_param:
464   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)",
465               _mesa_lookup_enum_by_nr(params[0]));
466   return GL_FALSE;
467}
468
469
470/**
471 * Set a float-valued texture parameter
472 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
473 */
474static GLboolean
475set_tex_parameterf(struct gl_context *ctx,
476                   struct gl_texture_object *texObj,
477                   GLenum pname, const GLfloat *params)
478{
479   switch (pname) {
480   case GL_TEXTURE_MIN_LOD:
481      if (texObj->Sampler.MinLod == params[0])
482         return GL_FALSE;
483      flush(ctx);
484      texObj->Sampler.MinLod = params[0];
485      return GL_TRUE;
486
487   case GL_TEXTURE_MAX_LOD:
488      if (texObj->Sampler.MaxLod == params[0])
489         return GL_FALSE;
490      flush(ctx);
491      texObj->Sampler.MaxLod = params[0];
492      return GL_TRUE;
493
494   case GL_TEXTURE_PRIORITY:
495      flush(ctx);
496      texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
497      return GL_TRUE;
498
499   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
500      if (ctx->Extensions.EXT_texture_filter_anisotropic) {
501         if (texObj->Sampler.MaxAnisotropy == params[0])
502            return GL_FALSE;
503         if (params[0] < 1.0) {
504            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
505            return GL_FALSE;
506         }
507         flush(ctx);
508         /* clamp to max, that's what NVIDIA does */
509         texObj->Sampler.MaxAnisotropy = MIN2(params[0],
510                                      ctx->Const.MaxTextureMaxAnisotropy);
511         return GL_TRUE;
512      }
513      else {
514         static GLuint count = 0;
515         if (count++ < 10)
516            _mesa_error(ctx, GL_INVALID_ENUM,
517                        "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
518      }
519      return GL_FALSE;
520
521   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
522      if (ctx->Extensions.ARB_shadow_ambient) {
523         if (texObj->Sampler.CompareFailValue != params[0]) {
524            flush(ctx);
525            texObj->Sampler.CompareFailValue = CLAMP(params[0], 0.0F, 1.0F);
526            return GL_TRUE;
527         }
528      }
529      else {
530         _mesa_error(ctx, GL_INVALID_ENUM,
531                    "glTexParameter(pname=GL_TEXTURE_COMPARE_FAIL_VALUE_ARB)");
532      }
533      return GL_FALSE;
534
535   case GL_TEXTURE_LOD_BIAS:
536      /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */
537      if (ctx->Extensions.EXT_texture_lod_bias) {
538         if (texObj->Sampler.LodBias != params[0]) {
539            flush(ctx);
540            texObj->Sampler.LodBias = params[0];
541            return GL_TRUE;
542         }
543         return GL_FALSE;
544      }
545      break;
546
547   case GL_TEXTURE_BORDER_COLOR:
548      flush(ctx);
549      /* ARB_texture_float disables clamping */
550      if (ctx->Extensions.ARB_texture_float) {
551         texObj->Sampler.BorderColor.f[RCOMP] = params[0];
552         texObj->Sampler.BorderColor.f[GCOMP] = params[1];
553         texObj->Sampler.BorderColor.f[BCOMP] = params[2];
554         texObj->Sampler.BorderColor.f[ACOMP] = params[3];
555      } else {
556         texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F);
557         texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F);
558         texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F);
559         texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F);
560      }
561      return GL_TRUE;
562
563   default:
564      _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
565   }
566   return GL_FALSE;
567}
568
569
570void GLAPIENTRY
571_mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
572{
573   GLboolean need_update;
574   struct gl_texture_object *texObj;
575   GET_CURRENT_CONTEXT(ctx);
576   ASSERT_OUTSIDE_BEGIN_END(ctx);
577
578   texObj = get_texobj(ctx, target, GL_FALSE);
579   if (!texObj)
580      return;
581
582   switch (pname) {
583   case GL_TEXTURE_MIN_FILTER:
584   case GL_TEXTURE_MAG_FILTER:
585   case GL_TEXTURE_WRAP_S:
586   case GL_TEXTURE_WRAP_T:
587   case GL_TEXTURE_WRAP_R:
588   case GL_TEXTURE_BASE_LEVEL:
589   case GL_TEXTURE_MAX_LEVEL:
590   case GL_GENERATE_MIPMAP_SGIS:
591   case GL_TEXTURE_COMPARE_MODE_ARB:
592   case GL_TEXTURE_COMPARE_FUNC_ARB:
593   case GL_DEPTH_TEXTURE_MODE_ARB:
594   case GL_TEXTURE_SRGB_DECODE_EXT:
595   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
596      {
597         /* convert float param to int */
598         GLint p[4];
599         p[0] = (GLint) param;
600         p[1] = p[2] = p[3] = 0;
601         need_update = set_tex_parameteri(ctx, texObj, pname, p);
602      }
603      break;
604   default:
605      {
606         /* this will generate an error if pname is illegal */
607         GLfloat p[4];
608         p[0] = param;
609         p[1] = p[2] = p[3] = 0.0F;
610         need_update = set_tex_parameterf(ctx, texObj, pname, p);
611      }
612   }
613
614   if (ctx->Driver.TexParameter && need_update) {
615      ctx->Driver.TexParameter(ctx, target, texObj, pname, &param);
616   }
617}
618
619
620void GLAPIENTRY
621_mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
622{
623   GLboolean need_update;
624   struct gl_texture_object *texObj;
625   GET_CURRENT_CONTEXT(ctx);
626   ASSERT_OUTSIDE_BEGIN_END(ctx);
627
628   texObj = get_texobj(ctx, target, GL_FALSE);
629   if (!texObj)
630      return;
631
632   switch (pname) {
633   case GL_TEXTURE_MIN_FILTER:
634   case GL_TEXTURE_MAG_FILTER:
635   case GL_TEXTURE_WRAP_S:
636   case GL_TEXTURE_WRAP_T:
637   case GL_TEXTURE_WRAP_R:
638   case GL_TEXTURE_BASE_LEVEL:
639   case GL_TEXTURE_MAX_LEVEL:
640   case GL_GENERATE_MIPMAP_SGIS:
641   case GL_TEXTURE_COMPARE_MODE_ARB:
642   case GL_TEXTURE_COMPARE_FUNC_ARB:
643   case GL_DEPTH_TEXTURE_MODE_ARB:
644   case GL_TEXTURE_SRGB_DECODE_EXT:
645   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
646      {
647         /* convert float param to int */
648         GLint p[4];
649         p[0] = (GLint) params[0];
650         p[1] = p[2] = p[3] = 0;
651         need_update = set_tex_parameteri(ctx, texObj, pname, p);
652      }
653      break;
654
655#if FEATURE_OES_draw_texture
656   case GL_TEXTURE_CROP_RECT_OES:
657      {
658         /* convert float params to int */
659         GLint iparams[4];
660         iparams[0] = (GLint) params[0];
661         iparams[1] = (GLint) params[1];
662         iparams[2] = (GLint) params[2];
663         iparams[3] = (GLint) params[3];
664         need_update = set_tex_parameteri(ctx, texObj, pname, iparams);
665      }
666      break;
667#endif
668
669   default:
670      /* this will generate an error if pname is illegal */
671      need_update = set_tex_parameterf(ctx, texObj, pname, params);
672   }
673
674   if (ctx->Driver.TexParameter && need_update) {
675      ctx->Driver.TexParameter(ctx, target, texObj, pname, params);
676   }
677}
678
679
680void GLAPIENTRY
681_mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
682{
683   GLboolean need_update;
684   struct gl_texture_object *texObj;
685   GET_CURRENT_CONTEXT(ctx);
686   ASSERT_OUTSIDE_BEGIN_END(ctx);
687
688   texObj = get_texobj(ctx, target, GL_FALSE);
689   if (!texObj)
690      return;
691
692   switch (pname) {
693   case GL_TEXTURE_MIN_LOD:
694   case GL_TEXTURE_MAX_LOD:
695   case GL_TEXTURE_PRIORITY:
696   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
697   case GL_TEXTURE_LOD_BIAS:
698   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
699      {
700         GLfloat fparam[4];
701         fparam[0] = (GLfloat) param;
702         fparam[1] = fparam[2] = fparam[3] = 0.0F;
703         /* convert int param to float */
704         need_update = set_tex_parameterf(ctx, texObj, pname, fparam);
705      }
706      break;
707   default:
708      /* this will generate an error if pname is illegal */
709      {
710         GLint iparam[4];
711         iparam[0] = param;
712         iparam[1] = iparam[2] = iparam[3] = 0;
713         need_update = set_tex_parameteri(ctx, texObj, pname, iparam);
714      }
715   }
716
717   if (ctx->Driver.TexParameter && need_update) {
718      GLfloat fparam = (GLfloat) param;
719      ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam);
720   }
721}
722
723
724void GLAPIENTRY
725_mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
726{
727   GLboolean need_update;
728   struct gl_texture_object *texObj;
729   GET_CURRENT_CONTEXT(ctx);
730   ASSERT_OUTSIDE_BEGIN_END(ctx);
731
732   texObj = get_texobj(ctx, target, GL_FALSE);
733   if (!texObj)
734      return;
735
736   switch (pname) {
737   case GL_TEXTURE_BORDER_COLOR:
738      {
739         /* convert int params to float */
740         GLfloat fparams[4];
741         fparams[0] = INT_TO_FLOAT(params[0]);
742         fparams[1] = INT_TO_FLOAT(params[1]);
743         fparams[2] = INT_TO_FLOAT(params[2]);
744         fparams[3] = INT_TO_FLOAT(params[3]);
745         need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
746      }
747      break;
748   case GL_TEXTURE_MIN_LOD:
749   case GL_TEXTURE_MAX_LOD:
750   case GL_TEXTURE_PRIORITY:
751   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
752   case GL_TEXTURE_LOD_BIAS:
753   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
754      {
755         /* convert int param to float */
756         GLfloat fparams[4];
757         fparams[0] = (GLfloat) params[0];
758         fparams[1] = fparams[2] = fparams[3] = 0.0F;
759         need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
760      }
761      break;
762   default:
763      /* this will generate an error if pname is illegal */
764      need_update = set_tex_parameteri(ctx, texObj, pname, params);
765   }
766
767   if (ctx->Driver.TexParameter && need_update) {
768      GLfloat fparams[4];
769      fparams[0] = INT_TO_FLOAT(params[0]);
770      if (pname == GL_TEXTURE_BORDER_COLOR ||
771          pname == GL_TEXTURE_CROP_RECT_OES) {
772         fparams[1] = INT_TO_FLOAT(params[1]);
773         fparams[2] = INT_TO_FLOAT(params[2]);
774         fparams[3] = INT_TO_FLOAT(params[3]);
775      }
776      ctx->Driver.TexParameter(ctx, target, texObj, pname, fparams);
777   }
778}
779
780
781/**
782 * Set tex parameter to integer value(s).  Primarily intended to set
783 * integer-valued texture border color (for integer-valued textures).
784 * New in GL 3.0.
785 */
786void GLAPIENTRY
787_mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params)
788{
789   struct gl_texture_object *texObj;
790   GET_CURRENT_CONTEXT(ctx);
791   ASSERT_OUTSIDE_BEGIN_END(ctx);
792
793   texObj = get_texobj(ctx, target, GL_FALSE);
794   if (!texObj)
795      return;
796
797   switch (pname) {
798   case GL_TEXTURE_BORDER_COLOR:
799      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
800      /* set the integer-valued border color */
801      COPY_4V(texObj->Sampler.BorderColor.i, params);
802      break;
803   default:
804      _mesa_TexParameteriv(target, pname, params);
805      break;
806   }
807   /* XXX no driver hook for TexParameterIiv() yet */
808}
809
810
811/**
812 * Set tex parameter to unsigned integer value(s).  Primarily intended to set
813 * uint-valued texture border color (for integer-valued textures).
814 * New in GL 3.0
815 */
816void GLAPIENTRY
817_mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params)
818{
819   struct gl_texture_object *texObj;
820   GET_CURRENT_CONTEXT(ctx);
821   ASSERT_OUTSIDE_BEGIN_END(ctx);
822
823   texObj = get_texobj(ctx, target, GL_FALSE);
824   if (!texObj)
825      return;
826
827   switch (pname) {
828   case GL_TEXTURE_BORDER_COLOR:
829      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
830      /* set the unsigned integer-valued border color */
831      COPY_4V(texObj->Sampler.BorderColor.ui, params);
832      break;
833   default:
834      _mesa_TexParameteriv(target, pname, (const GLint *) params);
835      break;
836   }
837   /* XXX no driver hook for TexParameterIuiv() yet */
838}
839
840
841
842
843void GLAPIENTRY
844_mesa_GetTexLevelParameterfv( GLenum target, GLint level,
845                              GLenum pname, GLfloat *params )
846{
847   GLint iparam;
848   _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
849   *params = (GLfloat) iparam;
850}
851
852
853void GLAPIENTRY
854_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
855                              GLenum pname, GLint *params )
856{
857   const struct gl_texture_unit *texUnit;
858   struct gl_texture_object *texObj;
859   const struct gl_texture_image *img = NULL;
860   GLint maxLevels;
861   gl_format texFormat;
862   GET_CURRENT_CONTEXT(ctx);
863   ASSERT_OUTSIDE_BEGIN_END(ctx);
864
865   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
866      _mesa_error(ctx, GL_INVALID_OPERATION,
867                  "glGetTexLevelParameteriv(current unit)");
868      return;
869   }
870
871   texUnit = _mesa_get_current_tex_unit(ctx);
872
873   /* this will catch bad target values */
874   maxLevels = _mesa_max_texture_levels(ctx, target);
875   if (maxLevels == 0) {
876      _mesa_error(ctx, GL_INVALID_ENUM,
877                  "glGetTexLevelParameter[if]v(target=0x%x)", target);
878      return;
879   }
880
881   if (level < 0 || level >= maxLevels) {
882      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
883      return;
884   }
885
886   texObj = _mesa_select_tex_object(ctx, texUnit, target);
887
888   img = _mesa_select_tex_image(ctx, texObj, target, level);
889   if (!img || img->TexFormat == MESA_FORMAT_NONE) {
890      /* undefined texture image */
891      if (pname == GL_TEXTURE_COMPONENTS)
892         *params = 1;
893      else
894         *params = 0;
895      return;
896   }
897
898   texFormat = img->TexFormat;
899
900   switch (pname) {
901      case GL_TEXTURE_WIDTH:
902         *params = img->Width;
903         break;
904      case GL_TEXTURE_HEIGHT:
905         *params = img->Height;
906         break;
907      case GL_TEXTURE_DEPTH:
908         *params = img->Depth;
909         break;
910      case GL_TEXTURE_INTERNAL_FORMAT:
911         if (_mesa_is_format_compressed(texFormat)) {
912            /* need to return the actual compressed format */
913            *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
914         }
915         else {
916	    /* If the true internal format is not compressed but the user
917	     * requested a generic compressed format, we have to return the
918	     * generic base format that matches.
919	     *
920	     * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
921	     *
922	     *     "If no specific compressed format is available,
923	     *     internalformat is instead replaced by the corresponding base
924	     *     internal format."
925	     *
926	     * Otherwise just return the user's requested internal format
927	     */
928	    const GLenum f =
929	       _mesa_gl_compressed_format_base_format(img->InternalFormat);
930
931	    *params = (f != 0) ? f : img->InternalFormat;
932	 }
933         break;
934      case GL_TEXTURE_BORDER:
935         *params = img->Border;
936         break;
937      case GL_TEXTURE_RED_SIZE:
938         if (img->_BaseFormat == GL_RED) {
939            *params = _mesa_get_format_bits(texFormat, pname);
940	    break;
941	 }
942	 /* FALLTHROUGH */
943      case GL_TEXTURE_GREEN_SIZE:
944         if (img->_BaseFormat == GL_RG) {
945            *params = _mesa_get_format_bits(texFormat, pname);
946	    break;
947	 }
948	 /* FALLTHROUGH */
949      case GL_TEXTURE_BLUE_SIZE:
950         if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
951            *params = _mesa_get_format_bits(texFormat, pname);
952         else
953            *params = 0;
954         break;
955      case GL_TEXTURE_ALPHA_SIZE:
956         if (img->_BaseFormat == GL_ALPHA ||
957             img->_BaseFormat == GL_LUMINANCE_ALPHA ||
958             img->_BaseFormat == GL_RGBA)
959            *params = _mesa_get_format_bits(texFormat, pname);
960         else
961            *params = 0;
962         break;
963      case GL_TEXTURE_INTENSITY_SIZE:
964         if (img->_BaseFormat != GL_INTENSITY)
965            *params = 0;
966         else {
967            *params = _mesa_get_format_bits(texFormat, pname);
968            if (*params == 0) {
969               /* intensity probably stored as rgb texture */
970               *params = MIN2(_mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE),
971                              _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE));
972            }
973         }
974         break;
975      case GL_TEXTURE_LUMINANCE_SIZE:
976         if (img->_BaseFormat != GL_LUMINANCE &&
977             img->_BaseFormat != GL_LUMINANCE_ALPHA)
978            *params = 0;
979         else {
980            *params = _mesa_get_format_bits(texFormat, pname);
981            if (*params == 0) {
982               /* luminance probably stored as rgb texture */
983               *params = MIN2(_mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE),
984                              _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE));
985            }
986         }
987         break;
988      case GL_TEXTURE_DEPTH_SIZE_ARB:
989         if (!ctx->Extensions.ARB_depth_texture)
990            goto invalid_pname;
991         *params = _mesa_get_format_bits(texFormat, pname);
992         break;
993      case GL_TEXTURE_STENCIL_SIZE_EXT:
994         if (!ctx->Extensions.EXT_packed_depth_stencil &&
995             !ctx->Extensions.ARB_framebuffer_object)
996            goto invalid_pname;
997         *params = _mesa_get_format_bits(texFormat, pname);
998         break;
999      case GL_TEXTURE_SHARED_SIZE:
1000         if (ctx->VersionMajor < 3 &&
1001             !ctx->Extensions.EXT_texture_shared_exponent)
1002            goto invalid_pname;
1003         *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
1004         break;
1005
1006      /* GL_ARB_texture_compression */
1007      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1008	 if (_mesa_is_format_compressed(texFormat) &&
1009             !_mesa_is_proxy_texture(target)) {
1010            *params = _mesa_format_image_size(texFormat, img->Width,
1011                                              img->Height, img->Depth);
1012	 }
1013	 else {
1014	    _mesa_error(ctx, GL_INVALID_OPERATION,
1015			"glGetTexLevelParameter[if]v(pname)");
1016	 }
1017         break;
1018      case GL_TEXTURE_COMPRESSED:
1019         *params = (GLint) _mesa_is_format_compressed(texFormat);
1020         break;
1021
1022      /* GL_ARB_texture_float */
1023      case GL_TEXTURE_RED_TYPE_ARB:
1024         if (!ctx->Extensions.ARB_texture_float)
1025            goto invalid_pname;
1026         *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE) ?
1027            _mesa_get_format_datatype(texFormat) : GL_NONE;
1028         break;
1029      case GL_TEXTURE_GREEN_TYPE_ARB:
1030         if (!ctx->Extensions.ARB_texture_float)
1031            goto invalid_pname;
1032         *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE) ?
1033            _mesa_get_format_datatype(texFormat) : GL_NONE;
1034         break;
1035      case GL_TEXTURE_BLUE_TYPE_ARB:
1036         if (!ctx->Extensions.ARB_texture_float)
1037            goto invalid_pname;
1038         *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_BLUE_SIZE) ?
1039            _mesa_get_format_datatype(texFormat) : GL_NONE;
1040         break;
1041      case GL_TEXTURE_ALPHA_TYPE_ARB:
1042         if (!ctx->Extensions.ARB_texture_float)
1043            goto invalid_pname;
1044         *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_ALPHA_SIZE) ?
1045            _mesa_get_format_datatype(texFormat) : GL_NONE;
1046         break;
1047      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1048         if (!ctx->Extensions.ARB_texture_float)
1049            goto invalid_pname;
1050         *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_LUMINANCE_SIZE) ?
1051            _mesa_get_format_datatype(texFormat) : GL_NONE;
1052         break;
1053      case GL_TEXTURE_INTENSITY_TYPE_ARB:
1054         if (!ctx->Extensions.ARB_texture_float)
1055            goto invalid_pname;
1056         *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_INTENSITY_SIZE) ?
1057            _mesa_get_format_datatype(texFormat) : GL_NONE;
1058         break;
1059      case GL_TEXTURE_DEPTH_TYPE_ARB:
1060         if (!ctx->Extensions.ARB_texture_float)
1061            goto invalid_pname;
1062         *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_DEPTH_SIZE) ?
1063            _mesa_get_format_datatype(texFormat) : GL_NONE;
1064         break;
1065
1066      default:
1067         goto invalid_pname;
1068   }
1069
1070   /* no error if we get here */
1071   return;
1072
1073invalid_pname:
1074   _mesa_error(ctx, GL_INVALID_ENUM,
1075               "glGetTexLevelParameter[if]v(pname=%s)",
1076               _mesa_lookup_enum_by_nr(pname));
1077}
1078
1079
1080
1081void GLAPIENTRY
1082_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
1083{
1084   struct gl_texture_object *obj;
1085   GET_CURRENT_CONTEXT(ctx);
1086   ASSERT_OUTSIDE_BEGIN_END(ctx);
1087
1088   obj = get_texobj(ctx, target, GL_TRUE);
1089   if (!obj)
1090      return;
1091
1092   _mesa_lock_texture(ctx, obj);
1093   switch (pname) {
1094      case GL_TEXTURE_MAG_FILTER:
1095	 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
1096	 break;
1097      case GL_TEXTURE_MIN_FILTER:
1098         *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter);
1099         break;
1100      case GL_TEXTURE_WRAP_S:
1101         *params = ENUM_TO_FLOAT(obj->Sampler.WrapS);
1102         break;
1103      case GL_TEXTURE_WRAP_T:
1104         *params = ENUM_TO_FLOAT(obj->Sampler.WrapT);
1105         break;
1106      case GL_TEXTURE_WRAP_R:
1107         *params = ENUM_TO_FLOAT(obj->Sampler.WrapR);
1108         break;
1109      case GL_TEXTURE_BORDER_COLOR:
1110         if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
1111            _mesa_update_state_locked(ctx);
1112         if (ctx->Color._ClampFragmentColor) {
1113            params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1114            params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1115            params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1116            params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1117         }
1118         else {
1119            params[0] = obj->Sampler.BorderColor.f[0];
1120            params[1] = obj->Sampler.BorderColor.f[1];
1121            params[2] = obj->Sampler.BorderColor.f[2];
1122            params[3] = obj->Sampler.BorderColor.f[3];
1123         }
1124         break;
1125      case GL_TEXTURE_RESIDENT:
1126         *params = ctx->Driver.IsTextureResident ?
1127            ctx->Driver.IsTextureResident(ctx, obj) : 1.0F;
1128         break;
1129      case GL_TEXTURE_PRIORITY:
1130         *params = obj->Priority;
1131         break;
1132      case GL_TEXTURE_MIN_LOD:
1133         *params = obj->Sampler.MinLod;
1134         break;
1135      case GL_TEXTURE_MAX_LOD:
1136         *params = obj->Sampler.MaxLod;
1137         break;
1138      case GL_TEXTURE_BASE_LEVEL:
1139         *params = (GLfloat) obj->BaseLevel;
1140         break;
1141      case GL_TEXTURE_MAX_LEVEL:
1142         *params = (GLfloat) obj->MaxLevel;
1143         break;
1144      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1145         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1146            goto invalid_pname;
1147         *params = obj->Sampler.MaxAnisotropy;
1148         break;
1149      case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
1150         if (!ctx->Extensions.ARB_shadow_ambient)
1151            goto invalid_pname;
1152         *params = obj->Sampler.CompareFailValue;
1153         break;
1154      case GL_GENERATE_MIPMAP_SGIS:
1155	 *params = (GLfloat) obj->GenerateMipmap;
1156         break;
1157      case GL_TEXTURE_COMPARE_MODE_ARB:
1158         if (!ctx->Extensions.ARB_shadow)
1159            goto invalid_pname;
1160         *params = (GLfloat) obj->Sampler.CompareMode;
1161         break;
1162      case GL_TEXTURE_COMPARE_FUNC_ARB:
1163         if (!ctx->Extensions.ARB_shadow)
1164            goto invalid_pname;
1165         *params = (GLfloat) obj->Sampler.CompareFunc;
1166         break;
1167      case GL_DEPTH_TEXTURE_MODE_ARB:
1168         if (!ctx->Extensions.ARB_depth_texture)
1169            goto invalid_pname;
1170         *params = (GLfloat) obj->Sampler.DepthMode;
1171         break;
1172      case GL_TEXTURE_LOD_BIAS:
1173         if (!ctx->Extensions.EXT_texture_lod_bias)
1174            goto invalid_pname;
1175         *params = obj->Sampler.LodBias;
1176         break;
1177#if FEATURE_OES_draw_texture
1178      case GL_TEXTURE_CROP_RECT_OES:
1179         params[0] = obj->CropRect[0];
1180         params[1] = obj->CropRect[1];
1181         params[2] = obj->CropRect[2];
1182         params[3] = obj->CropRect[3];
1183         break;
1184#endif
1185
1186      case GL_TEXTURE_SWIZZLE_R_EXT:
1187      case GL_TEXTURE_SWIZZLE_G_EXT:
1188      case GL_TEXTURE_SWIZZLE_B_EXT:
1189      case GL_TEXTURE_SWIZZLE_A_EXT:
1190         if (!ctx->Extensions.EXT_texture_swizzle)
1191            goto invalid_pname;
1192         *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1193         break;
1194
1195      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1196         if (!ctx->Extensions.EXT_texture_swizzle) {
1197            goto invalid_pname;
1198         }
1199         else {
1200            GLuint comp;
1201            for (comp = 0; comp < 4; comp++) {
1202               params[comp] = (GLfloat) obj->Swizzle[comp];
1203            }
1204         }
1205         break;
1206
1207      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1208         if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1209            goto invalid_pname;
1210         *params = (GLfloat) obj->Sampler.CubeMapSeamless;
1211         break;
1212
1213      default:
1214         goto invalid_pname;
1215   }
1216
1217   /* no error if we get here */
1218   _mesa_unlock_texture(ctx, obj);
1219   return;
1220
1221invalid_pname:
1222   _mesa_unlock_texture(ctx, obj);
1223   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
1224}
1225
1226
1227void GLAPIENTRY
1228_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1229{
1230   struct gl_texture_object *obj;
1231   GET_CURRENT_CONTEXT(ctx);
1232   ASSERT_OUTSIDE_BEGIN_END(ctx);
1233
1234   obj = get_texobj(ctx, target, GL_TRUE);
1235   if (!obj)
1236      return;
1237
1238   _mesa_lock_texture(ctx, obj);
1239   switch (pname) {
1240      case GL_TEXTURE_MAG_FILTER:
1241         *params = (GLint) obj->Sampler.MagFilter;
1242         break;;
1243      case GL_TEXTURE_MIN_FILTER:
1244         *params = (GLint) obj->Sampler.MinFilter;
1245         break;;
1246      case GL_TEXTURE_WRAP_S:
1247         *params = (GLint) obj->Sampler.WrapS;
1248         break;;
1249      case GL_TEXTURE_WRAP_T:
1250         *params = (GLint) obj->Sampler.WrapT;
1251         break;;
1252      case GL_TEXTURE_WRAP_R:
1253         *params = (GLint) obj->Sampler.WrapR;
1254         break;;
1255      case GL_TEXTURE_BORDER_COLOR:
1256         {
1257            GLfloat b[4];
1258            b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1259            b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1260            b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1261            b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1262            params[0] = FLOAT_TO_INT(b[0]);
1263            params[1] = FLOAT_TO_INT(b[1]);
1264            params[2] = FLOAT_TO_INT(b[2]);
1265            params[3] = FLOAT_TO_INT(b[3]);
1266         }
1267         break;;
1268      case GL_TEXTURE_RESIDENT:
1269         *params = ctx->Driver.IsTextureResident ?
1270            ctx->Driver.IsTextureResident(ctx, obj) : 1;
1271         break;;
1272      case GL_TEXTURE_PRIORITY:
1273         *params = FLOAT_TO_INT(obj->Priority);
1274         break;;
1275      case GL_TEXTURE_MIN_LOD:
1276         *params = (GLint) obj->Sampler.MinLod;
1277         break;;
1278      case GL_TEXTURE_MAX_LOD:
1279         *params = (GLint) obj->Sampler.MaxLod;
1280         break;;
1281      case GL_TEXTURE_BASE_LEVEL:
1282         *params = obj->BaseLevel;
1283         break;;
1284      case GL_TEXTURE_MAX_LEVEL:
1285         *params = obj->MaxLevel;
1286         break;;
1287      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1288         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1289            goto invalid_pname;
1290         *params = (GLint) obj->Sampler.MaxAnisotropy;
1291         break;
1292      case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
1293         if (!ctx->Extensions.ARB_shadow_ambient)
1294            goto invalid_pname;
1295         *params = (GLint) FLOAT_TO_INT(obj->Sampler.CompareFailValue);
1296         break;
1297      case GL_GENERATE_MIPMAP_SGIS:
1298	 *params = (GLint) obj->GenerateMipmap;
1299         break;
1300      case GL_TEXTURE_COMPARE_MODE_ARB:
1301         if (!ctx->Extensions.ARB_shadow)
1302            goto invalid_pname;
1303         *params = (GLint) obj->Sampler.CompareMode;
1304         break;
1305      case GL_TEXTURE_COMPARE_FUNC_ARB:
1306         if (!ctx->Extensions.ARB_shadow)
1307            goto invalid_pname;
1308         *params = (GLint) obj->Sampler.CompareFunc;
1309         break;
1310      case GL_DEPTH_TEXTURE_MODE_ARB:
1311         if (!ctx->Extensions.ARB_depth_texture)
1312            goto invalid_pname;
1313         *params = (GLint) obj->Sampler.DepthMode;
1314         break;
1315      case GL_TEXTURE_LOD_BIAS:
1316         if (!ctx->Extensions.EXT_texture_lod_bias)
1317            goto invalid_pname;
1318         *params = (GLint) obj->Sampler.LodBias;
1319         break;
1320#if FEATURE_OES_draw_texture
1321      case GL_TEXTURE_CROP_RECT_OES:
1322         params[0] = obj->CropRect[0];
1323         params[1] = obj->CropRect[1];
1324         params[2] = obj->CropRect[2];
1325         params[3] = obj->CropRect[3];
1326         break;
1327#endif
1328      case GL_TEXTURE_SWIZZLE_R_EXT:
1329      case GL_TEXTURE_SWIZZLE_G_EXT:
1330      case GL_TEXTURE_SWIZZLE_B_EXT:
1331      case GL_TEXTURE_SWIZZLE_A_EXT:
1332         if (!ctx->Extensions.EXT_texture_swizzle)
1333            goto invalid_pname;
1334         *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1335         break;
1336
1337      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1338         if (!ctx->Extensions.EXT_texture_swizzle)
1339            goto invalid_pname;
1340         COPY_4V(params, obj->Swizzle);
1341         break;
1342
1343      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1344         if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1345            goto invalid_pname;
1346         *params = (GLint) obj->Sampler.CubeMapSeamless;
1347         break;
1348
1349      default:
1350         goto invalid_pname;
1351   }
1352
1353   /* no error if we get here */
1354   _mesa_unlock_texture(ctx, obj);
1355   return;
1356
1357invalid_pname:
1358   _mesa_unlock_texture(ctx, obj);
1359   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1360}
1361
1362
1363/** New in GL 3.0 */
1364void GLAPIENTRY
1365_mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
1366{
1367   struct gl_texture_object *texObj;
1368   GET_CURRENT_CONTEXT(ctx);
1369   ASSERT_OUTSIDE_BEGIN_END(ctx);
1370
1371   texObj = get_texobj(ctx, target, GL_TRUE);
1372   if (!texObj)
1373      return;
1374
1375   switch (pname) {
1376   case GL_TEXTURE_BORDER_COLOR:
1377      COPY_4V(params, texObj->Sampler.BorderColor.i);
1378      break;
1379   default:
1380      _mesa_GetTexParameteriv(target, pname, params);
1381   }
1382}
1383
1384
1385/** New in GL 3.0 */
1386void GLAPIENTRY
1387_mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
1388{
1389   struct gl_texture_object *texObj;
1390   GET_CURRENT_CONTEXT(ctx);
1391   ASSERT_OUTSIDE_BEGIN_END(ctx);
1392
1393   texObj = get_texobj(ctx, target, GL_TRUE);
1394   if (!texObj)
1395      return;
1396
1397   switch (pname) {
1398   case GL_TEXTURE_BORDER_COLOR:
1399      COPY_4V(params, texObj->Sampler.BorderColor.i);
1400      break;
1401   default:
1402      {
1403         GLint ip[4];
1404         _mesa_GetTexParameteriv(target, pname, ip);
1405         params[0] = ip[0];
1406         if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
1407             pname == GL_TEXTURE_CROP_RECT_OES) {
1408            params[1] = ip[1];
1409            params[2] = ip[2];
1410            params[3] = ip[3];
1411         }
1412      }
1413   }
1414}
1415