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