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  */
55 static GLboolean
validate_texture_wrap_mode(struct gl_context * ctx,GLenum target,GLenum wrap)56 validate_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  */
119 static struct gl_texture_object *
get_texobj(struct gl_context * ctx,GLenum target,GLboolean get)120 get_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  */
187 static GLint
comp_to_swizzle(GLenum comp)188 comp_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 
209 static void
set_swizzle_component(GLuint * swizzle,GLuint comp,GLuint swz)210 set_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  */
226 static inline void
flush(struct gl_context * ctx)227 flush(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  */
240 static inline void
incomplete(struct gl_context * ctx,struct gl_texture_object * texObj)241 incomplete(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  */
252 static GLboolean
set_tex_parameteri(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum pname,const GLint * params)253 set_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 
519 invalid_pname:
520    _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
521                _mesa_lookup_enum_by_nr(pname));
522    return GL_FALSE;
523 
524 invalid_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  */
535 static GLboolean
set_tex_parameterf(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum pname,const GLfloat * params)536 set_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 
629 invalid_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 
636 void GLAPIENTRY
_mesa_TexParameterf(GLenum target,GLenum pname,GLfloat param)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 
697 void GLAPIENTRY
_mesa_TexParameterfv(GLenum target,GLenum pname,const GLfloat * params)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 
773 void GLAPIENTRY
_mesa_TexParameteri(GLenum target,GLenum pname,GLint param)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 
817 void GLAPIENTRY
_mesa_TexParameteriv(GLenum target,GLenum pname,const GLint * params)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  */
879 void GLAPIENTRY
_mesa_TexParameterIiv(GLenum target,GLenum pname,const GLint * params)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  */
909 void GLAPIENTRY
_mesa_TexParameterIuiv(GLenum target,GLenum pname,const GLuint * params)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 
934 static GLboolean
legal_get_tex_level_parameter_target(struct gl_context * ctx,GLenum target)935 legal_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 
987 static void
get_tex_level_parameter_image(struct gl_context * ctx,const struct gl_texture_object * texObj,GLenum target,GLint level,GLenum pname,GLint * params)988 get_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 
1127 invalid_pname:
1128    _mesa_error(ctx, GL_INVALID_ENUM,
1129                "glGetTexLevelParameter[if]v(pname=%s)",
1130                _mesa_lookup_enum_by_nr(pname));
1131 }
1132 
1133 
1134 static void
get_tex_level_parameter_buffer(struct gl_context * ctx,const struct gl_texture_object * texObj,GLenum pname,GLint * params)1135 get_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 
1226 invalid_pname:
1227    _mesa_error(ctx, GL_INVALID_ENUM,
1228                "glGetTexLevelParameter[if]v(pname=%s)",
1229                _mesa_lookup_enum_by_nr(pname));
1230 }
1231 
1232 
1233 void GLAPIENTRY
_mesa_GetTexLevelParameterfv(GLenum target,GLint level,GLenum pname,GLfloat * params)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 
1243 void GLAPIENTRY
_mesa_GetTexLevelParameteriv(GLenum target,GLint level,GLenum pname,GLint * params)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 
1284 void GLAPIENTRY
_mesa_GetTexParameterfv(GLenum target,GLenum pname,GLfloat * params)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 
1465 invalid_pname:
1466    _mesa_unlock_texture(ctx, obj);
1467    _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
1468 }
1469 
1470 
1471 void GLAPIENTRY
_mesa_GetTexParameteriv(GLenum target,GLenum pname,GLint * params)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 
1645 invalid_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 */
1652 void GLAPIENTRY
_mesa_GetTexParameterIiv(GLenum target,GLenum pname,GLint * params)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 */
1674 void GLAPIENTRY
_mesa_GetTexParameterIuiv(GLenum target,GLenum pname,GLuint * params)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