mesa/es: Validate glGetTexParameter pnames 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 (!_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
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
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
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
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
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
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
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
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
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
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
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
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
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 default:
1452 goto invalid_pname;
1453 }
1454
1455 /* no error if we get here */
1456 _mesa_unlock_texture(ctx, obj);
1457 return;
1458
1459 invalid_pname:
1460 _mesa_unlock_texture(ctx, obj);
1461 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
1462 }
1463
1464
1465 void GLAPIENTRY
1466 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1467 {
1468 struct gl_texture_object *obj;
1469 GET_CURRENT_CONTEXT(ctx);
1470 ASSERT_OUTSIDE_BEGIN_END(ctx);
1471
1472 obj = get_texobj(ctx, target, GL_TRUE);
1473 if (!obj)
1474 return;
1475
1476 _mesa_lock_texture(ctx, obj);
1477 switch (pname) {
1478 case GL_TEXTURE_MAG_FILTER:
1479 *params = (GLint) obj->Sampler.MagFilter;
1480 break;
1481 case GL_TEXTURE_MIN_FILTER:
1482 *params = (GLint) obj->Sampler.MinFilter;
1483 break;
1484 case GL_TEXTURE_WRAP_S:
1485 *params = (GLint) obj->Sampler.WrapS;
1486 break;
1487 case GL_TEXTURE_WRAP_T:
1488 *params = (GLint) obj->Sampler.WrapT;
1489 break;
1490 case GL_TEXTURE_WRAP_R:
1491 *params = (GLint) obj->Sampler.WrapR;
1492 break;
1493 case GL_TEXTURE_BORDER_COLOR:
1494 if (!_mesa_is_desktop_gl(ctx))
1495 goto invalid_pname;
1496
1497 {
1498 GLfloat b[4];
1499 b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1500 b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1501 b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1502 b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1503 params[0] = FLOAT_TO_INT(b[0]);
1504 params[1] = FLOAT_TO_INT(b[1]);
1505 params[2] = FLOAT_TO_INT(b[2]);
1506 params[3] = FLOAT_TO_INT(b[3]);
1507 }
1508 break;
1509 case GL_TEXTURE_RESIDENT:
1510 if (ctx->API != API_OPENGL)
1511 goto invalid_pname;
1512
1513 *params = 1;
1514 break;
1515 case GL_TEXTURE_PRIORITY:
1516 if (ctx->API != API_OPENGL)
1517 goto invalid_pname;
1518
1519 *params = FLOAT_TO_INT(obj->Priority);
1520 break;
1521 case GL_TEXTURE_MIN_LOD:
1522 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1523 goto invalid_pname;
1524
1525 *params = (GLint) obj->Sampler.MinLod;
1526 break;
1527 case GL_TEXTURE_MAX_LOD:
1528 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1529 goto invalid_pname;
1530
1531 *params = (GLint) obj->Sampler.MaxLod;
1532 break;
1533 case GL_TEXTURE_BASE_LEVEL:
1534 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1535 goto invalid_pname;
1536
1537 *params = obj->BaseLevel;
1538 break;
1539 case GL_TEXTURE_MAX_LEVEL:
1540 *params = obj->MaxLevel;
1541 break;
1542 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1543 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1544 goto invalid_pname;
1545 *params = (GLint) obj->Sampler.MaxAnisotropy;
1546 break;
1547 case GL_GENERATE_MIPMAP_SGIS:
1548 if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES)
1549 goto invalid_pname;
1550
1551 *params = (GLint) obj->GenerateMipmap;
1552 break;
1553 case GL_TEXTURE_COMPARE_MODE_ARB:
1554 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1555 && !_mesa_is_gles3(ctx))
1556 goto invalid_pname;
1557 *params = (GLint) obj->Sampler.CompareMode;
1558 break;
1559 case GL_TEXTURE_COMPARE_FUNC_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.CompareFunc;
1564 break;
1565 case GL_DEPTH_TEXTURE_MODE_ARB:
1566 if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_depth_texture)
1567 goto invalid_pname;
1568 *params = (GLint) obj->DepthMode;
1569 break;
1570 case GL_TEXTURE_LOD_BIAS:
1571 if (ctx->API != API_OPENGL)
1572 goto invalid_pname;
1573
1574 *params = (GLint) obj->Sampler.LodBias;
1575 break;
1576 #if FEATURE_OES_draw_texture
1577 case GL_TEXTURE_CROP_RECT_OES:
1578 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
1579 goto invalid_pname;
1580
1581 params[0] = obj->CropRect[0];
1582 params[1] = obj->CropRect[1];
1583 params[2] = obj->CropRect[2];
1584 params[3] = obj->CropRect[3];
1585 break;
1586 #endif
1587 case GL_TEXTURE_SWIZZLE_R_EXT:
1588 case GL_TEXTURE_SWIZZLE_G_EXT:
1589 case GL_TEXTURE_SWIZZLE_B_EXT:
1590 case GL_TEXTURE_SWIZZLE_A_EXT:
1591 if ((!_mesa_is_desktop_gl(ctx)
1592 || !ctx->Extensions.EXT_texture_swizzle)
1593 && !_mesa_is_gles3(ctx))
1594 goto invalid_pname;
1595 *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1596 break;
1597
1598 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1599 if ((!_mesa_is_desktop_gl(ctx)
1600 || !ctx->Extensions.EXT_texture_swizzle)
1601 && !_mesa_is_gles3(ctx))
1602 goto invalid_pname;
1603 COPY_4V(params, obj->Swizzle);
1604 break;
1605
1606 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1607 if (!_mesa_is_desktop_gl(ctx)
1608 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
1609 goto invalid_pname;
1610 *params = (GLint) obj->Sampler.CubeMapSeamless;
1611 break;
1612
1613 case GL_TEXTURE_IMMUTABLE_FORMAT:
1614 if (!ctx->Extensions.ARB_texture_storage)
1615 goto invalid_pname;
1616 *params = (GLint) obj->Immutable;
1617 break;
1618
1619 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1620 if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)
1621 goto invalid_pname;
1622 *params = obj->RequiredTextureImageUnits;
1623 break;
1624
1625 default:
1626 goto invalid_pname;
1627 }
1628
1629 /* no error if we get here */
1630 _mesa_unlock_texture(ctx, obj);
1631 return;
1632
1633 invalid_pname:
1634 _mesa_unlock_texture(ctx, obj);
1635 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1636 }
1637
1638
1639 /** New in GL 3.0 */
1640 void GLAPIENTRY
1641 _mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
1642 {
1643 struct gl_texture_object *texObj;
1644 GET_CURRENT_CONTEXT(ctx);
1645 ASSERT_OUTSIDE_BEGIN_END(ctx);
1646
1647 texObj = get_texobj(ctx, target, GL_TRUE);
1648 if (!texObj)
1649 return;
1650
1651 switch (pname) {
1652 case GL_TEXTURE_BORDER_COLOR:
1653 COPY_4V(params, texObj->Sampler.BorderColor.i);
1654 break;
1655 default:
1656 _mesa_GetTexParameteriv(target, pname, params);
1657 }
1658 }
1659
1660
1661 /** New in GL 3.0 */
1662 void GLAPIENTRY
1663 _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
1664 {
1665 struct gl_texture_object *texObj;
1666 GET_CURRENT_CONTEXT(ctx);
1667 ASSERT_OUTSIDE_BEGIN_END(ctx);
1668
1669 texObj = get_texobj(ctx, target, GL_TRUE);
1670 if (!texObj)
1671 return;
1672
1673 switch (pname) {
1674 case GL_TEXTURE_BORDER_COLOR:
1675 COPY_4V(params, texObj->Sampler.BorderColor.i);
1676 break;
1677 default:
1678 {
1679 GLint ip[4];
1680 _mesa_GetTexParameteriv(target, pname, ip);
1681 params[0] = ip[0];
1682 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
1683 pname == GL_TEXTURE_CROP_RECT_OES) {
1684 params[1] = ip[1];
1685 params[2] = ip[2];
1686 params[3] = ip[3];
1687 }
1688 }
1689 }
1690 }