mesa: refactor: move various ENUM_TO_x macros into macros.h
[mesa.git] / src / mesa / main / texparam.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2008 Brian Paul 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file texparam.c
27 *
28 * glTexParameter-related functions
29 */
30
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/enums.h"
35 #include "main/colormac.h"
36 #include "main/macros.h"
37 #include "main/texcompress.h"
38 #include "main/texparam.h"
39 #include "main/teximage.h"
40
41
42 /**
43 * Check if a coordinate wrap mode is supported for the texture target.
44 * \return GL_TRUE if legal, GL_FALSE otherwise
45 */
46 static GLboolean
47 validate_texture_wrap_mode(GLcontext * ctx, GLenum target, GLenum wrap)
48 {
49 const struct gl_extensions * const e = & ctx->Extensions;
50
51 if (wrap == GL_CLAMP || wrap == GL_CLAMP_TO_EDGE ||
52 (wrap == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
53 /* any texture target */
54 return GL_TRUE;
55 }
56 else if (target != GL_TEXTURE_RECTANGLE_NV &&
57 (wrap == GL_REPEAT ||
58 (wrap == GL_MIRRORED_REPEAT &&
59 e->ARB_texture_mirrored_repeat) ||
60 (wrap == GL_MIRROR_CLAMP_EXT &&
61 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
62 (wrap == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
63 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
64 (wrap == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
65 (e->EXT_texture_mirror_clamp)))) {
66 /* non-rectangle texture */
67 return GL_TRUE;
68 }
69
70 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
71 return GL_FALSE;
72 }
73
74
75 void GLAPIENTRY
76 _mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
77 {
78 _mesa_TexParameterfv(target, pname, &param);
79 }
80
81
82 void GLAPIENTRY
83 _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
84 {
85 const GLenum eparam = (GLenum) (GLint) params[0];
86 struct gl_texture_unit *texUnit;
87 struct gl_texture_object *texObj;
88 GET_CURRENT_CONTEXT(ctx);
89 ASSERT_OUTSIDE_BEGIN_END(ctx);
90
91 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
92 _mesa_debug(ctx, "glTexParameter %s %s %.1f(%s)...\n",
93 _mesa_lookup_enum_by_nr(target),
94 _mesa_lookup_enum_by_nr(pname),
95 *params,
96 _mesa_lookup_enum_by_nr(eparam));
97
98 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
99 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameterfv(current unit)");
100 return;
101 }
102
103 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
104
105 switch (target) {
106 case GL_TEXTURE_1D:
107 texObj = texUnit->Current1D;
108 break;
109 case GL_TEXTURE_2D:
110 texObj = texUnit->Current2D;
111 break;
112 case GL_TEXTURE_3D:
113 texObj = texUnit->Current3D;
114 break;
115 case GL_TEXTURE_CUBE_MAP:
116 if (!ctx->Extensions.ARB_texture_cube_map) {
117 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
118 return;
119 }
120 texObj = texUnit->CurrentCubeMap;
121 break;
122 case GL_TEXTURE_RECTANGLE_NV:
123 if (!ctx->Extensions.NV_texture_rectangle) {
124 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
125 return;
126 }
127 texObj = texUnit->CurrentRect;
128 break;
129 case GL_TEXTURE_1D_ARRAY_EXT:
130 if (!ctx->Extensions.MESA_texture_array) {
131 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
132 return;
133 }
134 texObj = texUnit->Current1DArray;
135 break;
136 case GL_TEXTURE_2D_ARRAY_EXT:
137 if (!ctx->Extensions.MESA_texture_array) {
138 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
139 return;
140 }
141 texObj = texUnit->Current2DArray;
142 break;
143 default:
144 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
145 return;
146 }
147
148 switch (pname) {
149 case GL_TEXTURE_MIN_FILTER:
150 /* A small optimization */
151 if (texObj->MinFilter == eparam)
152 return;
153 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
154 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
155 texObj->MinFilter = eparam;
156 }
157 else if ((eparam==GL_NEAREST_MIPMAP_NEAREST ||
158 eparam==GL_LINEAR_MIPMAP_NEAREST ||
159 eparam==GL_NEAREST_MIPMAP_LINEAR ||
160 eparam==GL_LINEAR_MIPMAP_LINEAR) &&
161 texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
162 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
163 texObj->MinFilter = eparam;
164 }
165 else {
166 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
167 return;
168 }
169 break;
170 case GL_TEXTURE_MAG_FILTER:
171 /* A small optimization */
172 if (texObj->MagFilter == eparam)
173 return;
174
175 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
176 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
177 texObj->MagFilter = eparam;
178 }
179 else {
180 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
181 return;
182 }
183 break;
184 case GL_TEXTURE_WRAP_S:
185 if (texObj->WrapS == eparam)
186 return;
187 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
188 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
189 texObj->WrapS = eparam;
190 }
191 else {
192 return;
193 }
194 break;
195 case GL_TEXTURE_WRAP_T:
196 if (texObj->WrapT == eparam)
197 return;
198 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
199 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
200 texObj->WrapT = eparam;
201 }
202 else {
203 return;
204 }
205 break;
206 case GL_TEXTURE_WRAP_R:
207 if (texObj->WrapR == eparam)
208 return;
209 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
210 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
211 texObj->WrapR = eparam;
212 }
213 else {
214 return;
215 }
216 break;
217 case GL_TEXTURE_BORDER_COLOR:
218 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
219 texObj->BorderColor[RCOMP] = params[0];
220 texObj->BorderColor[GCOMP] = params[1];
221 texObj->BorderColor[BCOMP] = params[2];
222 texObj->BorderColor[ACOMP] = params[3];
223 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[RCOMP], params[0]);
224 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[GCOMP], params[1]);
225 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[BCOMP], params[2]);
226 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[ACOMP], params[3]);
227 break;
228 case GL_TEXTURE_MIN_LOD:
229 if (texObj->MinLod == params[0])
230 return;
231 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
232 texObj->MinLod = params[0];
233 break;
234 case GL_TEXTURE_MAX_LOD:
235 if (texObj->MaxLod == params[0])
236 return;
237 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
238 texObj->MaxLod = params[0];
239 break;
240 case GL_TEXTURE_BASE_LEVEL:
241 if (params[0] < 0.0) {
242 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
243 return;
244 }
245 if (target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0.0) {
246 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
247 return;
248 }
249 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
250 texObj->BaseLevel = (GLint) params[0];
251 break;
252 case GL_TEXTURE_MAX_LEVEL:
253 if (params[0] < 0.0) {
254 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
255 return;
256 }
257 if (target == GL_TEXTURE_RECTANGLE_ARB) {
258 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(param)");
259 return;
260 }
261 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
262 texObj->MaxLevel = (GLint) params[0];
263 break;
264 case GL_TEXTURE_PRIORITY:
265 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
266 texObj->Priority = CLAMP( params[0], 0.0F, 1.0F );
267 break;
268 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
269 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
270 if (params[0] < 1.0) {
271 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
272 return;
273 }
274 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
275 /* clamp to max, that's what NVIDIA does */
276 texObj->MaxAnisotropy = MIN2(params[0],
277 ctx->Const.MaxTextureMaxAnisotropy);
278 }
279 else {
280 _mesa_error(ctx, GL_INVALID_ENUM,
281 "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
282 return;
283 }
284 break;
285 case GL_TEXTURE_COMPARE_SGIX:
286 if (ctx->Extensions.SGIX_shadow) {
287 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
288 texObj->CompareFlag = params[0] ? GL_TRUE : GL_FALSE;
289 }
290 else {
291 _mesa_error(ctx, GL_INVALID_ENUM,
292 "glTexParameter(pname=GL_TEXTURE_COMPARE_SGIX)");
293 return;
294 }
295 break;
296 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
297 if (ctx->Extensions.SGIX_shadow) {
298 GLenum op = (GLenum) params[0];
299 if (op == GL_TEXTURE_LEQUAL_R_SGIX ||
300 op == GL_TEXTURE_GEQUAL_R_SGIX) {
301 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
302 texObj->CompareOperator = op;
303 }
304 else {
305 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)");
306 }
307 }
308 else {
309 _mesa_error(ctx, GL_INVALID_ENUM,
310 "glTexParameter(pname=GL_TEXTURE_COMPARE_OPERATOR_SGIX)");
311 return;
312 }
313 break;
314 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
315 if (ctx->Extensions.SGIX_shadow_ambient) {
316 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
317 texObj->ShadowAmbient = CLAMP(params[0], 0.0F, 1.0F);
318 }
319 else {
320 _mesa_error(ctx, GL_INVALID_ENUM,
321 "glTexParameter(pname=GL_SHADOW_AMBIENT_SGIX)");
322 return;
323 }
324 break;
325 case GL_GENERATE_MIPMAP_SGIS:
326 if (ctx->Extensions.SGIS_generate_mipmap) {
327 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
328 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
329 }
330 else {
331 _mesa_error(ctx, GL_INVALID_ENUM,
332 "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
333 return;
334 }
335 break;
336 case GL_TEXTURE_COMPARE_MODE_ARB:
337 if (ctx->Extensions.ARB_shadow) {
338 const GLenum mode = (GLenum) params[0];
339 if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) {
340 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
341 texObj->CompareMode = mode;
342 }
343 else {
344 _mesa_error(ctx, GL_INVALID_ENUM,
345 "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB: 0x%x)", mode);
346 return;
347 }
348 }
349 else {
350 _mesa_error(ctx, GL_INVALID_ENUM,
351 "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)");
352 return;
353 }
354 break;
355 case GL_TEXTURE_COMPARE_FUNC_ARB:
356 if (ctx->Extensions.ARB_shadow) {
357 const GLenum func = (GLenum) params[0];
358 if (func == GL_LEQUAL || func == GL_GEQUAL) {
359 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
360 texObj->CompareFunc = func;
361 }
362 else if (ctx->Extensions.EXT_shadow_funcs &&
363 (func == GL_EQUAL ||
364 func == GL_NOTEQUAL ||
365 func == GL_LESS ||
366 func == GL_GREATER ||
367 func == GL_ALWAYS ||
368 func == GL_NEVER)) {
369 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
370 texObj->CompareFunc = func;
371 }
372 else {
373 _mesa_error(ctx, GL_INVALID_ENUM,
374 "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)");
375 return;
376 }
377 }
378 else {
379 _mesa_error(ctx, GL_INVALID_ENUM,
380 "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)");
381 return;
382 }
383 break;
384 case GL_DEPTH_TEXTURE_MODE_ARB:
385 if (ctx->Extensions.ARB_depth_texture) {
386 const GLenum result = (GLenum) params[0];
387 if (result == GL_LUMINANCE || result == GL_INTENSITY
388 || result == GL_ALPHA) {
389 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
390 texObj->DepthMode = result;
391 }
392 else {
393 _mesa_error(ctx, GL_INVALID_ENUM,
394 "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)");
395 return;
396 }
397 }
398 else {
399 _mesa_error(ctx, GL_INVALID_ENUM,
400 "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)");
401 return;
402 }
403 break;
404 case GL_TEXTURE_LOD_BIAS:
405 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias*/
406 if (ctx->Extensions.EXT_texture_lod_bias) {
407 if (texObj->LodBias != params[0]) {
408 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
409 texObj->LodBias = params[0];
410 }
411 }
412 break;
413
414 default:
415 _mesa_error(ctx, GL_INVALID_ENUM,
416 "glTexParameter(pname=0x%x)", pname);
417 return;
418 }
419
420 texObj->_Complete = GL_FALSE;
421
422 if (ctx->Driver.TexParameter) {
423 (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params );
424 }
425 }
426
427
428 void GLAPIENTRY
429 _mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
430 {
431 GLfloat fparam[4];
432 if (pname == GL_TEXTURE_PRIORITY)
433 fparam[0] = INT_TO_FLOAT(param);
434 else
435 fparam[0] = (GLfloat) param;
436 fparam[1] = fparam[2] = fparam[3] = 0.0;
437 _mesa_TexParameterfv(target, pname, fparam);
438 }
439
440
441 void GLAPIENTRY
442 _mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
443 {
444 GLfloat fparam[4];
445 if (pname == GL_TEXTURE_BORDER_COLOR) {
446 fparam[0] = INT_TO_FLOAT(params[0]);
447 fparam[1] = INT_TO_FLOAT(params[1]);
448 fparam[2] = INT_TO_FLOAT(params[2]);
449 fparam[3] = INT_TO_FLOAT(params[3]);
450 }
451 else {
452 if (pname == GL_TEXTURE_PRIORITY)
453 fparam[0] = INT_TO_FLOAT(params[0]);
454 else
455 fparam[0] = (GLfloat) params[0];
456 fparam[1] = fparam[2] = fparam[3] = 0.0F;
457 }
458 _mesa_TexParameterfv(target, pname, fparam);
459 }
460
461
462 void GLAPIENTRY
463 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
464 GLenum pname, GLfloat *params )
465 {
466 GLint iparam;
467 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
468 *params = (GLfloat) iparam;
469 }
470
471
472 static GLuint
473 tex_image_dimensions(GLcontext *ctx, GLenum target)
474 {
475 switch (target) {
476 case GL_TEXTURE_1D:
477 case GL_PROXY_TEXTURE_1D:
478 return 1;
479 case GL_TEXTURE_2D:
480 case GL_PROXY_TEXTURE_2D:
481 return 2;
482 case GL_TEXTURE_3D:
483 case GL_PROXY_TEXTURE_3D:
484 return 3;
485 case GL_TEXTURE_CUBE_MAP:
486 case GL_PROXY_TEXTURE_CUBE_MAP:
487 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
488 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
489 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
490 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
491 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
492 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
493 return ctx->Extensions.ARB_texture_cube_map ? 2 : 0;
494 case GL_TEXTURE_RECTANGLE_NV:
495 case GL_PROXY_TEXTURE_RECTANGLE_NV:
496 return ctx->Extensions.NV_texture_rectangle ? 2 : 0;
497 case GL_TEXTURE_1D_ARRAY_EXT:
498 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
499 return ctx->Extensions.MESA_texture_array ? 2 : 0;
500 case GL_TEXTURE_2D_ARRAY_EXT:
501 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
502 return ctx->Extensions.MESA_texture_array ? 3 : 0;
503 default:
504 _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()");
505 return 0;
506 }
507 }
508
509
510 void GLAPIENTRY
511 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
512 GLenum pname, GLint *params )
513 {
514 const struct gl_texture_unit *texUnit;
515 struct gl_texture_object *texObj;
516 const struct gl_texture_image *img = NULL;
517 GLuint dimensions;
518 GLboolean isProxy;
519 GLint maxLevels;
520 GET_CURRENT_CONTEXT(ctx);
521 ASSERT_OUTSIDE_BEGIN_END(ctx);
522
523 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
524 _mesa_error(ctx, GL_INVALID_OPERATION,
525 "glGetTexLevelParameteriv(current unit)");
526 return;
527 }
528
529 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
530
531 /* this will catch bad target values */
532 dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */
533 if (dimensions == 0) {
534 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
535 return;
536 }
537
538 maxLevels = _mesa_max_texture_levels(ctx, target);
539 if (maxLevels == 0) {
540 /* should not happen since <target> was just checked above */
541 _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter");
542 return;
543 }
544
545 if (level < 0 || level >= maxLevels) {
546 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
547 return;
548 }
549
550 texObj = _mesa_select_tex_object(ctx, texUnit, target);
551 _mesa_lock_texture(ctx, texObj);
552
553 img = _mesa_select_tex_image(ctx, texObj, target, level);
554 if (!img || !img->TexFormat) {
555 /* undefined texture image */
556 if (pname == GL_TEXTURE_COMPONENTS)
557 *params = 1;
558 else
559 *params = 0;
560 goto out;
561 }
562
563 isProxy = _mesa_is_proxy_texture(target);
564
565 switch (pname) {
566 case GL_TEXTURE_WIDTH:
567 *params = img->Width;
568 break;
569 case GL_TEXTURE_HEIGHT:
570 *params = img->Height;
571 break;
572 case GL_TEXTURE_DEPTH:
573 *params = img->Depth;
574 break;
575 case GL_TEXTURE_INTERNAL_FORMAT:
576 *params = img->InternalFormat;
577 break;
578 case GL_TEXTURE_BORDER:
579 *params = img->Border;
580 break;
581 case GL_TEXTURE_RED_SIZE:
582 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
583 *params = img->TexFormat->RedBits;
584 else
585 *params = 0;
586 break;
587 case GL_TEXTURE_GREEN_SIZE:
588 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
589 *params = img->TexFormat->GreenBits;
590 else
591 *params = 0;
592 break;
593 case GL_TEXTURE_BLUE_SIZE:
594 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
595 *params = img->TexFormat->BlueBits;
596 else
597 *params = 0;
598 break;
599 case GL_TEXTURE_ALPHA_SIZE:
600 if (img->_BaseFormat == GL_ALPHA ||
601 img->_BaseFormat == GL_LUMINANCE_ALPHA ||
602 img->_BaseFormat == GL_RGBA)
603 *params = img->TexFormat->AlphaBits;
604 else
605 *params = 0;
606 break;
607 case GL_TEXTURE_INTENSITY_SIZE:
608 if (img->_BaseFormat != GL_INTENSITY)
609 *params = 0;
610 else if (img->TexFormat->IntensityBits > 0)
611 *params = img->TexFormat->IntensityBits;
612 else /* intensity probably stored as rgb texture */
613 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
614 break;
615 case GL_TEXTURE_LUMINANCE_SIZE:
616 if (img->_BaseFormat != GL_LUMINANCE &&
617 img->_BaseFormat != GL_LUMINANCE_ALPHA)
618 *params = 0;
619 else if (img->TexFormat->LuminanceBits > 0)
620 *params = img->TexFormat->LuminanceBits;
621 else /* luminance probably stored as rgb texture */
622 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
623 break;
624 case GL_TEXTURE_INDEX_SIZE_EXT:
625 if (img->_BaseFormat == GL_COLOR_INDEX)
626 *params = img->TexFormat->IndexBits;
627 else
628 *params = 0;
629 break;
630 case GL_TEXTURE_DEPTH_SIZE_ARB:
631 if (ctx->Extensions.SGIX_depth_texture ||
632 ctx->Extensions.ARB_depth_texture)
633 *params = img->TexFormat->DepthBits;
634 else
635 _mesa_error(ctx, GL_INVALID_ENUM,
636 "glGetTexLevelParameter[if]v(pname)");
637 break;
638 case GL_TEXTURE_STENCIL_SIZE_EXT:
639 if (ctx->Extensions.EXT_packed_depth_stencil) {
640 *params = img->TexFormat->StencilBits;
641 }
642 else {
643 _mesa_error(ctx, GL_INVALID_ENUM,
644 "glGetTexLevelParameter[if]v(pname)");
645 }
646 break;
647
648 /* GL_ARB_texture_compression */
649 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
650 if (ctx->Extensions.ARB_texture_compression) {
651 if (img->IsCompressed && !isProxy) {
652 /* Don't use ctx->Driver.CompressedTextureSize() since that
653 * may returned a padded hardware size.
654 */
655 *params = _mesa_compressed_texture_size(ctx, img->Width,
656 img->Height, img->Depth,
657 img->TexFormat->MesaFormat);
658 }
659 else {
660 _mesa_error(ctx, GL_INVALID_OPERATION,
661 "glGetTexLevelParameter[if]v(pname)");
662 }
663 }
664 else {
665 _mesa_error(ctx, GL_INVALID_ENUM,
666 "glGetTexLevelParameter[if]v(pname)");
667 }
668 break;
669 case GL_TEXTURE_COMPRESSED:
670 if (ctx->Extensions.ARB_texture_compression) {
671 *params = (GLint) img->IsCompressed;
672 }
673 else {
674 _mesa_error(ctx, GL_INVALID_ENUM,
675 "glGetTexLevelParameter[if]v(pname)");
676 }
677 break;
678
679 /* GL_ARB_texture_float */
680 case GL_TEXTURE_RED_TYPE_ARB:
681 if (ctx->Extensions.ARB_texture_float) {
682 *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE;
683 }
684 else {
685 _mesa_error(ctx, GL_INVALID_ENUM,
686 "glGetTexLevelParameter[if]v(pname)");
687 }
688 break;
689 case GL_TEXTURE_GREEN_TYPE_ARB:
690 if (ctx->Extensions.ARB_texture_float) {
691 *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
692 }
693 else {
694 _mesa_error(ctx, GL_INVALID_ENUM,
695 "glGetTexLevelParameter[if]v(pname)");
696 }
697 break;
698 case GL_TEXTURE_BLUE_TYPE_ARB:
699 if (ctx->Extensions.ARB_texture_float) {
700 *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
701 }
702 else {
703 _mesa_error(ctx, GL_INVALID_ENUM,
704 "glGetTexLevelParameter[if]v(pname)");
705 }
706 break;
707 case GL_TEXTURE_ALPHA_TYPE_ARB:
708 if (ctx->Extensions.ARB_texture_float) {
709 *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
710 }
711 else {
712 _mesa_error(ctx, GL_INVALID_ENUM,
713 "glGetTexLevelParameter[if]v(pname)");
714 }
715 break;
716 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
717 if (ctx->Extensions.ARB_texture_float) {
718 *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
719 }
720 else {
721 _mesa_error(ctx, GL_INVALID_ENUM,
722 "glGetTexLevelParameter[if]v(pname)");
723 }
724 break;
725 case GL_TEXTURE_INTENSITY_TYPE_ARB:
726 if (ctx->Extensions.ARB_texture_float) {
727 *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
728 }
729 else {
730 _mesa_error(ctx, GL_INVALID_ENUM,
731 "glGetTexLevelParameter[if]v(pname)");
732 }
733 break;
734 case GL_TEXTURE_DEPTH_TYPE_ARB:
735 if (ctx->Extensions.ARB_texture_float) {
736 *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
737 }
738 else {
739 _mesa_error(ctx, GL_INVALID_ENUM,
740 "glGetTexLevelParameter[if]v(pname)");
741 }
742 break;
743
744 default:
745 _mesa_error(ctx, GL_INVALID_ENUM,
746 "glGetTexLevelParameter[if]v(pname)");
747 }
748
749 out:
750 _mesa_unlock_texture(ctx, texObj);
751 }
752
753
754
755 void GLAPIENTRY
756 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
757 {
758 struct gl_texture_unit *texUnit;
759 struct gl_texture_object *obj;
760 GLboolean error = GL_FALSE;
761 GET_CURRENT_CONTEXT(ctx);
762 ASSERT_OUTSIDE_BEGIN_END(ctx);
763
764 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
765 _mesa_error(ctx, GL_INVALID_OPERATION,
766 "glGetTexParameterfv(current unit)");
767 return;
768 }
769
770 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
771
772 obj = _mesa_select_tex_object(ctx, texUnit, target);
773 if (!obj) {
774 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
775 return;
776 }
777
778 _mesa_lock_texture(ctx, obj);
779 switch (pname) {
780 case GL_TEXTURE_MAG_FILTER:
781 *params = ENUM_TO_FLOAT(obj->MagFilter);
782 break;
783 case GL_TEXTURE_MIN_FILTER:
784 *params = ENUM_TO_FLOAT(obj->MinFilter);
785 break;
786 case GL_TEXTURE_WRAP_S:
787 *params = ENUM_TO_FLOAT(obj->WrapS);
788 break;
789 case GL_TEXTURE_WRAP_T:
790 *params = ENUM_TO_FLOAT(obj->WrapT);
791 break;
792 case GL_TEXTURE_WRAP_R:
793 *params = ENUM_TO_FLOAT(obj->WrapR);
794 break;
795 case GL_TEXTURE_BORDER_COLOR:
796 params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
797 params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
798 params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
799 params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
800 break;
801 case GL_TEXTURE_RESIDENT:
802 {
803 GLboolean resident;
804 if (ctx->Driver.IsTextureResident)
805 resident = ctx->Driver.IsTextureResident(ctx, obj);
806 else
807 resident = GL_TRUE;
808 *params = ENUM_TO_FLOAT(resident);
809 }
810 break;
811 case GL_TEXTURE_PRIORITY:
812 *params = obj->Priority;
813 break;
814 case GL_TEXTURE_MIN_LOD:
815 *params = obj->MinLod;
816 break;
817 case GL_TEXTURE_MAX_LOD:
818 *params = obj->MaxLod;
819 break;
820 case GL_TEXTURE_BASE_LEVEL:
821 *params = (GLfloat) obj->BaseLevel;
822 break;
823 case GL_TEXTURE_MAX_LEVEL:
824 *params = (GLfloat) obj->MaxLevel;
825 break;
826 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
827 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
828 *params = obj->MaxAnisotropy;
829 }
830 else
831 error = 1;
832 break;
833 case GL_TEXTURE_COMPARE_SGIX:
834 if (ctx->Extensions.SGIX_shadow) {
835 *params = (GLfloat) obj->CompareFlag;
836 }
837 else
838 error = 1;
839 break;
840 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
841 if (ctx->Extensions.SGIX_shadow) {
842 *params = (GLfloat) obj->CompareOperator;
843 }
844 else
845 error = 1;
846 break;
847 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
848 if (ctx->Extensions.SGIX_shadow_ambient) {
849 *params = obj->ShadowAmbient;
850 }
851 else
852 error = 1;
853 break;
854 case GL_GENERATE_MIPMAP_SGIS:
855 if (ctx->Extensions.SGIS_generate_mipmap) {
856 *params = (GLfloat) obj->GenerateMipmap;
857 }
858 else
859 error = 1;
860 break;
861 case GL_TEXTURE_COMPARE_MODE_ARB:
862 if (ctx->Extensions.ARB_shadow) {
863 *params = (GLfloat) obj->CompareMode;
864 }
865 else
866 error = 1;
867 break;
868 case GL_TEXTURE_COMPARE_FUNC_ARB:
869 if (ctx->Extensions.ARB_shadow) {
870 *params = (GLfloat) obj->CompareFunc;
871 }
872 else
873 error = 1;
874 break;
875 case GL_DEPTH_TEXTURE_MODE_ARB:
876 if (ctx->Extensions.ARB_depth_texture) {
877 *params = (GLfloat) obj->DepthMode;
878 }
879 else
880 error = 1;
881 break;
882 case GL_TEXTURE_LOD_BIAS:
883 if (ctx->Extensions.EXT_texture_lod_bias) {
884 *params = obj->LodBias;
885 }
886 else
887 error = 1;
888 break;
889 default:
890 error = 1;
891 break;
892 }
893 if (error)
894 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
895 pname);
896
897 _mesa_unlock_texture(ctx, obj);
898 }
899
900
901 void GLAPIENTRY
902 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
903 {
904 struct gl_texture_unit *texUnit;
905 struct gl_texture_object *obj;
906 GET_CURRENT_CONTEXT(ctx);
907 ASSERT_OUTSIDE_BEGIN_END(ctx);
908
909 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
910 _mesa_error(ctx, GL_INVALID_OPERATION,
911 "glGetTexParameteriv(current unit)");
912 return;
913 }
914
915 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
916
917 obj = _mesa_select_tex_object(ctx, texUnit, target);
918 if (!obj) {
919 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(target)");
920 return;
921 }
922
923 switch (pname) {
924 case GL_TEXTURE_MAG_FILTER:
925 *params = (GLint) obj->MagFilter;
926 return;
927 case GL_TEXTURE_MIN_FILTER:
928 *params = (GLint) obj->MinFilter;
929 return;
930 case GL_TEXTURE_WRAP_S:
931 *params = (GLint) obj->WrapS;
932 return;
933 case GL_TEXTURE_WRAP_T:
934 *params = (GLint) obj->WrapT;
935 return;
936 case GL_TEXTURE_WRAP_R:
937 *params = (GLint) obj->WrapR;
938 return;
939 case GL_TEXTURE_BORDER_COLOR:
940 {
941 GLfloat b[4];
942 b[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
943 b[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
944 b[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
945 b[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
946 params[0] = FLOAT_TO_INT(b[0]);
947 params[1] = FLOAT_TO_INT(b[1]);
948 params[2] = FLOAT_TO_INT(b[2]);
949 params[3] = FLOAT_TO_INT(b[3]);
950 }
951 return;
952 case GL_TEXTURE_RESIDENT:
953 {
954 GLboolean resident;
955 if (ctx->Driver.IsTextureResident)
956 resident = ctx->Driver.IsTextureResident(ctx, obj);
957 else
958 resident = GL_TRUE;
959 *params = (GLint) resident;
960 }
961 return;
962 case GL_TEXTURE_PRIORITY:
963 *params = FLOAT_TO_INT(obj->Priority);
964 return;
965 case GL_TEXTURE_MIN_LOD:
966 *params = (GLint) obj->MinLod;
967 return;
968 case GL_TEXTURE_MAX_LOD:
969 *params = (GLint) obj->MaxLod;
970 return;
971 case GL_TEXTURE_BASE_LEVEL:
972 *params = obj->BaseLevel;
973 return;
974 case GL_TEXTURE_MAX_LEVEL:
975 *params = obj->MaxLevel;
976 return;
977 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
978 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
979 *params = (GLint) obj->MaxAnisotropy;
980 return;
981 }
982 break;
983 case GL_TEXTURE_COMPARE_SGIX:
984 if (ctx->Extensions.SGIX_shadow) {
985 *params = (GLint) obj->CompareFlag;
986 return;
987 }
988 break;
989 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
990 if (ctx->Extensions.SGIX_shadow) {
991 *params = (GLint) obj->CompareOperator;
992 return;
993 }
994 break;
995 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
996 if (ctx->Extensions.SGIX_shadow_ambient) {
997 *params = (GLint) FLOAT_TO_INT(obj->ShadowAmbient);
998 return;
999 }
1000 break;
1001 case GL_GENERATE_MIPMAP_SGIS:
1002 if (ctx->Extensions.SGIS_generate_mipmap) {
1003 *params = (GLint) obj->GenerateMipmap;
1004 return;
1005 }
1006 break;
1007 case GL_TEXTURE_COMPARE_MODE_ARB:
1008 if (ctx->Extensions.ARB_shadow) {
1009 *params = (GLint) obj->CompareMode;
1010 return;
1011 }
1012 break;
1013 case GL_TEXTURE_COMPARE_FUNC_ARB:
1014 if (ctx->Extensions.ARB_shadow) {
1015 *params = (GLint) obj->CompareFunc;
1016 return;
1017 }
1018 break;
1019 case GL_DEPTH_TEXTURE_MODE_ARB:
1020 if (ctx->Extensions.ARB_depth_texture) {
1021 *params = (GLint) obj->DepthMode;
1022 return;
1023 }
1024 break;
1025 case GL_TEXTURE_LOD_BIAS:
1026 if (ctx->Extensions.EXT_texture_lod_bias) {
1027 *params = (GLint) obj->LodBias;
1028 return;
1029 }
1030 break;
1031 default:
1032 ; /* silence warnings */
1033 }
1034 /* If we get here, pname was an unrecognized enum */
1035 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1036 }