mesa: remove FEATURE_OES_draw_texture define.
[mesa.git] / src / mesa / main / texparam.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.5
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 /**
27 * \file texparam.c
28 *
29 * glTexParameter-related functions
30 */
31
32 #include <stdbool.h>
33 #include "main/glheader.h"
34 #include "main/colormac.h"
35 #include "main/context.h"
36 #include "main/enums.h"
37 #include "main/formats.h"
38 #include "main/glformats.h"
39 #include "main/macros.h"
40 #include "main/mfeatures.h"
41 #include "main/mtypes.h"
42 #include "main/state.h"
43 #include "main/texcompress.h"
44 #include "main/texobj.h"
45 #include "main/texparam.h"
46 #include "main/teximage.h"
47 #include "main/texstate.h"
48 #include "program/prog_instruction.h"
49
50
51 /**
52 * Check if a coordinate wrap mode is supported for the texture target.
53 * \return GL_TRUE if legal, GL_FALSE otherwise
54 */
55 static GLboolean
56 validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap)
57 {
58 const struct gl_extensions * const e = & ctx->Extensions;
59 const bool is_desktop_gl = _mesa_is_desktop_gl(ctx);
60 bool supported;
61
62 switch (wrap) {
63 case GL_CLAMP:
64 /* GL_CLAMP was removed in the core profile, and it has never existed in
65 * OpenGL ES.
66 */
67 supported = (ctx->API == API_OPENGL)
68 && (target != GL_TEXTURE_EXTERNAL_OES);
69 break;
70
71 case GL_CLAMP_TO_EDGE:
72 supported = true;
73 break;
74
75 case GL_CLAMP_TO_BORDER:
76 supported = is_desktop_gl && e->ARB_texture_border_clamp
77 && (target != GL_TEXTURE_EXTERNAL_OES);
78 break;
79
80 case GL_REPEAT:
81 case GL_MIRRORED_REPEAT:
82 supported = (target != GL_TEXTURE_RECTANGLE_NV)
83 && (target != GL_TEXTURE_EXTERNAL_OES);
84 break;
85
86 case GL_MIRROR_CLAMP_EXT:
87 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
88 supported = is_desktop_gl
89 && (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)
90 && (target != GL_TEXTURE_RECTANGLE_NV)
91 && (target != GL_TEXTURE_EXTERNAL_OES);
92 break;
93
94 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
95 supported = is_desktop_gl && e->EXT_texture_mirror_clamp
96 && (target != GL_TEXTURE_RECTANGLE_NV)
97 && (target != GL_TEXTURE_EXTERNAL_OES);
98 break;
99
100 default:
101 supported = false;
102 break;
103 }
104
105 if (!supported)
106 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", wrap );
107
108 return supported;
109 }
110
111
112 /**
113 * Get current texture object for given target.
114 * Return NULL if any error (and record the error).
115 * Note that this is different from _mesa_select_tex_object() in that proxy
116 * targets are not accepted.
117 * Only the glGetTexLevelParameter() functions accept proxy targets.
118 */
119 static struct gl_texture_object *
120 get_texobj(struct gl_context *ctx, GLenum target, GLboolean get)
121 {
122 struct gl_texture_unit *texUnit;
123
124 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
125 _mesa_error(ctx, GL_INVALID_OPERATION,
126 "gl%sTexParameter(current unit)", get ? "Get" : "");
127 return NULL;
128 }
129
130 texUnit = _mesa_get_current_tex_unit(ctx);
131
132 switch (target) {
133 case GL_TEXTURE_1D:
134 if (_mesa_is_desktop_gl(ctx))
135 return texUnit->CurrentTex[TEXTURE_1D_INDEX];
136 break;
137 case GL_TEXTURE_2D:
138 return texUnit->CurrentTex[TEXTURE_2D_INDEX];
139 case GL_TEXTURE_3D:
140 if (ctx->API != API_OPENGLES)
141 return texUnit->CurrentTex[TEXTURE_3D_INDEX];
142 break;
143 case GL_TEXTURE_CUBE_MAP:
144 if (ctx->Extensions.ARB_texture_cube_map) {
145 return texUnit->CurrentTex[TEXTURE_CUBE_INDEX];
146 }
147 break;
148 case GL_TEXTURE_RECTANGLE_NV:
149 if (_mesa_is_desktop_gl(ctx)
150 && ctx->Extensions.NV_texture_rectangle) {
151 return texUnit->CurrentTex[TEXTURE_RECT_INDEX];
152 }
153 break;
154 case GL_TEXTURE_1D_ARRAY_EXT:
155 if (_mesa_is_desktop_gl(ctx)
156 && (ctx->Extensions.MESA_texture_array ||
157 ctx->Extensions.EXT_texture_array)) {
158 return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX];
159 }
160 break;
161 case GL_TEXTURE_2D_ARRAY_EXT:
162 if ((_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
163 && (ctx->Extensions.MESA_texture_array ||
164 ctx->Extensions.EXT_texture_array)) {
165 return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX];
166 }
167 break;
168 case GL_TEXTURE_EXTERNAL_OES:
169 if (_mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external) {
170 return texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX];
171 }
172 break;
173 default:
174 ;
175 }
176
177 _mesa_error(ctx, GL_INVALID_ENUM,
178 "gl%sTexParameter(target)", get ? "Get" : "");
179 return NULL;
180 }
181
182
183 /**
184 * Convert GL_RED/GREEN/BLUE/ALPHA/ZERO/ONE to SWIZZLE_X/Y/Z/W/ZERO/ONE.
185 * \return -1 if error.
186 */
187 static GLint
188 comp_to_swizzle(GLenum comp)
189 {
190 switch (comp) {
191 case GL_RED:
192 return SWIZZLE_X;
193 case GL_GREEN:
194 return SWIZZLE_Y;
195 case GL_BLUE:
196 return SWIZZLE_Z;
197 case GL_ALPHA:
198 return SWIZZLE_W;
199 case GL_ZERO:
200 return SWIZZLE_ZERO;
201 case GL_ONE:
202 return SWIZZLE_ONE;
203 default:
204 return -1;
205 }
206 }
207
208
209 static void
210 set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
211 {
212 ASSERT(comp < 4);
213 ASSERT(swz <= SWIZZLE_NIL);
214 {
215 GLuint mask = 0x7 << (3 * comp);
216 GLuint s = (*swizzle & ~mask) | (swz << (3 * comp));
217 *swizzle = s;
218 }
219 }
220
221
222 /**
223 * This is called just prior to changing any texture object state which
224 * will not effect texture completeness.
225 */
226 static inline void
227 flush(struct gl_context *ctx)
228 {
229 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
230 }
231
232
233 /**
234 * This is called just prior to changing any texture object state which
235 * can effect texture completeness (texture base level, max level).
236 * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE
237 * state flag and then mark the texture object as 'incomplete' so that any
238 * per-texture derived state gets recomputed.
239 */
240 static inline void
241 incomplete(struct gl_context *ctx, struct gl_texture_object *texObj)
242 {
243 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
244 _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
245 }
246
247
248 /**
249 * Set an integer-valued texture parameter
250 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
251 */
252 static GLboolean
253 set_tex_parameteri(struct gl_context *ctx,
254 struct gl_texture_object *texObj,
255 GLenum pname, const GLint *params)
256 {
257 switch (pname) {
258 case GL_TEXTURE_MIN_FILTER:
259 if (texObj->Sampler.MinFilter == params[0])
260 return GL_FALSE;
261 switch (params[0]) {
262 case GL_NEAREST:
263 case GL_LINEAR:
264 flush(ctx);
265 texObj->Sampler.MinFilter = params[0];
266 return GL_TRUE;
267 case GL_NEAREST_MIPMAP_NEAREST:
268 case GL_LINEAR_MIPMAP_NEAREST:
269 case GL_NEAREST_MIPMAP_LINEAR:
270 case GL_LINEAR_MIPMAP_LINEAR:
271 if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
272 texObj->Target != GL_TEXTURE_EXTERNAL_OES) {
273 flush(ctx);
274 texObj->Sampler.MinFilter = params[0];
275 return GL_TRUE;
276 }
277 /* fall-through */
278 default:
279 goto invalid_param;
280 }
281 return GL_FALSE;
282
283 case GL_TEXTURE_MAG_FILTER:
284 if (texObj->Sampler.MagFilter == params[0])
285 return GL_FALSE;
286 switch (params[0]) {
287 case GL_NEAREST:
288 case GL_LINEAR:
289 flush(ctx); /* does not effect completeness */
290 texObj->Sampler.MagFilter = params[0];
291 return GL_TRUE;
292 default:
293 goto invalid_param;
294 }
295 return GL_FALSE;
296
297 case GL_TEXTURE_WRAP_S:
298 if (texObj->Sampler.WrapS == params[0])
299 return GL_FALSE;
300 if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
301 flush(ctx);
302 texObj->Sampler.WrapS = params[0];
303 return GL_TRUE;
304 }
305 return GL_FALSE;
306
307 case GL_TEXTURE_WRAP_T:
308 if (texObj->Sampler.WrapT == params[0])
309 return GL_FALSE;
310 if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
311 flush(ctx);
312 texObj->Sampler.WrapT = params[0];
313 return GL_TRUE;
314 }
315 return GL_FALSE;
316
317 case GL_TEXTURE_WRAP_R:
318 if (texObj->Sampler.WrapR == params[0])
319 return GL_FALSE;
320 if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
321 flush(ctx);
322 texObj->Sampler.WrapR = params[0];
323 return GL_TRUE;
324 }
325 return GL_FALSE;
326
327 case GL_TEXTURE_BASE_LEVEL:
328 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
329 goto invalid_pname;
330
331 if (texObj->BaseLevel == params[0])
332 return GL_FALSE;
333 if (params[0] < 0 ||
334 (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
335 _mesa_error(ctx, GL_INVALID_VALUE,
336 "glTexParameter(param=%d)", params[0]);
337 return GL_FALSE;
338 }
339 incomplete(ctx, texObj);
340 texObj->BaseLevel = params[0];
341 return GL_TRUE;
342
343 case GL_TEXTURE_MAX_LEVEL:
344 if (texObj->MaxLevel == params[0])
345 return GL_FALSE;
346 if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
347 _mesa_error(ctx, GL_INVALID_OPERATION,
348 "glTexParameter(param=%d)", params[0]);
349 return GL_FALSE;
350 }
351 incomplete(ctx, texObj);
352 texObj->MaxLevel = params[0];
353 return GL_TRUE;
354
355 case GL_GENERATE_MIPMAP_SGIS:
356 if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES)
357 goto invalid_pname;
358
359 if (params[0] && texObj->Target == GL_TEXTURE_EXTERNAL_OES)
360 goto invalid_param;
361 if (texObj->GenerateMipmap != params[0]) {
362 /* no flush() */
363 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
364 return GL_TRUE;
365 }
366 return GL_FALSE;
367
368 case GL_TEXTURE_COMPARE_MODE_ARB:
369 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow)
370 || _mesa_is_gles3(ctx)) {
371 if (texObj->Sampler.CompareMode == params[0])
372 return GL_FALSE;
373 if (params[0] == GL_NONE ||
374 params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
375 flush(ctx);
376 texObj->Sampler.CompareMode = params[0];
377 return GL_TRUE;
378 }
379 goto invalid_param;
380 }
381 goto invalid_pname;
382
383 case GL_TEXTURE_COMPARE_FUNC_ARB:
384 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow)
385 || _mesa_is_gles3(ctx)) {
386 if (texObj->Sampler.CompareFunc == params[0])
387 return GL_FALSE;
388 switch (params[0]) {
389 case GL_LEQUAL:
390 case GL_GEQUAL:
391 flush(ctx);
392 texObj->Sampler.CompareFunc = params[0];
393 return GL_TRUE;
394 case GL_EQUAL:
395 case GL_NOTEQUAL:
396 case GL_LESS:
397 case GL_GREATER:
398 case GL_ALWAYS:
399 case GL_NEVER:
400 if (ctx->Extensions.EXT_shadow_funcs) {
401 flush(ctx);
402 texObj->Sampler.CompareFunc = params[0];
403 return GL_TRUE;
404 }
405 /* fall-through */
406 default:
407 goto invalid_param;
408 }
409 }
410 goto invalid_pname;
411
412 case GL_DEPTH_TEXTURE_MODE_ARB:
413 /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has never
414 * existed in OpenGL ES.
415 */
416 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_depth_texture) {
417 if (texObj->DepthMode == params[0])
418 return GL_FALSE;
419 if (params[0] == GL_LUMINANCE ||
420 params[0] == GL_INTENSITY ||
421 params[0] == GL_ALPHA ||
422 (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
423 flush(ctx);
424 texObj->DepthMode = params[0];
425 return GL_TRUE;
426 }
427 goto invalid_param;
428 }
429 goto invalid_pname;
430
431 case GL_TEXTURE_CROP_RECT_OES:
432 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
433 goto invalid_pname;
434
435 texObj->CropRect[0] = params[0];
436 texObj->CropRect[1] = params[1];
437 texObj->CropRect[2] = params[2];
438 texObj->CropRect[3] = params[3];
439 return GL_TRUE;
440
441 case GL_TEXTURE_SWIZZLE_R_EXT:
442 case GL_TEXTURE_SWIZZLE_G_EXT:
443 case GL_TEXTURE_SWIZZLE_B_EXT:
444 case GL_TEXTURE_SWIZZLE_A_EXT:
445 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle)
446 || _mesa_is_gles3(ctx)) {
447 const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
448 const GLint swz = comp_to_swizzle(params[0]);
449 if (swz < 0) {
450 _mesa_error(ctx, GL_INVALID_OPERATION,
451 "glTexParameter(swizzle 0x%x)", params[0]);
452 return GL_FALSE;
453 }
454 ASSERT(comp < 4);
455
456 flush(ctx);
457 texObj->Swizzle[comp] = params[0];
458 set_swizzle_component(&texObj->_Swizzle, comp, swz);
459 return GL_TRUE;
460 }
461 goto invalid_pname;
462
463 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
464 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_swizzle)
465 || _mesa_is_gles3(ctx)) {
466 GLuint comp;
467 flush(ctx);
468 for (comp = 0; comp < 4; comp++) {
469 const GLint swz = comp_to_swizzle(params[comp]);
470 if (swz >= 0) {
471 texObj->Swizzle[comp] = params[comp];
472 set_swizzle_component(&texObj->_Swizzle, comp, swz);
473 }
474 else {
475 _mesa_error(ctx, GL_INVALID_OPERATION,
476 "glTexParameter(swizzle 0x%x)", params[comp]);
477 return GL_FALSE;
478 }
479 }
480 return GL_TRUE;
481 }
482 goto invalid_pname;
483
484 case GL_TEXTURE_SRGB_DECODE_EXT:
485 if (_mesa_is_desktop_gl(ctx)
486 && ctx->Extensions.EXT_texture_sRGB_decode) {
487 GLenum decode = params[0];
488 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
489 if (texObj->Sampler.sRGBDecode != decode) {
490 flush(ctx);
491 texObj->Sampler.sRGBDecode = decode;
492 }
493 return GL_TRUE;
494 }
495 }
496 goto invalid_pname;
497
498 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
499 if (_mesa_is_desktop_gl(ctx)
500 && ctx->Extensions.AMD_seamless_cubemap_per_texture) {
501 GLenum param = params[0];
502 if (param != GL_TRUE && param != GL_FALSE) {
503 goto invalid_param;
504 }
505 if (param != texObj->Sampler.CubeMapSeamless) {
506 flush(ctx);
507 texObj->Sampler.CubeMapSeamless = param;
508 }
509 return GL_TRUE;
510 }
511 goto invalid_pname;
512
513 default:
514 goto invalid_pname;
515 }
516
517 invalid_pname:
518 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
519 _mesa_lookup_enum_by_nr(pname));
520 return GL_FALSE;
521
522 invalid_param:
523 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)",
524 _mesa_lookup_enum_by_nr(params[0]));
525 return GL_FALSE;
526 }
527
528
529 /**
530 * Set a float-valued texture parameter
531 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
532 */
533 static GLboolean
534 set_tex_parameterf(struct gl_context *ctx,
535 struct gl_texture_object *texObj,
536 GLenum pname, const GLfloat *params)
537 {
538 switch (pname) {
539 case GL_TEXTURE_MIN_LOD:
540 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
541 goto invalid_pname;
542
543 if (texObj->Sampler.MinLod == params[0])
544 return GL_FALSE;
545 flush(ctx);
546 texObj->Sampler.MinLod = params[0];
547 return GL_TRUE;
548
549 case GL_TEXTURE_MAX_LOD:
550 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
551 goto invalid_pname;
552
553 if (texObj->Sampler.MaxLod == params[0])
554 return GL_FALSE;
555 flush(ctx);
556 texObj->Sampler.MaxLod = params[0];
557 return GL_TRUE;
558
559 case GL_TEXTURE_PRIORITY:
560 if (ctx->API != API_OPENGL)
561 goto invalid_pname;
562
563 flush(ctx);
564 texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
565 return GL_TRUE;
566
567 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
568 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
569 if (texObj->Sampler.MaxAnisotropy == params[0])
570 return GL_FALSE;
571 if (params[0] < 1.0) {
572 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
573 return GL_FALSE;
574 }
575 flush(ctx);
576 /* clamp to max, that's what NVIDIA does */
577 texObj->Sampler.MaxAnisotropy = MIN2(params[0],
578 ctx->Const.MaxTextureMaxAnisotropy);
579 return GL_TRUE;
580 }
581 else {
582 static GLuint count = 0;
583 if (count++ < 10)
584 goto invalid_pname;
585 }
586 return GL_FALSE;
587
588 case GL_TEXTURE_LOD_BIAS:
589 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias.
590 * It was removed in core-profile, and it has never existed in OpenGL
591 * ES.
592 */
593 if (ctx->API != API_OPENGL)
594 goto invalid_pname;
595
596 if (texObj->Sampler.LodBias != params[0]) {
597 flush(ctx);
598 texObj->Sampler.LodBias = params[0];
599 return GL_TRUE;
600 }
601 break;
602
603 case GL_TEXTURE_BORDER_COLOR:
604 if (!_mesa_is_desktop_gl(ctx))
605 goto invalid_pname;
606
607 flush(ctx);
608 /* ARB_texture_float disables clamping */
609 if (ctx->Extensions.ARB_texture_float) {
610 texObj->Sampler.BorderColor.f[RCOMP] = params[0];
611 texObj->Sampler.BorderColor.f[GCOMP] = params[1];
612 texObj->Sampler.BorderColor.f[BCOMP] = params[2];
613 texObj->Sampler.BorderColor.f[ACOMP] = params[3];
614 } else {
615 texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F);
616 texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F);
617 texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F);
618 texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F);
619 }
620 return GL_TRUE;
621
622 default:
623 goto invalid_pname;
624 }
625 return GL_FALSE;
626
627 invalid_pname:
628 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
629 _mesa_lookup_enum_by_nr(pname));
630 return GL_FALSE;
631 }
632
633
634 void GLAPIENTRY
635 _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
636 {
637 GLboolean need_update;
638 struct gl_texture_object *texObj;
639 GET_CURRENT_CONTEXT(ctx);
640 ASSERT_OUTSIDE_BEGIN_END(ctx);
641
642 texObj = get_texobj(ctx, target, GL_FALSE);
643 if (!texObj)
644 return;
645
646 switch (pname) {
647 case GL_TEXTURE_MIN_FILTER:
648 case GL_TEXTURE_MAG_FILTER:
649 case GL_TEXTURE_WRAP_S:
650 case GL_TEXTURE_WRAP_T:
651 case GL_TEXTURE_WRAP_R:
652 case GL_TEXTURE_BASE_LEVEL:
653 case GL_TEXTURE_MAX_LEVEL:
654 case GL_GENERATE_MIPMAP_SGIS:
655 case GL_TEXTURE_COMPARE_MODE_ARB:
656 case GL_TEXTURE_COMPARE_FUNC_ARB:
657 case GL_DEPTH_TEXTURE_MODE_ARB:
658 case GL_TEXTURE_SRGB_DECODE_EXT:
659 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
660 {
661 /* convert float param to int */
662 GLint p[4];
663 p[0] = (GLint) param;
664 p[1] = p[2] = p[3] = 0;
665 need_update = set_tex_parameteri(ctx, texObj, pname, p);
666 }
667 break;
668 case GL_TEXTURE_SWIZZLE_R_EXT:
669 case GL_TEXTURE_SWIZZLE_G_EXT:
670 case GL_TEXTURE_SWIZZLE_B_EXT:
671 case GL_TEXTURE_SWIZZLE_A_EXT:
672 {
673 GLint p[4];
674 p[0] = (GLint) param;
675 p[1] = p[2] = p[3] = 0;
676 need_update = set_tex_parameteri(ctx, texObj, pname, p);
677 }
678 break;
679 default:
680 {
681 /* this will generate an error if pname is illegal */
682 GLfloat p[4];
683 p[0] = param;
684 p[1] = p[2] = p[3] = 0.0F;
685 need_update = set_tex_parameterf(ctx, texObj, pname, p);
686 }
687 }
688
689 if (ctx->Driver.TexParameter && need_update) {
690 ctx->Driver.TexParameter(ctx, target, texObj, pname, &param);
691 }
692 }
693
694
695 void GLAPIENTRY
696 _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
697 {
698 GLboolean need_update;
699 struct gl_texture_object *texObj;
700 GET_CURRENT_CONTEXT(ctx);
701 ASSERT_OUTSIDE_BEGIN_END(ctx);
702
703 texObj = get_texobj(ctx, target, GL_FALSE);
704 if (!texObj)
705 return;
706
707 switch (pname) {
708 case GL_TEXTURE_MIN_FILTER:
709 case GL_TEXTURE_MAG_FILTER:
710 case GL_TEXTURE_WRAP_S:
711 case GL_TEXTURE_WRAP_T:
712 case GL_TEXTURE_WRAP_R:
713 case GL_TEXTURE_BASE_LEVEL:
714 case GL_TEXTURE_MAX_LEVEL:
715 case GL_GENERATE_MIPMAP_SGIS:
716 case GL_TEXTURE_COMPARE_MODE_ARB:
717 case GL_TEXTURE_COMPARE_FUNC_ARB:
718 case GL_DEPTH_TEXTURE_MODE_ARB:
719 case GL_TEXTURE_SRGB_DECODE_EXT:
720 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
721 {
722 /* convert float param to int */
723 GLint p[4];
724 p[0] = (GLint) params[0];
725 p[1] = p[2] = p[3] = 0;
726 need_update = set_tex_parameteri(ctx, texObj, pname, p);
727 }
728 break;
729 case GL_TEXTURE_CROP_RECT_OES:
730 {
731 /* convert float params to int */
732 GLint iparams[4];
733 iparams[0] = (GLint) params[0];
734 iparams[1] = (GLint) params[1];
735 iparams[2] = (GLint) params[2];
736 iparams[3] = (GLint) params[3];
737 need_update = set_tex_parameteri(ctx, texObj, pname, iparams);
738 }
739 break;
740 case GL_TEXTURE_SWIZZLE_R_EXT:
741 case GL_TEXTURE_SWIZZLE_G_EXT:
742 case GL_TEXTURE_SWIZZLE_B_EXT:
743 case GL_TEXTURE_SWIZZLE_A_EXT:
744 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
745 {
746 GLint p[4] = {0, 0, 0, 0};
747 p[0] = (GLint) params[0];
748 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT) {
749 p[1] = (GLint) params[1];
750 p[2] = (GLint) params[2];
751 p[3] = (GLint) params[3];
752 }
753 need_update = set_tex_parameteri(ctx, texObj, pname, p);
754 }
755 break;
756 default:
757 /* this will generate an error if pname is illegal */
758 need_update = set_tex_parameterf(ctx, texObj, pname, params);
759 }
760
761 if (ctx->Driver.TexParameter && need_update) {
762 ctx->Driver.TexParameter(ctx, target, texObj, pname, params);
763 }
764 }
765
766
767 void GLAPIENTRY
768 _mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
769 {
770 GLboolean need_update;
771 struct gl_texture_object *texObj;
772 GET_CURRENT_CONTEXT(ctx);
773 ASSERT_OUTSIDE_BEGIN_END(ctx);
774
775 texObj = get_texobj(ctx, target, GL_FALSE);
776 if (!texObj)
777 return;
778
779 switch (pname) {
780 case GL_TEXTURE_MIN_LOD:
781 case GL_TEXTURE_MAX_LOD:
782 case GL_TEXTURE_PRIORITY:
783 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
784 case GL_TEXTURE_LOD_BIAS:
785 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
786 {
787 GLfloat fparam[4];
788 fparam[0] = (GLfloat) param;
789 fparam[1] = fparam[2] = fparam[3] = 0.0F;
790 /* convert int param to float */
791 need_update = set_tex_parameterf(ctx, texObj, pname, fparam);
792 }
793 break;
794 default:
795 /* this will generate an error if pname is illegal */
796 {
797 GLint iparam[4];
798 iparam[0] = param;
799 iparam[1] = iparam[2] = iparam[3] = 0;
800 need_update = set_tex_parameteri(ctx, texObj, pname, iparam);
801 }
802 }
803
804 if (ctx->Driver.TexParameter && need_update) {
805 GLfloat fparam = (GLfloat) param;
806 ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam);
807 }
808 }
809
810
811 void GLAPIENTRY
812 _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
813 {
814 GLboolean need_update;
815 struct gl_texture_object *texObj;
816 GET_CURRENT_CONTEXT(ctx);
817 ASSERT_OUTSIDE_BEGIN_END(ctx);
818
819 texObj = get_texobj(ctx, target, GL_FALSE);
820 if (!texObj)
821 return;
822
823 switch (pname) {
824 case GL_TEXTURE_BORDER_COLOR:
825 {
826 /* convert int params to float */
827 GLfloat fparams[4];
828 fparams[0] = INT_TO_FLOAT(params[0]);
829 fparams[1] = INT_TO_FLOAT(params[1]);
830 fparams[2] = INT_TO_FLOAT(params[2]);
831 fparams[3] = INT_TO_FLOAT(params[3]);
832 need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
833 }
834 break;
835 case GL_TEXTURE_MIN_LOD:
836 case GL_TEXTURE_MAX_LOD:
837 case GL_TEXTURE_PRIORITY:
838 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
839 case GL_TEXTURE_LOD_BIAS:
840 case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
841 {
842 /* convert int param to float */
843 GLfloat fparams[4];
844 fparams[0] = (GLfloat) params[0];
845 fparams[1] = fparams[2] = fparams[3] = 0.0F;
846 need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
847 }
848 break;
849 default:
850 /* this will generate an error if pname is illegal */
851 need_update = set_tex_parameteri(ctx, texObj, pname, params);
852 }
853
854 if (ctx->Driver.TexParameter && need_update) {
855 GLfloat fparams[4];
856 fparams[0] = INT_TO_FLOAT(params[0]);
857 if (pname == GL_TEXTURE_BORDER_COLOR ||
858 pname == GL_TEXTURE_CROP_RECT_OES) {
859 fparams[1] = INT_TO_FLOAT(params[1]);
860 fparams[2] = INT_TO_FLOAT(params[2]);
861 fparams[3] = INT_TO_FLOAT(params[3]);
862 }
863 ctx->Driver.TexParameter(ctx, target, texObj, pname, fparams);
864 }
865 }
866
867
868 /**
869 * Set tex parameter to integer value(s). Primarily intended to set
870 * integer-valued texture border color (for integer-valued textures).
871 * New in GL 3.0.
872 */
873 void GLAPIENTRY
874 _mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params)
875 {
876 struct gl_texture_object *texObj;
877 GET_CURRENT_CONTEXT(ctx);
878 ASSERT_OUTSIDE_BEGIN_END(ctx);
879
880 texObj = get_texobj(ctx, target, GL_FALSE);
881 if (!texObj)
882 return;
883
884 switch (pname) {
885 case GL_TEXTURE_BORDER_COLOR:
886 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
887 /* set the integer-valued border color */
888 COPY_4V(texObj->Sampler.BorderColor.i, params);
889 break;
890 default:
891 _mesa_TexParameteriv(target, pname, params);
892 break;
893 }
894 /* XXX no driver hook for TexParameterIiv() yet */
895 }
896
897
898 /**
899 * Set tex parameter to unsigned integer value(s). Primarily intended to set
900 * uint-valued texture border color (for integer-valued textures).
901 * New in GL 3.0
902 */
903 void GLAPIENTRY
904 _mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params)
905 {
906 struct gl_texture_object *texObj;
907 GET_CURRENT_CONTEXT(ctx);
908 ASSERT_OUTSIDE_BEGIN_END(ctx);
909
910 texObj = get_texobj(ctx, target, GL_FALSE);
911 if (!texObj)
912 return;
913
914 switch (pname) {
915 case GL_TEXTURE_BORDER_COLOR:
916 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
917 /* set the unsigned integer-valued border color */
918 COPY_4V(texObj->Sampler.BorderColor.ui, params);
919 break;
920 default:
921 _mesa_TexParameteriv(target, pname, (const GLint *) params);
922 break;
923 }
924 /* XXX no driver hook for TexParameterIuiv() yet */
925 }
926
927
928 static GLboolean
929 legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target)
930 {
931 switch (target) {
932 case GL_TEXTURE_1D:
933 case GL_PROXY_TEXTURE_1D:
934 case GL_TEXTURE_2D:
935 case GL_PROXY_TEXTURE_2D:
936 case GL_TEXTURE_3D:
937 case GL_PROXY_TEXTURE_3D:
938 return GL_TRUE;
939 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
940 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
941 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
942 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
943 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
944 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
945 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
946 return ctx->Extensions.ARB_texture_cube_map;
947 case GL_TEXTURE_RECTANGLE_NV:
948 case GL_PROXY_TEXTURE_RECTANGLE_NV:
949 return ctx->Extensions.NV_texture_rectangle;
950 case GL_TEXTURE_1D_ARRAY_EXT:
951 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
952 case GL_TEXTURE_2D_ARRAY_EXT:
953 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
954 return (ctx->Extensions.MESA_texture_array ||
955 ctx->Extensions.EXT_texture_array);
956 case GL_TEXTURE_BUFFER:
957 /* GetTexLevelParameter accepts GL_TEXTURE_BUFFER in GL 3.1+ contexts,
958 * but not in earlier versions that expose ARB_texture_buffer_object.
959 *
960 * From the ARB_texture_buffer_object spec:
961 * "(7) Do buffer textures support texture parameters (TexParameter) or
962 * queries (GetTexParameter, GetTexLevelParameter, GetTexImage)?
963 *
964 * RESOLVED: No. [...] Note that the spec edits above don't add
965 * explicit error language for any of these cases. That is because
966 * each of the functions enumerate the set of valid <target>
967 * parameters. Not editing the spec to allow TEXTURE_BUFFER_ARB in
968 * these cases means that target is not legal, and an INVALID_ENUM
969 * error should be generated."
970 *
971 * From the OpenGL 3.1 spec:
972 * "target may also be TEXTURE_BUFFER, indicating the texture buffer."
973 */
974 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
975 default:
976 return GL_FALSE;
977 }
978 }
979
980
981 static void
982 get_tex_level_parameter_image(struct gl_context *ctx,
983 const struct gl_texture_object *texObj,
984 GLenum target, GLint level,
985 GLenum pname, GLint *params)
986 {
987 const struct gl_texture_image *img = NULL;
988 gl_format texFormat;
989
990 img = _mesa_select_tex_image(ctx, texObj, target, level);
991 if (!img || img->TexFormat == MESA_FORMAT_NONE) {
992 /* undefined texture image */
993 if (pname == GL_TEXTURE_COMPONENTS)
994 *params = 1;
995 else
996 *params = 0;
997 return;
998 }
999
1000 texFormat = img->TexFormat;
1001
1002 switch (pname) {
1003 case GL_TEXTURE_WIDTH:
1004 *params = img->Width;
1005 break;
1006 case GL_TEXTURE_HEIGHT:
1007 *params = img->Height;
1008 break;
1009 case GL_TEXTURE_DEPTH:
1010 *params = img->Depth;
1011 break;
1012 case GL_TEXTURE_INTERNAL_FORMAT:
1013 if (_mesa_is_format_compressed(texFormat)) {
1014 /* need to return the actual compressed format */
1015 *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
1016 }
1017 else {
1018 /* If the true internal format is not compressed but the user
1019 * requested a generic compressed format, we have to return the
1020 * generic base format that matches.
1021 *
1022 * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
1023 *
1024 * "If no specific compressed format is available,
1025 * internalformat is instead replaced by the corresponding base
1026 * internal format."
1027 *
1028 * Otherwise just return the user's requested internal format
1029 */
1030 const GLenum f =
1031 _mesa_gl_compressed_format_base_format(img->InternalFormat);
1032
1033 *params = (f != 0) ? f : img->InternalFormat;
1034 }
1035 break;
1036 case GL_TEXTURE_BORDER:
1037 *params = img->Border;
1038 break;
1039 case GL_TEXTURE_RED_SIZE:
1040 case GL_TEXTURE_GREEN_SIZE:
1041 case GL_TEXTURE_BLUE_SIZE:
1042 case GL_TEXTURE_ALPHA_SIZE:
1043 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1044 *params = _mesa_get_format_bits(texFormat, pname);
1045 else
1046 *params = 0;
1047 break;
1048 case GL_TEXTURE_INTENSITY_SIZE:
1049 case GL_TEXTURE_LUMINANCE_SIZE:
1050 if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
1051 *params = _mesa_get_format_bits(texFormat, pname);
1052 if (*params == 0) {
1053 /* intensity or luminance is probably stored as RGB[A] */
1054 *params = MIN2(_mesa_get_format_bits(texFormat,
1055 GL_TEXTURE_RED_SIZE),
1056 _mesa_get_format_bits(texFormat,
1057 GL_TEXTURE_GREEN_SIZE));
1058 }
1059 }
1060 else {
1061 *params = 0;
1062 }
1063 break;
1064 case GL_TEXTURE_DEPTH_SIZE_ARB:
1065 if (!ctx->Extensions.ARB_depth_texture)
1066 goto invalid_pname;
1067 *params = _mesa_get_format_bits(texFormat, pname);
1068 break;
1069 case GL_TEXTURE_STENCIL_SIZE_EXT:
1070 if (!ctx->Extensions.EXT_packed_depth_stencil &&
1071 !ctx->Extensions.ARB_framebuffer_object)
1072 goto invalid_pname;
1073 *params = _mesa_get_format_bits(texFormat, pname);
1074 break;
1075 case GL_TEXTURE_SHARED_SIZE:
1076 if (ctx->Version < 30 &&
1077 !ctx->Extensions.EXT_texture_shared_exponent)
1078 goto invalid_pname;
1079 *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
1080 break;
1081
1082 /* GL_ARB_texture_compression */
1083 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1084 if (_mesa_is_format_compressed(texFormat) &&
1085 !_mesa_is_proxy_texture(target)) {
1086 *params = _mesa_format_image_size(texFormat, img->Width,
1087 img->Height, img->Depth);
1088 }
1089 else {
1090 _mesa_error(ctx, GL_INVALID_OPERATION,
1091 "glGetTexLevelParameter[if]v(pname)");
1092 }
1093 break;
1094 case GL_TEXTURE_COMPRESSED:
1095 *params = (GLint) _mesa_is_format_compressed(texFormat);
1096 break;
1097
1098 /* GL_ARB_texture_float */
1099 case GL_TEXTURE_RED_TYPE_ARB:
1100 case GL_TEXTURE_GREEN_TYPE_ARB:
1101 case GL_TEXTURE_BLUE_TYPE_ARB:
1102 case GL_TEXTURE_ALPHA_TYPE_ARB:
1103 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1104 case GL_TEXTURE_INTENSITY_TYPE_ARB:
1105 case GL_TEXTURE_DEPTH_TYPE_ARB:
1106 if (!ctx->Extensions.ARB_texture_float)
1107 goto invalid_pname;
1108 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
1109 *params = _mesa_get_format_datatype(texFormat);
1110 else
1111 *params = GL_NONE;
1112 break;
1113
1114 default:
1115 goto invalid_pname;
1116 }
1117
1118 /* no error if we get here */
1119 return;
1120
1121 invalid_pname:
1122 _mesa_error(ctx, GL_INVALID_ENUM,
1123 "glGetTexLevelParameter[if]v(pname=%s)",
1124 _mesa_lookup_enum_by_nr(pname));
1125 }
1126
1127
1128 static void
1129 get_tex_level_parameter_buffer(struct gl_context *ctx,
1130 const struct gl_texture_object *texObj,
1131 GLenum pname, GLint *params)
1132 {
1133 const struct gl_buffer_object *bo = texObj->BufferObject;
1134 gl_format texFormat = texObj->_BufferObjectFormat;
1135 GLenum internalFormat = texObj->BufferObjectFormat;
1136 GLenum baseFormat = _mesa_get_format_base_format(texFormat);
1137
1138 if (!bo) {
1139 /* undefined texture buffer object */
1140 *params = pname == GL_TEXTURE_COMPONENTS ? 1 : 0;
1141 return;
1142 }
1143
1144 switch (pname) {
1145 case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
1146 *params = bo->Name;
1147 break;
1148 case GL_TEXTURE_WIDTH:
1149 *params = bo->Size;
1150 break;
1151 case GL_TEXTURE_HEIGHT:
1152 case GL_TEXTURE_DEPTH:
1153 case GL_TEXTURE_BORDER:
1154 case GL_TEXTURE_SHARED_SIZE:
1155 case GL_TEXTURE_COMPRESSED:
1156 *params = 0;
1157 break;
1158 case GL_TEXTURE_INTERNAL_FORMAT:
1159 *params = internalFormat;
1160 break;
1161 case GL_TEXTURE_RED_SIZE:
1162 case GL_TEXTURE_GREEN_SIZE:
1163 case GL_TEXTURE_BLUE_SIZE:
1164 case GL_TEXTURE_ALPHA_SIZE:
1165 if (_mesa_base_format_has_channel(baseFormat, pname))
1166 *params = _mesa_get_format_bits(texFormat, pname);
1167 else
1168 *params = 0;
1169 break;
1170 case GL_TEXTURE_INTENSITY_SIZE:
1171 case GL_TEXTURE_LUMINANCE_SIZE:
1172 if (_mesa_base_format_has_channel(baseFormat, pname)) {
1173 *params = _mesa_get_format_bits(texFormat, pname);
1174 if (*params == 0) {
1175 /* intensity or luminance is probably stored as RGB[A] */
1176 *params = MIN2(_mesa_get_format_bits(texFormat,
1177 GL_TEXTURE_RED_SIZE),
1178 _mesa_get_format_bits(texFormat,
1179 GL_TEXTURE_GREEN_SIZE));
1180 }
1181 } else {
1182 *params = 0;
1183 }
1184 break;
1185 case GL_TEXTURE_DEPTH_SIZE_ARB:
1186 case GL_TEXTURE_STENCIL_SIZE_EXT:
1187 *params = _mesa_get_format_bits(texFormat, pname);
1188 break;
1189
1190 /* GL_ARB_texture_compression */
1191 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
1192 /* Always illegal for GL_TEXTURE_BUFFER */
1193 _mesa_error(ctx, GL_INVALID_OPERATION,
1194 "glGetTexLevelParameter[if]v(pname)");
1195 break;
1196
1197 /* GL_ARB_texture_float */
1198 case GL_TEXTURE_RED_TYPE_ARB:
1199 case GL_TEXTURE_GREEN_TYPE_ARB:
1200 case GL_TEXTURE_BLUE_TYPE_ARB:
1201 case GL_TEXTURE_ALPHA_TYPE_ARB:
1202 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
1203 case GL_TEXTURE_INTENSITY_TYPE_ARB:
1204 case GL_TEXTURE_DEPTH_TYPE_ARB:
1205 if (!ctx->Extensions.ARB_texture_float)
1206 goto invalid_pname;
1207 if (_mesa_base_format_has_channel(baseFormat, pname))
1208 *params = _mesa_get_format_datatype(texFormat);
1209 else
1210 *params = GL_NONE;
1211 break;
1212
1213 default:
1214 goto invalid_pname;
1215 }
1216
1217 /* no error if we get here */
1218 return;
1219
1220 invalid_pname:
1221 _mesa_error(ctx, GL_INVALID_ENUM,
1222 "glGetTexLevelParameter[if]v(pname=%s)",
1223 _mesa_lookup_enum_by_nr(pname));
1224 }
1225
1226
1227 void GLAPIENTRY
1228 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
1229 GLenum pname, GLfloat *params )
1230 {
1231 GLint iparam;
1232 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
1233 *params = (GLfloat) iparam;
1234 }
1235
1236
1237 void GLAPIENTRY
1238 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
1239 GLenum pname, GLint *params )
1240 {
1241 const struct gl_texture_unit *texUnit;
1242 struct gl_texture_object *texObj;
1243 GLint maxLevels;
1244 GET_CURRENT_CONTEXT(ctx);
1245 ASSERT_OUTSIDE_BEGIN_END(ctx);
1246
1247 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
1248 _mesa_error(ctx, GL_INVALID_OPERATION,
1249 "glGetTexLevelParameteriv(current unit)");
1250 return;
1251 }
1252
1253 texUnit = _mesa_get_current_tex_unit(ctx);
1254
1255 if (!legal_get_tex_level_parameter_target(ctx, target)) {
1256 _mesa_error(ctx, GL_INVALID_ENUM,
1257 "glGetTexLevelParameter[if]v(target=0x%x)", target);
1258 return;
1259 }
1260
1261 maxLevels = _mesa_max_texture_levels(ctx, target);
1262 assert(maxLevels != 0);
1263
1264 if (level < 0 || level >= maxLevels) {
1265 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
1266 return;
1267 }
1268
1269 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1270
1271 if (target == GL_TEXTURE_BUFFER)
1272 get_tex_level_parameter_buffer(ctx, texObj, pname, params);
1273 else
1274 get_tex_level_parameter_image(ctx, texObj, target, level, pname, params);
1275 }
1276
1277
1278 void GLAPIENTRY
1279 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
1280 {
1281 struct gl_texture_object *obj;
1282 GET_CURRENT_CONTEXT(ctx);
1283 ASSERT_OUTSIDE_BEGIN_END(ctx);
1284
1285 obj = get_texobj(ctx, target, GL_TRUE);
1286 if (!obj)
1287 return;
1288
1289 _mesa_lock_texture(ctx, obj);
1290 switch (pname) {
1291 case GL_TEXTURE_MAG_FILTER:
1292 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
1293 break;
1294 case GL_TEXTURE_MIN_FILTER:
1295 *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter);
1296 break;
1297 case GL_TEXTURE_WRAP_S:
1298 *params = ENUM_TO_FLOAT(obj->Sampler.WrapS);
1299 break;
1300 case GL_TEXTURE_WRAP_T:
1301 *params = ENUM_TO_FLOAT(obj->Sampler.WrapT);
1302 break;
1303 case GL_TEXTURE_WRAP_R:
1304 *params = ENUM_TO_FLOAT(obj->Sampler.WrapR);
1305 break;
1306 case GL_TEXTURE_BORDER_COLOR:
1307 if (!_mesa_is_desktop_gl(ctx))
1308 goto invalid_pname;
1309
1310 if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
1311 _mesa_update_state_locked(ctx);
1312 if (ctx->Color._ClampFragmentColor) {
1313 params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1314 params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1315 params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1316 params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1317 }
1318 else {
1319 params[0] = obj->Sampler.BorderColor.f[0];
1320 params[1] = obj->Sampler.BorderColor.f[1];
1321 params[2] = obj->Sampler.BorderColor.f[2];
1322 params[3] = obj->Sampler.BorderColor.f[3];
1323 }
1324 break;
1325 case GL_TEXTURE_RESIDENT:
1326 if (ctx->API != API_OPENGL)
1327 goto invalid_pname;
1328
1329 *params = 1.0F;
1330 break;
1331 case GL_TEXTURE_PRIORITY:
1332 if (ctx->API != API_OPENGL)
1333 goto invalid_pname;
1334
1335 *params = obj->Priority;
1336 break;
1337 case GL_TEXTURE_MIN_LOD:
1338 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1339 goto invalid_pname;
1340
1341 *params = obj->Sampler.MinLod;
1342 break;
1343 case GL_TEXTURE_MAX_LOD:
1344 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1345 goto invalid_pname;
1346
1347 *params = obj->Sampler.MaxLod;
1348 break;
1349 case GL_TEXTURE_BASE_LEVEL:
1350 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1351 goto invalid_pname;
1352
1353 *params = (GLfloat) obj->BaseLevel;
1354 break;
1355 case GL_TEXTURE_MAX_LEVEL:
1356 *params = (GLfloat) obj->MaxLevel;
1357 break;
1358 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1359 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1360 goto invalid_pname;
1361 *params = obj->Sampler.MaxAnisotropy;
1362 break;
1363 case GL_GENERATE_MIPMAP_SGIS:
1364 if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES)
1365 goto invalid_pname;
1366
1367 *params = (GLfloat) obj->GenerateMipmap;
1368 break;
1369 case GL_TEXTURE_COMPARE_MODE_ARB:
1370 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1371 && !_mesa_is_gles3(ctx))
1372 goto invalid_pname;
1373 *params = (GLfloat) obj->Sampler.CompareMode;
1374 break;
1375 case GL_TEXTURE_COMPARE_FUNC_ARB:
1376 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1377 && !_mesa_is_gles3(ctx))
1378 goto invalid_pname;
1379 *params = (GLfloat) obj->Sampler.CompareFunc;
1380 break;
1381 case GL_DEPTH_TEXTURE_MODE_ARB:
1382 /* GL_DEPTH_TEXTURE_MODE_ARB is removed in core-profile and it has
1383 * never existed in OpenGL ES.
1384 */
1385 if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_depth_texture)
1386 goto invalid_pname;
1387 *params = (GLfloat) obj->DepthMode;
1388 break;
1389 case GL_TEXTURE_LOD_BIAS:
1390 if (ctx->API != API_OPENGL)
1391 goto invalid_pname;
1392
1393 *params = obj->Sampler.LodBias;
1394 break;
1395 case GL_TEXTURE_CROP_RECT_OES:
1396 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
1397 goto invalid_pname;
1398
1399 params[0] = obj->CropRect[0];
1400 params[1] = obj->CropRect[1];
1401 params[2] = obj->CropRect[2];
1402 params[3] = obj->CropRect[3];
1403 break;
1404
1405 case GL_TEXTURE_SWIZZLE_R_EXT:
1406 case GL_TEXTURE_SWIZZLE_G_EXT:
1407 case GL_TEXTURE_SWIZZLE_B_EXT:
1408 case GL_TEXTURE_SWIZZLE_A_EXT:
1409 if ((!_mesa_is_desktop_gl(ctx)
1410 || !ctx->Extensions.EXT_texture_swizzle)
1411 && !_mesa_is_gles3(ctx))
1412 goto invalid_pname;
1413 *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1414 break;
1415
1416 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1417 if ((!_mesa_is_desktop_gl(ctx)
1418 || !ctx->Extensions.EXT_texture_swizzle)
1419 && !_mesa_is_gles3(ctx)) {
1420 goto invalid_pname;
1421 }
1422 else {
1423 GLuint comp;
1424 for (comp = 0; comp < 4; comp++) {
1425 params[comp] = (GLfloat) obj->Swizzle[comp];
1426 }
1427 }
1428 break;
1429
1430 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1431 if (!_mesa_is_desktop_gl(ctx)
1432 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
1433 goto invalid_pname;
1434 *params = (GLfloat) obj->Sampler.CubeMapSeamless;
1435 break;
1436
1437 case GL_TEXTURE_IMMUTABLE_FORMAT:
1438 if (!ctx->Extensions.ARB_texture_storage)
1439 goto invalid_pname;
1440 *params = (GLfloat) obj->Immutable;
1441 break;
1442
1443 default:
1444 goto invalid_pname;
1445 }
1446
1447 /* no error if we get here */
1448 _mesa_unlock_texture(ctx, obj);
1449 return;
1450
1451 invalid_pname:
1452 _mesa_unlock_texture(ctx, obj);
1453 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
1454 }
1455
1456
1457 void GLAPIENTRY
1458 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1459 {
1460 struct gl_texture_object *obj;
1461 GET_CURRENT_CONTEXT(ctx);
1462 ASSERT_OUTSIDE_BEGIN_END(ctx);
1463
1464 obj = get_texobj(ctx, target, GL_TRUE);
1465 if (!obj)
1466 return;
1467
1468 _mesa_lock_texture(ctx, obj);
1469 switch (pname) {
1470 case GL_TEXTURE_MAG_FILTER:
1471 *params = (GLint) obj->Sampler.MagFilter;
1472 break;
1473 case GL_TEXTURE_MIN_FILTER:
1474 *params = (GLint) obj->Sampler.MinFilter;
1475 break;
1476 case GL_TEXTURE_WRAP_S:
1477 *params = (GLint) obj->Sampler.WrapS;
1478 break;
1479 case GL_TEXTURE_WRAP_T:
1480 *params = (GLint) obj->Sampler.WrapT;
1481 break;
1482 case GL_TEXTURE_WRAP_R:
1483 *params = (GLint) obj->Sampler.WrapR;
1484 break;
1485 case GL_TEXTURE_BORDER_COLOR:
1486 if (!_mesa_is_desktop_gl(ctx))
1487 goto invalid_pname;
1488
1489 {
1490 GLfloat b[4];
1491 b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
1492 b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
1493 b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
1494 b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
1495 params[0] = FLOAT_TO_INT(b[0]);
1496 params[1] = FLOAT_TO_INT(b[1]);
1497 params[2] = FLOAT_TO_INT(b[2]);
1498 params[3] = FLOAT_TO_INT(b[3]);
1499 }
1500 break;
1501 case GL_TEXTURE_RESIDENT:
1502 if (ctx->API != API_OPENGL)
1503 goto invalid_pname;
1504
1505 *params = 1;
1506 break;
1507 case GL_TEXTURE_PRIORITY:
1508 if (ctx->API != API_OPENGL)
1509 goto invalid_pname;
1510
1511 *params = FLOAT_TO_INT(obj->Priority);
1512 break;
1513 case GL_TEXTURE_MIN_LOD:
1514 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1515 goto invalid_pname;
1516
1517 *params = (GLint) obj->Sampler.MinLod;
1518 break;
1519 case GL_TEXTURE_MAX_LOD:
1520 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1521 goto invalid_pname;
1522
1523 *params = (GLint) obj->Sampler.MaxLod;
1524 break;
1525 case GL_TEXTURE_BASE_LEVEL:
1526 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
1527 goto invalid_pname;
1528
1529 *params = obj->BaseLevel;
1530 break;
1531 case GL_TEXTURE_MAX_LEVEL:
1532 *params = obj->MaxLevel;
1533 break;
1534 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1535 if (!ctx->Extensions.EXT_texture_filter_anisotropic)
1536 goto invalid_pname;
1537 *params = (GLint) obj->Sampler.MaxAnisotropy;
1538 break;
1539 case GL_GENERATE_MIPMAP_SGIS:
1540 if (ctx->API != API_OPENGL && ctx->API != API_OPENGLES)
1541 goto invalid_pname;
1542
1543 *params = (GLint) obj->GenerateMipmap;
1544 break;
1545 case GL_TEXTURE_COMPARE_MODE_ARB:
1546 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1547 && !_mesa_is_gles3(ctx))
1548 goto invalid_pname;
1549 *params = (GLint) obj->Sampler.CompareMode;
1550 break;
1551 case GL_TEXTURE_COMPARE_FUNC_ARB:
1552 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_shadow)
1553 && !_mesa_is_gles3(ctx))
1554 goto invalid_pname;
1555 *params = (GLint) obj->Sampler.CompareFunc;
1556 break;
1557 case GL_DEPTH_TEXTURE_MODE_ARB:
1558 if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_depth_texture)
1559 goto invalid_pname;
1560 *params = (GLint) obj->DepthMode;
1561 break;
1562 case GL_TEXTURE_LOD_BIAS:
1563 if (ctx->API != API_OPENGL)
1564 goto invalid_pname;
1565
1566 *params = (GLint) obj->Sampler.LodBias;
1567 break;
1568 case GL_TEXTURE_CROP_RECT_OES:
1569 if (ctx->API != API_OPENGLES || !ctx->Extensions.OES_draw_texture)
1570 goto invalid_pname;
1571
1572 params[0] = obj->CropRect[0];
1573 params[1] = obj->CropRect[1];
1574 params[2] = obj->CropRect[2];
1575 params[3] = obj->CropRect[3];
1576 break;
1577 case GL_TEXTURE_SWIZZLE_R_EXT:
1578 case GL_TEXTURE_SWIZZLE_G_EXT:
1579 case GL_TEXTURE_SWIZZLE_B_EXT:
1580 case GL_TEXTURE_SWIZZLE_A_EXT:
1581 if ((!_mesa_is_desktop_gl(ctx)
1582 || !ctx->Extensions.EXT_texture_swizzle)
1583 && !_mesa_is_gles3(ctx))
1584 goto invalid_pname;
1585 *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
1586 break;
1587
1588 case GL_TEXTURE_SWIZZLE_RGBA_EXT:
1589 if ((!_mesa_is_desktop_gl(ctx)
1590 || !ctx->Extensions.EXT_texture_swizzle)
1591 && !_mesa_is_gles3(ctx))
1592 goto invalid_pname;
1593 COPY_4V(params, obj->Swizzle);
1594 break;
1595
1596 case GL_TEXTURE_CUBE_MAP_SEAMLESS:
1597 if (!_mesa_is_desktop_gl(ctx)
1598 || !ctx->Extensions.AMD_seamless_cubemap_per_texture)
1599 goto invalid_pname;
1600 *params = (GLint) obj->Sampler.CubeMapSeamless;
1601 break;
1602
1603 case GL_TEXTURE_IMMUTABLE_FORMAT:
1604 if (!ctx->Extensions.ARB_texture_storage)
1605 goto invalid_pname;
1606 *params = (GLint) obj->Immutable;
1607 break;
1608
1609 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
1610 if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)
1611 goto invalid_pname;
1612 *params = obj->RequiredTextureImageUnits;
1613 break;
1614
1615 default:
1616 goto invalid_pname;
1617 }
1618
1619 /* no error if we get here */
1620 _mesa_unlock_texture(ctx, obj);
1621 return;
1622
1623 invalid_pname:
1624 _mesa_unlock_texture(ctx, obj);
1625 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1626 }
1627
1628
1629 /** New in GL 3.0 */
1630 void GLAPIENTRY
1631 _mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params)
1632 {
1633 struct gl_texture_object *texObj;
1634 GET_CURRENT_CONTEXT(ctx);
1635 ASSERT_OUTSIDE_BEGIN_END(ctx);
1636
1637 texObj = get_texobj(ctx, target, GL_TRUE);
1638 if (!texObj)
1639 return;
1640
1641 switch (pname) {
1642 case GL_TEXTURE_BORDER_COLOR:
1643 COPY_4V(params, texObj->Sampler.BorderColor.i);
1644 break;
1645 default:
1646 _mesa_GetTexParameteriv(target, pname, params);
1647 }
1648 }
1649
1650
1651 /** New in GL 3.0 */
1652 void GLAPIENTRY
1653 _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params)
1654 {
1655 struct gl_texture_object *texObj;
1656 GET_CURRENT_CONTEXT(ctx);
1657 ASSERT_OUTSIDE_BEGIN_END(ctx);
1658
1659 texObj = get_texobj(ctx, target, GL_TRUE);
1660 if (!texObj)
1661 return;
1662
1663 switch (pname) {
1664 case GL_TEXTURE_BORDER_COLOR:
1665 COPY_4V(params, texObj->Sampler.BorderColor.i);
1666 break;
1667 default:
1668 {
1669 GLint ip[4];
1670 _mesa_GetTexParameteriv(target, pname, ip);
1671 params[0] = ip[0];
1672 if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT ||
1673 pname == GL_TEXTURE_CROP_RECT_OES) {
1674 params[1] = ip[1];
1675 params[2] = ip[2];
1676 params[3] = ip[3];
1677 }
1678 }
1679 }
1680 }