mesa/es: Validate glTexParameter targets in Mesa code rather than the ES wrapper
[mesa.git] / src / mesa / main / texparam.c
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
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 *
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
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
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
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
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
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 (texObj->BaseLevel == params[0])
329 return GL_FALSE;
330 if (params[0] < 0 ||
331 (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
332 _mesa_error(ctx, GL_INVALID_VALUE,
333 "glTexParameter(param=%d)", params[0]);
334 return GL_FALSE;
335 }
336 incomplete(ctx, texObj);
337 texObj->BaseLevel = params[0];
338 return GL_TRUE;
339
340 case GL_TEXTURE_MAX_LEVEL:
341 if (texObj->MaxLevel == params[0])
342 return GL_FALSE;
343 if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
344 _mesa_error(ctx, GL_INVALID_OPERATION,
345 "glTexParameter(param=%d)", params[0]);
346 return GL_FALSE;
347 }
348 incomplete(ctx, texObj);
349 texObj->MaxLevel = params[0];
350 return GL_TRUE;
351
352 case GL_GENERATE_MIPMAP_SGIS:
353 if (params[0] && texObj->Target == GL_TEXTURE_EXTERNAL_OES)
354 goto invalid_param;
355 if (texObj->GenerateMipmap != params[0]) {
356 /* no flush() */
357 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
358 return GL_TRUE;
359 }
360 return GL_FALSE;
361
362 case GL_TEXTURE_COMPARE_MODE_ARB:
363 if (ctx->Extensions.ARB_shadow) {
364 if (texObj->Sampler.CompareMode == params[0])
365 return GL_FALSE;
366 if (params[0] == GL_NONE ||
367 params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
368 flush(ctx);
369 texObj->Sampler.CompareMode = params[0];
370 return GL_TRUE;
371 }
372 goto invalid_param;
373 }
374 goto invalid_pname;
375
376 case GL_TEXTURE_COMPARE_FUNC_ARB:
377 if (ctx->Extensions.ARB_shadow) {
378 if (texObj->Sampler.CompareFunc == params[0])
379 return GL_FALSE;
380 switch (params[0]) {
381 case GL_LEQUAL:
382 case GL_GEQUAL:
383 flush(ctx);
384 texObj->Sampler.CompareFunc = params[0];
385 return GL_TRUE;
386 case GL_EQUAL:
387 case GL_NOTEQUAL:
388 case GL_LESS:
389 case GL_GREATER:
390 case GL_ALWAYS:
391 case GL_NEVER:
392 if (ctx->Extensions.EXT_shadow_funcs) {
393 flush(ctx);
394 texObj->Sampler.CompareFunc = params[0];
395 return GL_TRUE;
396 }
397 /* fall-through */
398 default:
399 goto invalid_param;
400 }
401 }
402 goto invalid_pname;
403
404 case GL_DEPTH_TEXTURE_MODE_ARB:
405 if (ctx->Extensions.ARB_depth_texture) {
406 if (texObj->DepthMode == params[0])
407 return GL_FALSE;
408 if (params[0] == GL_LUMINANCE ||
409 params[0] == GL_INTENSITY ||
410 params[0] == GL_ALPHA ||
411 (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
412 flush(ctx);
413 texObj->DepthMode = params[0];
414 return GL_TRUE;
415 }
416 goto invalid_param;
417 }
418 goto invalid_pname;
419
420 #if FEATURE_OES_draw_texture
421 case GL_TEXTURE_CROP_RECT_OES:
422 texObj->CropRect[0] = params[0];
423 texObj->CropRect[1] = params[1];
424 texObj->CropRect[2] = params[2];
425 texObj->CropRect[3] = params[3];
426 return GL_TRUE;
427 #endif
428
429 case GL_TEXTURE_SWIZZLE_R_EXT:
430 case GL_TEXTURE_SWIZZLE_G_EXT:
431 case GL_TEXTURE_SWIZZLE_B_EXT:
432 case GL_TEXTURE_SWIZZLE_A_EXT:
433 if (ctx->Extensions.EXT_texture_swizzle) {
434 const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
435 const GLint swz = comp_to_swizzle(params[0]);
436 if (swz < 0) {
437 _mesa_error(ctx, GL_INVALID_OPERATION,
438 "glTexParameter(swizzle 0x%x)", params[0]);
439 return GL_FALSE;
440 }
441 ASSERT(comp < 4);
442
443 flush(ctx);
444 texObj->Swizzle[comp] = params[0];
445 set_swizzle_component(&texObj->_Swizzle, comp, swz);
446 return GL_TRUE;
447 }
448 goto invalid_pname;
449
450 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
451 if (ctx->Extensions.EXT_texture_swizzle) {
452 GLuint comp;
453 flush(ctx);
454 for (comp = 0; comp < 4; comp++) {
455 const GLint swz = comp_to_swizzle(params[comp]);
456 if (swz >= 0) {
457 texObj->Swizzle[comp] = params[comp];
458 set_swizzle_component(&texObj->_Swizzle, comp, swz);
459 }
460 else {
461 _mesa_error(ctx, GL_INVALID_OPERATION,
462 "glTexParameter(swizzle 0x%x)", params[comp]);
463 return GL_FALSE;
464 }
465 }
466 return GL_TRUE;
467 }
468 goto invalid_pname;
469
470 case GL_TEXTURE_SRGB_DECODE_EXT:
471 if (ctx->Extensions.EXT_texture_sRGB_decode) {
472 GLenum decode = params[0];
473 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
474 if (texObj->Sampler.sRGBDecode != decode) {
475 flush(ctx);
476 texObj->Sampler.sRGBDecode = decode;
477 }
478 return GL_TRUE;
479 }
480 }
481 goto invalid_pname;
482
483 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
484 if (ctx->Extensions.AMD_seamless_cubemap_per_texture) {
485 GLenum param = params[0];
486 if (param != GL_TRUE && param != GL_FALSE) {
487 goto invalid_param;
488 }
489 if (param != texObj->Sampler.CubeMapSeamless) {
490 flush(ctx);
491 texObj->Sampler.CubeMapSeamless = param;
492 }
493 return GL_TRUE;
494 }
495 goto invalid_pname;
496
497 default:
498 goto invalid_pname;
499 }
500
501 invalid_pname:
502 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
503 _mesa_lookup_enum_by_nr(pname));
504 return GL_FALSE;
505
506 invalid_param:
507 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)",
508 _mesa_lookup_enum_by_nr(params[0]));
509 return GL_FALSE;
510 }
511
512
513 /**
514 * Set a float-valued texture parameter
515 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
516 */
517 static GLboolean
518 set_tex_parameterf(struct gl_context *ctx,
519 struct gl_texture_object *texObj,
520 GLenum pname, const GLfloat *params)
521 {
522 switch (pname) {
523 case GL_TEXTURE_MIN_LOD:
524 if (texObj->Sampler.MinLod == params[0])
525 return GL_FALSE;
526 flush(ctx);
527 texObj->Sampler.MinLod = params[0];
528 return GL_TRUE;
529
530 case GL_TEXTURE_MAX_LOD:
531 if (texObj->Sampler.MaxLod == params[0])
532 return GL_FALSE;
533 flush(ctx);
534 texObj->Sampler.MaxLod = params[0];
535 return GL_TRUE;
536
537 case GL_TEXTURE_PRIORITY:
538 flush(ctx);
539 texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
540 return GL_TRUE;
541
542 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
543 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
544 if (texObj->Sampler.MaxAnisotropy == params[0])
545 return GL_FALSE;
546 if (params[0] < 1.0) {
547 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
548 return GL_FALSE;
549 }
550 flush(ctx);
551 /* clamp to max, that's what NVIDIA does */
552 texObj->Sampler.MaxAnisotropy = MIN2(params[0],
553 ctx->Const.MaxTextureMaxAnisotropy);
554 return GL_TRUE;
555 }
556 else {
557 static GLuint count = 0;
558 if (count++ < 10)
559 _mesa_error(ctx, GL_INVALID_ENUM,
560 "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
561 }
562 return GL_FALSE;
563
564 case GL_TEXTURE_LOD_BIAS:
565 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */
566 if (texObj->Sampler.LodBias != params[0]) {
567 flush(ctx);
568 texObj->Sampler.LodBias = params[0];
569 return GL_TRUE;
570 }
571 break;
572
573 case GL_TEXTURE_BORDER_COLOR:
574 flush(ctx);
575 /* ARB_texture_float disables clamping */
576 if (ctx->Extensions.ARB_texture_float) {
577 texObj->Sampler.BorderColor.f[RCOMP] = params[0];
578 texObj->Sampler.BorderColor.f[GCOMP] = params[1];
579 texObj->Sampler.BorderColor.f[BCOMP] = params[2];
580 texObj->Sampler.BorderColor.f[ACOMP] = params[3];
581 } else {
582 texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F);
583 texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F);
584 texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F);
585 texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F);
586 }
587 return GL_TRUE;
588
589 default:
590 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
591 }
592 return GL_FALSE;
593 }
594
595
596 void GLAPIENTRY
597 _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
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, GL_FALSE);
605 if (!texObj)
606 return;
607
608 switch (pname) {
609 case GL_TEXTURE_MIN_FILTER:
610 case GL_TEXTURE_MAG_FILTER:
611 case GL_TEXTURE_WRAP_S:
612 case GL_TEXTURE_WRAP_T:
613 case GL_TEXTURE_WRAP_R:
614 case GL_TEXTURE_BASE_LEVEL:
615 case GL_TEXTURE_MAX_LEVEL:
616 case GL_GENERATE_MIPMAP_SGIS:
617 case GL_TEXTURE_COMPARE_MODE_ARB:
618 case GL_TEXTURE_COMPARE_FUNC_ARB:
619 case GL_DEPTH_TEXTURE_MODE_ARB:
620 case GL_TEXTURE_SRGB_DECODE_EXT:
621 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
622 {
623 /* convert float param to int */
624 GLint p[4];
625 p[0] = (GLint) param;
626 p[1] = p[2] = p[3] = 0;
627 need_update = set_tex_parameteri(ctx, texObj, pname, p);
628 }
629 break;
630 case GL_TEXTURE_SWIZZLE_R_EXT:
631 case GL_TEXTURE_SWIZZLE_G_EXT:
632 case GL_TEXTURE_SWIZZLE_B_EXT:
633 case GL_TEXTURE_SWIZZLE_A_EXT:
634 {
635 GLint p[4];
636 p[0] = (GLint) param;
637 p[1] = p[2] = p[3] = 0;
638 need_update = set_tex_parameteri(ctx, texObj, pname, p);
639 }
640 break;
641 default:
642 {
643 /* this will generate an error if pname is illegal */
644 GLfloat p[4];
645 p[0] = param;
646 p[1] = p[2] = p[3] = 0.0F;
647 need_update = set_tex_parameterf(ctx, texObj, pname, p);
648 }
649 }
650
651 if (ctx->Driver.TexParameter && need_update) {
652 ctx->Driver.TexParameter(ctx, target, texObj, pname, &param);
653 }
654 }
655
656
657 void GLAPIENTRY
658 _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
659 {
660 GLboolean need_update;
661 struct gl_texture_object *texObj;
662 GET_CURRENT_CONTEXT(ctx);
663 ASSERT_OUTSIDE_BEGIN_END(ctx);
664
665 texObj = get_texobj(ctx, target, GL_FALSE);
666 if (!texObj)
667 return;
668
669 switch (pname) {
670 case GL_TEXTURE_MIN_FILTER:
671 case GL_TEXTURE_MAG_FILTER:
672 case GL_TEXTURE_WRAP_S:
673 case GL_TEXTURE_WRAP_T:
674 case GL_TEXTURE_WRAP_R:
675 case GL_TEXTURE_BASE_LEVEL:
676 case GL_TEXTURE_MAX_LEVEL:
677 case GL_GENERATE_MIPMAP_SGIS:
678 case GL_TEXTURE_COMPARE_MODE_ARB:
679 case GL_TEXTURE_COMPARE_FUNC_ARB:
680 case GL_DEPTH_TEXTURE_MODE_ARB:
681 case GL_TEXTURE_SRGB_DECODE_EXT:
682 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
683 {
684 /* convert float param to int */
685 GLint p[4];
686 p[0] = (GLint) params[0];
687 p[1] = p[2] = p[3] = 0;
688 need_update = set_tex_parameteri(ctx, texObj, pname, p);
689 }
690 break;
691
692 #if FEATURE_OES_draw_texture
693 case GL_TEXTURE_CROP_RECT_OES:
694 {
695 /* convert float params to int */
696 GLint iparams[4];
697 iparams[0] = (GLint) params[0];
698 iparams[1] = (GLint) params[1];
699 iparams[2] = (GLint) params[2];
700 iparams[3] = (GLint) params[3];
701 need_update = set_tex_parameteri(ctx, texObj, pname, iparams);
702 }
703 break;
704 #endif
705
706 case GL_TEXTURE_SWIZZLE_R_EXT:
707 case GL_TEXTURE_SWIZZLE_G_EXT:
708 case GL_TEXTURE_SWIZZLE_B_EXT:
709 case GL_TEXTURE_SWIZZLE_A_EXT:
710 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
711 {
712 GLint p[4] = {0, 0, 0, 0};
713 p[0] = (GLint) params[0];
714 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT) {
715 p[1] = (GLint) params[1];
716 p[2] = (GLint) params[2];
717 p[3] = (GLint) params[3];
718 }
719 need_update = set_tex_parameteri(ctx, texObj, pname, p);
720 }
721 break;
722 default:
723 /* this will generate an error if pname is illegal */
724 need_update = set_tex_parameterf(ctx, texObj, pname, params);
725 }
726
727 if (ctx->Driver.TexParameter && need_update) {
728 ctx->Driver.TexParameter(ctx, target, texObj, pname, params);
729 }
730 }
731
732
733 void GLAPIENTRY
734 _mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
735 {
736 GLboolean need_update;
737 struct gl_texture_object *texObj;
738 GET_CURRENT_CONTEXT(ctx);
739 ASSERT_OUTSIDE_BEGIN_END(ctx);
740
741 texObj = get_texobj(ctx, target, GL_FALSE);
742 if (!texObj)
743 return;
744
745 switch (pname) {
746 case GL_TEXTURE_MIN_LOD:
747 case GL_TEXTURE_MAX_LOD:
748 case GL_TEXTURE_PRIORITY:
749 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
750 case GL_TEXTURE_LOD_BIAS:
751 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
752 {
753 GLfloat fparam[4];
754 fparam[0] = (GLfloat) param;
755 fparam[1] = fparam[2] = fparam[3] = 0.0F;
756 /* convert int param to float */
757 need_update = set_tex_parameterf(ctx, texObj, pname, fparam);
758 }
759 break;
760 default:
761 /* this will generate an error if pname is illegal */
762 {
763 GLint iparam[4];
764 iparam[0] = param;
765 iparam[1] = iparam[2] = iparam[3] = 0;
766 need_update = set_tex_parameteri(ctx, texObj, pname, iparam);
767 }
768 }
769
770 if (ctx->Driver.TexParameter && need_update) {
771 GLfloat fparam = (GLfloat) param;
772 ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam);
773 }
774 }
775
776
777 void GLAPIENTRY
778 _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
779 {
780 GLboolean need_update;
781 struct gl_texture_object *texObj;
782 GET_CURRENT_CONTEXT(ctx);
783 ASSERT_OUTSIDE_BEGIN_END(ctx);
784
785 texObj = get_texobj(ctx, target, GL_FALSE);
786 if (!texObj)
787 return;
788
789 switch (pname) {
790 case GL_TEXTURE_BORDER_COLOR:
791 {
792 /* convert int params to float */
793 GLfloat fparams[4];
794 fparams[0] = INT_TO_FLOAT(params[0]);
795 fparams[1] = INT_TO_FLOAT(params[1]);
796 fparams[2] = INT_TO_FLOAT(params[2]);
797 fparams[3] = INT_TO_FLOAT(params[3]);
798 need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
799 }
800 break;
801 case GL_TEXTURE_MIN_LOD:
802 case GL_TEXTURE_MAX_LOD:
803 case GL_TEXTURE_PRIORITY:
804 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
805 case GL_TEXTURE_LOD_BIAS:
806 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
807 {
808 /* convert int param to float */
809 GLfloat fparams[4];
810 fparams[0] = (GLfloat) params[0];
811 fparams[1] = fparams[2] = fparams[3] = 0.0F;
812 need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
813 }
814 break;
815 default:
816 /* this will generate an error if pname is illegal */
817 need_update = set_tex_parameteri(ctx, texObj, pname, params);
818 }
819
820 if (ctx->Driver.TexParameter && need_update) {
821 GLfloat fparams[4];
822 fparams[0] = INT_TO_FLOAT(params[0]);
823 if (pname == GL_TEXTURE_BORDER_COLOR ||
824 pname == GL_TEXTURE_CROP_RECT_OES) {
825 fparams[1] = INT_TO_FLOAT(params[1]);
826 fparams[2] = INT_TO_FLOAT(params[2]);
827 fparams[3] = INT_TO_FLOAT(params[3]);
828 }
829 ctx->Driver.TexParameter(ctx, target, texObj, pname, fparams);
830 }
831 }
832
833
834 /**
835 * Set tex parameter to integer value(s). Primarily intended to set
836 * integer-valued texture border color (for integer-valued textures).
837 * New in GL 3.0.
838 */
839 void GLAPIENTRY
840 _mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params)
841 {
842 struct gl_texture_object *texObj;
843 GET_CURRENT_CONTEXT(ctx);
844 ASSERT_OUTSIDE_BEGIN_END(ctx);
845
846 texObj = get_texobj(ctx, target, GL_FALSE);
847 if (!texObj)
848 return;
849
850 switch (pname) {
851 case GL_TEXTURE_BORDER_COLOR:
852 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
853 /* set the integer-valued border color */
854 COPY_4V(texObj->Sampler.BorderColor.i, params);
855 break;
856 default:
857 _mesa_TexParameteriv(target, pname, params);
858 break;
859 }
860 /* XXX no driver hook for TexParameterIiv() yet */
861 }
862
863
864 /**
865 * Set tex parameter to unsigned integer value(s). Primarily intended to set
866 * uint-valued texture border color (for integer-valued textures).
867 * New in GL 3.0
868 */
869 void GLAPIENTRY
870 _mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params)
871 {
872 struct gl_texture_object *texObj;
873 GET_CURRENT_CONTEXT(ctx);
874 ASSERT_OUTSIDE_BEGIN_END(ctx);
875
876 texObj = get_texobj(ctx, target, GL_FALSE);
877 if (!texObj)
878 return;
879
880 switch (pname) {
881 case GL_TEXTURE_BORDER_COLOR:
882 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
883 /* set the unsigned integer-valued border color */
884 COPY_4V(texObj->Sampler.BorderColor.ui, params);
885 break;
886 default:
887 _mesa_TexParameteriv(target, pname, (const GLint *) params);
888 break;
889 }
890 /* XXX no driver hook for TexParameterIuiv() yet */
891 }
892
893
894 static GLboolean
895 legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target)
896 {
897 switch (target) {
898 case GL_TEXTURE_1D:
899 case GL_PROXY_TEXTURE_1D:
900 case GL_TEXTURE_2D:
901 case GL_PROXY_TEXTURE_2D:
902 case GL_TEXTURE_3D:
903 case GL_PROXY_TEXTURE_3D:
904 return GL_TRUE;
905 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
906 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
907 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
908 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
909 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
910 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
911 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
912 return ctx->Extensions.ARB_texture_cube_map;
913 case GL_TEXTURE_RECTANGLE_NV:
914 case GL_PROXY_TEXTURE_RECTANGLE_NV:
915 return ctx->Extensions.NV_texture_rectangle;
916 case GL_TEXTURE_1D_ARRAY_EXT:
917 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
918 case GL_TEXTURE_2D_ARRAY_EXT:
919 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
920 return (ctx->Extensions.MESA_texture_array ||
921 ctx->Extensions.EXT_texture_array);
922 case GL_TEXTURE_BUFFER:
923 /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts,
924 * but not in earlier versions that expose ARB_texture_buffer_object.
925 *
926 * From the ARB_texture_buffer_object spec:
927 * "(7) Do buffer textures support texture parameters (TexParameter) or
928 * queries (GetTexParameter, GetTexLevelParameter, GetTexImage)?
929 *
930 * RESOLVED: No. [...] Note that the spec edits above don't add
931 * explicit error language for any of these cases. That is because
932 * each of the functions enumerate the set of valid <target>
933 * parameters. Not editing the spec to allow TEXTURE_BUFFER_ARB in
934 * these cases means that target is not legal, and an INVALID_ENUM
935 * error should be generated."
936 *
937 * From the OpenGL 3.1 spec:
938 * "target may also be TEXTURE_BUFFER, indicating the texture buffer."
939 */
940 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
941 default:
942 return GL_FALSE;
943 }
944 }
945
946
947 static void
948 get_tex_level_parameter_image(struct gl_context *ctx,
949 const struct gl_texture_object *texObj,
950 GLenum target, GLint level,
951 GLenum pname, GLint *params)
952 {
953 const struct gl_texture_image *img = NULL;
954 gl_format texFormat;
955
956 img = _mesa_select_tex_image(ctx, texObj, target, level);
957 if (!img || img->TexFormat == MESA_FORMAT_NONE) {
958 /* undefined texture image */
959 if (pname == GL_TEXTURE_COMPONENTS)
960 *params = 1;
961 else
962 *params = 0;
963 return;
964 }
965
966 texFormat = img->TexFormat;
967
968 switch (pname) {
969 case GL_TEXTURE_WIDTH:
970 *params = img->Width;
971 break;
972 case GL_TEXTURE_HEIGHT:
973 *params = img->Height;
974 break;
975 case GL_TEXTURE_DEPTH:
976 *params = img->Depth;
977 break;
978 case GL_TEXTURE_INTERNAL_FORMAT:
979 if (_mesa_is_format_compressed(texFormat)) {
980 /* need to return the actual compressed format */
981 *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
982 }
983 else {
984 /* If the true internal format is not compressed but the user
985 * requested a generic compressed format, we have to return the
986 * generic base format that matches.
987 *
988 * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
989 *
990 * "If no specific compressed format is available,
991 * internalformat is instead replaced by the corresponding base
992 * internal format."
993 *
994 * Otherwise just return the user's requested internal format
995 */
996 const GLenum f =
997 _mesa_gl_compressed_format_base_format(img->InternalFormat);
998
999 *params = (f != 0) ? f : img->InternalFormat;
1000 }
1001 break;
1002 case GL_TEXTURE_BORDER:
1003 *params = img->Border;
1004 break;
1005 case GL_TEXTURE_RED_SIZE:
1006 case GL_TEXTURE_GREEN_SIZE:
1007 case GL_TEXTURE_BLUE_SIZE:
1008 case GL_TEXTURE_ALPHA_SIZE:
1009 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1010 *params = _mesa_get_format_bits(texFormat, pname);
1011 else
1012 *params = 0;
1013 break;
1014 case GL_TEXTURE_INTENSITY_SIZE:
1015 case GL_TEXTURE_LUMINANCE_SIZE:
1016 if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
1017 *params = _mesa_get_format_bits(texFormat, pname);
1018 if (*params == 0) {
1019 /* intensity or luminance is probably stored as RGB[A] */
1020 *params = MIN2(_mesa_get_format_bits(texFormat,
1021 GL_TEXTURE_RED_SIZE),
1022 _mesa_get_format_bits(texFormat,
1023 GL_TEXTURE_GREEN_SIZE));
1024 }
1025 }
1026 else {
1027 *params = 0;
1028 }
1029 break;
1030 case GL_TEXTURE_DEPTH_SIZE_ARB:
1031 if (!ctx->Extensions.ARB_depth_texture)
1032 goto invalid_pname;
1033 *params = _mesa_get_format_bits(texFormat, pname);
1034 break;
1035 case GL_TEXTURE_STENCIL_SIZE_EXT:
1036 if (!ctx->Extensions.EXT_packed_depth_stencil &&
1037 !ctx->Extensions.ARB_framebuffer_object)
1038 goto invalid_pname;
1039 *params = _mesa_get_format_bits(texFormat, pname);
1040 break;
1041 case GL_TEXTURE_SHARED_SIZE:
1042 if (ctx->Version < 30 &&
1043 !ctx->Extensions.EXT_texture_shared_exponent)
1044 goto invalid_pname;
1045 *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
1046 break;
1047
1048 /* GL_ARB_texture_compression */
1049 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1050 if (_mesa_is_format_compressed(texFormat) &&
1051 !_mesa_is_proxy_texture(target)) {
1052 *params = _mesa_format_image_size(texFormat, img->Width,
1053 img->Height, img->Depth);
1054 }
1055 else {
1056 _mesa_error(ctx, GL_INVALID_OPERATION,
1057 "glGetTexLevelParameter[if]v(pname)");
1058 }
1059 break;
1060 case GL_TEXTURE_COMPRESSED:
1061 *params = (GLint) _mesa_is_format_compressed(texFormat);
1062 break;
1063
1064 /* GL_ARB_texture_float */
1065 case GL_TEXTURE_RED_TYPE_ARB:
1066 case GL_TEXTURE_GREEN_TYPE_ARB:
1067 case GL_TEXTURE_BLUE_TYPE_ARB:
1068 case GL_TEXTURE_ALPHA_TYPE_ARB:
1069 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1070 case GL_TEXTURE_INTENSITY_TYPE_ARB:
1071 case GL_TEXTURE_DEPTH_TYPE_ARB:
1072 if (!ctx->Extensions.ARB_texture_float)
1073 goto invalid_pname;
1074 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1075 *params = _mesa_get_format_datatype(texFormat);
1076 else
1077 *params = GL_NONE;
1078 break;
1079
1080 default:
1081 goto invalid_pname;
1082 }
1083
1084 /* no error if we get here */
1085 return;
1086
1087 invalid_pname:
1088 _mesa_error(ctx, GL_INVALID_ENUM,
1089 "glGetTexLevelParameter[if]v(pname=%s)",
1090 _mesa_lookup_enum_by_nr(pname));
1091 }
1092
1093
1094 static void
1095 get_tex_level_parameter_buffer(struct gl_context *ctx,
1096 const struct gl_texture_object *texObj,
1097 GLenum pname, GLint *params)
1098 {
1099 const struct gl_buffer_object *bo = texObj->BufferObject;
1100 gl_format texFormat = texObj->_BufferObjectFormat;
1101 GLenum internalFormat = texObj->BufferObjectFormat;
1102 GLenum baseFormat = _mesa_get_format_base_format(texFormat);
1103
1104 if (!bo) {
1105 /* undefined texture buffer object */
1106 *params = pname == GL_TEXTURE_COMPONENTS ? 1 : 0;
1107 return;
1108 }
1109
1110 switch (pname) {
1111 case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
1112 *params = bo->Name;
1113 break;
1114 case GL_TEXTURE_WIDTH:
1115 *params = bo->Size;
1116 break;
1117 case GL_TEXTURE_HEIGHT:
1118 case GL_TEXTURE_DEPTH:
1119 case GL_TEXTURE_BORDER:
1120 case GL_TEXTURE_SHARED_SIZE:
1121 case GL_TEXTURE_COMPRESSED:
1122 *params = 0;
1123 break;
1124 case GL_TEXTURE_INTERNAL_FORMAT:
1125 *params = internalFormat;
1126 break;
1127 case GL_TEXTURE_RED_SIZE:
1128 case GL_TEXTURE_GREEN_SIZE:
1129 case GL_TEXTURE_BLUE_SIZE:
1130 case GL_TEXTURE_ALPHA_SIZE:
1131 if (_mesa_base_format_has_channel(baseFormat, pname))
1132 *params = _mesa_get_format_bits(texFormat, pname);
1133 else
1134 *params = 0;
1135 break;
1136 case GL_TEXTURE_INTENSITY_SIZE:
1137 case GL_TEXTURE_LUMINANCE_SIZE:
1138 if (_mesa_base_format_has_channel(baseFormat, pname)) {
1139 *params = _mesa_get_format_bits(texFormat, pname);
1140 if (*params == 0) {
1141 /* intensity or luminance is probably stored as RGB[A] */
1142 *params = MIN2(_mesa_get_format_bits(texFormat,
1143 GL_TEXTURE_RED_SIZE),
1144 _mesa_get_format_bits(texFormat,
1145 GL_TEXTURE_GREEN_SIZE));
1146 }
1147 } else {
1148 *params = 0;
1149 }
1150 break;
1151 case GL_TEXTURE_DEPTH_SIZE_ARB:
1152 case GL_TEXTURE_STENCIL_SIZE_EXT:
1153 *params = _mesa_get_format_bits(texFormat, pname);
1154 break;
1155
1156 /* GL_ARB_texture_compression */
1157 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1158 /* Always illegal for GL_TEXTURE_BUFFER */
1159 _mesa_error(ctx, GL_INVALID_OPERATION,
1160 "glGetTexLevelParameter[if]v(pname)");
1161 break;
1162
1163 /* GL_ARB_texture_float */
1164 case GL_TEXTURE_RED_TYPE_ARB:
1165 case GL_TEXTURE_GREEN_TYPE_ARB:
1166 case GL_TEXTURE_BLUE_TYPE_ARB:
1167 case GL_TEXTURE_ALPHA_TYPE_ARB:
1168 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1169 case GL_TEXTURE_INTENSITY_TYPE_ARB:
1170 case GL_TEXTURE_DEPTH_TYPE_ARB:
1171 if (!ctx->Extensions.ARB_texture_float)
1172 goto invalid_pname;
1173 if (_mesa_base_format_has_channel(baseFormat, pname))
1174 *params = _mesa_get_format_datatype(texFormat);
1175 else
1176 *params = GL_NONE;
1177 break;
1178
1179 default:
1180 goto invalid_pname;
1181 }
1182
1183 /* no error if we get here */
1184 return;
1185
1186 invalid_pname:
1187 _mesa_error(ctx, GL_INVALID_ENUM,
1188 "glGetTexLevelParameter[if]v(pname=%s)",
1189 _mesa_lookup_enum_by_nr(pname));
1190 }
1191
1192
1193 void GLAPIENTRY
1194 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
1195 GLenum pname, GLfloat *params )
1196 {
1197 GLint iparam;
1198 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
1199 *params = (GLfloat) iparam;
1200 }
1201
1202
1203 void GLAPIENTRY
1204 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
1205 GLenum pname, GLint *params )
1206 {
1207 const struct gl_texture_unit *texUnit;
1208 struct gl_texture_object *texObj;
1209 GLint maxLevels;
1210 GET_CURRENT_CONTEXT(ctx);
1211 ASSERT_OUTSIDE_BEGIN_END(ctx);
1212
1213 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
1214 _mesa_error(ctx, GL_INVALID_OPERATION,
1215 "glGetTexLevelParameteriv(current unit)");
1216 return;
1217 }
1218
1219 texUnit = _mesa_get_current_tex_unit(ctx);
1220
1221 if (!legal_get_tex_level_parameter_target(ctx, target)) {
1222 _mesa_error(ctx, GL_INVALID_ENUM,
1223 "glGetTexLevelParameter[if]v(target=0x%x)", target);
1224 return;
1225 }
1226
1227 maxLevels = _mesa_max_texture_levels(ctx, target);
1228 assert(maxLevels != 0);
1229
1230 if (level < 0 || level >= maxLevels) {
1231 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
1232 return;
1233 }
1234
1235 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1236
1237 if (target == GL_TEXTURE_BUFFER)
1238 get_tex_level_parameter_buffer(ctx, texObj, pname, params);
1239 else
1240 get_tex_level_parameter_image(ctx, texObj, target, level, pname, params);
1241 }
1242
1243
1244 void GLAPIENTRY
1245 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
1246 {
1247 struct gl_texture_object *obj;
1248 GET_CURRENT_CONTEXT(ctx);
1249 ASSERT_OUTSIDE_BEGIN_END(ctx);
1250
1251 obj = get_texobj(ctx, target, GL_TRUE);
1252 if (!obj)
1253 return;
1254
1255 _mesa_lock_texture(ctx, obj);
1256 switch (pname) {
1257 case GL_TEXTURE_MAG_FILTER:
1258 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
1259 break;
1260 case GL_TEXTURE_MIN_FILTER:
1261 *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter);
1262 break;
1263 case GL_TEXTURE_WRAP_S:
1264 *params = ENUM_TO_FLOAT(obj->Sampler.WrapS);
1265 break;
1266 case GL_TEXTURE_WRAP_T:
1267 *params = ENUM_TO_FLOAT(obj->Sampler.WrapT);
1268 break;
1269 case GL_TEXTURE_WRAP_R:
1270 *params = ENUM_TO_FLOAT(obj->Sampler.WrapR);
1271 break;
1272 case GL_TEXTURE_BORDER_COLOR:
1273 if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
1274 _mesa_update_state_locked(ctx);
1275 if (ctx->Color._ClampFragmentColor) {
1276 params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1277 params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1278 params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1279 params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1280 }
1281 else {
1282 params[0] = obj->Sampler.BorderColor.f[0];
1283 params[1] = obj->Sampler.BorderColor.f[1];
1284 params[2] = obj->Sampler.BorderColor.f[2];
1285 params[3] = obj->Sampler.BorderColor.f[3];
1286 }
1287 break;
1288 case GL_TEXTURE_RESIDENT:
1289 *params = 1.0F;
1290 break;
1291 case GL_TEXTURE_PRIORITY:
1292 *params = obj->Priority;
1293 break;
1294 case GL_TEXTURE_MIN_LOD:
1295 *params = obj->Sampler.MinLod;
1296 break;
1297 case GL_TEXTURE_MAX_LOD:
1298 *params = obj->Sampler.MaxLod;
1299 break;
1300 case GL_TEXTURE_BASE_LEVEL:
1301 *params = (GLfloat) obj->BaseLevel;
1302 break;
1303 case GL_TEXTURE_MAX_LEVEL:
1304 *params = (GLfloat) obj->MaxLevel;
1305 break;
1306 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1307 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1308 goto invalid_pname;
1309 *params = obj->Sampler.MaxAnisotropy;
1310 break;
1311 case GL_GENERATE_MIPMAP_SGIS:
1312 *params = (GLfloat) obj->GenerateMipmap;
1313 break;
1314 case GL_TEXTURE_COMPARE_MODE_ARB:
1315 if (!ctx->Extensions.ARB_shadow)
1316 goto invalid_pname;
1317 *params = (GLfloat) obj->Sampler.CompareMode;
1318 break;
1319 case GL_TEXTURE_COMPARE_FUNC_ARB:
1320 if (!ctx->Extensions.ARB_shadow)
1321 goto invalid_pname;
1322 *params = (GLfloat) obj->Sampler.CompareFunc;
1323 break;
1324 case GL_DEPTH_TEXTURE_MODE_ARB:
1325 if (!ctx->Extensions.ARB_depth_texture)
1326 goto invalid_pname;
1327 *params = (GLfloat) obj->DepthMode;
1328 break;
1329 case GL_TEXTURE_LOD_BIAS:
1330 *params = obj->Sampler.LodBias;
1331 break;
1332 #if FEATURE_OES_draw_texture
1333 case GL_TEXTURE_CROP_RECT_OES:
1334 params[0] = obj->CropRect[0];
1335 params[1] = obj->CropRect[1];
1336 params[2] = obj->CropRect[2];
1337 params[3] = obj->CropRect[3];
1338 break;
1339 #endif
1340
1341 case GL_TEXTURE_SWIZZLE_R_EXT:
1342 case GL_TEXTURE_SWIZZLE_G_EXT:
1343 case GL_TEXTURE_SWIZZLE_B_EXT:
1344 case GL_TEXTURE_SWIZZLE_A_EXT:
1345 if (!ctx->Extensions.EXT_texture_swizzle)
1346 goto invalid_pname;
1347 *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1348 break;
1349
1350 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1351 if (!ctx->Extensions.EXT_texture_swizzle) {
1352 goto invalid_pname;
1353 }
1354 else {
1355 GLuint comp;
1356 for (comp = 0; comp < 4; comp++) {
1357 params[comp] = (GLfloat) obj->Swizzle[comp];
1358 }
1359 }
1360 break;
1361
1362 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1363 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1364 goto invalid_pname;
1365 *params = (GLfloat) obj->Sampler.CubeMapSeamless;
1366 break;
1367
1368 case GL_TEXTURE_IMMUTABLE_FORMAT:
1369 if (!ctx->Extensions.ARB_texture_storage)
1370 goto invalid_pname;
1371 *params = (GLfloat) obj->Immutable;
1372 break;
1373
1374 default:
1375 goto invalid_pname;
1376 }
1377
1378 /* no error if we get here */
1379 _mesa_unlock_texture(ctx, obj);
1380 return;
1381
1382 invalid_pname:
1383 _mesa_unlock_texture(ctx, obj);
1384 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
1385 }
1386
1387
1388 void GLAPIENTRY
1389 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1390 {
1391 struct gl_texture_object *obj;
1392 GET_CURRENT_CONTEXT(ctx);
1393 ASSERT_OUTSIDE_BEGIN_END(ctx);
1394
1395 obj = get_texobj(ctx, target, GL_TRUE);
1396 if (!obj)
1397 return;
1398
1399 _mesa_lock_texture(ctx, obj);
1400 switch (pname) {
1401 case GL_TEXTURE_MAG_FILTER:
1402 *params = (GLint) obj->Sampler.MagFilter;
1403 break;
1404 case GL_TEXTURE_MIN_FILTER:
1405 *params = (GLint) obj->Sampler.MinFilter;
1406 break;
1407 case GL_TEXTURE_WRAP_S:
1408 *params = (GLint) obj->Sampler.WrapS;
1409 break;
1410 case GL_TEXTURE_WRAP_T:
1411 *params = (GLint) obj->Sampler.WrapT;
1412 break;
1413 case GL_TEXTURE_WRAP_R:
1414 *params = (GLint) obj->Sampler.WrapR;
1415 break;
1416 case GL_TEXTURE_BORDER_COLOR:
1417 {
1418 GLfloat b[4];
1419 b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1420 b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1421 b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1422 b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1423 params[0] = FLOAT_TO_INT(b[0]);
1424 params[1] = FLOAT_TO_INT(b[1]);
1425 params[2] = FLOAT_TO_INT(b[2]);
1426 params[3] = FLOAT_TO_INT(b[3]);
1427 }
1428 break;
1429 case GL_TEXTURE_RESIDENT:
1430 *params = 1;
1431 break;
1432 case GL_TEXTURE_PRIORITY:
1433 *params = FLOAT_TO_INT(obj->Priority);
1434 break;
1435 case GL_TEXTURE_MIN_LOD:
1436 *params = (GLint) obj->Sampler.MinLod;
1437 break;
1438 case GL_TEXTURE_MAX_LOD:
1439 *params = (GLint) obj->Sampler.MaxLod;
1440 break;
1441 case GL_TEXTURE_BASE_LEVEL:
1442 *params = obj->BaseLevel;
1443 break;
1444 case GL_TEXTURE_MAX_LEVEL:
1445 *params = obj->MaxLevel;
1446 break;
1447 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1448 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1449 goto invalid_pname;
1450 *params = (GLint) obj->Sampler.MaxAnisotropy;
1451 break;
1452 case GL_GENERATE_MIPMAP_SGIS:
1453 *params = (GLint) obj->GenerateMipmap;
1454 break;
1455 case GL_TEXTURE_COMPARE_MODE_ARB:
1456 if (!ctx->Extensions.ARB_shadow)
1457 goto invalid_pname;
1458 *params = (GLint) obj->Sampler.CompareMode;
1459 break;
1460 case GL_TEXTURE_COMPARE_FUNC_ARB:
1461 if (!ctx->Extensions.ARB_shadow)
1462 goto invalid_pname;
1463 *params = (GLint) obj->Sampler.CompareFunc;
1464 break;
1465 case GL_DEPTH_TEXTURE_MODE_ARB:
1466 if (!ctx->Extensions.ARB_depth_texture)
1467 goto invalid_pname;
1468 *params = (GLint) obj->DepthMode;
1469 break;
1470 case GL_TEXTURE_LOD_BIAS:
1471 *params = (GLint) obj->Sampler.LodBias;
1472 break;
1473 #if FEATURE_OES_draw_texture
1474 case GL_TEXTURE_CROP_RECT_OES:
1475 params[0] = obj->CropRect[0];
1476 params[1] = obj->CropRect[1];
1477 params[2] = obj->CropRect[2];
1478 params[3] = obj->CropRect[3];
1479 break;
1480 #endif
1481 case GL_TEXTURE_SWIZZLE_R_EXT:
1482 case GL_TEXTURE_SWIZZLE_G_EXT:
1483 case GL_TEXTURE_SWIZZLE_B_EXT:
1484 case GL_TEXTURE_SWIZZLE_A_EXT:
1485 if (!ctx->Extensions.EXT_texture_swizzle)
1486 goto invalid_pname;
1487 *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1488 break;
1489
1490 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1491 if (!ctx->Extensions.EXT_texture_swizzle)
1492 goto invalid_pname;
1493 COPY_4V(params, obj->Swizzle);
1494 break;
1495
1496 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1497 if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
1498 goto invalid_pname;
1499 *params = (GLint) obj->Sampler.CubeMapSeamless;
1500 break;
1501
1502 case GL_TEXTURE_IMMUTABLE_FORMAT:
1503 if (!ctx->Extensions.ARB_texture_storage)
1504 goto invalid_pname;
1505 *params = (GLint) obj->Immutable;
1506 break;
1507
1508 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1509 if (!ctx->Extensions.OES_EGL_image_external)
1510 goto invalid_pname;
1511 *params = obj->RequiredTextureImageUnits;
1512 break;
1513
1514 default:
1515 goto invalid_pname;
1516 }
1517
1518 /* no error if we get here */
1519 _mesa_unlock_texture(ctx, obj);
1520 return;
1521
1522 invalid_pname:
1523 _mesa_unlock_texture(ctx, obj);
1524 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1525 }
1526
1527
1528 /** New in GL 3.0 */
1529 void GLAPIENTRY
1530 _mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
1531 {
1532 struct gl_texture_object *texObj;
1533 GET_CURRENT_CONTEXT(ctx);
1534 ASSERT_OUTSIDE_BEGIN_END(ctx);
1535
1536 texObj = get_texobj(ctx, target, GL_TRUE);
1537 if (!texObj)
1538 return;
1539
1540 switch (pname) {
1541 case GL_TEXTURE_BORDER_COLOR:
1542 COPY_4V(params, texObj->Sampler.BorderColor.i);
1543 break;
1544 default:
1545 _mesa_GetTexParameteriv(target, pname, params);
1546 }
1547 }
1548
1549
1550 /** New in GL 3.0 */
1551 void GLAPIENTRY
1552 _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
1553 {
1554 struct gl_texture_object *texObj;
1555 GET_CURRENT_CONTEXT(ctx);
1556 ASSERT_OUTSIDE_BEGIN_END(ctx);
1557
1558 texObj = get_texobj(ctx, target, GL_TRUE);
1559 if (!texObj)
1560 return;
1561
1562 switch (pname) {
1563 case GL_TEXTURE_BORDER_COLOR:
1564 COPY_4V(params, texObj->Sampler.BorderColor.i);
1565 break;
1566 default:
1567 {
1568 GLint ip[4];
1569 _mesa_GetTexParameteriv(target, pname, ip);
1570 params[0] = ip[0];
1571 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
1572 pname == GL_TEXTURE_CROP_RECT_OES) {
1573 params[1] = ip[1];
1574 params[2] = ip[2];
1575 params[3] = ip[3];
1576 }
1577 }
1578 }
1579 }