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