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