1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * 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/blend.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/mtypes.h"
41#include "main/state.h"
42#include "main/texcompress.h"
43#include "main/texobj.h"
44#include "main/texparam.h"
45#include "main/teximage.h"
46#include "main/texstate.h"
47#include "program/prog_instruction.h"
48
49
50/**
51 * Check if a coordinate wrap mode is supported for the texture target.
52 * \return GL_TRUE if legal, GL_FALSE otherwise
53 */
54static GLboolean
55validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap)
56{
57   const struct gl_extensions * const e = & ctx->Extensions;
58   const bool is_desktop_gl = _mesa_is_desktop_gl(ctx);
59   bool supported;
60
61   switch (wrap) {
62   case GL_CLAMP:
63      /* GL_CLAMP was removed in the core profile, and it has never existed in
64       * OpenGL ES.
65       */
66      supported = (ctx->API == API_OPENGL_COMPAT)
67         && (target != GL_TEXTURE_EXTERNAL_OES);
68      break;
69
70   case GL_CLAMP_TO_EDGE:
71      supported = true;
72      break;
73
74   case GL_CLAMP_TO_BORDER:
75      supported = ctx->API != API_OPENGLES && e->ARB_texture_border_clamp
76         && (target != GL_TEXTURE_EXTERNAL_OES);
77      break;
78
79   case GL_REPEAT:
80   case GL_MIRRORED_REPEAT:
81      supported = (target != GL_TEXTURE_RECTANGLE_NV)
82         && (target != GL_TEXTURE_EXTERNAL_OES);
83      break;
84
85   case GL_MIRROR_CLAMP_EXT:
86      supported = is_desktop_gl
87         && (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)
88         && (target != GL_TEXTURE_RECTANGLE_NV)
89         && (target != GL_TEXTURE_EXTERNAL_OES);
90      break;
91
92   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
93      supported = is_desktop_gl
94         && (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp || e->ARB_texture_mirror_clamp_to_edge)
95         && (target != GL_TEXTURE_RECTANGLE_NV)
96         && (target != GL_TEXTURE_EXTERNAL_OES);
97      break;
98
99   case GL_MIRROR_CLAMP_TO_BORDER_EXT:
100      supported = is_desktop_gl && e->EXT_texture_mirror_clamp
101         && (target != GL_TEXTURE_RECTANGLE_NV)
102         && (target != GL_TEXTURE_EXTERNAL_OES);
103      break;
104
105   default:
106      supported = false;
107      break;
108   }
109
110   if (!supported)
111      _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", wrap );
112
113   return supported;
114}
115
116
117/**
118 * Get current texture object for given target.
119 * Return NULL if any error (and record the error).
120 * Note that this is different from _mesa_get_current_tex_object() in that
121 * proxy targets are not accepted.
122 * Only the glGetTexLevelParameter() functions accept proxy targets.
123 */
124static struct gl_texture_object *
125get_texobj_by_target(struct gl_context *ctx, GLenum target, GLboolean get)
126{
127   struct gl_texture_unit *texUnit;
128   int targetIndex;
129
130   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
131      _mesa_error(ctx, GL_INVALID_OPERATION,
132                  "gl%sTexParameter(current unit)", get ? "Get" : "");
133      return NULL;
134   }
135
136   texUnit = _mesa_get_current_tex_unit(ctx);
137
138   targetIndex = _mesa_tex_target_to_index(ctx, target);
139   if (targetIndex < 0 || targetIndex == TEXTURE_BUFFER_INDEX) {
140      _mesa_error(ctx, GL_INVALID_ENUM,
141                  "gl%sTexParameter(target)", get ? "Get" : "");
142      return NULL;
143   }
144   assert(targetIndex < NUM_TEXTURE_TARGETS);
145
146   return texUnit->CurrentTex[targetIndex];
147}
148
149/**
150 * Get current texture object for given name.
151 * Return NULL if any error (and record the error).
152 * Note that proxy targets are not accepted.
153 * Only the glGetTexLevelParameter() functions accept proxy targets.
154 */
155static struct gl_texture_object *
156get_texobj_by_name(struct gl_context *ctx, GLuint texture, GLboolean get)
157{
158   struct gl_texture_object *texObj;
159
160   texObj = _mesa_lookup_texture(ctx, texture);
161   if (!texObj) {
162      /*
163       * User passed a non-generated name.
164       * Throw the error in the caller.
165       */
166      return NULL;
167   }
168
169   switch (texObj->Target) {
170   case GL_TEXTURE_1D:
171   case GL_TEXTURE_1D_ARRAY:
172   case GL_TEXTURE_2D:
173   case GL_TEXTURE_2D_ARRAY:
174   case GL_TEXTURE_2D_MULTISAMPLE:
175   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
176   case GL_TEXTURE_3D:
177   case GL_TEXTURE_CUBE_MAP:
178   case GL_TEXTURE_CUBE_MAP_ARRAY:
179   case GL_TEXTURE_RECTANGLE:
180      return texObj;
181   default:
182      _mesa_error(ctx, GL_INVALID_ENUM,
183                  "gl%sTextureParameter(target)", get ? "Get" : "");
184      return NULL;
185   }
186
187}
188
189
190/**
191 * Convert GL_RED/GREEN/BLUE/ALPHA/ZERO/ONE to SWIZZLE_X/Y/Z/W/ZERO/ONE.
192 * \return -1 if error.
193 */
194static GLint
195comp_to_swizzle(GLenum comp)
196{
197   switch (comp) {
198   case GL_RED:
199      return SWIZZLE_X;
200   case GL_GREEN:
201      return SWIZZLE_Y;
202   case GL_BLUE:
203      return SWIZZLE_Z;
204   case GL_ALPHA:
205      return SWIZZLE_W;
206   case GL_ZERO:
207      return SWIZZLE_ZERO;
208   case GL_ONE:
209      return SWIZZLE_ONE;
210   default:
211      return -1;
212   }
213}
214
215
216static void
217set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
218{
219   assert(comp < 4);
220   assert(swz <= SWIZZLE_NIL);
221   {
222      GLuint mask = 0x7 << (3 * comp);
223      GLuint s = (*swizzle & ~mask) | (swz << (3 * comp));
224      *swizzle = s;
225   }
226}
227
228
229/**
230 * This is called just prior to changing any texture object state which
231 * will not affect texture completeness.
232 */
233static inline void
234flush(struct gl_context *ctx)
235{
236   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
237}
238
239
240/**
241 * This is called just prior to changing any texture object state which
242 * could affect texture completeness (texture base level, max level).
243 * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE
244 * state flag and then mark the texture object as 'incomplete' so that any
245 * per-texture derived state gets recomputed.
246 */
247static inline void
248incomplete(struct gl_context *ctx, struct gl_texture_object *texObj)
249{
250   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
251   _mesa_dirty_texobj(ctx, texObj);
252}
253
254
255GLboolean
256_mesa_target_allows_setting_sampler_parameters(GLenum target)
257{
258   switch (target) {
259   case GL_TEXTURE_2D_MULTISAMPLE:
260   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
261      return GL_FALSE;
262
263   default:
264      return GL_TRUE;
265   }
266}
267
268
269/**
270 * Set an integer-valued texture parameter
271 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
272 */
273static GLboolean
274set_tex_parameteri(struct gl_context *ctx,
275                   struct gl_texture_object *texObj,
276                   GLenum pname, const GLint *params, bool dsa)
277{
278   const char *suffix = dsa ? "ture" : "";
279
280   switch (pname) {
281   case GL_TEXTURE_MIN_FILTER:
282      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
283         goto invalid_enum;
284
285      if (texObj->Sampler.MinFilter == params[0])
286         return GL_FALSE;
287      switch (params[0]) {
288      case GL_NEAREST:
289      case GL_LINEAR:
290         flush(ctx);
291         texObj->Sampler.MinFilter = params[0];
292         return GL_TRUE;
293      case GL_NEAREST_MIPMAP_NEAREST:
294      case GL_LINEAR_MIPMAP_NEAREST:
295      case GL_NEAREST_MIPMAP_LINEAR:
296      case GL_LINEAR_MIPMAP_LINEAR:
297         if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
298             texObj->Target != GL_TEXTURE_EXTERNAL_OES) {
299            flush(ctx);
300            texObj->Sampler.MinFilter = params[0];
301            return GL_TRUE;
302         }
303         /* fall-through */
304      default:
305         goto invalid_param;
306      }
307      return GL_FALSE;
308
309   case GL_TEXTURE_MAG_FILTER:
310      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
311         goto invalid_enum;
312
313      if (texObj->Sampler.MagFilter == params[0])
314         return GL_FALSE;
315      switch (params[0]) {
316      case GL_NEAREST:
317      case GL_LINEAR:
318         flush(ctx); /* does not effect completeness */
319         texObj->Sampler.MagFilter = params[0];
320         return GL_TRUE;
321      default:
322         goto invalid_param;
323      }
324      return GL_FALSE;
325
326   case GL_TEXTURE_WRAP_S:
327      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
328         goto invalid_enum;
329
330      if (texObj->Sampler.WrapS == params[0])
331         return GL_FALSE;
332      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
333         flush(ctx);
334         texObj->Sampler.WrapS = params[0];
335         return GL_TRUE;
336      }
337      return GL_FALSE;
338
339   case GL_TEXTURE_WRAP_T:
340      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
341         goto invalid_enum;
342
343      if (texObj->Sampler.WrapT == params[0])
344         return GL_FALSE;
345      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
346         flush(ctx);
347         texObj->Sampler.WrapT = params[0];
348         return GL_TRUE;
349      }
350      return GL_FALSE;
351
352   case GL_TEXTURE_WRAP_R:
353      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
354         goto invalid_enum;
355
356      if (texObj->Sampler.WrapR == params[0])
357         return GL_FALSE;
358      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
359         flush(ctx);
360         texObj->Sampler.WrapR = params[0];
361         return GL_TRUE;
362      }
363      return GL_FALSE;
364
365   case GL_TEXTURE_BASE_LEVEL:
366      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
367         goto invalid_pname;
368
369      if (texObj->BaseLevel == params[0])
370         return GL_FALSE;
371
372      if ((texObj->Target == GL_TEXTURE_2D_MULTISAMPLE ||
373           texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) && params[0] != 0)
374         goto invalid_operation;
375
376      if (params[0] < 0) {
377         _mesa_error(ctx, GL_INVALID_VALUE,
378                     "glTex%sParameter(param=%d)", suffix, params[0]);
379         return GL_FALSE;
380      }
381      if (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0) {
382         _mesa_error(ctx, GL_INVALID_OPERATION,
383                     "glTex%sParameter(target=%s, param=%d)", suffix,
384                     _mesa_enum_to_string(texObj->Target), params[0]);
385         return GL_FALSE;
386      }
387      incomplete(ctx, texObj);
388
389      /** See note about ARB_texture_storage below */
390      if (texObj->Immutable)
391         texObj->BaseLevel = MIN2(texObj->ImmutableLevels - 1, params[0]);
392      else
393         texObj->BaseLevel = params[0];
394
395      return GL_TRUE;
396
397   case GL_TEXTURE_MAX_LEVEL:
398      if (texObj->MaxLevel == params[0])
399         return GL_FALSE;
400
401      if (params[0] < 0 ||
402          (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] > 0)) {
403         _mesa_error(ctx, GL_INVALID_VALUE,
404                     "glTex%sParameter(param=%d)", suffix,
405                     params[0]);
406         return GL_FALSE;
407      }
408      incomplete(ctx, texObj);
409
410      /** From ARB_texture_storage:
411       * However, if TEXTURE_IMMUTABLE_FORMAT is TRUE, then level_base is
412       * clamped to the range [0, <levels> - 1] and level_max is then clamped to
413       * the range [level_base, <levels> - 1], where <levels> is the parameter
414       * passed the call to TexStorage* for the texture object.
415       */
416      if (texObj->Immutable)
417          texObj->MaxLevel = CLAMP(params[0], texObj->BaseLevel,
418                                   texObj->ImmutableLevels - 1);
419      else
420         texObj->MaxLevel = params[0];
421
422      return GL_TRUE;
423
424   case GL_GENERATE_MIPMAP_SGIS:
425      if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
426         goto invalid_pname;
427
428      if (params[0] && texObj->Target == GL_TEXTURE_EXTERNAL_OES)
429         goto invalid_param;
430      if (texObj->GenerateMipmap != params[0]) {
431         /* no flush() */
432	 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
433	 return GL_TRUE;
434      }
435      return GL_FALSE;
436
437   case GL_TEXTURE_COMPARE_MODE_ARB:
438      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow)
439          || _mesa_is_gles3(ctx)) {
440
441         if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
442            goto invalid_enum;
443
444         if (texObj->Sampler.CompareMode == params[0])
445            return GL_FALSE;
446         if (params[0] == GL_NONE ||
447             params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
448            flush(ctx);
449            texObj->Sampler.CompareMode = params[0];
450            return GL_TRUE;
451         }
452         goto invalid_param;
453      }
454      goto invalid_pname;
455
456   case GL_TEXTURE_COMPARE_FUNC_ARB:
457      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow)
458          || _mesa_is_gles3(ctx)) {
459
460         if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
461            goto invalid_enum;
462
463         if (texObj->Sampler.CompareFunc == params[0])
464            return GL_FALSE;
465         switch (params[0]) {
466         case GL_LEQUAL:
467         case GL_GEQUAL:
468         case GL_EQUAL:
469         case GL_NOTEQUAL:
470         case GL_LESS:
471         case GL_GREATER:
472         case GL_ALWAYS:
473         case GL_NEVER:
474            flush(ctx);
475            texObj->Sampler.CompareFunc = params[0];
476            return GL_TRUE;
477         default:
478            goto invalid_param;
479         }
480      }
481      goto invalid_pname;
482
483   case GL_DEPTH_TEXTURE_MODE_ARB:
484      /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has never
485       * existed in OpenGL ES.
486       */
487      if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_texture) {
488         if (texObj->DepthMode == params[0])
489            return GL_FALSE;
490         if (params[0] == GL_LUMINANCE ||
491             params[0] == GL_INTENSITY ||
492             params[0] == GL_ALPHA ||
493             (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
494            flush(ctx);
495            texObj->DepthMode = params[0];
496            return GL_TRUE;
497         }
498         goto invalid_param;
499      }
500      goto invalid_pname;
501
502   case GL_DEPTH_STENCIL_TEXTURE_MODE:
503      if (_mesa_has_ARB_stencil_texturing(ctx) || _mesa_is_gles31(ctx)) {
504         bool stencil = params[0] == GL_STENCIL_INDEX;
505         if (!stencil && params[0] != GL_DEPTH_COMPONENT)
506            goto invalid_param;
507
508         if (texObj->StencilSampling == stencil)
509            return GL_FALSE;
510
511         texObj->StencilSampling = stencil;
512         return GL_TRUE;
513      }
514      goto invalid_pname;
515
516   case GL_TEXTURE_CROP_RECT_OES:
517      if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
518         goto invalid_pname;
519
520      texObj->CropRect[0] = params[0];
521      texObj->CropRect[1] = params[1];
522      texObj->CropRect[2] = params[2];
523      texObj->CropRect[3] = params[3];
524      return GL_TRUE;
525
526   case GL_TEXTURE_SWIZZLE_R_EXT:
527   case GL_TEXTURE_SWIZZLE_G_EXT:
528   case GL_TEXTURE_SWIZZLE_B_EXT:
529   case GL_TEXTURE_SWIZZLE_A_EXT:
530      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle)
531          || _mesa_is_gles3(ctx)) {
532         const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
533         const GLint swz = comp_to_swizzle(params[0]);
534         if (swz < 0) {
535            _mesa_error(ctx, GL_INVALID_ENUM,
536                        "glTex%sParameter(swizzle 0x%x)", suffix, params[0]);
537            return GL_FALSE;
538         }
539         assert(comp < 4);
540
541         flush(ctx);
542         texObj->Swizzle[comp] = params[0];
543         set_swizzle_component(&texObj->_Swizzle, comp, swz);
544         return GL_TRUE;
545      }
546      goto invalid_pname;
547
548   case GL_TEXTURE_SWIZZLE_RGBA_EXT:
549      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle)
550          || _mesa_is_gles3(ctx)) {
551         GLuint comp;
552         flush(ctx);
553         for (comp = 0; comp < 4; comp++) {
554            const GLint swz = comp_to_swizzle(params[comp]);
555            if (swz >= 0) {
556               texObj->Swizzle[comp] = params[comp];
557               set_swizzle_component(&texObj->_Swizzle, comp, swz);
558            }
559            else {
560               _mesa_error(ctx, GL_INVALID_ENUM,
561                           "glTex%sParameter(swizzle 0x%x)",
562                           suffix, params[comp]);
563               return GL_FALSE;
564            }
565         }
566         return GL_TRUE;
567      }
568      goto invalid_pname;
569
570   case GL_TEXTURE_SRGB_DECODE_EXT:
571      if (ctx->Extensions.EXT_texture_sRGB_decode) {
572         GLenum decode = params[0];
573
574         if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
575            goto invalid_enum;
576
577	 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
578	    if (texObj->Sampler.sRGBDecode != decode) {
579	       flush(ctx);
580	       texObj->Sampler.sRGBDecode = decode;
581	    }
582	    return GL_TRUE;
583	 }
584      }
585      goto invalid_pname;
586
587   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
588      if (_mesa_is_desktop_gl(ctx)
589          && ctx->Extensions.AMD_seamless_cubemap_per_texture) {
590         GLenum param = params[0];
591
592         if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
593            goto invalid_enum;
594
595         if (param != GL_TRUE && param != GL_FALSE) {
596            goto invalid_param;
597         }
598         if (param != texObj->Sampler.CubeMapSeamless) {
599            flush(ctx);
600            texObj->Sampler.CubeMapSeamless = param;
601         }
602         return GL_TRUE;
603      }
604      goto invalid_pname;
605
606   default:
607      goto invalid_pname;
608   }
609
610invalid_pname:
611   _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
612               suffix, _mesa_enum_to_string(pname));
613   return GL_FALSE;
614
615invalid_param:
616   _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(param=%s)",
617               suffix, _mesa_enum_to_string(params[0]));
618   return GL_FALSE;
619
620invalid_operation:
621   _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sParameter(pname=%s)",
622               suffix, _mesa_enum_to_string(pname));
623   return GL_FALSE;
624
625invalid_enum:
626   _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
627               suffix, _mesa_enum_to_string(pname));
628   return GL_FALSE;
629}
630
631
632/**
633 * Set a float-valued texture parameter
634 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
635 */
636static GLboolean
637set_tex_parameterf(struct gl_context *ctx,
638                   struct gl_texture_object *texObj,
639                   GLenum pname, const GLfloat *params, bool dsa)
640{
641   const char *suffix = dsa ? "ture" : "";
642
643   switch (pname) {
644   case GL_TEXTURE_MIN_LOD:
645      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
646         goto invalid_pname;
647
648      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
649         goto invalid_enum;
650
651      if (texObj->Sampler.MinLod == params[0])
652         return GL_FALSE;
653      flush(ctx);
654      texObj->Sampler.MinLod = params[0];
655      return GL_TRUE;
656
657   case GL_TEXTURE_MAX_LOD:
658      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
659         goto invalid_pname;
660
661      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
662         goto invalid_enum;
663
664      if (texObj->Sampler.MaxLod == params[0])
665         return GL_FALSE;
666      flush(ctx);
667      texObj->Sampler.MaxLod = params[0];
668      return GL_TRUE;
669
670   case GL_TEXTURE_PRIORITY:
671      if (ctx->API != API_OPENGL_COMPAT)
672         goto invalid_pname;
673
674      flush(ctx);
675      texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
676      return GL_TRUE;
677
678   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
679      if (ctx->Extensions.EXT_texture_filter_anisotropic) {
680         if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
681            goto invalid_enum;
682
683         if (texObj->Sampler.MaxAnisotropy == params[0])
684            return GL_FALSE;
685         if (params[0] < 1.0F) {
686            _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sParameter(param)",
687                        suffix);
688            return GL_FALSE;
689         }
690         flush(ctx);
691         /* clamp to max, that's what NVIDIA does */
692         texObj->Sampler.MaxAnisotropy = MIN2(params[0],
693                                      ctx->Const.MaxTextureMaxAnisotropy);
694         return GL_TRUE;
695      }
696      else {
697         static GLuint count = 0;
698         if (count++ < 10)
699            goto invalid_pname;
700      }
701      return GL_FALSE;
702
703   case GL_TEXTURE_LOD_BIAS:
704      /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias. */
705      if (_mesa_is_gles(ctx))
706         goto invalid_pname;
707
708      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
709         goto invalid_enum;
710
711      if (texObj->Sampler.LodBias != params[0]) {
712	 flush(ctx);
713	 texObj->Sampler.LodBias = params[0];
714	 return GL_TRUE;
715      }
716      break;
717
718   case GL_TEXTURE_BORDER_COLOR:
719      if (ctx->API == API_OPENGLES ||
720          !ctx->Extensions.ARB_texture_border_clamp)
721         goto invalid_pname;
722
723      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target))
724         goto invalid_enum;
725
726      flush(ctx);
727      /* ARB_texture_float disables clamping */
728      if (ctx->Extensions.ARB_texture_float) {
729         texObj->Sampler.BorderColor.f[RCOMP] = params[0];
730         texObj->Sampler.BorderColor.f[GCOMP] = params[1];
731         texObj->Sampler.BorderColor.f[BCOMP] = params[2];
732         texObj->Sampler.BorderColor.f[ACOMP] = params[3];
733      } else {
734         texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F);
735         texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F);
736         texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F);
737         texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F);
738      }
739      return GL_TRUE;
740
741   default:
742      goto invalid_pname;
743   }
744   return GL_FALSE;
745
746invalid_pname:
747   _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
748               suffix, _mesa_enum_to_string(pname));
749   return GL_FALSE;
750
751invalid_enum:
752   _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
753               suffix, _mesa_enum_to_string(pname));
754   return GL_FALSE;
755}
756
757
758void
759_mesa_texture_parameterf(struct gl_context *ctx,
760                         struct gl_texture_object *texObj,
761                         GLenum pname, GLfloat param, bool dsa)
762{
763   GLboolean need_update;
764
765   switch (pname) {
766   case GL_TEXTURE_MIN_FILTER:
767   case GL_TEXTURE_MAG_FILTER:
768   case GL_TEXTURE_WRAP_S:
769   case GL_TEXTURE_WRAP_T:
770   case GL_TEXTURE_WRAP_R:
771   case GL_TEXTURE_BASE_LEVEL:
772   case GL_TEXTURE_MAX_LEVEL:
773   case GL_GENERATE_MIPMAP_SGIS:
774   case GL_TEXTURE_COMPARE_MODE_ARB:
775   case GL_TEXTURE_COMPARE_FUNC_ARB:
776   case GL_DEPTH_TEXTURE_MODE_ARB:
777   case GL_DEPTH_STENCIL_TEXTURE_MODE:
778   case GL_TEXTURE_SRGB_DECODE_EXT:
779   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
780   case GL_TEXTURE_SWIZZLE_R_EXT:
781   case GL_TEXTURE_SWIZZLE_G_EXT:
782   case GL_TEXTURE_SWIZZLE_B_EXT:
783   case GL_TEXTURE_SWIZZLE_A_EXT:
784      {
785         GLint p[4];
786         p[0] = (param > 0) ?
787                ((param > INT_MAX) ? INT_MAX : (GLint) (param + 0.5)) :
788                ((param < INT_MIN) ? INT_MIN : (GLint) (param - 0.5));
789
790         p[1] = p[2] = p[3] = 0;
791         need_update = set_tex_parameteri(ctx, texObj, pname, p, dsa);
792      }
793      break;
794   case GL_TEXTURE_BORDER_COLOR:
795   case GL_TEXTURE_SWIZZLE_RGBA:
796      _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameterf(non-scalar pname)",
797                  dsa ? "ture" : "");
798      return;
799   default:
800      {
801         /* this will generate an error if pname is illegal */
802         GLfloat p[4];
803         p[0] = param;
804         p[1] = p[2] = p[3] = 0.0F;
805         need_update = set_tex_parameterf(ctx, texObj, pname, p, dsa);
806      }
807   }
808
809   if (ctx->Driver.TexParameter && need_update) {
810      ctx->Driver.TexParameter(ctx, texObj, pname);
811   }
812}
813
814
815void
816_mesa_texture_parameterfv(struct gl_context *ctx,
817                          struct gl_texture_object *texObj,
818                          GLenum pname, const GLfloat *params, bool dsa)
819{
820   GLboolean need_update;
821   switch (pname) {
822   case GL_TEXTURE_MIN_FILTER:
823   case GL_TEXTURE_MAG_FILTER:
824   case GL_TEXTURE_WRAP_S:
825   case GL_TEXTURE_WRAP_T:
826   case GL_TEXTURE_WRAP_R:
827   case GL_TEXTURE_BASE_LEVEL:
828   case GL_TEXTURE_MAX_LEVEL:
829   case GL_GENERATE_MIPMAP_SGIS:
830   case GL_TEXTURE_COMPARE_MODE_ARB:
831   case GL_TEXTURE_COMPARE_FUNC_ARB:
832   case GL_DEPTH_TEXTURE_MODE_ARB:
833   case GL_DEPTH_STENCIL_TEXTURE_MODE:
834   case GL_TEXTURE_SRGB_DECODE_EXT:
835   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
836      {
837         /* convert float param to int */
838         GLint p[4];
839         p[0] = (GLint) params[0];
840         p[1] = p[2] = p[3] = 0;
841         need_update = set_tex_parameteri(ctx, texObj, pname, p, dsa);
842      }
843      break;
844   case GL_TEXTURE_CROP_RECT_OES:
845      {
846         /* convert float params to int */
847         GLint iparams[4];
848         iparams[0] = (GLint) params[0];
849         iparams[1] = (GLint) params[1];
850         iparams[2] = (GLint) params[2];
851         iparams[3] = (GLint) params[3];
852         need_update = set_tex_parameteri(ctx, texObj, pname, iparams, dsa);
853      }
854      break;
855   case GL_TEXTURE_SWIZZLE_R_EXT:
856   case GL_TEXTURE_SWIZZLE_G_EXT:
857   case GL_TEXTURE_SWIZZLE_B_EXT:
858   case GL_TEXTURE_SWIZZLE_A_EXT:
859   case GL_TEXTURE_SWIZZLE_RGBA_EXT:
860      {
861         GLint p[4] = {0, 0, 0, 0};
862         p[0] = (GLint) params[0];
863         if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT) {
864            p[1] = (GLint) params[1];
865            p[2] = (GLint) params[2];
866            p[3] = (GLint) params[3];
867         }
868         need_update = set_tex_parameteri(ctx, texObj, pname, p, dsa);
869      }
870      break;
871   default:
872      /* this will generate an error if pname is illegal */
873      need_update = set_tex_parameterf(ctx, texObj, pname, params, dsa);
874   }
875
876   if (ctx->Driver.TexParameter && need_update) {
877      ctx->Driver.TexParameter(ctx, texObj, pname);
878   }
879}
880
881
882void
883_mesa_texture_parameteri(struct gl_context *ctx,
884                         struct gl_texture_object *texObj,
885                         GLenum pname, GLint param, bool dsa)
886{
887   GLboolean need_update;
888   switch (pname) {
889   case GL_TEXTURE_MIN_LOD:
890   case GL_TEXTURE_MAX_LOD:
891   case GL_TEXTURE_PRIORITY:
892   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
893   case GL_TEXTURE_LOD_BIAS:
894   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
895      {
896         GLfloat fparam[4];
897         fparam[0] = (GLfloat) param;
898         fparam[1] = fparam[2] = fparam[3] = 0.0F;
899         /* convert int param to float */
900         need_update = set_tex_parameterf(ctx, texObj, pname, fparam, dsa);
901      }
902      break;
903   case GL_TEXTURE_BORDER_COLOR:
904   case GL_TEXTURE_SWIZZLE_RGBA:
905      {
906         _mesa_error(ctx, GL_INVALID_ENUM,
907                     "glTex%sParameteri(non-scalar pname)",
908                     dsa ? "ture" : "");
909         return;
910      }
911   default:
912      /* this will generate an error if pname is illegal */
913      {
914         GLint iparam[4];
915         iparam[0] = param;
916         iparam[1] = iparam[2] = iparam[3] = 0;
917         need_update = set_tex_parameteri(ctx, texObj, pname, iparam, dsa);
918      }
919   }
920
921   if (ctx->Driver.TexParameter && need_update) {
922      ctx->Driver.TexParameter(ctx, texObj, pname);
923   }
924}
925
926
927void
928_mesa_texture_parameteriv(struct gl_context *ctx,
929                          struct gl_texture_object *texObj,
930                          GLenum pname, const GLint *params, bool dsa)
931{
932   GLboolean need_update;
933
934   switch (pname) {
935   case GL_TEXTURE_BORDER_COLOR:
936      {
937         if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target)) {
938            _mesa_error(ctx, GL_INVALID_ENUM, "glTextureParameteriv(texture)");
939            return;
940         }
941         /* convert int params to float */
942         GLfloat fparams[4];
943         fparams[0] = INT_TO_FLOAT(params[0]);
944         fparams[1] = INT_TO_FLOAT(params[1]);
945         fparams[2] = INT_TO_FLOAT(params[2]);
946         fparams[3] = INT_TO_FLOAT(params[3]);
947         need_update = set_tex_parameterf(ctx, texObj, pname, fparams, dsa);
948      }
949      break;
950   case GL_TEXTURE_MIN_LOD:
951   case GL_TEXTURE_MAX_LOD:
952   case GL_TEXTURE_PRIORITY:
953   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
954   case GL_TEXTURE_LOD_BIAS:
955   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
956      {
957         /* convert int param to float */
958         GLfloat fparams[4];
959         fparams[0] = (GLfloat) params[0];
960         fparams[1] = fparams[2] = fparams[3] = 0.0F;
961         need_update = set_tex_parameterf(ctx, texObj, pname, fparams, dsa);
962      }
963      break;
964   default:
965      /* this will generate an error if pname is illegal */
966      need_update = set_tex_parameteri(ctx, texObj, pname, params, dsa);
967   }
968
969   if (ctx->Driver.TexParameter && need_update) {
970      ctx->Driver.TexParameter(ctx, texObj, pname);
971   }
972}
973
974void
975_mesa_texture_parameterIiv(struct gl_context *ctx,
976                           struct gl_texture_object *texObj,
977                           GLenum pname, const GLint *params, bool dsa)
978{
979   switch (pname) {
980   case GL_TEXTURE_BORDER_COLOR:
981      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target)) {
982         _mesa_error(ctx, GL_INVALID_ENUM, "glTextureParameterIiv(texture)");
983         return;
984      }
985      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
986      /* set the integer-valued border color */
987      COPY_4V(texObj->Sampler.BorderColor.i, params);
988      break;
989   default:
990      _mesa_texture_parameteriv(ctx, texObj, pname, params, dsa);
991      break;
992   }
993   /* XXX no driver hook for TexParameterIiv() yet */
994}
995
996void
997_mesa_texture_parameterIuiv(struct gl_context *ctx,
998                            struct gl_texture_object *texObj,
999                            GLenum pname, const GLuint *params, bool dsa)
1000{
1001   switch (pname) {
1002   case GL_TEXTURE_BORDER_COLOR:
1003      if (!_mesa_target_allows_setting_sampler_parameters(texObj->Target)) {
1004         _mesa_error(ctx, GL_INVALID_ENUM, "glTextureParameterIuiv(texture)");
1005         return;
1006      }
1007      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1008      /* set the unsigned integer-valued border color */
1009      COPY_4V(texObj->Sampler.BorderColor.ui, params);
1010      break;
1011   default:
1012      _mesa_texture_parameteriv(ctx, texObj, pname, (const GLint *) params,
1013                                dsa);
1014      break;
1015   }
1016   /* XXX no driver hook for TexParameterIuiv() yet */
1017}
1018
1019void GLAPIENTRY
1020_mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
1021{
1022   struct gl_texture_object *texObj;
1023   GET_CURRENT_CONTEXT(ctx);
1024
1025   texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1026   if (!texObj)
1027      return;
1028
1029   _mesa_texture_parameterf(ctx, texObj, pname, param, false);
1030}
1031
1032void GLAPIENTRY
1033_mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
1034{
1035   struct gl_texture_object *texObj;
1036   GET_CURRENT_CONTEXT(ctx);
1037
1038   texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1039   if (!texObj)
1040      return;
1041
1042   _mesa_texture_parameterfv(ctx, texObj, pname, params, false);
1043}
1044
1045void GLAPIENTRY
1046_mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
1047{
1048   struct gl_texture_object *texObj;
1049   GET_CURRENT_CONTEXT(ctx);
1050
1051   texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1052   if (!texObj)
1053      return;
1054
1055   _mesa_texture_parameteri(ctx, texObj, pname, param, false);
1056}
1057
1058void GLAPIENTRY
1059_mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
1060{
1061   struct gl_texture_object *texObj;
1062   GET_CURRENT_CONTEXT(ctx);
1063
1064   texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1065   if (!texObj)
1066      return;
1067
1068   _mesa_texture_parameteriv(ctx, texObj, pname, params, false);
1069}
1070
1071/**
1072 * Set tex parameter to integer value(s).  Primarily intended to set
1073 * integer-valued texture border color (for integer-valued textures).
1074 * New in GL 3.0.
1075 */
1076void GLAPIENTRY
1077_mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params)
1078{
1079   struct gl_texture_object *texObj;
1080   GET_CURRENT_CONTEXT(ctx);
1081
1082   texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1083   if (!texObj)
1084      return;
1085
1086   _mesa_texture_parameterIiv(ctx, texObj, pname, params, false);
1087}
1088
1089/**
1090 * Set tex parameter to unsigned integer value(s).  Primarily intended to set
1091 * uint-valued texture border color (for integer-valued textures).
1092 * New in GL 3.0
1093 */
1094void GLAPIENTRY
1095_mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params)
1096{
1097   struct gl_texture_object *texObj;
1098   GET_CURRENT_CONTEXT(ctx);
1099
1100   texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1101   if (!texObj)
1102      return;
1103
1104   _mesa_texture_parameterIuiv(ctx, texObj, pname, params, false);
1105}
1106
1107
1108void GLAPIENTRY
1109_mesa_TextureParameterfv(GLuint texture, GLenum pname, const GLfloat *params)
1110{
1111   struct gl_texture_object *texObj;
1112   GET_CURRENT_CONTEXT(ctx);
1113
1114   texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1115   if (!texObj) {
1116      /* User passed a non-generated name. */
1117      _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameterfv(texture)");
1118      return;
1119   }
1120
1121   _mesa_texture_parameterfv(ctx, texObj, pname, params, true);
1122}
1123
1124void GLAPIENTRY
1125_mesa_TextureParameterf(GLuint texture, GLenum pname, GLfloat param)
1126{
1127   struct gl_texture_object *texObj;
1128   GET_CURRENT_CONTEXT(ctx);
1129
1130   texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1131   if (!texObj) {
1132      /* User passed a non-generated name. */
1133      _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameterf(texture)");
1134      return;
1135   }
1136
1137   _mesa_texture_parameterf(ctx, texObj, pname, param, true);
1138}
1139
1140void GLAPIENTRY
1141_mesa_TextureParameteri(GLuint texture, GLenum pname, GLint param)
1142{
1143   struct gl_texture_object *texObj;
1144   GET_CURRENT_CONTEXT(ctx);
1145
1146   texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1147   if (!texObj) {
1148      /* User passed a non-generated name. */
1149      _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameteri(texture)");
1150      return;
1151   }
1152
1153   _mesa_texture_parameteri(ctx, texObj, pname, param, true);
1154}
1155
1156void GLAPIENTRY
1157_mesa_TextureParameteriv(GLuint texture, GLenum pname,
1158                         const GLint *params)
1159{
1160   struct gl_texture_object *texObj;
1161   GET_CURRENT_CONTEXT(ctx);
1162
1163   texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1164   if (!texObj) {
1165      /* User passed a non-generated name. */
1166      _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameteriv(texture)");
1167      return;
1168   }
1169
1170   _mesa_texture_parameteriv(ctx, texObj, pname, params, true);
1171}
1172
1173
1174void GLAPIENTRY
1175_mesa_TextureParameterIiv(GLuint texture, GLenum pname, const GLint *params)
1176{
1177   struct gl_texture_object *texObj;
1178   GET_CURRENT_CONTEXT(ctx);
1179
1180   texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1181   if (!texObj) {
1182      /* User passed a non-generated name. */
1183      _mesa_error(ctx, GL_INVALID_OPERATION,
1184                  "glTextureParameterIiv(texture)");
1185      return;
1186   }
1187
1188   _mesa_texture_parameterIiv(ctx, texObj, pname, params, true);
1189}
1190
1191void GLAPIENTRY
1192_mesa_TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint *params)
1193{
1194   struct gl_texture_object *texObj;
1195   GET_CURRENT_CONTEXT(ctx);
1196
1197   texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1198   if (!texObj) {
1199      /* User passed a non-generated name. */
1200      _mesa_error(ctx, GL_INVALID_OPERATION,
1201                  "glTextureParameterIuiv(texture)");
1202      return;
1203   }
1204
1205   _mesa_texture_parameterIuiv(ctx, texObj, pname, params, true);
1206}
1207
1208GLboolean
1209_mesa_legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target,
1210                                           bool dsa)
1211{
1212   /* Common targets for desktop GL and GLES 3.1. */
1213   switch (target) {
1214   case GL_TEXTURE_2D:
1215   case GL_TEXTURE_3D:
1216      return GL_TRUE;
1217   case GL_TEXTURE_2D_ARRAY_EXT:
1218      return ctx->Extensions.EXT_texture_array;
1219   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1220   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1221   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1222   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1223   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1224   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1225      return ctx->Extensions.ARB_texture_cube_map;
1226   case GL_TEXTURE_2D_MULTISAMPLE:
1227   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1228      return ctx->Extensions.ARB_texture_multisample;
1229   case GL_TEXTURE_BUFFER:
1230      /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts,
1231       * but not in earlier versions that expose ARB_texture_buffer_object.
1232       *
1233       * From the ARB_texture_buffer_object spec:
1234       * "(7) Do buffer textures support texture parameters (TexParameter) or
1235       *      queries (GetTexParameter, GetTexLevelParameter, GetTexImage)?
1236       *
1237       *    RESOLVED:  No. [...] Note that the spec edits above don't add
1238       *    explicit error language for any of these cases.  That is because
1239       *    each of the functions enumerate the set of valid <target>
1240       *    parameters.  Not editing the spec to allow TEXTURE_BUFFER_ARB in
1241       *    these cases means that target is not legal, and an INVALID_ENUM
1242       *    error should be generated."
1243       *
1244       * From the OpenGL 3.1 spec:
1245       * "target may also be TEXTURE_BUFFER, indicating the texture buffer."
1246       */
1247      return (ctx->API == API_OPENGL_CORE && ctx->Version >= 31) ||
1248         _mesa_has_OES_texture_buffer(ctx);
1249   case GL_TEXTURE_CUBE_MAP_ARRAY:
1250      return _mesa_has_texture_cube_map_array(ctx);
1251   }
1252
1253   if (!_mesa_is_desktop_gl(ctx))
1254      return GL_FALSE;
1255
1256   /* Rest of the desktop GL targets. */
1257   switch (target) {
1258   case GL_TEXTURE_1D:
1259   case GL_PROXY_TEXTURE_1D:
1260   case GL_PROXY_TEXTURE_2D:
1261   case GL_PROXY_TEXTURE_3D:
1262      return GL_TRUE;
1263   case GL_PROXY_TEXTURE_CUBE_MAP:
1264      return ctx->Extensions.ARB_texture_cube_map;
1265   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
1266      return ctx->Extensions.ARB_texture_cube_map_array;
1267   case GL_TEXTURE_RECTANGLE_NV:
1268   case GL_PROXY_TEXTURE_RECTANGLE_NV:
1269      return ctx->Extensions.NV_texture_rectangle;
1270   case GL_TEXTURE_1D_ARRAY_EXT:
1271   case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1272   case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1273      return ctx->Extensions.EXT_texture_array;
1274   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
1275   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
1276      return ctx->Extensions.ARB_texture_multisample;
1277
1278   /*  This is a valid target for dsa, but the OpenGL 4.5 core spec
1279    *  (30.10.2014) Section 8.11 Texture Queries says:
1280    *       "For GetTextureLevelParameter* only, texture may also be a cube
1281    *       map texture object.  In this case the query is always performed
1282    *       for face zero (the TEXTURE_CUBE_MAP_POSITIVE_X face), since there
1283    *       is no way to specify another face."
1284    */
1285   case GL_TEXTURE_CUBE_MAP:
1286      return dsa;
1287   default:
1288      return GL_FALSE;
1289   }
1290}
1291
1292
1293static void
1294get_tex_level_parameter_image(struct gl_context *ctx,
1295                              const struct gl_texture_object *texObj,
1296                              GLenum target, GLint level,
1297                              GLenum pname, GLint *params,
1298                              bool dsa)
1299{
1300   const struct gl_texture_image *img = NULL;
1301   struct gl_texture_image dummy_image;
1302   mesa_format texFormat;
1303   const char *suffix = dsa ? "ture" : "";
1304
1305   img = _mesa_select_tex_image(texObj, target, level);
1306   if (!img || img->TexFormat == MESA_FORMAT_NONE) {
1307      /* In case of undefined texture image return the default values.
1308       *
1309       * From OpenGL 4.0 spec, page 398:
1310       *    "The initial internal format of a texel array is RGBA
1311       *     instead of 1. TEXTURE_COMPONENTS is deprecated; always
1312       *     use TEXTURE_INTERNAL_FORMAT."
1313       */
1314      memset(&dummy_image, 0, sizeof(dummy_image));
1315      dummy_image.TexFormat = MESA_FORMAT_NONE;
1316      dummy_image.InternalFormat = GL_RGBA;
1317      dummy_image._BaseFormat = GL_NONE;
1318      dummy_image.FixedSampleLocations = GL_TRUE;
1319
1320      img = &dummy_image;
1321   }
1322
1323   texFormat = img->TexFormat;
1324
1325   switch (pname) {
1326      case GL_TEXTURE_WIDTH:
1327         *params = img->Width;
1328         break;
1329      case GL_TEXTURE_HEIGHT:
1330         *params = img->Height;
1331         break;
1332      case GL_TEXTURE_DEPTH:
1333         *params = img->Depth;
1334         break;
1335      case GL_TEXTURE_INTERNAL_FORMAT:
1336         if (_mesa_is_format_compressed(texFormat)) {
1337            /* need to return the actual compressed format */
1338            *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
1339         }
1340         else {
1341	    /* If the true internal format is not compressed but the user
1342	     * requested a generic compressed format, we have to return the
1343	     * generic base format that matches.
1344	     *
1345	     * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
1346	     *
1347	     *     "If no specific compressed format is available,
1348	     *     internalformat is instead replaced by the corresponding base
1349	     *     internal format."
1350	     *
1351	     * Otherwise just return the user's requested internal format
1352	     */
1353	    const GLenum f =
1354	       _mesa_gl_compressed_format_base_format(img->InternalFormat);
1355
1356	    *params = (f != 0) ? f : img->InternalFormat;
1357	 }
1358         break;
1359      case GL_TEXTURE_BORDER:
1360         if (ctx->API != API_OPENGL_COMPAT)
1361            goto invalid_pname;
1362         *params = img->Border;
1363         break;
1364      case GL_TEXTURE_RED_SIZE:
1365      case GL_TEXTURE_GREEN_SIZE:
1366      case GL_TEXTURE_BLUE_SIZE:
1367      case GL_TEXTURE_ALPHA_SIZE:
1368         if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1369            *params = _mesa_get_format_bits(texFormat, pname);
1370         else
1371            *params = 0;
1372         break;
1373      case GL_TEXTURE_INTENSITY_SIZE:
1374      case GL_TEXTURE_LUMINANCE_SIZE:
1375         if (ctx->API != API_OPENGL_COMPAT)
1376            goto invalid_pname;
1377         if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
1378            *params = _mesa_get_format_bits(texFormat, pname);
1379            if (*params == 0) {
1380               /* intensity or luminance is probably stored as RGB[A] */
1381               *params = MIN2(_mesa_get_format_bits(texFormat,
1382                                                    GL_TEXTURE_RED_SIZE),
1383                              _mesa_get_format_bits(texFormat,
1384                                                    GL_TEXTURE_GREEN_SIZE));
1385            }
1386         }
1387         else {
1388            *params = 0;
1389         }
1390         break;
1391      case GL_TEXTURE_DEPTH_SIZE_ARB:
1392         if (!ctx->Extensions.ARB_depth_texture)
1393            goto invalid_pname;
1394         *params = _mesa_get_format_bits(texFormat, pname);
1395         break;
1396      case GL_TEXTURE_STENCIL_SIZE:
1397         *params = _mesa_get_format_bits(texFormat, pname);
1398         break;
1399      case GL_TEXTURE_SHARED_SIZE:
1400         if (ctx->Version < 30 &&
1401             !ctx->Extensions.EXT_texture_shared_exponent)
1402            goto invalid_pname;
1403         *params = texFormat == MESA_FORMAT_R9G9B9E5_FLOAT ? 5 : 0;
1404         break;
1405
1406      /* GL_ARB_texture_compression */
1407      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1408	 if (_mesa_is_format_compressed(texFormat) &&
1409             !_mesa_is_proxy_texture(target)) {
1410            *params = _mesa_format_image_size(texFormat, img->Width,
1411                                              img->Height, img->Depth);
1412    }
1413    else {
1414       _mesa_error(ctx, GL_INVALID_OPERATION,
1415                   "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1416                   _mesa_enum_to_string(pname));
1417    }
1418         break;
1419      case GL_TEXTURE_COMPRESSED:
1420         *params = (GLint) _mesa_is_format_compressed(texFormat);
1421         break;
1422
1423      /* GL_ARB_texture_float */
1424      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1425      case GL_TEXTURE_INTENSITY_TYPE_ARB:
1426         if (ctx->API != API_OPENGL_COMPAT)
1427            goto invalid_pname;
1428         /* FALLTHROUGH */
1429      case GL_TEXTURE_RED_TYPE_ARB:
1430      case GL_TEXTURE_GREEN_TYPE_ARB:
1431      case GL_TEXTURE_BLUE_TYPE_ARB:
1432      case GL_TEXTURE_ALPHA_TYPE_ARB:
1433      case GL_TEXTURE_DEPTH_TYPE_ARB:
1434         if (!ctx->Extensions.ARB_texture_float)
1435            goto invalid_pname;
1436	 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1437	    *params = _mesa_get_format_datatype(texFormat);
1438	 else
1439	    *params = GL_NONE;
1440         break;
1441
1442      /* GL_ARB_texture_multisample */
1443      case GL_TEXTURE_SAMPLES:
1444         if (!ctx->Extensions.ARB_texture_multisample)
1445            goto invalid_pname;
1446         *params = img->NumSamples;
1447         break;
1448
1449      case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
1450         if (!ctx->Extensions.ARB_texture_multisample)
1451            goto invalid_pname;
1452         *params = img->FixedSampleLocations;
1453         break;
1454
1455      /* There is never a buffer data store here, but these pnames still have
1456       * to work.
1457       */
1458
1459      /* GL_ARB_texture_buffer_object */
1460      case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
1461         if (!ctx->Extensions.ARB_texture_buffer_object)
1462            goto invalid_pname;
1463         *params = 0;
1464         break;
1465
1466      /* GL_ARB_texture_buffer_range */
1467      case GL_TEXTURE_BUFFER_OFFSET:
1468         if (!ctx->Extensions.ARB_texture_buffer_range)
1469            goto invalid_pname;
1470         *params = 0;
1471         break;
1472      case GL_TEXTURE_BUFFER_SIZE:
1473         if (!ctx->Extensions.ARB_texture_buffer_range)
1474            goto invalid_pname;
1475         *params = 0;
1476         break;
1477
1478      default:
1479         goto invalid_pname;
1480   }
1481
1482   /* no error if we get here */
1483   return;
1484
1485invalid_pname:
1486   _mesa_error(ctx, GL_INVALID_ENUM,
1487               "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1488               _mesa_enum_to_string(pname));
1489}
1490
1491
1492/**
1493 * Handle a glGetTexLevelParamteriv() call for a texture buffer.
1494 */
1495static void
1496get_tex_level_parameter_buffer(struct gl_context *ctx,
1497                               const struct gl_texture_object *texObj,
1498                               GLenum pname, GLint *params, bool dsa)
1499{
1500   const struct gl_buffer_object *bo = texObj->BufferObject;
1501   mesa_format texFormat = texObj->_BufferObjectFormat;
1502   int bytes = MAX2(1, _mesa_get_format_bytes(texFormat));
1503   GLenum internalFormat = texObj->BufferObjectFormat;
1504   GLenum baseFormat = _mesa_get_format_base_format(texFormat);
1505   const char *suffix = dsa ? "ture" : "";
1506
1507   assert(texObj->Target == GL_TEXTURE_BUFFER);
1508
1509   if (!bo) {
1510      /* undefined texture buffer object */
1511      switch (pname) {
1512      case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
1513         *params = GL_TRUE;
1514         break;
1515      case GL_TEXTURE_INTERNAL_FORMAT:
1516         *params = internalFormat;
1517         break;
1518      default:
1519         *params = 0;
1520         break;
1521      }
1522      return;
1523   }
1524
1525   switch (pname) {
1526      case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
1527         *params = bo->Name;
1528         break;
1529      case GL_TEXTURE_WIDTH:
1530         *params = ((texObj->BufferSize == -1) ? bo->Size : texObj->BufferSize)
1531            / bytes;
1532         break;
1533      case GL_TEXTURE_HEIGHT:
1534      case GL_TEXTURE_DEPTH:
1535         *params = 1;
1536         break;
1537      case GL_TEXTURE_BORDER:
1538      case GL_TEXTURE_SHARED_SIZE:
1539      case GL_TEXTURE_COMPRESSED:
1540         *params = 0;
1541         break;
1542      case GL_TEXTURE_INTERNAL_FORMAT:
1543         *params = internalFormat;
1544         break;
1545      case GL_TEXTURE_RED_SIZE:
1546      case GL_TEXTURE_GREEN_SIZE:
1547      case GL_TEXTURE_BLUE_SIZE:
1548      case GL_TEXTURE_ALPHA_SIZE:
1549         if (_mesa_base_format_has_channel(baseFormat, pname))
1550            *params = _mesa_get_format_bits(texFormat, pname);
1551         else
1552            *params = 0;
1553         break;
1554      case GL_TEXTURE_INTENSITY_SIZE:
1555      case GL_TEXTURE_LUMINANCE_SIZE:
1556         if (_mesa_base_format_has_channel(baseFormat, pname)) {
1557            *params = _mesa_get_format_bits(texFormat, pname);
1558            if (*params == 0) {
1559               /* intensity or luminance is probably stored as RGB[A] */
1560               *params = MIN2(_mesa_get_format_bits(texFormat,
1561                                                    GL_TEXTURE_RED_SIZE),
1562                              _mesa_get_format_bits(texFormat,
1563                                                    GL_TEXTURE_GREEN_SIZE));
1564            }
1565         } else {
1566            *params = 0;
1567         }
1568         break;
1569      case GL_TEXTURE_DEPTH_SIZE_ARB:
1570      case GL_TEXTURE_STENCIL_SIZE_EXT:
1571         *params = _mesa_get_format_bits(texFormat, pname);
1572         break;
1573
1574      /* GL_ARB_texture_buffer_range */
1575      case GL_TEXTURE_BUFFER_OFFSET:
1576         if (!ctx->Extensions.ARB_texture_buffer_range)
1577            goto invalid_pname;
1578         *params = texObj->BufferOffset;
1579         break;
1580      case GL_TEXTURE_BUFFER_SIZE:
1581         if (!ctx->Extensions.ARB_texture_buffer_range)
1582            goto invalid_pname;
1583         *params = (texObj->BufferSize == -1) ? bo->Size : texObj->BufferSize;
1584         break;
1585
1586      /* GL_ARB_texture_multisample */
1587      case GL_TEXTURE_SAMPLES:
1588         if (!ctx->Extensions.ARB_texture_multisample)
1589            goto invalid_pname;
1590         *params = 0;
1591         break;
1592
1593      case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
1594         if (!ctx->Extensions.ARB_texture_multisample)
1595            goto invalid_pname;
1596         *params = GL_TRUE;
1597         break;
1598
1599      /* GL_ARB_texture_compression */
1600      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1601         /* Always illegal for GL_TEXTURE_BUFFER */
1602         _mesa_error(ctx, GL_INVALID_OPERATION,
1603                     "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1604                     _mesa_enum_to_string(pname));
1605         break;
1606
1607      /* GL_ARB_texture_float */
1608      case GL_TEXTURE_RED_TYPE_ARB:
1609      case GL_TEXTURE_GREEN_TYPE_ARB:
1610      case GL_TEXTURE_BLUE_TYPE_ARB:
1611      case GL_TEXTURE_ALPHA_TYPE_ARB:
1612      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1613      case GL_TEXTURE_INTENSITY_TYPE_ARB:
1614      case GL_TEXTURE_DEPTH_TYPE_ARB:
1615         if (!ctx->Extensions.ARB_texture_float)
1616            goto invalid_pname;
1617         if (_mesa_base_format_has_channel(baseFormat, pname))
1618            *params = _mesa_get_format_datatype(texFormat);
1619         else
1620            *params = GL_NONE;
1621         break;
1622
1623      default:
1624         goto invalid_pname;
1625   }
1626
1627   /* no error if we get here */
1628   return;
1629
1630invalid_pname:
1631   _mesa_error(ctx, GL_INVALID_ENUM,
1632               "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1633               _mesa_enum_to_string(pname));
1634}
1635
1636static bool
1637valid_tex_level_parameteriv_target(struct gl_context *ctx, GLenum target,
1638                                   bool dsa)
1639{
1640   const char *suffix = dsa ? "ture" : "";
1641   if (!_mesa_legal_get_tex_level_parameter_target(ctx, target, dsa)) {
1642      _mesa_error(ctx, GL_INVALID_ENUM,
1643                  "glGetTex%sLevelParameter[if]v(target=%s)", suffix,
1644                  _mesa_enum_to_string(target));
1645      return false;
1646   }
1647   return true;
1648}
1649
1650/**
1651 * This isn't exposed to the rest of the driver because it is a part of the
1652 * OpenGL API that is rarely used.
1653 */
1654static void
1655get_tex_level_parameteriv(struct gl_context *ctx,
1656                          struct gl_texture_object *texObj,
1657                          GLenum target, GLint level,
1658                          GLenum pname, GLint *params,
1659                          bool dsa)
1660{
1661   GLint maxLevels;
1662   const char *suffix = dsa ? "ture" : "";
1663
1664   /* Check for errors */
1665   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
1666      _mesa_error(ctx, GL_INVALID_OPERATION,
1667                  "glGetTex%sLevelParameter[if]v("
1668                  "current unit >= max combined texture units)", suffix);
1669      return;
1670   }
1671
1672   maxLevels = _mesa_max_texture_levels(ctx, target);
1673   assert(maxLevels != 0);
1674
1675   if (level < 0 || level >= maxLevels) {
1676      _mesa_error(ctx, GL_INVALID_VALUE,
1677                  "glGetTex%sLevelParameter[if]v(level out of range)", suffix);
1678      return;
1679   }
1680
1681   /* Get the level parameter */
1682   if (target == GL_TEXTURE_BUFFER) {
1683      get_tex_level_parameter_buffer(ctx, texObj, pname, params, dsa);
1684   }
1685   else {
1686      get_tex_level_parameter_image(ctx, texObj, target,
1687                                    level, pname, params, dsa);
1688   }
1689}
1690
1691void GLAPIENTRY
1692_mesa_GetTexLevelParameterfv( GLenum target, GLint level,
1693                              GLenum pname, GLfloat *params )
1694{
1695   struct gl_texture_object *texObj;
1696   GLint iparam;
1697   GET_CURRENT_CONTEXT(ctx);
1698
1699   if (!valid_tex_level_parameteriv_target(ctx, target, false))
1700      return;
1701
1702   texObj = _mesa_get_current_tex_object(ctx, target);
1703   if (!texObj)
1704      return;
1705
1706   get_tex_level_parameteriv(ctx, texObj, target, level,
1707                             pname, &iparam, false);
1708
1709   *params = (GLfloat) iparam;
1710}
1711
1712void GLAPIENTRY
1713_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
1714                              GLenum pname, GLint *params )
1715{
1716   struct gl_texture_object *texObj;
1717   GET_CURRENT_CONTEXT(ctx);
1718
1719   if (!valid_tex_level_parameteriv_target(ctx, target, false))
1720      return;
1721
1722   texObj = _mesa_get_current_tex_object(ctx, target);
1723   if (!texObj)
1724      return;
1725
1726   get_tex_level_parameteriv(ctx, texObj, target, level,
1727                             pname, params, false);
1728}
1729
1730void GLAPIENTRY
1731_mesa_GetTextureLevelParameterfv(GLuint texture, GLint level,
1732                                 GLenum pname, GLfloat *params)
1733{
1734   struct gl_texture_object *texObj;
1735   GLint iparam;
1736   GET_CURRENT_CONTEXT(ctx);
1737
1738   texObj = _mesa_lookup_texture_err(ctx, texture,
1739                                     "glGetTextureLevelParameterfv");
1740   if (!texObj)
1741      return;
1742
1743   if (!valid_tex_level_parameteriv_target(ctx, texObj->Target, true))
1744      return;
1745
1746   get_tex_level_parameteriv(ctx, texObj, texObj->Target, level,
1747                             pname, &iparam, true);
1748
1749   *params = (GLfloat) iparam;
1750}
1751
1752void GLAPIENTRY
1753_mesa_GetTextureLevelParameteriv(GLuint texture, GLint level,
1754                                 GLenum pname, GLint *params)
1755{
1756   struct gl_texture_object *texObj;
1757   GET_CURRENT_CONTEXT(ctx);
1758
1759   texObj = _mesa_lookup_texture_err(ctx, texture,
1760                                     "glGetTextureLevelParameteriv");
1761   if (!texObj)
1762      return;
1763
1764   if (!valid_tex_level_parameteriv_target(ctx, texObj->Target, true))
1765      return;
1766
1767   get_tex_level_parameteriv(ctx, texObj, texObj->Target, level,
1768                             pname, params, true);
1769}
1770
1771/**
1772 * This isn't exposed to the rest of the driver because it is a part of the
1773 * OpenGL API that is rarely used.
1774 */
1775static void
1776get_tex_parameterfv(struct gl_context *ctx,
1777                    struct gl_texture_object *obj,
1778                    GLenum pname, GLfloat *params, bool dsa)
1779{
1780   _mesa_lock_context_textures(ctx);
1781   switch (pname) {
1782      case GL_TEXTURE_MAG_FILTER:
1783	 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
1784	 break;
1785      case GL_TEXTURE_MIN_FILTER:
1786         *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter);
1787         break;
1788      case GL_TEXTURE_WRAP_S:
1789         *params = ENUM_TO_FLOAT(obj->Sampler.WrapS);
1790         break;
1791      case GL_TEXTURE_WRAP_T:
1792         *params = ENUM_TO_FLOAT(obj->Sampler.WrapT);
1793         break;
1794      case GL_TEXTURE_WRAP_R:
1795         *params = ENUM_TO_FLOAT(obj->Sampler.WrapR);
1796         break;
1797      case GL_TEXTURE_BORDER_COLOR:
1798         if (ctx->API == API_OPENGLES ||
1799             !ctx->Extensions.ARB_texture_border_clamp)
1800            goto invalid_pname;
1801
1802         if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
1803            _mesa_update_state_locked(ctx);
1804         if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) {
1805            params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1806            params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1807            params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1808            params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1809         }
1810         else {
1811            params[0] = obj->Sampler.BorderColor.f[0];
1812            params[1] = obj->Sampler.BorderColor.f[1];
1813            params[2] = obj->Sampler.BorderColor.f[2];
1814            params[3] = obj->Sampler.BorderColor.f[3];
1815         }
1816         break;
1817      case GL_TEXTURE_RESIDENT:
1818         if (ctx->API != API_OPENGL_COMPAT)
1819            goto invalid_pname;
1820
1821         *params = 1.0F;
1822         break;
1823      case GL_TEXTURE_PRIORITY:
1824         if (ctx->API != API_OPENGL_COMPAT)
1825            goto invalid_pname;
1826
1827         *params = obj->Priority;
1828         break;
1829      case GL_TEXTURE_MIN_LOD:
1830         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1831            goto invalid_pname;
1832
1833         *params = obj->Sampler.MinLod;
1834         break;
1835      case GL_TEXTURE_MAX_LOD:
1836         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1837            goto invalid_pname;
1838
1839         *params = obj->Sampler.MaxLod;
1840         break;
1841      case GL_TEXTURE_BASE_LEVEL:
1842         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1843            goto invalid_pname;
1844
1845         *params = (GLfloat) obj->BaseLevel;
1846         break;
1847      case GL_TEXTURE_MAX_LEVEL:
1848         *params = (GLfloat) obj->MaxLevel;
1849         break;
1850      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1851         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1852            goto invalid_pname;
1853         *params = obj->Sampler.MaxAnisotropy;
1854         break;
1855      case GL_GENERATE_MIPMAP_SGIS:
1856         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
1857            goto invalid_pname;
1858
1859	 *params = (GLfloat) obj->GenerateMipmap;
1860         break;
1861      case GL_TEXTURE_COMPARE_MODE_ARB:
1862         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1863             && !_mesa_is_gles3(ctx))
1864            goto invalid_pname;
1865         *params = (GLfloat) obj->Sampler.CompareMode;
1866         break;
1867      case GL_TEXTURE_COMPARE_FUNC_ARB:
1868         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1869             && !_mesa_is_gles3(ctx))
1870            goto invalid_pname;
1871         *params = (GLfloat) obj->Sampler.CompareFunc;
1872         break;
1873      case GL_DEPTH_TEXTURE_MODE_ARB:
1874         /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has
1875          * never existed in OpenGL ES.
1876          */
1877         if (ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_depth_texture)
1878            goto invalid_pname;
1879         *params = (GLfloat) obj->DepthMode;
1880         break;
1881      case GL_DEPTH_STENCIL_TEXTURE_MODE:
1882         if (!_mesa_has_ARB_stencil_texturing(ctx) && !_mesa_is_gles31(ctx))
1883            goto invalid_pname;
1884         *params = (GLfloat)
1885            (obj->StencilSampling ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT);
1886         break;
1887      case GL_TEXTURE_LOD_BIAS:
1888         if (_mesa_is_gles(ctx))
1889            goto invalid_pname;
1890
1891         *params = obj->Sampler.LodBias;
1892         break;
1893      case GL_TEXTURE_CROP_RECT_OES:
1894         if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
1895            goto invalid_pname;
1896
1897         params[0] = (GLfloat) obj->CropRect[0];
1898         params[1] = (GLfloat) obj->CropRect[1];
1899         params[2] = (GLfloat) obj->CropRect[2];
1900         params[3] = (GLfloat) obj->CropRect[3];
1901         break;
1902
1903      case GL_TEXTURE_SWIZZLE_R_EXT:
1904      case GL_TEXTURE_SWIZZLE_G_EXT:
1905      case GL_TEXTURE_SWIZZLE_B_EXT:
1906      case GL_TEXTURE_SWIZZLE_A_EXT:
1907         if ((!_mesa_is_desktop_gl(ctx)
1908              || !ctx->Extensions.EXT_texture_swizzle)
1909             && !_mesa_is_gles3(ctx))
1910            goto invalid_pname;
1911         *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1912         break;
1913
1914      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1915         if ((!_mesa_is_desktop_gl(ctx)
1916              || !ctx->Extensions.EXT_texture_swizzle)
1917             && !_mesa_is_gles3(ctx)) {
1918            goto invalid_pname;
1919         }
1920         else {
1921            GLuint comp;
1922            for (comp = 0; comp < 4; comp++) {
1923               params[comp] = (GLfloat) obj->Swizzle[comp];
1924            }
1925         }
1926         break;
1927
1928      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1929         if (!_mesa_is_desktop_gl(ctx)
1930             || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
1931            goto invalid_pname;
1932         *params = (GLfloat) obj->Sampler.CubeMapSeamless;
1933         break;
1934
1935      case GL_TEXTURE_IMMUTABLE_FORMAT:
1936         *params = (GLfloat) obj->Immutable;
1937         break;
1938
1939      case GL_TEXTURE_IMMUTABLE_LEVELS:
1940         if (_mesa_is_gles3(ctx) ||
1941             (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_view))
1942            *params = (GLfloat) obj->ImmutableLevels;
1943         else
1944            goto invalid_pname;
1945         break;
1946
1947      case GL_TEXTURE_VIEW_MIN_LEVEL:
1948         if (!ctx->Extensions.ARB_texture_view)
1949            goto invalid_pname;
1950         *params = (GLfloat) obj->MinLevel;
1951         break;
1952
1953      case GL_TEXTURE_VIEW_NUM_LEVELS:
1954         if (!ctx->Extensions.ARB_texture_view)
1955            goto invalid_pname;
1956         *params = (GLfloat) obj->NumLevels;
1957         break;
1958
1959      case GL_TEXTURE_VIEW_MIN_LAYER:
1960         if (!ctx->Extensions.ARB_texture_view)
1961            goto invalid_pname;
1962         *params = (GLfloat) obj->MinLayer;
1963         break;
1964
1965      case GL_TEXTURE_VIEW_NUM_LAYERS:
1966         if (!ctx->Extensions.ARB_texture_view)
1967            goto invalid_pname;
1968         *params = (GLfloat) obj->NumLayers;
1969         break;
1970
1971      case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1972         if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)
1973            goto invalid_pname;
1974         *params = (GLfloat) obj->RequiredTextureImageUnits;
1975         break;
1976
1977      case GL_TEXTURE_SRGB_DECODE_EXT:
1978         if (!ctx->Extensions.EXT_texture_sRGB_decode)
1979            goto invalid_pname;
1980         *params = (GLfloat) obj->Sampler.sRGBDecode;
1981         break;
1982
1983      case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
1984         if (!ctx->Extensions.ARB_shader_image_load_store)
1985            goto invalid_pname;
1986         *params = (GLfloat) obj->ImageFormatCompatibilityType;
1987         break;
1988
1989      case GL_TEXTURE_TARGET:
1990         if (ctx->API != API_OPENGL_CORE)
1991            goto invalid_pname;
1992         *params = ENUM_TO_FLOAT(obj->Target);
1993         break;
1994
1995      default:
1996         goto invalid_pname;
1997   }
1998
1999   /* no error if we get here */
2000   _mesa_unlock_context_textures(ctx);
2001   return;
2002
2003invalid_pname:
2004   _mesa_unlock_context_textures(ctx);
2005   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sParameterfv(pname=0x%x)",
2006               dsa ? "ture" : "", pname);
2007}
2008
2009
2010static void
2011get_tex_parameteriv(struct gl_context *ctx,
2012                    struct gl_texture_object *obj,
2013                    GLenum pname, GLint *params, bool dsa)
2014{
2015   _mesa_lock_texture(ctx, obj);
2016   switch (pname) {
2017      case GL_TEXTURE_MAG_FILTER:
2018         *params = (GLint) obj->Sampler.MagFilter;
2019         break;
2020      case GL_TEXTURE_MIN_FILTER:
2021         *params = (GLint) obj->Sampler.MinFilter;
2022         break;
2023      case GL_TEXTURE_WRAP_S:
2024         *params = (GLint) obj->Sampler.WrapS;
2025         break;
2026      case GL_TEXTURE_WRAP_T:
2027         *params = (GLint) obj->Sampler.WrapT;
2028         break;
2029      case GL_TEXTURE_WRAP_R:
2030         *params = (GLint) obj->Sampler.WrapR;
2031         break;
2032      case GL_TEXTURE_BORDER_COLOR:
2033         if (ctx->API == API_OPENGLES ||
2034             !ctx->Extensions.ARB_texture_border_clamp)
2035            goto invalid_pname;
2036
2037         {
2038            GLfloat b[4];
2039            b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
2040            b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
2041            b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
2042            b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
2043            params[0] = FLOAT_TO_INT(b[0]);
2044            params[1] = FLOAT_TO_INT(b[1]);
2045            params[2] = FLOAT_TO_INT(b[2]);
2046            params[3] = FLOAT_TO_INT(b[3]);
2047         }
2048         break;
2049      case GL_TEXTURE_RESIDENT:
2050         if (ctx->API != API_OPENGL_COMPAT)
2051            goto invalid_pname;
2052
2053         *params = 1;
2054         break;
2055      case GL_TEXTURE_PRIORITY:
2056         if (ctx->API != API_OPENGL_COMPAT)
2057            goto invalid_pname;
2058
2059         *params = FLOAT_TO_INT(obj->Priority);
2060         break;
2061      case GL_TEXTURE_MIN_LOD:
2062         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
2063            goto invalid_pname;
2064         /* GL spec 'Data Conversions' section specifies that floating-point
2065          * value in integer Get function is rounded to nearest integer
2066          */
2067         *params = IROUND(obj->Sampler.MinLod);
2068         break;
2069      case GL_TEXTURE_MAX_LOD:
2070         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
2071            goto invalid_pname;
2072         /* GL spec 'Data Conversions' section specifies that floating-point
2073          * value in integer Get function is rounded to nearest integer
2074          */
2075         *params = IROUND(obj->Sampler.MaxLod);
2076         break;
2077      case GL_TEXTURE_BASE_LEVEL:
2078         if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
2079            goto invalid_pname;
2080
2081         *params = obj->BaseLevel;
2082         break;
2083      case GL_TEXTURE_MAX_LEVEL:
2084         *params = obj->MaxLevel;
2085         break;
2086      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
2087         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
2088            goto invalid_pname;
2089         /* GL spec 'Data Conversions' section specifies that floating-point
2090          * value in integer Get function is rounded to nearest integer
2091          */
2092         *params = IROUND(obj->Sampler.MaxAnisotropy);
2093         break;
2094      case GL_GENERATE_MIPMAP_SGIS:
2095         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
2096            goto invalid_pname;
2097
2098	 *params = (GLint) obj->GenerateMipmap;
2099         break;
2100      case GL_TEXTURE_COMPARE_MODE_ARB:
2101         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
2102             && !_mesa_is_gles3(ctx))
2103            goto invalid_pname;
2104         *params = (GLint) obj->Sampler.CompareMode;
2105         break;
2106      case GL_TEXTURE_COMPARE_FUNC_ARB:
2107         if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
2108             && !_mesa_is_gles3(ctx))
2109            goto invalid_pname;
2110         *params = (GLint) obj->Sampler.CompareFunc;
2111         break;
2112      case GL_DEPTH_TEXTURE_MODE_ARB:
2113         if (ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_depth_texture)
2114            goto invalid_pname;
2115         *params = (GLint) obj->DepthMode;
2116         break;
2117      case GL_DEPTH_STENCIL_TEXTURE_MODE:
2118         if (!_mesa_has_ARB_stencil_texturing(ctx) && !_mesa_is_gles31(ctx))
2119            goto invalid_pname;
2120         *params = (GLint)
2121            (obj->StencilSampling ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT);
2122         break;
2123      case GL_TEXTURE_LOD_BIAS:
2124         if (_mesa_is_gles(ctx))
2125            goto invalid_pname;
2126
2127         /* GL spec 'Data Conversions' section specifies that floating-point
2128          * value in integer Get function is rounded to nearest integer
2129          */
2130         *params = IROUND(obj->Sampler.LodBias);
2131         break;
2132      case GL_TEXTURE_CROP_RECT_OES:
2133         if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
2134            goto invalid_pname;
2135
2136         params[0] = obj->CropRect[0];
2137         params[1] = obj->CropRect[1];
2138         params[2] = obj->CropRect[2];
2139         params[3] = obj->CropRect[3];
2140         break;
2141      case GL_TEXTURE_SWIZZLE_R_EXT:
2142      case GL_TEXTURE_SWIZZLE_G_EXT:
2143      case GL_TEXTURE_SWIZZLE_B_EXT:
2144      case GL_TEXTURE_SWIZZLE_A_EXT:
2145         if ((!_mesa_is_desktop_gl(ctx)
2146              || !ctx->Extensions.EXT_texture_swizzle)
2147             && !_mesa_is_gles3(ctx))
2148            goto invalid_pname;
2149         *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
2150         break;
2151
2152      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
2153         if ((!_mesa_is_desktop_gl(ctx)
2154              || !ctx->Extensions.EXT_texture_swizzle)
2155             && !_mesa_is_gles3(ctx))
2156            goto invalid_pname;
2157         COPY_4V(params, obj->Swizzle);
2158         break;
2159
2160      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
2161         if (!_mesa_is_desktop_gl(ctx)
2162             || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
2163            goto invalid_pname;
2164         *params = (GLint) obj->Sampler.CubeMapSeamless;
2165         break;
2166
2167      case GL_TEXTURE_IMMUTABLE_FORMAT:
2168         *params = (GLint) obj->Immutable;
2169         break;
2170
2171      case GL_TEXTURE_IMMUTABLE_LEVELS:
2172         if (_mesa_is_gles3(ctx) ||
2173             (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_view))
2174            *params = obj->ImmutableLevels;
2175         else
2176            goto invalid_pname;
2177         break;
2178
2179      case GL_TEXTURE_VIEW_MIN_LEVEL:
2180         if (!ctx->Extensions.ARB_texture_view)
2181            goto invalid_pname;
2182         *params = (GLint) obj->MinLevel;
2183         break;
2184
2185      case GL_TEXTURE_VIEW_NUM_LEVELS:
2186         if (!ctx->Extensions.ARB_texture_view)
2187            goto invalid_pname;
2188         *params = (GLint) obj->NumLevels;
2189         break;
2190
2191      case GL_TEXTURE_VIEW_MIN_LAYER:
2192         if (!ctx->Extensions.ARB_texture_view)
2193            goto invalid_pname;
2194         *params = (GLint) obj->MinLayer;
2195         break;
2196
2197      case GL_TEXTURE_VIEW_NUM_LAYERS:
2198         if (!ctx->Extensions.ARB_texture_view)
2199            goto invalid_pname;
2200         *params = (GLint) obj->NumLayers;
2201         break;
2202
2203      case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2204         if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)
2205            goto invalid_pname;
2206         *params = obj->RequiredTextureImageUnits;
2207         break;
2208
2209      case GL_TEXTURE_SRGB_DECODE_EXT:
2210         if (!ctx->Extensions.EXT_texture_sRGB_decode)
2211            goto invalid_pname;
2212         *params = obj->Sampler.sRGBDecode;
2213         break;
2214
2215      case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
2216         if (!ctx->Extensions.ARB_shader_image_load_store)
2217            goto invalid_pname;
2218         *params = obj->ImageFormatCompatibilityType;
2219         break;
2220
2221      case GL_TEXTURE_TARGET:
2222         if (ctx->API != API_OPENGL_CORE)
2223            goto invalid_pname;
2224         *params = (GLint) obj->Target;
2225         break;
2226
2227      default:
2228         goto invalid_pname;
2229   }
2230
2231   /* no error if we get here */
2232   _mesa_unlock_texture(ctx, obj);
2233   return;
2234
2235invalid_pname:
2236   _mesa_unlock_texture(ctx, obj);
2237   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sParameteriv(pname=0x%x)",
2238               dsa ? "ture" : "", pname);
2239}
2240
2241static void
2242get_tex_parameterIiv(struct gl_context *ctx,
2243                     struct gl_texture_object *obj,
2244                     GLenum pname, GLint *params, bool dsa)
2245{
2246   switch (pname) {
2247   case GL_TEXTURE_BORDER_COLOR:
2248      COPY_4V(params, obj->Sampler.BorderColor.i);
2249      break;
2250   default:
2251      get_tex_parameteriv(ctx, obj, pname, params, dsa);
2252   }
2253}
2254
2255static void
2256get_tex_parameterIuiv(struct gl_context *ctx,
2257                      struct gl_texture_object *obj,
2258                      GLenum pname, GLuint *params, bool dsa)
2259{
2260   switch (pname) {
2261   case GL_TEXTURE_BORDER_COLOR:
2262      COPY_4V(params, obj->Sampler.BorderColor.i);
2263      break;
2264   default:
2265      {
2266         GLint ip[4];
2267         get_tex_parameteriv(ctx, obj, pname, ip, dsa);
2268         params[0] = ip[0];
2269         if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
2270             pname == GL_TEXTURE_CROP_RECT_OES) {
2271            params[1] = ip[1];
2272            params[2] = ip[2];
2273            params[3] = ip[3];
2274         }
2275      }
2276   }
2277}
2278
2279void GLAPIENTRY
2280_mesa_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
2281{
2282   struct gl_texture_object *obj;
2283   GET_CURRENT_CONTEXT(ctx);
2284
2285   obj = get_texobj_by_target(ctx, target, GL_TRUE);
2286   if (!obj)
2287      return;
2288
2289   get_tex_parameterfv(ctx, obj, pname, params, false);
2290}
2291
2292void GLAPIENTRY
2293_mesa_GetTexParameteriv(GLenum target, GLenum pname, GLint *params)
2294{
2295   struct gl_texture_object *obj;
2296   GET_CURRENT_CONTEXT(ctx);
2297
2298   obj = get_texobj_by_target(ctx, target, GL_TRUE);
2299   if (!obj)
2300      return;
2301
2302   get_tex_parameteriv(ctx, obj, pname, params, false);
2303}
2304
2305/** New in GL 3.0 */
2306void GLAPIENTRY
2307_mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
2308{
2309   struct gl_texture_object *texObj;
2310   GET_CURRENT_CONTEXT(ctx);
2311
2312   texObj = get_texobj_by_target(ctx, target, GL_TRUE);
2313   if (!texObj)
2314      return;
2315
2316   get_tex_parameterIiv(ctx, texObj, pname, params, false);
2317}
2318
2319
2320/** New in GL 3.0 */
2321void GLAPIENTRY
2322_mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
2323{
2324   struct gl_texture_object *texObj;
2325   GET_CURRENT_CONTEXT(ctx);
2326
2327   texObj = get_texobj_by_target(ctx, target, GL_TRUE);
2328   if (!texObj)
2329      return;
2330
2331   get_tex_parameterIuiv(ctx, texObj, pname, params, false);
2332}
2333
2334
2335void GLAPIENTRY
2336_mesa_GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat *params)
2337{
2338   struct gl_texture_object *obj;
2339   GET_CURRENT_CONTEXT(ctx);
2340
2341   obj = get_texobj_by_name(ctx, texture, GL_TRUE);
2342   if (!obj) {
2343      /* User passed a non-generated name. */
2344      _mesa_error(ctx, GL_INVALID_OPERATION,
2345                  "glGetTextureParameterfv(texture)");
2346      return;
2347   }
2348
2349   get_tex_parameterfv(ctx, obj, pname, params, true);
2350}
2351
2352void GLAPIENTRY
2353_mesa_GetTextureParameteriv(GLuint texture, GLenum pname, GLint *params)
2354{
2355   struct gl_texture_object *obj;
2356   GET_CURRENT_CONTEXT(ctx);
2357
2358   obj = get_texobj_by_name(ctx, texture, GL_TRUE);
2359   if (!obj) {
2360      /* User passed a non-generated name. */
2361      _mesa_error(ctx, GL_INVALID_OPERATION,
2362                  "glGetTextureParameteriv(texture)");
2363      return;
2364   }
2365
2366   get_tex_parameteriv(ctx, obj, pname, params, true);
2367}
2368
2369void GLAPIENTRY
2370_mesa_GetTextureParameterIiv(GLuint texture, GLenum pname, GLint *params)
2371{
2372   struct gl_texture_object *texObj;
2373   GET_CURRENT_CONTEXT(ctx);
2374
2375   texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
2376   if (!texObj) {
2377      /* User passed a non-generated name. */
2378      _mesa_error(ctx, GL_INVALID_OPERATION,
2379                  "glGetTextureParameterIiv(texture)");
2380      return;
2381   }
2382
2383   get_tex_parameterIiv(ctx, texObj, pname, params, true);
2384}
2385
2386
2387void GLAPIENTRY
2388_mesa_GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint *params)
2389{
2390   struct gl_texture_object *texObj;
2391   GET_CURRENT_CONTEXT(ctx);
2392
2393   texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
2394   if (!texObj) {
2395      /* User passed a non-generated name. */
2396      _mesa_error(ctx, GL_INVALID_OPERATION,
2397                  "glGetTextureParameterIuiv(texture)");
2398      return;
2399   }
2400
2401   get_tex_parameterIuiv(ctx, texObj, pname, params, true);
2402}
2403