Merge remote-tracking branch 'origin/master' into vulkan
[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 static GLboolean
256 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 (!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 (!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 (!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 (!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 (!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 (!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 (!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 (_mesa_is_desktop_gl(ctx)
572 && ctx->Extensions.EXT_texture_sRGB_decode) {
573 GLenum decode = params[0];
574
575 if (!target_allows_setting_sampler_parameters(texObj->Target))
576 goto invalid_enum;
577
578 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
579 if (texObj->Sampler.sRGBDecode != decode) {
580 flush(ctx);
581 texObj->Sampler.sRGBDecode = decode;
582 }
583 return GL_TRUE;
584 }
585 }
586 goto invalid_pname;
587
588 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
589 if (_mesa_is_desktop_gl(ctx)
590 && ctx->Extensions.AMD_seamless_cubemap_per_texture) {
591 GLenum param = params[0];
592
593 if (!target_allows_setting_sampler_parameters(texObj->Target))
594 goto invalid_enum;
595
596 if (param != GL_TRUE && param != GL_FALSE) {
597 goto invalid_param;
598 }
599 if (param != texObj->Sampler.CubeMapSeamless) {
600 flush(ctx);
601 texObj->Sampler.CubeMapSeamless = param;
602 }
603 return GL_TRUE;
604 }
605 goto invalid_pname;
606
607 default:
608 goto invalid_pname;
609 }
610
611 invalid_pname:
612 _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
613 suffix, _mesa_enum_to_string(pname));
614 return GL_FALSE;
615
616 invalid_param:
617 _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(param=%s)",
618 suffix, _mesa_enum_to_string(params[0]));
619 return GL_FALSE;
620
621 invalid_operation:
622 _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sParameter(pname=%s)",
623 suffix, _mesa_enum_to_string(pname));
624 return GL_FALSE;
625
626 invalid_enum:
627 _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
628 suffix, _mesa_enum_to_string(pname));
629 return GL_FALSE;
630 }
631
632
633 /**
634 * Set a float-valued texture parameter
635 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
636 */
637 static GLboolean
638 set_tex_parameterf(struct gl_context *ctx,
639 struct gl_texture_object *texObj,
640 GLenum pname, const GLfloat *params, bool dsa)
641 {
642 const char *suffix = dsa ? "ture" : "";
643
644 switch (pname) {
645 case GL_TEXTURE_MIN_LOD:
646 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
647 goto invalid_pname;
648
649 if (!target_allows_setting_sampler_parameters(texObj->Target))
650 goto invalid_enum;
651
652 if (texObj->Sampler.MinLod == params[0])
653 return GL_FALSE;
654 flush(ctx);
655 texObj->Sampler.MinLod = params[0];
656 return GL_TRUE;
657
658 case GL_TEXTURE_MAX_LOD:
659 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
660 goto invalid_pname;
661
662 if (!target_allows_setting_sampler_parameters(texObj->Target))
663 goto invalid_enum;
664
665 if (texObj->Sampler.MaxLod == params[0])
666 return GL_FALSE;
667 flush(ctx);
668 texObj->Sampler.MaxLod = params[0];
669 return GL_TRUE;
670
671 case GL_TEXTURE_PRIORITY:
672 if (ctx->API != API_OPENGL_COMPAT)
673 goto invalid_pname;
674
675 flush(ctx);
676 texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
677 return GL_TRUE;
678
679 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
680 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
681 if (!target_allows_setting_sampler_parameters(texObj->Target))
682 goto invalid_enum;
683
684 if (texObj->Sampler.MaxAnisotropy == params[0])
685 return GL_FALSE;
686 if (params[0] < 1.0F) {
687 _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sParameter(param)",
688 suffix);
689 return GL_FALSE;
690 }
691 flush(ctx);
692 /* clamp to max, that's what NVIDIA does */
693 texObj->Sampler.MaxAnisotropy = MIN2(params[0],
694 ctx->Const.MaxTextureMaxAnisotropy);
695 return GL_TRUE;
696 }
697 else {
698 static GLuint count = 0;
699 if (count++ < 10)
700 goto invalid_pname;
701 }
702 return GL_FALSE;
703
704 case GL_TEXTURE_LOD_BIAS:
705 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias. */
706 if (_mesa_is_gles(ctx))
707 goto invalid_pname;
708
709 if (!target_allows_setting_sampler_parameters(texObj->Target))
710 goto invalid_enum;
711
712 if (texObj->Sampler.LodBias != params[0]) {
713 flush(ctx);
714 texObj->Sampler.LodBias = params[0];
715 return GL_TRUE;
716 }
717 break;
718
719 case GL_TEXTURE_BORDER_COLOR:
720 if (ctx->API == API_OPENGLES ||
721 !ctx->Extensions.ARB_texture_border_clamp)
722 goto invalid_pname;
723
724 if (!target_allows_setting_sampler_parameters(texObj->Target))
725 goto invalid_enum;
726
727 flush(ctx);
728 /* ARB_texture_float disables clamping */
729 if (ctx->Extensions.ARB_texture_float) {
730 texObj->Sampler.BorderColor.f[RCOMP] = params[0];
731 texObj->Sampler.BorderColor.f[GCOMP] = params[1];
732 texObj->Sampler.BorderColor.f[BCOMP] = params[2];
733 texObj->Sampler.BorderColor.f[ACOMP] = params[3];
734 } else {
735 texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F);
736 texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F);
737 texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F);
738 texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F);
739 }
740 return GL_TRUE;
741
742 default:
743 goto invalid_pname;
744 }
745 return GL_FALSE;
746
747 invalid_pname:
748 _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
749 suffix, _mesa_enum_to_string(pname));
750 return GL_FALSE;
751
752 invalid_enum:
753 _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameter(pname=%s)",
754 suffix, _mesa_enum_to_string(pname));
755 return GL_FALSE;
756 }
757
758
759 void
760 _mesa_texture_parameterf(struct gl_context *ctx,
761 struct gl_texture_object *texObj,
762 GLenum pname, GLfloat param, bool dsa)
763 {
764 GLboolean need_update;
765
766 switch (pname) {
767 case GL_TEXTURE_MIN_FILTER:
768 case GL_TEXTURE_MAG_FILTER:
769 case GL_TEXTURE_WRAP_S:
770 case GL_TEXTURE_WRAP_T:
771 case GL_TEXTURE_WRAP_R:
772 case GL_TEXTURE_BASE_LEVEL:
773 case GL_TEXTURE_MAX_LEVEL:
774 case GL_GENERATE_MIPMAP_SGIS:
775 case GL_TEXTURE_COMPARE_MODE_ARB:
776 case GL_TEXTURE_COMPARE_FUNC_ARB:
777 case GL_DEPTH_TEXTURE_MODE_ARB:
778 case GL_DEPTH_STENCIL_TEXTURE_MODE:
779 case GL_TEXTURE_SRGB_DECODE_EXT:
780 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
781 case GL_TEXTURE_SWIZZLE_R_EXT:
782 case GL_TEXTURE_SWIZZLE_G_EXT:
783 case GL_TEXTURE_SWIZZLE_B_EXT:
784 case GL_TEXTURE_SWIZZLE_A_EXT:
785 {
786 GLint p[4];
787 p[0] = (param > 0) ?
788 ((param > INT_MAX) ? INT_MAX : (GLint) (param + 0.5)) :
789 ((param < INT_MIN) ? INT_MIN : (GLint) (param - 0.5));
790
791 p[1] = p[2] = p[3] = 0;
792 need_update = set_tex_parameteri(ctx, texObj, pname, p, dsa);
793 }
794 break;
795 case GL_TEXTURE_BORDER_COLOR:
796 case GL_TEXTURE_SWIZZLE_RGBA:
797 _mesa_error(ctx, GL_INVALID_ENUM, "glTex%sParameterf(non-scalar pname)",
798 dsa ? "ture" : "");
799 return;
800 default:
801 {
802 /* this will generate an error if pname is illegal */
803 GLfloat p[4];
804 p[0] = param;
805 p[1] = p[2] = p[3] = 0.0F;
806 need_update = set_tex_parameterf(ctx, texObj, pname, p, dsa);
807 }
808 }
809
810 if (ctx->Driver.TexParameter && need_update) {
811 ctx->Driver.TexParameter(ctx, texObj, pname, &param);
812 }
813 }
814
815
816 void
817 _mesa_texture_parameterfv(struct gl_context *ctx,
818 struct gl_texture_object *texObj,
819 GLenum pname, const GLfloat *params, bool dsa)
820 {
821 GLboolean need_update;
822 switch (pname) {
823 case GL_TEXTURE_MIN_FILTER:
824 case GL_TEXTURE_MAG_FILTER:
825 case GL_TEXTURE_WRAP_S:
826 case GL_TEXTURE_WRAP_T:
827 case GL_TEXTURE_WRAP_R:
828 case GL_TEXTURE_BASE_LEVEL:
829 case GL_TEXTURE_MAX_LEVEL:
830 case GL_GENERATE_MIPMAP_SGIS:
831 case GL_TEXTURE_COMPARE_MODE_ARB:
832 case GL_TEXTURE_COMPARE_FUNC_ARB:
833 case GL_DEPTH_TEXTURE_MODE_ARB:
834 case GL_DEPTH_STENCIL_TEXTURE_MODE:
835 case GL_TEXTURE_SRGB_DECODE_EXT:
836 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
837 {
838 /* convert float param to int */
839 GLint p[4];
840 p[0] = (GLint) params[0];
841 p[1] = p[2] = p[3] = 0;
842 need_update = set_tex_parameteri(ctx, texObj, pname, p, dsa);
843 }
844 break;
845 case GL_TEXTURE_CROP_RECT_OES:
846 {
847 /* convert float params to int */
848 GLint iparams[4];
849 iparams[0] = (GLint) params[0];
850 iparams[1] = (GLint) params[1];
851 iparams[2] = (GLint) params[2];
852 iparams[3] = (GLint) params[3];
853 need_update = set_tex_parameteri(ctx, texObj, pname, iparams, dsa);
854 }
855 break;
856 case GL_TEXTURE_SWIZZLE_R_EXT:
857 case GL_TEXTURE_SWIZZLE_G_EXT:
858 case GL_TEXTURE_SWIZZLE_B_EXT:
859 case GL_TEXTURE_SWIZZLE_A_EXT:
860 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
861 {
862 GLint p[4] = {0, 0, 0, 0};
863 p[0] = (GLint) params[0];
864 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT) {
865 p[1] = (GLint) params[1];
866 p[2] = (GLint) params[2];
867 p[3] = (GLint) params[3];
868 }
869 need_update = set_tex_parameteri(ctx, texObj, pname, p, dsa);
870 }
871 break;
872 default:
873 /* this will generate an error if pname is illegal */
874 need_update = set_tex_parameterf(ctx, texObj, pname, params, dsa);
875 }
876
877 if (ctx->Driver.TexParameter && need_update) {
878 ctx->Driver.TexParameter(ctx, texObj, pname, params);
879 }
880 }
881
882
883 void
884 _mesa_texture_parameteri(struct gl_context *ctx,
885 struct gl_texture_object *texObj,
886 GLenum pname, GLint param, bool dsa)
887 {
888 GLboolean need_update;
889 switch (pname) {
890 case GL_TEXTURE_MIN_LOD:
891 case GL_TEXTURE_MAX_LOD:
892 case GL_TEXTURE_PRIORITY:
893 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
894 case GL_TEXTURE_LOD_BIAS:
895 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
896 {
897 GLfloat fparam[4];
898 fparam[0] = (GLfloat) param;
899 fparam[1] = fparam[2] = fparam[3] = 0.0F;
900 /* convert int param to float */
901 need_update = set_tex_parameterf(ctx, texObj, pname, fparam, dsa);
902 }
903 break;
904 case GL_TEXTURE_BORDER_COLOR:
905 case GL_TEXTURE_SWIZZLE_RGBA:
906 {
907 _mesa_error(ctx, GL_INVALID_ENUM,
908 "glTex%sParameteri(non-scalar pname)",
909 dsa ? "ture" : "");
910 return;
911 }
912 default:
913 /* this will generate an error if pname is illegal */
914 {
915 GLint iparam[4];
916 iparam[0] = param;
917 iparam[1] = iparam[2] = iparam[3] = 0;
918 need_update = set_tex_parameteri(ctx, texObj, pname, iparam, dsa);
919 }
920 }
921
922 if (ctx->Driver.TexParameter && need_update) {
923 GLfloat fparam = (GLfloat) param;
924 ctx->Driver.TexParameter(ctx, texObj, pname, &fparam);
925 }
926 }
927
928
929 void
930 _mesa_texture_parameteriv(struct gl_context *ctx,
931 struct gl_texture_object *texObj,
932 GLenum pname, const GLint *params, bool dsa)
933 {
934 GLboolean need_update;
935
936 switch (pname) {
937 case GL_TEXTURE_BORDER_COLOR:
938 {
939 /* convert int params to float */
940 GLfloat fparams[4];
941 fparams[0] = INT_TO_FLOAT(params[0]);
942 fparams[1] = INT_TO_FLOAT(params[1]);
943 fparams[2] = INT_TO_FLOAT(params[2]);
944 fparams[3] = INT_TO_FLOAT(params[3]);
945 need_update = set_tex_parameterf(ctx, texObj, pname, fparams, dsa);
946 }
947 break;
948 case GL_TEXTURE_MIN_LOD:
949 case GL_TEXTURE_MAX_LOD:
950 case GL_TEXTURE_PRIORITY:
951 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
952 case GL_TEXTURE_LOD_BIAS:
953 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
954 {
955 /* convert int param to float */
956 GLfloat fparams[4];
957 fparams[0] = (GLfloat) params[0];
958 fparams[1] = fparams[2] = fparams[3] = 0.0F;
959 need_update = set_tex_parameterf(ctx, texObj, pname, fparams, dsa);
960 }
961 break;
962 default:
963 /* this will generate an error if pname is illegal */
964 need_update = set_tex_parameteri(ctx, texObj, pname, params, dsa);
965 }
966
967 if (ctx->Driver.TexParameter && need_update) {
968 GLfloat fparams[4];
969 fparams[0] = INT_TO_FLOAT(params[0]);
970 if (pname == GL_TEXTURE_BORDER_COLOR ||
971 pname == GL_TEXTURE_CROP_RECT_OES) {
972 fparams[1] = INT_TO_FLOAT(params[1]);
973 fparams[2] = INT_TO_FLOAT(params[2]);
974 fparams[3] = INT_TO_FLOAT(params[3]);
975 }
976 ctx->Driver.TexParameter(ctx, texObj, pname, fparams);
977 }
978 }
979
980 void
981 _mesa_texture_parameterIiv(struct gl_context *ctx,
982 struct gl_texture_object *texObj,
983 GLenum pname, const GLint *params, bool dsa)
984 {
985 switch (pname) {
986 case GL_TEXTURE_BORDER_COLOR:
987 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
988 /* set the integer-valued border color */
989 COPY_4V(texObj->Sampler.BorderColor.i, params);
990 break;
991 default:
992 _mesa_texture_parameteriv(ctx, texObj, pname, params, dsa);
993 break;
994 }
995 /* XXX no driver hook for TexParameterIiv() yet */
996 }
997
998 void
999 _mesa_texture_parameterIuiv(struct gl_context *ctx,
1000 struct gl_texture_object *texObj,
1001 GLenum pname, const GLuint *params, bool dsa)
1002 {
1003 switch (pname) {
1004 case GL_TEXTURE_BORDER_COLOR:
1005 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1006 /* set the unsigned integer-valued border color */
1007 COPY_4V(texObj->Sampler.BorderColor.ui, params);
1008 break;
1009 default:
1010 _mesa_texture_parameteriv(ctx, texObj, pname, (const GLint *) params,
1011 dsa);
1012 break;
1013 }
1014 /* XXX no driver hook for TexParameterIuiv() yet */
1015 }
1016
1017 void GLAPIENTRY
1018 _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
1019 {
1020 struct gl_texture_object *texObj;
1021 GET_CURRENT_CONTEXT(ctx);
1022
1023 texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1024 if (!texObj)
1025 return;
1026
1027 _mesa_texture_parameterf(ctx, texObj, pname, param, false);
1028 }
1029
1030 void GLAPIENTRY
1031 _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
1032 {
1033 struct gl_texture_object *texObj;
1034 GET_CURRENT_CONTEXT(ctx);
1035
1036 texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1037 if (!texObj)
1038 return;
1039
1040 _mesa_texture_parameterfv(ctx, texObj, pname, params, false);
1041 }
1042
1043 void GLAPIENTRY
1044 _mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
1045 {
1046 struct gl_texture_object *texObj;
1047 GET_CURRENT_CONTEXT(ctx);
1048
1049 texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1050 if (!texObj)
1051 return;
1052
1053 _mesa_texture_parameteri(ctx, texObj, pname, param, false);
1054 }
1055
1056 void GLAPIENTRY
1057 _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
1058 {
1059 struct gl_texture_object *texObj;
1060 GET_CURRENT_CONTEXT(ctx);
1061
1062 texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1063 if (!texObj)
1064 return;
1065
1066 _mesa_texture_parameteriv(ctx, texObj, pname, params, false);
1067 }
1068
1069 /**
1070 * Set tex parameter to integer value(s). Primarily intended to set
1071 * integer-valued texture border color (for integer-valued textures).
1072 * New in GL 3.0.
1073 */
1074 void GLAPIENTRY
1075 _mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params)
1076 {
1077 struct gl_texture_object *texObj;
1078 GET_CURRENT_CONTEXT(ctx);
1079
1080 texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1081 if (!texObj)
1082 return;
1083
1084 _mesa_texture_parameterIiv(ctx, texObj, pname, params, false);
1085 }
1086
1087 /**
1088 * Set tex parameter to unsigned integer value(s). Primarily intended to set
1089 * uint-valued texture border color (for integer-valued textures).
1090 * New in GL 3.0
1091 */
1092 void GLAPIENTRY
1093 _mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params)
1094 {
1095 struct gl_texture_object *texObj;
1096 GET_CURRENT_CONTEXT(ctx);
1097
1098 texObj = get_texobj_by_target(ctx, target, GL_FALSE);
1099 if (!texObj)
1100 return;
1101
1102 _mesa_texture_parameterIuiv(ctx, texObj, pname, params, false);
1103 }
1104
1105
1106 void GLAPIENTRY
1107 _mesa_TextureParameterfv(GLuint texture, GLenum pname, const GLfloat *params)
1108 {
1109 struct gl_texture_object *texObj;
1110 GET_CURRENT_CONTEXT(ctx);
1111
1112 texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1113 if (!texObj) {
1114 /* User passed a non-generated name. */
1115 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameterfv(texture)");
1116 return;
1117 }
1118
1119 _mesa_texture_parameterfv(ctx, texObj, pname, params, true);
1120 }
1121
1122 void GLAPIENTRY
1123 _mesa_TextureParameterf(GLuint texture, GLenum pname, GLfloat param)
1124 {
1125 struct gl_texture_object *texObj;
1126 GET_CURRENT_CONTEXT(ctx);
1127
1128 texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1129 if (!texObj) {
1130 /* User passed a non-generated name. */
1131 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameterf(texture)");
1132 return;
1133 }
1134
1135 _mesa_texture_parameterf(ctx, texObj, pname, param, true);
1136 }
1137
1138 void GLAPIENTRY
1139 _mesa_TextureParameteri(GLuint texture, GLenum pname, GLint param)
1140 {
1141 struct gl_texture_object *texObj;
1142 GET_CURRENT_CONTEXT(ctx);
1143
1144 texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1145 if (!texObj) {
1146 /* User passed a non-generated name. */
1147 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameteri(texture)");
1148 return;
1149 }
1150
1151 _mesa_texture_parameteri(ctx, texObj, pname, param, true);
1152 }
1153
1154 void GLAPIENTRY
1155 _mesa_TextureParameteriv(GLuint texture, GLenum pname,
1156 const GLint *params)
1157 {
1158 struct gl_texture_object *texObj;
1159 GET_CURRENT_CONTEXT(ctx);
1160
1161 texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1162 if (!texObj) {
1163 /* User passed a non-generated name. */
1164 _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureParameteriv(texture)");
1165 return;
1166 }
1167
1168 _mesa_texture_parameteriv(ctx, texObj, pname, params, true);
1169 }
1170
1171
1172 void GLAPIENTRY
1173 _mesa_TextureParameterIiv(GLuint texture, GLenum pname, const GLint *params)
1174 {
1175 struct gl_texture_object *texObj;
1176 GET_CURRENT_CONTEXT(ctx);
1177
1178 texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1179 if (!texObj) {
1180 /* User passed a non-generated name. */
1181 _mesa_error(ctx, GL_INVALID_OPERATION,
1182 "glTextureParameterIiv(texture)");
1183 return;
1184 }
1185
1186 _mesa_texture_parameterIiv(ctx, texObj, pname, params, true);
1187 }
1188
1189 void GLAPIENTRY
1190 _mesa_TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint *params)
1191 {
1192 struct gl_texture_object *texObj;
1193 GET_CURRENT_CONTEXT(ctx);
1194
1195 texObj = get_texobj_by_name(ctx, texture, GL_FALSE);
1196 if (!texObj) {
1197 /* User passed a non-generated name. */
1198 _mesa_error(ctx, GL_INVALID_OPERATION,
1199 "glTextureParameterIuiv(texture)");
1200 return;
1201 }
1202
1203 _mesa_texture_parameterIuiv(ctx, texObj, pname, params, true);
1204 }
1205
1206 static GLboolean
1207 legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target,
1208 bool dsa)
1209 {
1210 /* Common targets for desktop GL and GLES 3.1. */
1211 switch (target) {
1212 case GL_TEXTURE_2D:
1213 case GL_TEXTURE_3D:
1214 return GL_TRUE;
1215 case GL_TEXTURE_2D_ARRAY_EXT:
1216 return ctx->Extensions.EXT_texture_array;
1217 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1218 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1219 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1220 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1221 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1222 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1223 return ctx->Extensions.ARB_texture_cube_map;
1224 case GL_TEXTURE_2D_MULTISAMPLE:
1225 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1226 return ctx->Extensions.ARB_texture_multisample;
1227 }
1228
1229 if (!_mesa_is_desktop_gl(ctx))
1230 return GL_FALSE;
1231
1232 /* Rest of the desktop GL targets. */
1233 switch (target) {
1234 case GL_TEXTURE_1D:
1235 case GL_PROXY_TEXTURE_1D:
1236 case GL_PROXY_TEXTURE_2D:
1237 case GL_PROXY_TEXTURE_3D:
1238 return GL_TRUE;
1239 case GL_PROXY_TEXTURE_CUBE_MAP:
1240 return ctx->Extensions.ARB_texture_cube_map;
1241 case GL_TEXTURE_CUBE_MAP_ARRAY_ARB:
1242 case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB:
1243 return ctx->Extensions.ARB_texture_cube_map_array;
1244 case GL_TEXTURE_RECTANGLE_NV:
1245 case GL_PROXY_TEXTURE_RECTANGLE_NV:
1246 return ctx->Extensions.NV_texture_rectangle;
1247 case GL_TEXTURE_1D_ARRAY_EXT:
1248 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1249 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1250 return ctx->Extensions.EXT_texture_array;
1251 case GL_TEXTURE_BUFFER:
1252 /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts,
1253 * but not in earlier versions that expose ARB_texture_buffer_object.
1254 *
1255 * From the ARB_texture_buffer_object spec:
1256 * "(7) Do buffer textures support texture parameters (TexParameter) or
1257 * queries (GetTexParameter, GetTexLevelParameter, GetTexImage)?
1258 *
1259 * RESOLVED: No. [...] Note that the spec edits above don't add
1260 * explicit error language for any of these cases. That is because
1261 * each of the functions enumerate the set of valid <target>
1262 * parameters. Not editing the spec to allow TEXTURE_BUFFER_ARB in
1263 * these cases means that target is not legal, and an INVALID_ENUM
1264 * error should be generated."
1265 *
1266 * From the OpenGL 3.1 spec:
1267 * "target may also be TEXTURE_BUFFER, indicating the texture buffer."
1268 */
1269 return ctx->API == API_OPENGL_CORE && ctx->Version >= 31;
1270 case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
1271 case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
1272 return ctx->Extensions.ARB_texture_multisample;
1273
1274 /* This is a valid target for dsa, but the OpenGL 4.5 core spec
1275 * (30.10.2014) Section 8.11 Texture Queries says:
1276 * "For GetTextureLevelParameter* only, texture may also be a cube
1277 * map texture object. In this case the query is always performed
1278 * for face zero (the TEXTURE_CUBE_MAP_POSITIVE_X face), since there
1279 * is no way to specify another face."
1280 */
1281 case GL_TEXTURE_CUBE_MAP:
1282 return dsa;
1283 default:
1284 return GL_FALSE;
1285 }
1286 }
1287
1288
1289 static void
1290 get_tex_level_parameter_image(struct gl_context *ctx,
1291 const struct gl_texture_object *texObj,
1292 GLenum target, GLint level,
1293 GLenum pname, GLint *params,
1294 bool dsa)
1295 {
1296 const struct gl_texture_image *img = NULL;
1297 struct gl_texture_image dummy_image;
1298 mesa_format texFormat;
1299 const char *suffix = dsa ? "ture" : "";
1300
1301 img = _mesa_select_tex_image(texObj, target, level);
1302 if (!img || img->TexFormat == MESA_FORMAT_NONE) {
1303 /* In case of undefined texture image return the default values.
1304 *
1305 * From OpenGL 4.0 spec, page 398:
1306 * "The initial internal format of a texel array is RGBA
1307 * instead of 1. TEXTURE_COMPONENTS is deprecated; always
1308 * use TEXTURE_INTERNAL_FORMAT."
1309 */
1310 memset(&dummy_image, 0, sizeof(dummy_image));
1311 dummy_image.TexFormat = MESA_FORMAT_NONE;
1312 dummy_image.InternalFormat = GL_RGBA;
1313 dummy_image._BaseFormat = GL_NONE;
1314 dummy_image.FixedSampleLocations = GL_TRUE;
1315
1316 img = &dummy_image;
1317 }
1318
1319 texFormat = img->TexFormat;
1320
1321 switch (pname) {
1322 case GL_TEXTURE_WIDTH:
1323 *params = img->Width;
1324 break;
1325 case GL_TEXTURE_HEIGHT:
1326 *params = img->Height;
1327 break;
1328 case GL_TEXTURE_DEPTH:
1329 *params = img->Depth;
1330 break;
1331 case GL_TEXTURE_INTERNAL_FORMAT:
1332 if (_mesa_is_format_compressed(texFormat)) {
1333 /* need to return the actual compressed format */
1334 *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
1335 }
1336 else {
1337 /* If the true internal format is not compressed but the user
1338 * requested a generic compressed format, we have to return the
1339 * generic base format that matches.
1340 *
1341 * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
1342 *
1343 * "If no specific compressed format is available,
1344 * internalformat is instead replaced by the corresponding base
1345 * internal format."
1346 *
1347 * Otherwise just return the user's requested internal format
1348 */
1349 const GLenum f =
1350 _mesa_gl_compressed_format_base_format(img->InternalFormat);
1351
1352 *params = (f != 0) ? f : img->InternalFormat;
1353 }
1354 break;
1355 case GL_TEXTURE_BORDER:
1356 if (ctx->API != API_OPENGL_COMPAT)
1357 goto invalid_pname;
1358 *params = img->Border;
1359 break;
1360 case GL_TEXTURE_RED_SIZE:
1361 case GL_TEXTURE_GREEN_SIZE:
1362 case GL_TEXTURE_BLUE_SIZE:
1363 case GL_TEXTURE_ALPHA_SIZE:
1364 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1365 *params = _mesa_get_format_bits(texFormat, pname);
1366 else
1367 *params = 0;
1368 break;
1369 case GL_TEXTURE_INTENSITY_SIZE:
1370 case GL_TEXTURE_LUMINANCE_SIZE:
1371 if (ctx->API != API_OPENGL_COMPAT)
1372 goto invalid_pname;
1373 if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
1374 *params = _mesa_get_format_bits(texFormat, pname);
1375 if (*params == 0) {
1376 /* intensity or luminance is probably stored as RGB[A] */
1377 *params = MIN2(_mesa_get_format_bits(texFormat,
1378 GL_TEXTURE_RED_SIZE),
1379 _mesa_get_format_bits(texFormat,
1380 GL_TEXTURE_GREEN_SIZE));
1381 }
1382 }
1383 else {
1384 *params = 0;
1385 }
1386 break;
1387 case GL_TEXTURE_DEPTH_SIZE_ARB:
1388 if (!ctx->Extensions.ARB_depth_texture)
1389 goto invalid_pname;
1390 *params = _mesa_get_format_bits(texFormat, pname);
1391 break;
1392 case GL_TEXTURE_STENCIL_SIZE:
1393 *params = _mesa_get_format_bits(texFormat, pname);
1394 break;
1395 case GL_TEXTURE_SHARED_SIZE:
1396 if (ctx->Version < 30 &&
1397 !ctx->Extensions.EXT_texture_shared_exponent)
1398 goto invalid_pname;
1399 *params = texFormat == MESA_FORMAT_R9G9B9E5_FLOAT ? 5 : 0;
1400 break;
1401
1402 /* GL_ARB_texture_compression */
1403 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1404 if (_mesa_is_format_compressed(texFormat) &&
1405 !_mesa_is_proxy_texture(target)) {
1406 *params = _mesa_format_image_size(texFormat, img->Width,
1407 img->Height, img->Depth);
1408 }
1409 else {
1410 _mesa_error(ctx, GL_INVALID_OPERATION,
1411 "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1412 _mesa_enum_to_string(pname));
1413 }
1414 break;
1415 case GL_TEXTURE_COMPRESSED:
1416 *params = (GLint) _mesa_is_format_compressed(texFormat);
1417 break;
1418
1419 /* GL_ARB_texture_float */
1420 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1421 case GL_TEXTURE_INTENSITY_TYPE_ARB:
1422 if (ctx->API != API_OPENGL_COMPAT)
1423 goto invalid_pname;
1424 /* FALLTHROUGH */
1425 case GL_TEXTURE_RED_TYPE_ARB:
1426 case GL_TEXTURE_GREEN_TYPE_ARB:
1427 case GL_TEXTURE_BLUE_TYPE_ARB:
1428 case GL_TEXTURE_ALPHA_TYPE_ARB:
1429 case GL_TEXTURE_DEPTH_TYPE_ARB:
1430 if (!ctx->Extensions.ARB_texture_float)
1431 goto invalid_pname;
1432 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1433 *params = _mesa_get_format_datatype(texFormat);
1434 else
1435 *params = GL_NONE;
1436 break;
1437
1438 /* GL_ARB_texture_multisample */
1439 case GL_TEXTURE_SAMPLES:
1440 if (!ctx->Extensions.ARB_texture_multisample)
1441 goto invalid_pname;
1442 *params = img->NumSamples;
1443 break;
1444
1445 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
1446 if (!ctx->Extensions.ARB_texture_multisample)
1447 goto invalid_pname;
1448 *params = img->FixedSampleLocations;
1449 break;
1450
1451 default:
1452 goto invalid_pname;
1453 }
1454
1455 /* no error if we get here */
1456 return;
1457
1458 invalid_pname:
1459 _mesa_error(ctx, GL_INVALID_ENUM,
1460 "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1461 _mesa_enum_to_string(pname));
1462 }
1463
1464
1465 static void
1466 get_tex_level_parameter_buffer(struct gl_context *ctx,
1467 const struct gl_texture_object *texObj,
1468 GLenum pname, GLint *params, bool dsa)
1469 {
1470 const struct gl_buffer_object *bo = texObj->BufferObject;
1471 mesa_format texFormat = texObj->_BufferObjectFormat;
1472 GLenum internalFormat = texObj->BufferObjectFormat;
1473 GLenum baseFormat = _mesa_get_format_base_format(texFormat);
1474 const char *suffix = dsa ? "ture" : "";
1475
1476 if (!bo) {
1477 /* undefined texture buffer object */
1478 *params = pname == GL_TEXTURE_COMPONENTS ? 1 : 0;
1479 return;
1480 }
1481
1482 switch (pname) {
1483 case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
1484 *params = bo->Name;
1485 break;
1486 case GL_TEXTURE_WIDTH:
1487 *params = bo->Size;
1488 break;
1489 case GL_TEXTURE_HEIGHT:
1490 case GL_TEXTURE_DEPTH:
1491 case GL_TEXTURE_BORDER:
1492 case GL_TEXTURE_SHARED_SIZE:
1493 case GL_TEXTURE_COMPRESSED:
1494 *params = 0;
1495 break;
1496 case GL_TEXTURE_INTERNAL_FORMAT:
1497 *params = internalFormat;
1498 break;
1499 case GL_TEXTURE_RED_SIZE:
1500 case GL_TEXTURE_GREEN_SIZE:
1501 case GL_TEXTURE_BLUE_SIZE:
1502 case GL_TEXTURE_ALPHA_SIZE:
1503 if (_mesa_base_format_has_channel(baseFormat, pname))
1504 *params = _mesa_get_format_bits(texFormat, pname);
1505 else
1506 *params = 0;
1507 break;
1508 case GL_TEXTURE_INTENSITY_SIZE:
1509 case GL_TEXTURE_LUMINANCE_SIZE:
1510 if (_mesa_base_format_has_channel(baseFormat, pname)) {
1511 *params = _mesa_get_format_bits(texFormat, pname);
1512 if (*params == 0) {
1513 /* intensity or luminance is probably stored as RGB[A] */
1514 *params = MIN2(_mesa_get_format_bits(texFormat,
1515 GL_TEXTURE_RED_SIZE),
1516 _mesa_get_format_bits(texFormat,
1517 GL_TEXTURE_GREEN_SIZE));
1518 }
1519 } else {
1520 *params = 0;
1521 }
1522 break;
1523 case GL_TEXTURE_DEPTH_SIZE_ARB:
1524 case GL_TEXTURE_STENCIL_SIZE_EXT:
1525 *params = _mesa_get_format_bits(texFormat, pname);
1526 break;
1527
1528 /* GL_ARB_texture_buffer_range */
1529 case GL_TEXTURE_BUFFER_OFFSET:
1530 if (!ctx->Extensions.ARB_texture_buffer_range)
1531 goto invalid_pname;
1532 *params = texObj->BufferOffset;
1533 break;
1534 case GL_TEXTURE_BUFFER_SIZE:
1535 if (!ctx->Extensions.ARB_texture_buffer_range)
1536 goto invalid_pname;
1537 *params = (texObj->BufferSize == -1) ? bo->Size : texObj->BufferSize;
1538 break;
1539
1540 /* GL_ARB_texture_compression */
1541 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1542 /* Always illegal for GL_TEXTURE_BUFFER */
1543 _mesa_error(ctx, GL_INVALID_OPERATION,
1544 "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1545 _mesa_enum_to_string(pname));
1546 break;
1547
1548 /* GL_ARB_texture_float */
1549 case GL_TEXTURE_RED_TYPE_ARB:
1550 case GL_TEXTURE_GREEN_TYPE_ARB:
1551 case GL_TEXTURE_BLUE_TYPE_ARB:
1552 case GL_TEXTURE_ALPHA_TYPE_ARB:
1553 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1554 case GL_TEXTURE_INTENSITY_TYPE_ARB:
1555 case GL_TEXTURE_DEPTH_TYPE_ARB:
1556 if (!ctx->Extensions.ARB_texture_float)
1557 goto invalid_pname;
1558 if (_mesa_base_format_has_channel(baseFormat, pname))
1559 *params = _mesa_get_format_datatype(texFormat);
1560 else
1561 *params = GL_NONE;
1562 break;
1563
1564 default:
1565 goto invalid_pname;
1566 }
1567
1568 /* no error if we get here */
1569 return;
1570
1571 invalid_pname:
1572 _mesa_error(ctx, GL_INVALID_ENUM,
1573 "glGetTex%sLevelParameter[if]v(pname=%s)", suffix,
1574 _mesa_enum_to_string(pname));
1575 }
1576
1577 static bool
1578 valid_tex_level_parameteriv_target(struct gl_context *ctx, GLenum target,
1579 bool dsa)
1580 {
1581 const char *suffix = dsa ? "ture" : "";
1582 if (!legal_get_tex_level_parameter_target(ctx, target, dsa)) {
1583 _mesa_error(ctx, GL_INVALID_ENUM,
1584 "glGetTex%sLevelParameter[if]v(target=%s)", suffix,
1585 _mesa_enum_to_string(target));
1586 return false;
1587 }
1588 return true;
1589 }
1590
1591 /**
1592 * This isn't exposed to the rest of the driver because it is a part of the
1593 * OpenGL API that is rarely used.
1594 */
1595 static void
1596 get_tex_level_parameteriv(struct gl_context *ctx,
1597 struct gl_texture_object *texObj,
1598 GLenum target, GLint level,
1599 GLenum pname, GLint *params,
1600 bool dsa)
1601 {
1602 GLint maxLevels;
1603 const char *suffix = dsa ? "ture" : "";
1604
1605 /* Check for errors */
1606 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
1607 _mesa_error(ctx, GL_INVALID_OPERATION,
1608 "glGetTex%sLevelParameter[if]v("
1609 "current unit >= max combined texture units)", suffix);
1610 return;
1611 }
1612
1613 maxLevels = _mesa_max_texture_levels(ctx, target);
1614 assert(maxLevels != 0);
1615
1616 if (level < 0 || level >= maxLevels) {
1617 _mesa_error(ctx, GL_INVALID_VALUE,
1618 "glGetTex%sLevelParameter[if]v(level out of range)", suffix);
1619 return;
1620 }
1621
1622 /* Get the level parameter */
1623 if (target == GL_TEXTURE_BUFFER) {
1624 get_tex_level_parameter_buffer(ctx, texObj, pname, params, dsa);
1625 }
1626 else {
1627 get_tex_level_parameter_image(ctx, texObj, target,
1628 level, pname, params, dsa);
1629 }
1630 }
1631
1632 void GLAPIENTRY
1633 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
1634 GLenum pname, GLfloat *params )
1635 {
1636 struct gl_texture_object *texObj;
1637 GLint iparam;
1638 GET_CURRENT_CONTEXT(ctx);
1639
1640 if (!valid_tex_level_parameteriv_target(ctx, target, false))
1641 return;
1642
1643 texObj = _mesa_get_current_tex_object(ctx, target);
1644 if (!texObj)
1645 return;
1646
1647 get_tex_level_parameteriv(ctx, texObj, target, level,
1648 pname, &iparam, false);
1649
1650 *params = (GLfloat) iparam;
1651 }
1652
1653 void GLAPIENTRY
1654 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
1655 GLenum pname, GLint *params )
1656 {
1657 struct gl_texture_object *texObj;
1658 GET_CURRENT_CONTEXT(ctx);
1659
1660 if (!valid_tex_level_parameteriv_target(ctx, target, false))
1661 return;
1662
1663 texObj = _mesa_get_current_tex_object(ctx, target);
1664 if (!texObj)
1665 return;
1666
1667 get_tex_level_parameteriv(ctx, texObj, target, level,
1668 pname, params, false);
1669 }
1670
1671 void GLAPIENTRY
1672 _mesa_GetTextureLevelParameterfv(GLuint texture, GLint level,
1673 GLenum pname, GLfloat *params)
1674 {
1675 struct gl_texture_object *texObj;
1676 GLint iparam;
1677 GET_CURRENT_CONTEXT(ctx);
1678
1679 texObj = _mesa_lookup_texture_err(ctx, texture,
1680 "glGetTextureLevelParameterfv");
1681 if (!texObj)
1682 return;
1683
1684 if (!valid_tex_level_parameteriv_target(ctx, texObj->Target, true))
1685 return;
1686
1687 get_tex_level_parameteriv(ctx, texObj, texObj->Target, level,
1688 pname, &iparam, true);
1689
1690 *params = (GLfloat) iparam;
1691 }
1692
1693 void GLAPIENTRY
1694 _mesa_GetTextureLevelParameteriv(GLuint texture, GLint level,
1695 GLenum pname, GLint *params)
1696 {
1697 struct gl_texture_object *texObj;
1698 GET_CURRENT_CONTEXT(ctx);
1699
1700 texObj = _mesa_lookup_texture_err(ctx, texture,
1701 "glGetTextureLevelParameteriv");
1702 if (!texObj)
1703 return;
1704
1705 if (!valid_tex_level_parameteriv_target(ctx, texObj->Target, true))
1706 return;
1707
1708 get_tex_level_parameteriv(ctx, texObj, texObj->Target, level,
1709 pname, params, true);
1710 }
1711
1712 /**
1713 * This isn't exposed to the rest of the driver because it is a part of the
1714 * OpenGL API that is rarely used.
1715 */
1716 static void
1717 get_tex_parameterfv(struct gl_context *ctx,
1718 struct gl_texture_object *obj,
1719 GLenum pname, GLfloat *params, bool dsa)
1720 {
1721 _mesa_lock_context_textures(ctx);
1722 switch (pname) {
1723 case GL_TEXTURE_MAG_FILTER:
1724 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
1725 break;
1726 case GL_TEXTURE_MIN_FILTER:
1727 *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter);
1728 break;
1729 case GL_TEXTURE_WRAP_S:
1730 *params = ENUM_TO_FLOAT(obj->Sampler.WrapS);
1731 break;
1732 case GL_TEXTURE_WRAP_T:
1733 *params = ENUM_TO_FLOAT(obj->Sampler.WrapT);
1734 break;
1735 case GL_TEXTURE_WRAP_R:
1736 *params = ENUM_TO_FLOAT(obj->Sampler.WrapR);
1737 break;
1738 case GL_TEXTURE_BORDER_COLOR:
1739 if (ctx->API == API_OPENGLES ||
1740 !ctx->Extensions.ARB_texture_border_clamp)
1741 goto invalid_pname;
1742
1743 if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
1744 _mesa_update_state_locked(ctx);
1745 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) {
1746 params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1747 params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1748 params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1749 params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1750 }
1751 else {
1752 params[0] = obj->Sampler.BorderColor.f[0];
1753 params[1] = obj->Sampler.BorderColor.f[1];
1754 params[2] = obj->Sampler.BorderColor.f[2];
1755 params[3] = obj->Sampler.BorderColor.f[3];
1756 }
1757 break;
1758 case GL_TEXTURE_RESIDENT:
1759 if (ctx->API != API_OPENGL_COMPAT)
1760 goto invalid_pname;
1761
1762 *params = 1.0F;
1763 break;
1764 case GL_TEXTURE_PRIORITY:
1765 if (ctx->API != API_OPENGL_COMPAT)
1766 goto invalid_pname;
1767
1768 *params = obj->Priority;
1769 break;
1770 case GL_TEXTURE_MIN_LOD:
1771 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1772 goto invalid_pname;
1773
1774 *params = obj->Sampler.MinLod;
1775 break;
1776 case GL_TEXTURE_MAX_LOD:
1777 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1778 goto invalid_pname;
1779
1780 *params = obj->Sampler.MaxLod;
1781 break;
1782 case GL_TEXTURE_BASE_LEVEL:
1783 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1784 goto invalid_pname;
1785
1786 *params = (GLfloat) obj->BaseLevel;
1787 break;
1788 case GL_TEXTURE_MAX_LEVEL:
1789 *params = (GLfloat) obj->MaxLevel;
1790 break;
1791 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1792 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1793 goto invalid_pname;
1794 *params = obj->Sampler.MaxAnisotropy;
1795 break;
1796 case GL_GENERATE_MIPMAP_SGIS:
1797 if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
1798 goto invalid_pname;
1799
1800 *params = (GLfloat) obj->GenerateMipmap;
1801 break;
1802 case GL_TEXTURE_COMPARE_MODE_ARB:
1803 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1804 && !_mesa_is_gles3(ctx))
1805 goto invalid_pname;
1806 *params = (GLfloat) obj->Sampler.CompareMode;
1807 break;
1808 case GL_TEXTURE_COMPARE_FUNC_ARB:
1809 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1810 && !_mesa_is_gles3(ctx))
1811 goto invalid_pname;
1812 *params = (GLfloat) obj->Sampler.CompareFunc;
1813 break;
1814 case GL_DEPTH_TEXTURE_MODE_ARB:
1815 /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has
1816 * never existed in OpenGL ES.
1817 */
1818 if (ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_depth_texture)
1819 goto invalid_pname;
1820 *params = (GLfloat) obj->DepthMode;
1821 break;
1822 case GL_DEPTH_STENCIL_TEXTURE_MODE:
1823 if (!_mesa_has_ARB_stencil_texturing(ctx) && !_mesa_is_gles31(ctx))
1824 goto invalid_pname;
1825 *params = (GLfloat)
1826 (obj->StencilSampling ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT);
1827 break;
1828 case GL_TEXTURE_LOD_BIAS:
1829 if (_mesa_is_gles(ctx))
1830 goto invalid_pname;
1831
1832 *params = obj->Sampler.LodBias;
1833 break;
1834 case GL_TEXTURE_CROP_RECT_OES:
1835 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
1836 goto invalid_pname;
1837
1838 params[0] = (GLfloat) obj->CropRect[0];
1839 params[1] = (GLfloat) obj->CropRect[1];
1840 params[2] = (GLfloat) obj->CropRect[2];
1841 params[3] = (GLfloat) obj->CropRect[3];
1842 break;
1843
1844 case GL_TEXTURE_SWIZZLE_R_EXT:
1845 case GL_TEXTURE_SWIZZLE_G_EXT:
1846 case GL_TEXTURE_SWIZZLE_B_EXT:
1847 case GL_TEXTURE_SWIZZLE_A_EXT:
1848 if ((!_mesa_is_desktop_gl(ctx)
1849 || !ctx->Extensions.EXT_texture_swizzle)
1850 && !_mesa_is_gles3(ctx))
1851 goto invalid_pname;
1852 *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1853 break;
1854
1855 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1856 if ((!_mesa_is_desktop_gl(ctx)
1857 || !ctx->Extensions.EXT_texture_swizzle)
1858 && !_mesa_is_gles3(ctx)) {
1859 goto invalid_pname;
1860 }
1861 else {
1862 GLuint comp;
1863 for (comp = 0; comp < 4; comp++) {
1864 params[comp] = (GLfloat) obj->Swizzle[comp];
1865 }
1866 }
1867 break;
1868
1869 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1870 if (!_mesa_is_desktop_gl(ctx)
1871 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
1872 goto invalid_pname;
1873 *params = (GLfloat) obj->Sampler.CubeMapSeamless;
1874 break;
1875
1876 case GL_TEXTURE_IMMUTABLE_FORMAT:
1877 *params = (GLfloat) obj->Immutable;
1878 break;
1879
1880 case GL_TEXTURE_IMMUTABLE_LEVELS:
1881 if (_mesa_is_gles3(ctx) ||
1882 (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_view))
1883 *params = (GLfloat) obj->ImmutableLevels;
1884 else
1885 goto invalid_pname;
1886 break;
1887
1888 case GL_TEXTURE_VIEW_MIN_LEVEL:
1889 if (!ctx->Extensions.ARB_texture_view)
1890 goto invalid_pname;
1891 *params = (GLfloat) obj->MinLevel;
1892 break;
1893
1894 case GL_TEXTURE_VIEW_NUM_LEVELS:
1895 if (!ctx->Extensions.ARB_texture_view)
1896 goto invalid_pname;
1897 *params = (GLfloat) obj->NumLevels;
1898 break;
1899
1900 case GL_TEXTURE_VIEW_MIN_LAYER:
1901 if (!ctx->Extensions.ARB_texture_view)
1902 goto invalid_pname;
1903 *params = (GLfloat) obj->MinLayer;
1904 break;
1905
1906 case GL_TEXTURE_VIEW_NUM_LAYERS:
1907 if (!ctx->Extensions.ARB_texture_view)
1908 goto invalid_pname;
1909 *params = (GLfloat) obj->NumLayers;
1910 break;
1911
1912 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1913 if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)
1914 goto invalid_pname;
1915 *params = (GLfloat) obj->RequiredTextureImageUnits;
1916 break;
1917
1918 case GL_TEXTURE_SRGB_DECODE_EXT:
1919 if (!ctx->Extensions.EXT_texture_sRGB_decode)
1920 goto invalid_pname;
1921 *params = (GLfloat) obj->Sampler.sRGBDecode;
1922 break;
1923
1924 case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
1925 if (!ctx->Extensions.ARB_shader_image_load_store)
1926 goto invalid_pname;
1927 *params = (GLfloat) obj->ImageFormatCompatibilityType;
1928 break;
1929
1930 case GL_TEXTURE_TARGET:
1931 if (ctx->API != API_OPENGL_CORE)
1932 goto invalid_pname;
1933 *params = ENUM_TO_FLOAT(obj->Target);
1934 break;
1935
1936 default:
1937 goto invalid_pname;
1938 }
1939
1940 /* no error if we get here */
1941 _mesa_unlock_context_textures(ctx);
1942 return;
1943
1944 invalid_pname:
1945 _mesa_unlock_context_textures(ctx);
1946 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sParameterfv(pname=0x%x)",
1947 dsa ? "ture" : "", pname);
1948 }
1949
1950
1951 static void
1952 get_tex_parameteriv(struct gl_context *ctx,
1953 struct gl_texture_object *obj,
1954 GLenum pname, GLint *params, bool dsa)
1955 {
1956 _mesa_lock_texture(ctx, obj);
1957 switch (pname) {
1958 case GL_TEXTURE_MAG_FILTER:
1959 *params = (GLint) obj->Sampler.MagFilter;
1960 break;
1961 case GL_TEXTURE_MIN_FILTER:
1962 *params = (GLint) obj->Sampler.MinFilter;
1963 break;
1964 case GL_TEXTURE_WRAP_S:
1965 *params = (GLint) obj->Sampler.WrapS;
1966 break;
1967 case GL_TEXTURE_WRAP_T:
1968 *params = (GLint) obj->Sampler.WrapT;
1969 break;
1970 case GL_TEXTURE_WRAP_R:
1971 *params = (GLint) obj->Sampler.WrapR;
1972 break;
1973 case GL_TEXTURE_BORDER_COLOR:
1974 if (ctx->API == API_OPENGLES ||
1975 !ctx->Extensions.ARB_texture_border_clamp)
1976 goto invalid_pname;
1977
1978 {
1979 GLfloat b[4];
1980 b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1981 b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1982 b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1983 b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1984 params[0] = FLOAT_TO_INT(b[0]);
1985 params[1] = FLOAT_TO_INT(b[1]);
1986 params[2] = FLOAT_TO_INT(b[2]);
1987 params[3] = FLOAT_TO_INT(b[3]);
1988 }
1989 break;
1990 case GL_TEXTURE_RESIDENT:
1991 if (ctx->API != API_OPENGL_COMPAT)
1992 goto invalid_pname;
1993
1994 *params = 1;
1995 break;
1996 case GL_TEXTURE_PRIORITY:
1997 if (ctx->API != API_OPENGL_COMPAT)
1998 goto invalid_pname;
1999
2000 *params = FLOAT_TO_INT(obj->Priority);
2001 break;
2002 case GL_TEXTURE_MIN_LOD:
2003 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
2004 goto invalid_pname;
2005 /* GL spec 'Data Conversions' section specifies that floating-point
2006 * value in integer Get function is rounded to nearest integer
2007 */
2008 *params = IROUND(obj->Sampler.MinLod);
2009 break;
2010 case GL_TEXTURE_MAX_LOD:
2011 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
2012 goto invalid_pname;
2013 /* GL spec 'Data Conversions' section specifies that floating-point
2014 * value in integer Get function is rounded to nearest integer
2015 */
2016 *params = IROUND(obj->Sampler.MaxLod);
2017 break;
2018 case GL_TEXTURE_BASE_LEVEL:
2019 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
2020 goto invalid_pname;
2021
2022 *params = obj->BaseLevel;
2023 break;
2024 case GL_TEXTURE_MAX_LEVEL:
2025 *params = obj->MaxLevel;
2026 break;
2027 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
2028 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
2029 goto invalid_pname;
2030 /* GL spec 'Data Conversions' section specifies that floating-point
2031 * value in integer Get function is rounded to nearest integer
2032 */
2033 *params = IROUND(obj->Sampler.MaxAnisotropy);
2034 break;
2035 case GL_GENERATE_MIPMAP_SGIS:
2036 if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
2037 goto invalid_pname;
2038
2039 *params = (GLint) obj->GenerateMipmap;
2040 break;
2041 case GL_TEXTURE_COMPARE_MODE_ARB:
2042 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
2043 && !_mesa_is_gles3(ctx))
2044 goto invalid_pname;
2045 *params = (GLint) obj->Sampler.CompareMode;
2046 break;
2047 case GL_TEXTURE_COMPARE_FUNC_ARB:
2048 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
2049 && !_mesa_is_gles3(ctx))
2050 goto invalid_pname;
2051 *params = (GLint) obj->Sampler.CompareFunc;
2052 break;
2053 case GL_DEPTH_TEXTURE_MODE_ARB:
2054 if (ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_depth_texture)
2055 goto invalid_pname;
2056 *params = (GLint) obj->DepthMode;
2057 break;
2058 case GL_DEPTH_STENCIL_TEXTURE_MODE:
2059 if (!_mesa_has_ARB_stencil_texturing(ctx) && !_mesa_is_gles31(ctx))
2060 goto invalid_pname;
2061 *params = (GLint)
2062 (obj->StencilSampling ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT);
2063 break;
2064 case GL_TEXTURE_LOD_BIAS:
2065 if (_mesa_is_gles(ctx))
2066 goto invalid_pname;
2067
2068 /* GL spec 'Data Conversions' section specifies that floating-point
2069 * value in integer Get function is rounded to nearest integer
2070 */
2071 *params = IROUND(obj->Sampler.LodBias);
2072 break;
2073 case GL_TEXTURE_CROP_RECT_OES:
2074 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
2075 goto invalid_pname;
2076
2077 params[0] = obj->CropRect[0];
2078 params[1] = obj->CropRect[1];
2079 params[2] = obj->CropRect[2];
2080 params[3] = obj->CropRect[3];
2081 break;
2082 case GL_TEXTURE_SWIZZLE_R_EXT:
2083 case GL_TEXTURE_SWIZZLE_G_EXT:
2084 case GL_TEXTURE_SWIZZLE_B_EXT:
2085 case GL_TEXTURE_SWIZZLE_A_EXT:
2086 if ((!_mesa_is_desktop_gl(ctx)
2087 || !ctx->Extensions.EXT_texture_swizzle)
2088 && !_mesa_is_gles3(ctx))
2089 goto invalid_pname;
2090 *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
2091 break;
2092
2093 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
2094 if ((!_mesa_is_desktop_gl(ctx)
2095 || !ctx->Extensions.EXT_texture_swizzle)
2096 && !_mesa_is_gles3(ctx))
2097 goto invalid_pname;
2098 COPY_4V(params, obj->Swizzle);
2099 break;
2100
2101 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
2102 if (!_mesa_is_desktop_gl(ctx)
2103 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
2104 goto invalid_pname;
2105 *params = (GLint) obj->Sampler.CubeMapSeamless;
2106 break;
2107
2108 case GL_TEXTURE_IMMUTABLE_FORMAT:
2109 *params = (GLint) obj->Immutable;
2110 break;
2111
2112 case GL_TEXTURE_IMMUTABLE_LEVELS:
2113 if (_mesa_is_gles3(ctx) ||
2114 (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_view))
2115 *params = obj->ImmutableLevels;
2116 else
2117 goto invalid_pname;
2118 break;
2119
2120 case GL_TEXTURE_VIEW_MIN_LEVEL:
2121 if (!ctx->Extensions.ARB_texture_view)
2122 goto invalid_pname;
2123 *params = (GLint) obj->MinLevel;
2124 break;
2125
2126 case GL_TEXTURE_VIEW_NUM_LEVELS:
2127 if (!ctx->Extensions.ARB_texture_view)
2128 goto invalid_pname;
2129 *params = (GLint) obj->NumLevels;
2130 break;
2131
2132 case GL_TEXTURE_VIEW_MIN_LAYER:
2133 if (!ctx->Extensions.ARB_texture_view)
2134 goto invalid_pname;
2135 *params = (GLint) obj->MinLayer;
2136 break;
2137
2138 case GL_TEXTURE_VIEW_NUM_LAYERS:
2139 if (!ctx->Extensions.ARB_texture_view)
2140 goto invalid_pname;
2141 *params = (GLint) obj->NumLayers;
2142 break;
2143
2144 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2145 if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)
2146 goto invalid_pname;
2147 *params = obj->RequiredTextureImageUnits;
2148 break;
2149
2150 case GL_TEXTURE_SRGB_DECODE_EXT:
2151 if (!ctx->Extensions.EXT_texture_sRGB_decode)
2152 goto invalid_pname;
2153 *params = obj->Sampler.sRGBDecode;
2154 break;
2155
2156 case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
2157 if (!ctx->Extensions.ARB_shader_image_load_store)
2158 goto invalid_pname;
2159 *params = obj->ImageFormatCompatibilityType;
2160 break;
2161
2162 case GL_TEXTURE_TARGET:
2163 if (ctx->API != API_OPENGL_CORE)
2164 goto invalid_pname;
2165 *params = (GLint) obj->Target;
2166 break;
2167
2168 default:
2169 goto invalid_pname;
2170 }
2171
2172 /* no error if we get here */
2173 _mesa_unlock_texture(ctx, obj);
2174 return;
2175
2176 invalid_pname:
2177 _mesa_unlock_texture(ctx, obj);
2178 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTex%sParameteriv(pname=0x%x)",
2179 dsa ? "ture" : "", pname);
2180 }
2181
2182 static void
2183 get_tex_parameterIiv(struct gl_context *ctx,
2184 struct gl_texture_object *obj,
2185 GLenum pname, GLint *params, bool dsa)
2186 {
2187 switch (pname) {
2188 case GL_TEXTURE_BORDER_COLOR:
2189 COPY_4V(params, obj->Sampler.BorderColor.i);
2190 break;
2191 default:
2192 get_tex_parameteriv(ctx, obj, pname, params, dsa);
2193 }
2194 }
2195
2196 static void
2197 get_tex_parameterIuiv(struct gl_context *ctx,
2198 struct gl_texture_object *obj,
2199 GLenum pname, GLuint *params, bool dsa)
2200 {
2201 switch (pname) {
2202 case GL_TEXTURE_BORDER_COLOR:
2203 COPY_4V(params, obj->Sampler.BorderColor.i);
2204 break;
2205 default:
2206 {
2207 GLint ip[4];
2208 get_tex_parameteriv(ctx, obj, pname, ip, dsa);
2209 params[0] = ip[0];
2210 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
2211 pname == GL_TEXTURE_CROP_RECT_OES) {
2212 params[1] = ip[1];
2213 params[2] = ip[2];
2214 params[3] = ip[3];
2215 }
2216 }
2217 }
2218 }
2219
2220 void GLAPIENTRY
2221 _mesa_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
2222 {
2223 struct gl_texture_object *obj;
2224 GET_CURRENT_CONTEXT(ctx);
2225
2226 obj = get_texobj_by_target(ctx, target, GL_TRUE);
2227 if (!obj)
2228 return;
2229
2230 get_tex_parameterfv(ctx, obj, pname, params, false);
2231 }
2232
2233 void GLAPIENTRY
2234 _mesa_GetTexParameteriv(GLenum target, GLenum pname, GLint *params)
2235 {
2236 struct gl_texture_object *obj;
2237 GET_CURRENT_CONTEXT(ctx);
2238
2239 obj = get_texobj_by_target(ctx, target, GL_TRUE);
2240 if (!obj)
2241 return;
2242
2243 get_tex_parameteriv(ctx, obj, pname, params, false);
2244 }
2245
2246 /** New in GL 3.0 */
2247 void GLAPIENTRY
2248 _mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
2249 {
2250 struct gl_texture_object *texObj;
2251 GET_CURRENT_CONTEXT(ctx);
2252
2253 texObj = get_texobj_by_target(ctx, target, GL_TRUE);
2254 if (!texObj)
2255 return;
2256
2257 get_tex_parameterIiv(ctx, texObj, pname, params, false);
2258 }
2259
2260
2261 /** New in GL 3.0 */
2262 void GLAPIENTRY
2263 _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
2264 {
2265 struct gl_texture_object *texObj;
2266 GET_CURRENT_CONTEXT(ctx);
2267
2268 texObj = get_texobj_by_target(ctx, target, GL_TRUE);
2269 if (!texObj)
2270 return;
2271
2272 get_tex_parameterIuiv(ctx, texObj, pname, params, false);
2273 }
2274
2275
2276 void GLAPIENTRY
2277 _mesa_GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat *params)
2278 {
2279 struct gl_texture_object *obj;
2280 GET_CURRENT_CONTEXT(ctx);
2281
2282 obj = get_texobj_by_name(ctx, texture, GL_TRUE);
2283 if (!obj) {
2284 /* User passed a non-generated name. */
2285 _mesa_error(ctx, GL_INVALID_OPERATION,
2286 "glGetTextureParameterfv(texture)");
2287 return;
2288 }
2289
2290 get_tex_parameterfv(ctx, obj, pname, params, true);
2291 }
2292
2293 void GLAPIENTRY
2294 _mesa_GetTextureParameteriv(GLuint texture, GLenum pname, GLint *params)
2295 {
2296 struct gl_texture_object *obj;
2297 GET_CURRENT_CONTEXT(ctx);
2298
2299 obj = get_texobj_by_name(ctx, texture, GL_TRUE);
2300 if (!obj) {
2301 /* User passed a non-generated name. */
2302 _mesa_error(ctx, GL_INVALID_OPERATION,
2303 "glGetTextureParameteriv(texture)");
2304 return;
2305 }
2306
2307 get_tex_parameteriv(ctx, obj, pname, params, true);
2308 }
2309
2310 void GLAPIENTRY
2311 _mesa_GetTextureParameterIiv(GLuint texture, GLenum pname, GLint *params)
2312 {
2313 struct gl_texture_object *texObj;
2314 GET_CURRENT_CONTEXT(ctx);
2315
2316 texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
2317 if (!texObj) {
2318 /* User passed a non-generated name. */
2319 _mesa_error(ctx, GL_INVALID_OPERATION,
2320 "glGetTextureParameterIiv(texture)");
2321 return;
2322 }
2323
2324 get_tex_parameterIiv(ctx, texObj, pname, params, true);
2325 }
2326
2327
2328 void GLAPIENTRY
2329 _mesa_GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint *params)
2330 {
2331 struct gl_texture_object *texObj;
2332 GET_CURRENT_CONTEXT(ctx);
2333
2334 texObj = get_texobj_by_name(ctx, texture, GL_TRUE);
2335 if (!texObj) {
2336 /* User passed a non-generated name. */
2337 _mesa_error(ctx, GL_INVALID_OPERATION,
2338 "glGetTextureParameterIuiv(texture)");
2339 return;
2340 }
2341
2342 get_tex_parameterIuiv(ctx, texObj, pname, params, true);
2343 }