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