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#include <stdbool.h>
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/glformats.h"
39#include "main/macros.h"
40#include "main/mfeatures.h"
41#include "main/mtypes.h"
42#include "main/state.h"
43#include "main/texcompress.h"
44#include "main/texobj.h"
45#include "main/texparam.h"
46#include "main/teximage.h"
47#include "main/texstate.h"
48#include "program/prog_instruction.h"
49
50
51/**
52 * Check if a coordinate wrap mode is supported for the texture target.
53 * \return GL_TRUE if legal, GL_FALSE otherwise
54 */
55static GLboolean
56validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap)
57{
58   const struct gl_extensions * const e = & ctx->Extensions;
59   const bool is_desktop_gl = _mesa_is_desktop_gl(ctx);
60   bool supported;
61
62   switch (wrap) {
63   case GL_CLAMP:
64      /* GL_CLAMP was removed in the core profile, and it has never existed in
65       * OpenGL ES.
66       */
67      supported = (ctx->API == API_OPENGL)
68         && (target != GL_TEXTURE_EXTERNAL_OES);
69      break;
70
71   case GL_CLAMP_TO_EDGE:
72      supported = true;
73      break;
74
75   case GL_CLAMP_TO_BORDER:
76      supported = is_desktop_gl && e->ARB_texture_border_clamp
77         && (target != GL_TEXTURE_EXTERNAL_OES);
78      break;
79
80   case GL_REPEAT:
81   case GL_MIRRORED_REPEAT:
82      supported = (target != GL_TEXTURE_RECTANGLE_NV)
83         && (target != GL_TEXTURE_EXTERNAL_OES);
84      break;
85
86   case GL_MIRROR_CLAMP_EXT:
87   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
88      supported = is_desktop_gl
89         && (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)
90	 && (target != GL_TEXTURE_RECTANGLE_NV)
91         && (target != GL_TEXTURE_EXTERNAL_OES);
92      break;
93
94   case GL_MIRROR_CLAMP_TO_BORDER_EXT:
95      supported = is_desktop_gl && e->EXT_texture_mirror_clamp
96	 && (target != GL_TEXTURE_RECTANGLE_NV)
97         && (target != GL_TEXTURE_EXTERNAL_OES);
98      break;
99
100   default:
101      supported = false;
102      break;
103   }
104
105   if (!supported)
106      _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", wrap );
107
108   return supported;
109}
110
111
112/**
113 * Get current texture object for given target.
114 * Return NULL if any error (and record the error).
115 * Note that this is different from _mesa_select_tex_object() in that proxy
116 * targets are not accepted.
117 * Only the glGetTexLevelParameter() functions accept proxy targets.
118 */
119static struct gl_texture_object *
120get_texobj(struct gl_context *ctx, GLenum target, GLboolean get)
121{
122   struct gl_texture_unit *texUnit;
123
124   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
125      _mesa_error(ctx, GL_INVALID_OPERATION,
126                  "gl%sTexParameter(current unit)", get ? "Get" : "");
127      return NULL;
128   }
129
130   texUnit = _mesa_get_current_tex_unit(ctx);
131
132   switch (target) {
133   case GL_TEXTURE_1D:
134      if (_mesa_is_desktop_gl(ctx))
135         return texUnit->CurrentTex[TEXTURE_1D_INDEX];
136      break;
137   case GL_TEXTURE_2D:
138      return texUnit->CurrentTex[TEXTURE_2D_INDEX];
139   case GL_TEXTURE_3D:
140      if (ctx->API != API_OPENGLES)
141         return texUnit->CurrentTex[TEXTURE_3D_INDEX];
142      break;
143   case GL_TEXTURE_CUBE_MAP:
144      if (ctx->Extensions.ARB_texture_cube_map) {
145         return texUnit->CurrentTex[TEXTURE_CUBE_INDEX];
146      }
147      break;
148   case GL_TEXTURE_RECTANGLE_NV:
149      if (_mesa_is_desktop_gl(ctx)
150          && ctx->Extensions.NV_texture_rectangle) {
151         return texUnit->CurrentTex[TEXTURE_RECT_INDEX];
152      }
153      break;
154   case GL_TEXTURE_1D_ARRAY_EXT:
155      if (_mesa_is_desktop_gl(ctx)
156          && (ctx->Extensions.MESA_texture_array ||
157              ctx->Extensions.EXT_texture_array)) {
158         return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX];
159      }
160      break;
161   case GL_TEXTURE_2D_ARRAY_EXT:
162      if ((_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
163          && (ctx->Extensions.MESA_texture_array ||
164              ctx->Extensions.EXT_texture_array)) {
165         return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX];
166      }
167      break;
168   case GL_TEXTURE_EXTERNAL_OES:
169      if (_mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external) {
170         return texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX];
171      }
172      break;
173   default:
174      ;
175   }
176
177   _mesa_error(ctx, GL_INVALID_ENUM,
178                  "gl%sTexParameter(target)", get ? "Get" : "");
179   return NULL;
180}
181
182
183/**
184 * Convert GL_RED/GREEN/BLUE/ALPHA/ZERO/ONE to SWIZZLE_X/Y/Z/W/ZERO/ONE.
185 * \return -1 if error.
186 */
187static GLint
188comp_to_swizzle(GLenum comp)
189{
190   switch (comp) {
191   case GL_RED:
192      return SWIZZLE_X;
193   case GL_GREEN:
194      return SWIZZLE_Y;
195   case GL_BLUE:
196      return SWIZZLE_Z;
197   case GL_ALPHA:
198      return SWIZZLE_W;
199   case GL_ZERO:
200      return SWIZZLE_ZERO;
201   case GL_ONE:
202      return SWIZZLE_ONE;
203   default:
204      return -1;
205   }
206}
207
208
209static void
210set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
211{
212   ASSERT(comp < 4);
213   ASSERT(swz <= SWIZZLE_NIL);
214   {
215      GLuint mask = 0x7 << (3 * comp);
216      GLuint s = (*swizzle & ~mask) | (swz << (3 * comp));
217      *swizzle = s;
218   }
219}
220
221
222/**
223 * This is called just prior to changing any texture object state which
224 * will not effect texture completeness.
225 */
226static inline void
227flush(struct gl_context *ctx)
228{
229   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
230}
231
232
233/**
234 * This is called just prior to changing any texture object state which
235 * can effect texture completeness (texture base level, max level).
236 * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE
237 * state flag and then mark the texture object as 'incomplete' so that any
238 * per-texture derived state gets recomputed.
239 */
240static inline void
241incomplete(struct gl_context *ctx, struct gl_texture_object *texObj)
242{
243   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
244   _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
245}
246
247
248/**
249 * Set an integer-valued texture parameter
250 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
251 */
252static GLboolean
253set_tex_parameteri(struct gl_context *ctx,
254                   struct gl_texture_object *texObj,
255                   GLenum pname, const GLint *params)
256{
257   switch (pname) {
258   case GL_TEXTURE_MIN_FILTER:
259      if (texObj->Sampler.MinFilter == params[0])
260         return GL_FALSE;
261      switch (params[0]) {
262      case GL_NEAREST:
263      case GL_LINEAR:
264         flush(ctx);
265         texObj->Sampler.MinFilter = params[0];
266         return GL_TRUE;
267      case GL_NEAREST_MIPMAP_NEAREST:
268      case GL_LINEAR_MIPMAP_NEAREST:
269      case GL_NEAREST_MIPMAP_LINEAR:
270      case GL_LINEAR_MIPMAP_LINEAR:
271         if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
272             texObj->Target != GL_TEXTURE_EXTERNAL_OES) {
273            flush(ctx);
274            texObj->Sampler.MinFilter = params[0];
275            return GL_TRUE;
276         }
277         /* fall-through */
278      default:
279         goto invalid_param;
280      }
281      return GL_FALSE;
282
283   case GL_TEXTURE_MAG_FILTER:
284      if (texObj->Sampler.MagFilter == params[0])
285         return GL_FALSE;
286      switch (params[0]) {
287      case GL_NEAREST:
288      case GL_LINEAR:
289         flush(ctx); /* does not effect completeness */
290         texObj->Sampler.MagFilter = params[0];
291         return GL_TRUE;
292      default:
293         goto invalid_param;
294      }
295      return GL_FALSE;
296
297   case GL_TEXTURE_WRAP_S:
298      if (texObj->Sampler.WrapS == params[0])
299         return GL_FALSE;
300      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
301         flush(ctx);
302         texObj->Sampler.WrapS = params[0];
303         return GL_TRUE;
304      }
305      return GL_FALSE;
306
307   case GL_TEXTURE_WRAP_T:
308      if (texObj->Sampler.WrapT == params[0])
309         return GL_FALSE;
310      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
311         flush(ctx);
312         texObj->Sampler.WrapT = params[0];
313         return GL_TRUE;
314      }
315      return GL_FALSE;
316
317   case GL_TEXTURE_WRAP_R:
318      if (texObj->Sampler.WrapR == params[0])
319         return GL_FALSE;
320      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
321         flush(ctx);
322         texObj->Sampler.WrapR = params[0];
323         return GL_TRUE;
324      }
325      return GL_FALSE;
326
327   case GL_TEXTURE_BASE_LEVEL:
328      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
329         goto invalid_pname;
330
331      if (texObj->BaseLevel == params[0])
332         return GL_FALSE;
333      if (params[0] < 0 ||
334          (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
335         _mesa_error(ctx, GL_INVALID_VALUE,
336                     "glTexParameter(param=%d)", params[0]);
337         return GL_FALSE;
338      }
339      incomplete(ctx, texObj);
340      texObj->BaseLevel = params[0];
341      return GL_TRUE;
342
343   case GL_TEXTURE_MAX_LEVEL:
344      if (texObj->MaxLevel == params[0])
345         return GL_FALSE;
346      if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
347         _mesa_error(ctx, GL_INVALID_OPERATION,
348                     "glTexParameter(param=%d)", params[0]);
349         return GL_FALSE;
350      }
351      incomplete(ctx, texObj);
352      texObj->MaxLevel = params[0];
353      return GL_TRUE;
354
355   case GL_GENERATE_MIPMAP_SGIS:
356      if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES)
357         goto invalid_pname;
358
359      if (params[0] && texObj->Target == GL_TEXTURE_EXTERNAL_OES)
360         goto invalid_param;
361      if (texObj->GenerateMipmap != params[0]) {
362         /* no flush() */
363	 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
364	 return GL_TRUE;
365      }
366      return GL_FALSE;
367
368   case GL_TEXTURE_COMPARE_MODE_ARB:
369      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow)
370          || _mesa_is_gles3(ctx)) {
371         if (texObj->Sampler.CompareMode == params[0])
372            return GL_FALSE;
373         if (params[0] == GL_NONE ||
374             params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
375            flush(ctx);
376            texObj->Sampler.CompareMode = params[0];
377            return GL_TRUE;
378         }
379         goto invalid_param;
380      }
381      goto invalid_pname;
382
383   case GL_TEXTURE_COMPARE_FUNC_ARB:
384      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow)
385          || _mesa_is_gles3(ctx)) {
386         if (texObj->Sampler.CompareFunc == params[0])
387            return GL_FALSE;
388         switch (params[0]) {
389         case GL_LEQUAL:
390         case GL_GEQUAL:
391            flush(ctx);
392            texObj->Sampler.CompareFunc = params[0];
393            return GL_TRUE;
394         case GL_EQUAL:
395         case GL_NOTEQUAL:
396         case GL_LESS:
397         case GL_GREATER:
398         case GL_ALWAYS:
399         case GL_NEVER:
400            if (ctx->Extensions.EXT_shadow_funcs) {
401               flush(ctx);
402               texObj->Sampler.CompareFunc = params[0];
403               return GL_TRUE;
404            }
405            /* fall-through */
406         default:
407            goto invalid_param;
408         }
409      }
410      goto invalid_pname;
411
412   case GL_DEPTH_TEXTURE_MODE_ARB:
413      /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has never
414       * existed in OpenGL ES.
415       */
416      if (ctx->API == API_OPENGL && ctx->Extensions.ARB_depth_texture) {
417         if (texObj->DepthMode == params[0])
418            return GL_FALSE;
419         if (params[0] == GL_LUMINANCE ||
420             params[0] == GL_INTENSITY ||
421             params[0] == GL_ALPHA ||
422             (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
423            flush(ctx);
424            texObj->DepthMode = params[0];
425            return GL_TRUE;
426         }
427         goto invalid_param;
428      }
429      goto invalid_pname;
430
431#if FEATURE_OES_draw_texture
432   case GL_TEXTURE_CROP_RECT_OES:
433      if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
434         goto invalid_pname;
435
436      texObj->CropRect[0] = params[0];
437      texObj->CropRect[1] = params[1];
438      texObj->CropRect[2] = params[2];
439      texObj->CropRect[3] = params[3];
440      return GL_TRUE;
441#endif
442
443   case GL_TEXTURE_SWIZZLE_R_EXT:
444   case GL_TEXTURE_SWIZZLE_G_EXT:
445   case GL_TEXTURE_SWIZZLE_B_EXT:
446   case GL_TEXTURE_SWIZZLE_A_EXT:
447      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle)
448          || _mesa_is_gles3(ctx)) {
449         const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
450         const GLint swz = comp_to_swizzle(params[0]);
451         if (swz < 0) {
452            _mesa_error(ctx, GL_INVALID_OPERATION,
453                        "glTexParameter(swizzle 0x%x)", params[0]);
454            return GL_FALSE;
455         }
456         ASSERT(comp < 4);
457
458         flush(ctx);
459         texObj->Swizzle[comp] = params[0];
460         set_swizzle_component(&texObj->_Swizzle, comp, swz);
461         return GL_TRUE;
462      }
463      goto invalid_pname;
464
465   case GL_TEXTURE_SWIZZLE_RGBA_EXT:
466      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle)
467          || _mesa_is_gles3(ctx)) {
468         GLuint comp;
469         flush(ctx);
470         for (comp = 0; comp < 4; comp++) {
471            const GLint swz = comp_to_swizzle(params[comp]);
472            if (swz >= 0) {
473               texObj->Swizzle[comp] = params[comp];
474               set_swizzle_component(&texObj->_Swizzle, comp, swz);
475            }
476            else {
477               _mesa_error(ctx, GL_INVALID_OPERATION,
478                           "glTexParameter(swizzle 0x%x)", params[comp]);
479               return GL_FALSE;
480            }
481         }
482         return GL_TRUE;
483      }
484      goto invalid_pname;
485
486   case GL_TEXTURE_SRGB_DECODE_EXT:
487      if (_mesa_is_desktop_gl(ctx)
488          && ctx->Extensions.EXT_texture_sRGB_decode) {
489	 GLenum decode = params[0];
490	 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
491	    if (texObj->Sampler.sRGBDecode != decode) {
492	       flush(ctx);
493	       texObj->Sampler.sRGBDecode = decode;
494	    }
495	    return GL_TRUE;
496	 }
497      }
498      goto invalid_pname;
499
500   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
501      if (_mesa_is_desktop_gl(ctx)
502          && ctx->Extensions.AMD_seamless_cubemap_per_texture) {
503         GLenum param = params[0];
504         if (param != GL_TRUE && param != GL_FALSE) {
505            goto invalid_param;
506         }
507         if (param != texObj->Sampler.CubeMapSeamless) {
508            flush(ctx);
509            texObj->Sampler.CubeMapSeamless = param;
510         }
511         return GL_TRUE;
512      }
513      goto invalid_pname;
514
515   default:
516      goto invalid_pname;
517   }
518
519invalid_pname:
520   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
521               _mesa_lookup_enum_by_nr(pname));
522   return GL_FALSE;
523
524invalid_param:
525   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)",
526               _mesa_lookup_enum_by_nr(params[0]));
527   return GL_FALSE;
528}
529
530
531/**
532 * Set a float-valued texture parameter
533 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
534 */
535static GLboolean
536set_tex_parameterf(struct gl_context *ctx,
537                   struct gl_texture_object *texObj,
538                   GLenum pname, const GLfloat *params)
539{
540   switch (pname) {
541   case GL_TEXTURE_MIN_LOD:
542      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
543         goto invalid_pname;
544
545      if (texObj->Sampler.MinLod == params[0])
546         return GL_FALSE;
547      flush(ctx);
548      texObj->Sampler.MinLod = params[0];
549      return GL_TRUE;
550
551   case GL_TEXTURE_MAX_LOD:
552      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
553         goto invalid_pname;
554
555      if (texObj->Sampler.MaxLod == params[0])
556         return GL_FALSE;
557      flush(ctx);
558      texObj->Sampler.MaxLod = params[0];
559      return GL_TRUE;
560
561   case GL_TEXTURE_PRIORITY:
562      if (ctx->API != API_OPENGL)
563         goto invalid_pname;
564
565      flush(ctx);
566      texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
567      return GL_TRUE;
568
569   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
570      if (ctx->Extensions.EXT_texture_filter_anisotropic) {
571         if (texObj->Sampler.MaxAnisotropy == params[0])
572            return GL_FALSE;
573         if (params[0] < 1.0) {
574            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
575            return GL_FALSE;
576         }
577         flush(ctx);
578         /* clamp to max, that's what NVIDIA does */
579         texObj->Sampler.MaxAnisotropy = MIN2(params[0],
580                                      ctx->Const.MaxTextureMaxAnisotropy);
581         return GL_TRUE;
582      }
583      else {
584         static GLuint count = 0;
585         if (count++ < 10)
586            goto invalid_pname;
587      }
588      return GL_FALSE;
589
590   case GL_TEXTURE_LOD_BIAS:
591      /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias.
592       * It was removed in core-profile, and it has never existed in OpenGL
593       * ES.
594       */
595      if (ctx->API != API_OPENGL)
596         goto invalid_pname;
597
598      if (texObj->Sampler.LodBias != params[0]) {
599	 flush(ctx);
600	 texObj->Sampler.LodBias = params[0];
601	 return GL_TRUE;
602      }
603      break;
604
605   case GL_TEXTURE_BORDER_COLOR:
606      if (!_mesa_is_desktop_gl(ctx))
607         goto invalid_pname;
608
609      flush(ctx);
610      /* ARB_texture_float disables clamping */
611      if (ctx->Extensions.ARB_texture_float) {
612         texObj->Sampler.BorderColor.f[RCOMP] = params[0];
613         texObj->Sampler.BorderColor.f[GCOMP] = params[1];
614         texObj->Sampler.BorderColor.f[BCOMP] = params[2];
615         texObj->Sampler.BorderColor.f[ACOMP] = params[3];
616      } else {
617         texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F);
618         texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F);
619         texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F);
620         texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F);
621      }
622      return GL_TRUE;
623
624   default:
625      goto invalid_pname;
626   }
627   return GL_FALSE;
628
629invalid_pname:
630   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
631               _mesa_lookup_enum_by_nr(pname));
632   return GL_FALSE;
633}
634
635
636void GLAPIENTRY
637_mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
638{
639   GLboolean need_update;
640   struct gl_texture_object *texObj;
641   GET_CURRENT_CONTEXT(ctx);
642   ASSERT_OUTSIDE_BEGIN_END(ctx);
643
644   texObj = get_texobj(ctx, target, GL_FALSE);
645   if (!texObj)
646      return;
647
648   switch (pname) {
649   case GL_TEXTURE_MIN_FILTER:
650   case GL_TEXTURE_MAG_FILTER:
651   case GL_TEXTURE_WRAP_S:
652   case GL_TEXTURE_WRAP_T:
653   case GL_TEXTURE_WRAP_R:
654   case GL_TEXTURE_BASE_LEVEL:
655   case GL_TEXTURE_MAX_LEVEL:
656   case GL_GENERATE_MIPMAP_SGIS:
657   case GL_TEXTURE_COMPARE_MODE_ARB:
658   case GL_TEXTURE_COMPARE_FUNC_ARB:
659   case GL_DEPTH_TEXTURE_MODE_ARB:
660   case GL_TEXTURE_SRGB_DECODE_EXT:
661   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
662      {
663         /* convert float param to int */
664         GLint p[4];
665         p[0] = (GLint) param;
666         p[1] = p[2] = p[3] = 0;
667         need_update = set_tex_parameteri(ctx, texObj, pname, p);
668      }
669      break;
670   case GL_TEXTURE_SWIZZLE_R_EXT:
671   case GL_TEXTURE_SWIZZLE_G_EXT:
672   case GL_TEXTURE_SWIZZLE_B_EXT:
673   case GL_TEXTURE_SWIZZLE_A_EXT:
674      {
675         GLint p[4];
676         p[0] = (GLint) param;
677         p[1] = p[2] = p[3] = 0;
678         need_update = set_tex_parameteri(ctx, texObj, pname, p);
679      }
680      break;
681   default:
682      {
683         /* this will generate an error if pname is illegal */
684         GLfloat p[4];
685         p[0] = param;
686         p[1] = p[2] = p[3] = 0.0F;
687         need_update = set_tex_parameterf(ctx, texObj, pname, p);
688      }
689   }
690
691   if (ctx->Driver.TexParameter && need_update) {
692      ctx->Driver.TexParameter(ctx, target, texObj, pname, &param);
693   }
694}
695
696
697void GLAPIENTRY
698_mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
699{
700   GLboolean need_update;
701   struct gl_texture_object *texObj;
702   GET_CURRENT_CONTEXT(ctx);
703   ASSERT_OUTSIDE_BEGIN_END(ctx);
704
705   texObj = get_texobj(ctx, target, GL_FALSE);
706   if (!texObj)
707      return;
708
709   switch (pname) {
710   case GL_TEXTURE_MIN_FILTER:
711   case GL_TEXTURE_MAG_FILTER:
712   case GL_TEXTURE_WRAP_S:
713   case GL_TEXTURE_WRAP_T:
714   case GL_TEXTURE_WRAP_R:
715   case GL_TEXTURE_BASE_LEVEL:
716   case GL_TEXTURE_MAX_LEVEL:
717   case GL_GENERATE_MIPMAP_SGIS:
718   case GL_TEXTURE_COMPARE_MODE_ARB:
719   case GL_TEXTURE_COMPARE_FUNC_ARB:
720   case GL_DEPTH_TEXTURE_MODE_ARB:
721   case GL_TEXTURE_SRGB_DECODE_EXT:
722   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
723      {
724         /* convert float param to int */
725         GLint p[4];
726         p[0] = (GLint) params[0];
727         p[1] = p[2] = p[3] = 0;
728         need_update = set_tex_parameteri(ctx, texObj, pname, p);
729      }
730      break;
731
732#if FEATURE_OES_draw_texture
733   case GL_TEXTURE_CROP_RECT_OES:
734      {
735         /* convert float params to int */
736         GLint iparams[4];
737         iparams[0] = (GLint) params[0];
738         iparams[1] = (GLint) params[1];
739         iparams[2] = (GLint) params[2];
740         iparams[3] = (GLint) params[3];
741         need_update = set_tex_parameteri(ctx, texObj, pname, iparams);
742      }
743      break;
744#endif
745
746   case GL_TEXTURE_SWIZZLE_R_EXT:
747   case GL_TEXTURE_SWIZZLE_G_EXT:
748   case GL_TEXTURE_SWIZZLE_B_EXT:
749   case GL_TEXTURE_SWIZZLE_A_EXT:
750   case GL_TEXTURE_SWIZZLE_RGBA_EXT:
751      {
752         GLint p[4] = {0, 0, 0, 0};
753         p[0] = (GLint) params[0];
754         if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT) {
755            p[1] = (GLint) params[1];
756            p[2] = (GLint) params[2];
757            p[3] = (GLint) params[3];
758         }
759         need_update = set_tex_parameteri(ctx, texObj, pname, p);
760      }
761      break;
762   default:
763      /* this will generate an error if pname is illegal */
764      need_update = set_tex_parameterf(ctx, texObj, pname, params);
765   }
766
767   if (ctx->Driver.TexParameter && need_update) {
768      ctx->Driver.TexParameter(ctx, target, texObj, pname, params);
769   }
770}
771
772
773void GLAPIENTRY
774_mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
775{
776   GLboolean need_update;
777   struct gl_texture_object *texObj;
778   GET_CURRENT_CONTEXT(ctx);
779   ASSERT_OUTSIDE_BEGIN_END(ctx);
780
781   texObj = get_texobj(ctx, target, GL_FALSE);
782   if (!texObj)
783      return;
784
785   switch (pname) {
786   case GL_TEXTURE_MIN_LOD:
787   case GL_TEXTURE_MAX_LOD:
788   case GL_TEXTURE_PRIORITY:
789   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
790   case GL_TEXTURE_LOD_BIAS:
791   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
792      {
793         GLfloat fparam[4];
794         fparam[0] = (GLfloat) param;
795         fparam[1] = fparam[2] = fparam[3] = 0.0F;
796         /* convert int param to float */
797         need_update = set_tex_parameterf(ctx, texObj, pname, fparam);
798      }
799      break;
800   default:
801      /* this will generate an error if pname is illegal */
802      {
803         GLint iparam[4];
804         iparam[0] = param;
805         iparam[1] = iparam[2] = iparam[3] = 0;
806         need_update = set_tex_parameteri(ctx, texObj, pname, iparam);
807      }
808   }
809
810   if (ctx->Driver.TexParameter && need_update) {
811      GLfloat fparam = (GLfloat) param;
812      ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam);
813   }
814}
815
816
817void GLAPIENTRY
818_mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
819{
820   GLboolean need_update;
821   struct gl_texture_object *texObj;
822   GET_CURRENT_CONTEXT(ctx);
823   ASSERT_OUTSIDE_BEGIN_END(ctx);
824
825   texObj = get_texobj(ctx, target, GL_FALSE);
826   if (!texObj)
827      return;
828
829   switch (pname) {
830   case GL_TEXTURE_BORDER_COLOR:
831      {
832         /* convert int params to float */
833         GLfloat fparams[4];
834         fparams[0] = INT_TO_FLOAT(params[0]);
835         fparams[1] = INT_TO_FLOAT(params[1]);
836         fparams[2] = INT_TO_FLOAT(params[2]);
837         fparams[3] = INT_TO_FLOAT(params[3]);
838         need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
839      }
840      break;
841   case GL_TEXTURE_MIN_LOD:
842   case GL_TEXTURE_MAX_LOD:
843   case GL_TEXTURE_PRIORITY:
844   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
845   case GL_TEXTURE_LOD_BIAS:
846   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
847      {
848         /* convert int param to float */
849         GLfloat fparams[4];
850         fparams[0] = (GLfloat) params[0];
851         fparams[1] = fparams[2] = fparams[3] = 0.0F;
852         need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
853      }
854      break;
855   default:
856      /* this will generate an error if pname is illegal */
857      need_update = set_tex_parameteri(ctx, texObj, pname, params);
858   }
859
860   if (ctx->Driver.TexParameter && need_update) {
861      GLfloat fparams[4];
862      fparams[0] = INT_TO_FLOAT(params[0]);
863      if (pname == GL_TEXTURE_BORDER_COLOR ||
864          pname == GL_TEXTURE_CROP_RECT_OES) {
865         fparams[1] = INT_TO_FLOAT(params[1]);
866         fparams[2] = INT_TO_FLOAT(params[2]);
867         fparams[3] = INT_TO_FLOAT(params[3]);
868      }
869      ctx->Driver.TexParameter(ctx, target, texObj, pname, fparams);
870   }
871}
872
873
874/**
875 * Set tex parameter to integer value(s).  Primarily intended to set
876 * integer-valued texture border color (for integer-valued textures).
877 * New in GL 3.0.
878 */
879void GLAPIENTRY
880_mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params)
881{
882   struct gl_texture_object *texObj;
883   GET_CURRENT_CONTEXT(ctx);
884   ASSERT_OUTSIDE_BEGIN_END(ctx);
885
886   texObj = get_texobj(ctx, target, GL_FALSE);
887   if (!texObj)
888      return;
889
890   switch (pname) {
891   case GL_TEXTURE_BORDER_COLOR:
892      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
893      /* set the integer-valued border color */
894      COPY_4V(texObj->Sampler.BorderColor.i, params);
895      break;
896   default:
897      _mesa_TexParameteriv(target, pname, params);
898      break;
899   }
900   /* XXX no driver hook for TexParameterIiv() yet */
901}
902
903
904/**
905 * Set tex parameter to unsigned integer value(s).  Primarily intended to set
906 * uint-valued texture border color (for integer-valued textures).
907 * New in GL 3.0
908 */
909void GLAPIENTRY
910_mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params)
911{
912   struct gl_texture_object *texObj;
913   GET_CURRENT_CONTEXT(ctx);
914   ASSERT_OUTSIDE_BEGIN_END(ctx);
915
916   texObj = get_texobj(ctx, target, GL_FALSE);
917   if (!texObj)
918      return;
919
920   switch (pname) {
921   case GL_TEXTURE_BORDER_COLOR:
922      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
923      /* set the unsigned integer-valued border color */
924      COPY_4V(texObj->Sampler.BorderColor.ui, params);
925      break;
926   default:
927      _mesa_TexParameteriv(target, pname, (const GLint *) params);
928      break;
929   }
930   /* XXX no driver hook for TexParameterIuiv() yet */
931}
932
933
934static GLboolean
935legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target)
936{
937   switch (target) {
938   case GL_TEXTURE_1D:
939   case GL_PROXY_TEXTURE_1D:
940   case GL_TEXTURE_2D:
941   case GL_PROXY_TEXTURE_2D:
942   case GL_TEXTURE_3D:
943   case GL_PROXY_TEXTURE_3D:
944      return GL_TRUE;
945   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
946   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
947   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
948   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
949   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
950   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
951   case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
952      return ctx->Extensions.ARB_texture_cube_map;
953   case GL_TEXTURE_RECTANGLE_NV:
954   case GL_PROXY_TEXTURE_RECTANGLE_NV:
955      return ctx->Extensions.NV_texture_rectangle;
956   case GL_TEXTURE_1D_ARRAY_EXT:
957   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
958   case GL_TEXTURE_2D_ARRAY_EXT:
959   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
960      return (ctx->Extensions.MESA_texture_array ||
961              ctx->Extensions.EXT_texture_array);
962   case GL_TEXTURE_BUFFER:
963      /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts,
964       * but not in earlier versions that expose ARB_texture_buffer_object.
965       *
966       * From the ARB_texture_buffer_object spec:
967       * "(7) Do buffer textures support texture parameters (TexParameter) or
968       *      queries (GetTexParameter, GetTexLevelParameter, GetTexImage)?
969       *
970       *    RESOLVED:  No. [...] Note that the spec edits above don't add
971       *    explicit error language for any of these cases.  That is because
972       *    each of the functions enumerate the set of valid <target>
973       *    parameters.  Not editing the spec to allow TEXTURE_BUFFER_ARB in
974       *    these cases means that target is not legal, and an INVALID_ENUM
975       *    error should be generated."
976       *
977       * From the OpenGL 3.1 spec:
978       * "target may also be TEXTURE_BUFFER, indicating the texture buffer."
979       */
980      return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
981   default:
982      return GL_FALSE;
983   }
984}
985
986
987static void
988get_tex_level_parameter_image(struct gl_context *ctx,
989                              const struct gl_texture_object *texObj,
990                              GLenum target, GLint level,
991                              GLenum pname, GLint *params)
992{
993   const struct gl_texture_image *img = NULL;
994   gl_format texFormat;
995
996   img = _mesa_select_tex_image(ctx, texObj, target, level);
997   if (!img || img->TexFormat == MESA_FORMAT_NONE) {
998      /* undefined texture image */
999      if (pname == GL_TEXTURE_COMPONENTS)
1000         *params = 1;
1001      else
1002         *params = 0;
1003      return;
1004   }
1005
1006   texFormat = img->TexFormat;
1007
1008   switch (pname) {
1009      case GL_TEXTURE_WIDTH:
1010         *params = img->Width;
1011         break;
1012      case GL_TEXTURE_HEIGHT:
1013         *params = img->Height;
1014         break;
1015      case GL_TEXTURE_DEPTH:
1016         *params = img->Depth;
1017         break;
1018      case GL_TEXTURE_INTERNAL_FORMAT:
1019         if (_mesa_is_format_compressed(texFormat)) {
1020            /* need to return the actual compressed format */
1021            *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
1022         }
1023         else {
1024	    /* If the true internal format is not compressed but the user
1025	     * requested a generic compressed format, we have to return the
1026	     * generic base format that matches.
1027	     *
1028	     * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
1029	     *
1030	     *     "If no specific compressed format is available,
1031	     *     internalformat is instead replaced by the corresponding base
1032	     *     internal format."
1033	     *
1034	     * Otherwise just return the user's requested internal format
1035	     */
1036	    const GLenum f =
1037	       _mesa_gl_compressed_format_base_format(img->InternalFormat);
1038
1039	    *params = (f != 0) ? f : img->InternalFormat;
1040	 }
1041         break;
1042      case GL_TEXTURE_BORDER:
1043         *params = img->Border;
1044         break;
1045      case GL_TEXTURE_RED_SIZE:
1046      case GL_TEXTURE_GREEN_SIZE:
1047      case GL_TEXTURE_BLUE_SIZE:
1048      case GL_TEXTURE_ALPHA_SIZE:
1049         if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1050            *params = _mesa_get_format_bits(texFormat, pname);
1051         else
1052            *params = 0;
1053         break;
1054      case GL_TEXTURE_INTENSITY_SIZE:
1055      case GL_TEXTURE_LUMINANCE_SIZE:
1056         if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
1057            *params = _mesa_get_format_bits(texFormat, pname);
1058            if (*params == 0) {
1059               /* intensity or luminance is probably stored as RGB[A] */
1060               *params = MIN2(_mesa_get_format_bits(texFormat,
1061                                                    GL_TEXTURE_RED_SIZE),
1062                              _mesa_get_format_bits(texFormat,
1063                                                    GL_TEXTURE_GREEN_SIZE));
1064            }
1065         }
1066         else {
1067            *params = 0;
1068         }
1069         break;
1070      case GL_TEXTURE_DEPTH_SIZE_ARB:
1071         if (!ctx->Extensions.ARB_depth_texture)
1072            goto invalid_pname;
1073         *params = _mesa_get_format_bits(texFormat, pname);
1074         break;
1075      case GL_TEXTURE_STENCIL_SIZE_EXT:
1076         if (!ctx->Extensions.EXT_packed_depth_stencil &&
1077             !ctx->Extensions.ARB_framebuffer_object)
1078            goto invalid_pname;
1079         *params = _mesa_get_format_bits(texFormat, pname);
1080         break;
1081      case GL_TEXTURE_SHARED_SIZE:
1082         if (ctx->Version < 30 &&
1083             !ctx->Extensions.EXT_texture_shared_exponent)
1084            goto invalid_pname;
1085         *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
1086         break;
1087
1088      /* GL_ARB_texture_compression */
1089      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1090	 if (_mesa_is_format_compressed(texFormat) &&
1091             !_mesa_is_proxy_texture(target)) {
1092            *params = _mesa_format_image_size(texFormat, img->Width,
1093                                              img->Height, img->Depth);
1094	 }
1095	 else {
1096	    _mesa_error(ctx, GL_INVALID_OPERATION,
1097			"glGetTexLevelParameter[if]v(pname)");
1098	 }
1099         break;
1100      case GL_TEXTURE_COMPRESSED:
1101         *params = (GLint) _mesa_is_format_compressed(texFormat);
1102         break;
1103
1104      /* GL_ARB_texture_float */
1105      case GL_TEXTURE_RED_TYPE_ARB:
1106      case GL_TEXTURE_GREEN_TYPE_ARB:
1107      case GL_TEXTURE_BLUE_TYPE_ARB:
1108      case GL_TEXTURE_ALPHA_TYPE_ARB:
1109      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1110      case GL_TEXTURE_INTENSITY_TYPE_ARB:
1111      case GL_TEXTURE_DEPTH_TYPE_ARB:
1112         if (!ctx->Extensions.ARB_texture_float)
1113            goto invalid_pname;
1114	 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1115	    *params = _mesa_get_format_datatype(texFormat);
1116	 else
1117	    *params = GL_NONE;
1118         break;
1119
1120      default:
1121         goto invalid_pname;
1122   }
1123
1124   /* no error if we get here */
1125   return;
1126
1127invalid_pname:
1128   _mesa_error(ctx, GL_INVALID_ENUM,
1129               "glGetTexLevelParameter[if]v(pname=%s)",
1130               _mesa_lookup_enum_by_nr(pname));
1131}
1132
1133
1134static void
1135get_tex_level_parameter_buffer(struct gl_context *ctx,
1136                               const struct gl_texture_object *texObj,
1137                               GLenum pname, GLint *params)
1138{
1139   const struct gl_buffer_object *bo = texObj->BufferObject;
1140   gl_format texFormat = texObj->_BufferObjectFormat;
1141   GLenum internalFormat = texObj->BufferObjectFormat;
1142   GLenum baseFormat = _mesa_get_format_base_format(texFormat);
1143
1144   if (!bo) {
1145      /* undefined texture buffer object */
1146      *params = pname == GL_TEXTURE_COMPONENTS ? 1 : 0;
1147      return;
1148   }
1149
1150   switch (pname) {
1151      case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
1152         *params = bo->Name;
1153         break;
1154      case GL_TEXTURE_WIDTH:
1155         *params = bo->Size;
1156         break;
1157      case GL_TEXTURE_HEIGHT:
1158      case GL_TEXTURE_DEPTH:
1159      case GL_TEXTURE_BORDER:
1160      case GL_TEXTURE_SHARED_SIZE:
1161      case GL_TEXTURE_COMPRESSED:
1162         *params = 0;
1163         break;
1164      case GL_TEXTURE_INTERNAL_FORMAT:
1165         *params = internalFormat;
1166         break;
1167      case GL_TEXTURE_RED_SIZE:
1168      case GL_TEXTURE_GREEN_SIZE:
1169      case GL_TEXTURE_BLUE_SIZE:
1170      case GL_TEXTURE_ALPHA_SIZE:
1171         if (_mesa_base_format_has_channel(baseFormat, pname))
1172            *params = _mesa_get_format_bits(texFormat, pname);
1173         else
1174            *params = 0;
1175         break;
1176      case GL_TEXTURE_INTENSITY_SIZE:
1177      case GL_TEXTURE_LUMINANCE_SIZE:
1178         if (_mesa_base_format_has_channel(baseFormat, pname)) {
1179            *params = _mesa_get_format_bits(texFormat, pname);
1180            if (*params == 0) {
1181               /* intensity or luminance is probably stored as RGB[A] */
1182               *params = MIN2(_mesa_get_format_bits(texFormat,
1183                                                    GL_TEXTURE_RED_SIZE),
1184                              _mesa_get_format_bits(texFormat,
1185                                                    GL_TEXTURE_GREEN_SIZE));
1186            }
1187         } else {
1188            *params = 0;
1189         }
1190         break;
1191      case GL_TEXTURE_DEPTH_SIZE_ARB:
1192      case GL_TEXTURE_STENCIL_SIZE_EXT:
1193         *params = _mesa_get_format_bits(texFormat, pname);
1194         break;
1195
1196      /* GL_ARB_texture_compression */
1197      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1198         /* Always illegal for GL_TEXTURE_BUFFER */
1199         _mesa_error(ctx, GL_INVALID_OPERATION,
1200                     "glGetTexLevelParameter[if]v(pname)");
1201         break;
1202
1203      /* GL_ARB_texture_float */
1204      case GL_TEXTURE_RED_TYPE_ARB:
1205      case GL_TEXTURE_GREEN_TYPE_ARB:
1206      case GL_TEXTURE_BLUE_TYPE_ARB:
1207      case GL_TEXTURE_ALPHA_TYPE_ARB:
1208      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1209      case GL_TEXTURE_INTENSITY_TYPE_ARB:
1210      case GL_TEXTURE_DEPTH_TYPE_ARB:
1211         if (!ctx->Extensions.ARB_texture_float)
1212            goto invalid_pname;
1213         if (_mesa_base_format_has_channel(baseFormat, pname))
1214            *params = _mesa_get_format_datatype(texFormat);
1215         else
1216            *params = GL_NONE;
1217         break;
1218
1219      default:
1220         goto invalid_pname;
1221   }
1222
1223   /* no error if we get here */
1224   return;
1225
1226invalid_pname:
1227   _mesa_error(ctx, GL_INVALID_ENUM,
1228               "glGetTexLevelParameter[if]v(pname=%s)",
1229               _mesa_lookup_enum_by_nr(pname));
1230}
1231
1232
1233void GLAPIENTRY
1234_mesa_GetTexLevelParameterfv( GLenum target, GLint level,
1235                              GLenum pname, GLfloat *params )
1236{
1237   GLint iparam;
1238   _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
1239   *params = (GLfloat) iparam;
1240}
1241
1242
1243void GLAPIENTRY
1244_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
1245                              GLenum pname, GLint *params )
1246{
1247   const struct gl_texture_unit *texUnit;
1248   struct gl_texture_object *texObj;
1249   GLint maxLevels;
1250   GET_CURRENT_CONTEXT(ctx);
1251   ASSERT_OUTSIDE_BEGIN_END(ctx);
1252
1253   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
1254      _mesa_error(ctx, GL_INVALID_OPERATION,
1255                  "glGetTexLevelParameteriv(current unit)");
1256      return;
1257   }
1258
1259   texUnit = _mesa_get_current_tex_unit(ctx);
1260
1261   if (!legal_get_tex_level_parameter_target(ctx, target)) {
1262      _mesa_error(ctx, GL_INVALID_ENUM,
1263                  "glGetTexLevelParameter[if]v(target=0x%x)", target);
1264      return;
1265   }
1266
1267   maxLevels = _mesa_max_texture_levels(ctx, target);
1268   assert(maxLevels != 0);
1269
1270   if (level < 0 || level >= maxLevels) {
1271      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
1272      return;
1273   }
1274
1275   texObj = _mesa_select_tex_object(ctx, texUnit, target);
1276
1277   if (target == GL_TEXTURE_BUFFER)
1278      get_tex_level_parameter_buffer(ctx, texObj, pname, params);
1279   else
1280      get_tex_level_parameter_image(ctx, texObj, target, level, pname, params);
1281}
1282
1283
1284void GLAPIENTRY
1285_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
1286{
1287   struct gl_texture_object *obj;
1288   GET_CURRENT_CONTEXT(ctx);
1289   ASSERT_OUTSIDE_BEGIN_END(ctx);
1290
1291   obj = get_texobj(ctx, target, GL_TRUE);
1292   if (!obj)
1293      return;
1294
1295   _mesa_lock_texture(ctx, obj);
1296   switch (pname) {
1297      case GL_TEXTURE_MAG_FILTER:
1298	 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
1299	 break;
1300      case GL_TEXTURE_MIN_FILTER:
1301         *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter);
1302         break;
1303      case GL_TEXTURE_WRAP_S:
1304         *params = ENUM_TO_FLOAT(obj->Sampler.WrapS);
1305         break;
1306      case GL_TEXTURE_WRAP_T:
1307         *params = ENUM_TO_FLOAT(obj->Sampler.WrapT);
1308         break;
1309      case GL_TEXTURE_WRAP_R:
1310         *params = ENUM_TO_FLOAT(obj->Sampler.WrapR);
1311         break;
1312      case GL_TEXTURE_BORDER_COLOR:
1313         if (!_mesa_is_desktop_gl(ctx))
1314            goto invalid_pname;
1315
1316         if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
1317            _mesa_update_state_locked(ctx);
1318         if (ctx->Color._ClampFragmentColor) {
1319            params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1320            params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1321            params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1322            params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1323         }
1324         else {
1325            params[0] = obj->Sampler.BorderColor.f[0];
1326            params[1] = obj->Sampler.BorderColor.f[1];
1327            params[2] = obj->Sampler.BorderColor.f[2];
1328            params[3] = obj->Sampler.BorderColor.f[3];
1329         }
1330         break;
1331      case GL_TEXTURE_RESIDENT:
1332         if (ctx->API != API_OPENGL)
1333            goto invalid_pname;
1334
1335         *params = 1.0F;
1336         break;
1337      case GL_TEXTURE_PRIORITY:
1338         if (ctx->API != API_OPENGL)
1339            goto invalid_pname;
1340
1341         *params = obj->Priority;
1342         break;
1343      case GL_TEXTURE_MIN_LOD:
1344         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1345            goto invalid_pname;
1346
1347         *params = obj->Sampler.MinLod;
1348         break;
1349      case GL_TEXTURE_MAX_LOD:
1350         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1351            goto invalid_pname;
1352
1353         *params = obj->Sampler.MaxLod;
1354         break;
1355      case GL_TEXTURE_BASE_LEVEL:
1356         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1357            goto invalid_pname;
1358
1359         *params = (GLfloat) obj->BaseLevel;
1360         break;
1361      case GL_TEXTURE_MAX_LEVEL:
1362         *params = (GLfloat) obj->MaxLevel;
1363         break;
1364      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1365         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1366            goto invalid_pname;
1367         *params = obj->Sampler.MaxAnisotropy;
1368         break;
1369      case GL_GENERATE_MIPMAP_SGIS:
1370         if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES)
1371            goto invalid_pname;
1372
1373	 *params = (GLfloat) obj->GenerateMipmap;
1374         break;
1375      case GL_TEXTURE_COMPARE_MODE_ARB:
1376         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1377             && !_mesa_is_gles3(ctx))
1378            goto invalid_pname;
1379         *params = (GLfloat) obj->Sampler.CompareMode;
1380         break;
1381      case GL_TEXTURE_COMPARE_FUNC_ARB:
1382         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1383             && !_mesa_is_gles3(ctx))
1384            goto invalid_pname;
1385         *params = (GLfloat) obj->Sampler.CompareFunc;
1386         break;
1387      case GL_DEPTH_TEXTURE_MODE_ARB:
1388         /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has
1389          * never existed in OpenGL ES.
1390          */
1391         if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_depth_texture)
1392            goto invalid_pname;
1393         *params = (GLfloat) obj->DepthMode;
1394         break;
1395      case GL_TEXTURE_LOD_BIAS:
1396         if (ctx->API != API_OPENGL)
1397            goto invalid_pname;
1398
1399         *params = obj->Sampler.LodBias;
1400         break;
1401#if FEATURE_OES_draw_texture
1402      case GL_TEXTURE_CROP_RECT_OES:
1403         if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
1404            goto invalid_pname;
1405
1406         params[0] = obj->CropRect[0];
1407         params[1] = obj->CropRect[1];
1408         params[2] = obj->CropRect[2];
1409         params[3] = obj->CropRect[3];
1410         break;
1411#endif
1412
1413      case GL_TEXTURE_SWIZZLE_R_EXT:
1414      case GL_TEXTURE_SWIZZLE_G_EXT:
1415      case GL_TEXTURE_SWIZZLE_B_EXT:
1416      case GL_TEXTURE_SWIZZLE_A_EXT:
1417         if ((!_mesa_is_desktop_gl(ctx)
1418              || !ctx->Extensions.EXT_texture_swizzle)
1419             && !_mesa_is_gles3(ctx))
1420            goto invalid_pname;
1421         *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1422         break;
1423
1424      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1425         if ((!_mesa_is_desktop_gl(ctx)
1426              || !ctx->Extensions.EXT_texture_swizzle)
1427             && !_mesa_is_gles3(ctx)) {
1428            goto invalid_pname;
1429         }
1430         else {
1431            GLuint comp;
1432            for (comp = 0; comp < 4; comp++) {
1433               params[comp] = (GLfloat) obj->Swizzle[comp];
1434            }
1435         }
1436         break;
1437
1438      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1439         if (!_mesa_is_desktop_gl(ctx)
1440             || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
1441            goto invalid_pname;
1442         *params = (GLfloat) obj->Sampler.CubeMapSeamless;
1443         break;
1444
1445      case GL_TEXTURE_IMMUTABLE_FORMAT:
1446         if (!ctx->Extensions.ARB_texture_storage)
1447            goto invalid_pname;
1448         *params = (GLfloat) obj->Immutable;
1449         break;
1450
1451      case GL_TEXTURE_SRGB_DECODE_EXT:
1452         if (!ctx->Extensions.EXT_texture_sRGB_decode)
1453            goto invalid_pname;
1454         *params = (GLfloat) obj->Sampler.sRGBDecode;
1455         break;
1456
1457      default:
1458         goto invalid_pname;
1459   }
1460
1461   /* no error if we get here */
1462   _mesa_unlock_texture(ctx, obj);
1463   return;
1464
1465invalid_pname:
1466   _mesa_unlock_texture(ctx, obj);
1467   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
1468}
1469
1470
1471void GLAPIENTRY
1472_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1473{
1474   struct gl_texture_object *obj;
1475   GET_CURRENT_CONTEXT(ctx);
1476   ASSERT_OUTSIDE_BEGIN_END(ctx);
1477
1478   obj = get_texobj(ctx, target, GL_TRUE);
1479   if (!obj)
1480      return;
1481
1482   _mesa_lock_texture(ctx, obj);
1483   switch (pname) {
1484      case GL_TEXTURE_MAG_FILTER:
1485         *params = (GLint) obj->Sampler.MagFilter;
1486         break;
1487      case GL_TEXTURE_MIN_FILTER:
1488         *params = (GLint) obj->Sampler.MinFilter;
1489         break;
1490      case GL_TEXTURE_WRAP_S:
1491         *params = (GLint) obj->Sampler.WrapS;
1492         break;
1493      case GL_TEXTURE_WRAP_T:
1494         *params = (GLint) obj->Sampler.WrapT;
1495         break;
1496      case GL_TEXTURE_WRAP_R:
1497         *params = (GLint) obj->Sampler.WrapR;
1498         break;
1499      case GL_TEXTURE_BORDER_COLOR:
1500         if (!_mesa_is_desktop_gl(ctx))
1501            goto invalid_pname;
1502
1503         {
1504            GLfloat b[4];
1505            b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1506            b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1507            b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1508            b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1509            params[0] = FLOAT_TO_INT(b[0]);
1510            params[1] = FLOAT_TO_INT(b[1]);
1511            params[2] = FLOAT_TO_INT(b[2]);
1512            params[3] = FLOAT_TO_INT(b[3]);
1513         }
1514         break;
1515      case GL_TEXTURE_RESIDENT:
1516         if (ctx->API != API_OPENGL)
1517            goto invalid_pname;
1518
1519         *params = 1;
1520         break;
1521      case GL_TEXTURE_PRIORITY:
1522         if (ctx->API != API_OPENGL)
1523            goto invalid_pname;
1524
1525         *params = FLOAT_TO_INT(obj->Priority);
1526         break;
1527      case GL_TEXTURE_MIN_LOD:
1528         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1529            goto invalid_pname;
1530
1531         *params = (GLint) obj->Sampler.MinLod;
1532         break;
1533      case GL_TEXTURE_MAX_LOD:
1534         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1535            goto invalid_pname;
1536
1537         *params = (GLint) obj->Sampler.MaxLod;
1538         break;
1539      case GL_TEXTURE_BASE_LEVEL:
1540         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1541            goto invalid_pname;
1542
1543         *params = obj->BaseLevel;
1544         break;
1545      case GL_TEXTURE_MAX_LEVEL:
1546         *params = obj->MaxLevel;
1547         break;
1548      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1549         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1550            goto invalid_pname;
1551         *params = (GLint) obj->Sampler.MaxAnisotropy;
1552         break;
1553      case GL_GENERATE_MIPMAP_SGIS:
1554         if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES)
1555            goto invalid_pname;
1556
1557	 *params = (GLint) obj->GenerateMipmap;
1558         break;
1559      case GL_TEXTURE_COMPARE_MODE_ARB:
1560         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1561             && !_mesa_is_gles3(ctx))
1562            goto invalid_pname;
1563         *params = (GLint) obj->Sampler.CompareMode;
1564         break;
1565      case GL_TEXTURE_COMPARE_FUNC_ARB:
1566         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1567             && !_mesa_is_gles3(ctx))
1568            goto invalid_pname;
1569         *params = (GLint) obj->Sampler.CompareFunc;
1570         break;
1571      case GL_DEPTH_TEXTURE_MODE_ARB:
1572         if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_depth_texture)
1573            goto invalid_pname;
1574         *params = (GLint) obj->DepthMode;
1575         break;
1576      case GL_TEXTURE_LOD_BIAS:
1577         if (ctx->API != API_OPENGL)
1578            goto invalid_pname;
1579
1580         *params = (GLint) obj->Sampler.LodBias;
1581         break;
1582#if FEATURE_OES_draw_texture
1583      case GL_TEXTURE_CROP_RECT_OES:
1584         if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
1585            goto invalid_pname;
1586
1587         params[0] = obj->CropRect[0];
1588         params[1] = obj->CropRect[1];
1589         params[2] = obj->CropRect[2];
1590         params[3] = obj->CropRect[3];
1591         break;
1592#endif
1593      case GL_TEXTURE_SWIZZLE_R_EXT:
1594      case GL_TEXTURE_SWIZZLE_G_EXT:
1595      case GL_TEXTURE_SWIZZLE_B_EXT:
1596      case GL_TEXTURE_SWIZZLE_A_EXT:
1597         if ((!_mesa_is_desktop_gl(ctx)
1598              || !ctx->Extensions.EXT_texture_swizzle)
1599             && !_mesa_is_gles3(ctx))
1600            goto invalid_pname;
1601         *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1602         break;
1603
1604      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1605         if ((!_mesa_is_desktop_gl(ctx)
1606              || !ctx->Extensions.EXT_texture_swizzle)
1607             && !_mesa_is_gles3(ctx))
1608            goto invalid_pname;
1609         COPY_4V(params, obj->Swizzle);
1610         break;
1611
1612      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1613         if (!_mesa_is_desktop_gl(ctx)
1614             || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
1615            goto invalid_pname;
1616         *params = (GLint) obj->Sampler.CubeMapSeamless;
1617         break;
1618
1619      case GL_TEXTURE_IMMUTABLE_FORMAT:
1620         if (!ctx->Extensions.ARB_texture_storage)
1621            goto invalid_pname;
1622         *params = (GLint) obj->Immutable;
1623         break;
1624
1625      case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1626         if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)
1627            goto invalid_pname;
1628         *params = obj->RequiredTextureImageUnits;
1629         break;
1630
1631      case GL_TEXTURE_SRGB_DECODE_EXT:
1632         if (!ctx->Extensions.EXT_texture_sRGB_decode)
1633            goto invalid_pname;
1634         *params = obj->Sampler.sRGBDecode;
1635         break;
1636
1637      default:
1638         goto invalid_pname;
1639   }
1640
1641   /* no error if we get here */
1642   _mesa_unlock_texture(ctx, obj);
1643   return;
1644
1645invalid_pname:
1646   _mesa_unlock_texture(ctx, obj);
1647   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1648}
1649
1650
1651/** New in GL 3.0 */
1652void GLAPIENTRY
1653_mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
1654{
1655   struct gl_texture_object *texObj;
1656   GET_CURRENT_CONTEXT(ctx);
1657   ASSERT_OUTSIDE_BEGIN_END(ctx);
1658
1659   texObj = get_texobj(ctx, target, GL_TRUE);
1660   if (!texObj)
1661      return;
1662
1663   switch (pname) {
1664   case GL_TEXTURE_BORDER_COLOR:
1665      COPY_4V(params, texObj->Sampler.BorderColor.i);
1666      break;
1667   default:
1668      _mesa_GetTexParameteriv(target, pname, params);
1669   }
1670}
1671
1672
1673/** New in GL 3.0 */
1674void GLAPIENTRY
1675_mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
1676{
1677   struct gl_texture_object *texObj;
1678   GET_CURRENT_CONTEXT(ctx);
1679   ASSERT_OUTSIDE_BEGIN_END(ctx);
1680
1681   texObj = get_texobj(ctx, target, GL_TRUE);
1682   if (!texObj)
1683      return;
1684
1685   switch (pname) {
1686   case GL_TEXTURE_BORDER_COLOR:
1687      COPY_4V(params, texObj->Sampler.BorderColor.i);
1688      break;
1689   default:
1690      {
1691         GLint ip[4];
1692         _mesa_GetTexParameteriv(target, pname, ip);
1693         params[0] = ip[0];
1694         if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
1695             pname == GL_TEXTURE_CROP_RECT_OES) {
1696            params[1] = ip[1];
1697            params[2] = ip[2];
1698            params[3] = ip[3];
1699         }
1700      }
1701   }
1702}
1703