Merge branch 'master' into gallium-0.2
[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 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
328 }
329 else {
330 _mesa_error(ctx, GL_INVALID_ENUM,
331 "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
332 return;
333 }
334 break;
335 case GL_TEXTURE_COMPARE_MODE_ARB:
336 if (ctx->Extensions.ARB_shadow) {
337 const GLenum mode = (GLenum) params[0];
338 if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) {
339 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
340 texObj->CompareMode = mode;
341 }
342 else {
343 _mesa_error(ctx, GL_INVALID_ENUM,
344 "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB: 0x%x)", mode);
345 return;
346 }
347 }
348 else {
349 _mesa_error(ctx, GL_INVALID_ENUM,
350 "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)");
351 return;
352 }
353 break;
354 case GL_TEXTURE_COMPARE_FUNC_ARB:
355 if (ctx->Extensions.ARB_shadow) {
356 const GLenum func = (GLenum) params[0];
357 if (func == GL_LEQUAL || func == GL_GEQUAL) {
358 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
359 texObj->CompareFunc = func;
360 }
361 else if (ctx->Extensions.EXT_shadow_funcs &&
362 (func == GL_EQUAL ||
363 func == GL_NOTEQUAL ||
364 func == GL_LESS ||
365 func == GL_GREATER ||
366 func == GL_ALWAYS ||
367 func == GL_NEVER)) {
368 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
369 texObj->CompareFunc = func;
370 }
371 else {
372 _mesa_error(ctx, GL_INVALID_ENUM,
373 "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)");
374 return;
375 }
376 }
377 else {
378 _mesa_error(ctx, GL_INVALID_ENUM,
379 "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)");
380 return;
381 }
382 break;
383 case GL_DEPTH_TEXTURE_MODE_ARB:
384 if (ctx->Extensions.ARB_depth_texture) {
385 const GLenum result = (GLenum) params[0];
386 if (result == GL_LUMINANCE || result == GL_INTENSITY
387 || result == GL_ALPHA) {
388 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
389 texObj->DepthMode = result;
390 }
391 else {
392 _mesa_error(ctx, GL_INVALID_ENUM,
393 "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)");
394 return;
395 }
396 }
397 else {
398 _mesa_error(ctx, GL_INVALID_ENUM,
399 "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)");
400 return;
401 }
402 break;
403 case GL_TEXTURE_LOD_BIAS:
404 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias*/
405 if (ctx->Extensions.EXT_texture_lod_bias) {
406 if (texObj->LodBias != params[0]) {
407 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
408 texObj->LodBias = params[0];
409 }
410 }
411 break;
412 #ifdef FEATURE_OES_draw_texture
413 case GL_TEXTURE_CROP_RECT_OES:
414 texObj->CropRect[0] = (GLint) params[0];
415 texObj->CropRect[1] = (GLint) params[1];
416 texObj->CropRect[2] = (GLint) params[2];
417 texObj->CropRect[3] = (GLint) params[3];
418 break;
419 #endif
420
421 default:
422 _mesa_error(ctx, GL_INVALID_ENUM,
423 "glTexParameter(pname=0x%x)", pname);
424 return;
425 }
426
427 texObj->_Complete = GL_FALSE;
428
429 if (ctx->Driver.TexParameter) {
430 (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params );
431 }
432 }
433
434
435 void GLAPIENTRY
436 _mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
437 {
438 GLfloat fparam[4];
439 if (pname == GL_TEXTURE_PRIORITY)
440 fparam[0] = INT_TO_FLOAT(param);
441 else
442 fparam[0] = (GLfloat) param;
443 fparam[1] = fparam[2] = fparam[3] = 0.0;
444 _mesa_TexParameterfv(target, pname, fparam);
445 }
446
447
448 void GLAPIENTRY
449 _mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
450 {
451 GLfloat fparam[4];
452 if (pname == GL_TEXTURE_BORDER_COLOR) {
453 fparam[0] = INT_TO_FLOAT(params[0]);
454 fparam[1] = INT_TO_FLOAT(params[1]);
455 fparam[2] = INT_TO_FLOAT(params[2]);
456 fparam[3] = INT_TO_FLOAT(params[3]);
457 }
458 else if (pname == GL_TEXTURE_CROP_RECT_OES) {
459 fparam[0] = (GLfloat) params[0];
460 fparam[1] = (GLfloat) params[1];
461 fparam[2] = (GLfloat) params[2];
462 fparam[3] = (GLfloat) params[3];
463 }
464 else {
465 if (pname == GL_TEXTURE_PRIORITY)
466 fparam[0] = INT_TO_FLOAT(params[0]);
467 else
468 fparam[0] = (GLfloat) params[0];
469 fparam[1] = fparam[2] = fparam[3] = 0.0F;
470 }
471 _mesa_TexParameterfv(target, pname, fparam);
472 }
473
474
475 void GLAPIENTRY
476 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
477 GLenum pname, GLfloat *params )
478 {
479 GLint iparam;
480 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
481 *params = (GLfloat) iparam;
482 }
483
484
485 static GLuint
486 tex_image_dimensions(GLcontext *ctx, GLenum target)
487 {
488 switch (target) {
489 case GL_TEXTURE_1D:
490 case GL_PROXY_TEXTURE_1D:
491 return 1;
492 case GL_TEXTURE_2D:
493 case GL_PROXY_TEXTURE_2D:
494 return 2;
495 case GL_TEXTURE_3D:
496 case GL_PROXY_TEXTURE_3D:
497 return 3;
498 case GL_TEXTURE_CUBE_MAP:
499 case GL_PROXY_TEXTURE_CUBE_MAP:
500 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
501 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
502 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
503 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
504 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
505 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
506 return ctx->Extensions.ARB_texture_cube_map ? 2 : 0;
507 case GL_TEXTURE_RECTANGLE_NV:
508 case GL_PROXY_TEXTURE_RECTANGLE_NV:
509 return ctx->Extensions.NV_texture_rectangle ? 2 : 0;
510 case GL_TEXTURE_1D_ARRAY_EXT:
511 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
512 return ctx->Extensions.MESA_texture_array ? 2 : 0;
513 case GL_TEXTURE_2D_ARRAY_EXT:
514 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
515 return ctx->Extensions.MESA_texture_array ? 3 : 0;
516 default:
517 _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()");
518 return 0;
519 }
520 }
521
522
523 void GLAPIENTRY
524 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
525 GLenum pname, GLint *params )
526 {
527 const struct gl_texture_unit *texUnit;
528 struct gl_texture_object *texObj;
529 const struct gl_texture_image *img = NULL;
530 GLuint dimensions;
531 GLboolean isProxy;
532 GLint maxLevels;
533 GET_CURRENT_CONTEXT(ctx);
534 ASSERT_OUTSIDE_BEGIN_END(ctx);
535
536 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
537 _mesa_error(ctx, GL_INVALID_OPERATION,
538 "glGetTexLevelParameteriv(current unit)");
539 return;
540 }
541
542 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
543
544 /* this will catch bad target values */
545 dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */
546 if (dimensions == 0) {
547 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
548 return;
549 }
550
551 maxLevels = _mesa_max_texture_levels(ctx, target);
552 if (maxLevels == 0) {
553 /* should not happen since <target> was just checked above */
554 _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter");
555 return;
556 }
557
558 if (level < 0 || level >= maxLevels) {
559 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
560 return;
561 }
562
563 texObj = _mesa_select_tex_object(ctx, texUnit, target);
564 _mesa_lock_texture(ctx, texObj);
565
566 img = _mesa_select_tex_image(ctx, texObj, target, level);
567 if (!img || !img->TexFormat) {
568 /* undefined texture image */
569 if (pname == GL_TEXTURE_COMPONENTS)
570 *params = 1;
571 else
572 *params = 0;
573 goto out;
574 }
575
576 isProxy = _mesa_is_proxy_texture(target);
577
578 switch (pname) {
579 case GL_TEXTURE_WIDTH:
580 *params = img->Width;
581 break;
582 case GL_TEXTURE_HEIGHT:
583 *params = img->Height;
584 break;
585 case GL_TEXTURE_DEPTH:
586 *params = img->Depth;
587 break;
588 case GL_TEXTURE_INTERNAL_FORMAT:
589 *params = img->InternalFormat;
590 break;
591 case GL_TEXTURE_BORDER:
592 *params = img->Border;
593 break;
594 case GL_TEXTURE_RED_SIZE:
595 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
596 *params = img->TexFormat->RedBits;
597 else
598 *params = 0;
599 break;
600 case GL_TEXTURE_GREEN_SIZE:
601 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
602 *params = img->TexFormat->GreenBits;
603 else
604 *params = 0;
605 break;
606 case GL_TEXTURE_BLUE_SIZE:
607 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
608 *params = img->TexFormat->BlueBits;
609 else
610 *params = 0;
611 break;
612 case GL_TEXTURE_ALPHA_SIZE:
613 if (img->_BaseFormat == GL_ALPHA ||
614 img->_BaseFormat == GL_LUMINANCE_ALPHA ||
615 img->_BaseFormat == GL_RGBA)
616 *params = img->TexFormat->AlphaBits;
617 else
618 *params = 0;
619 break;
620 case GL_TEXTURE_INTENSITY_SIZE:
621 if (img->_BaseFormat != GL_INTENSITY)
622 *params = 0;
623 else if (img->TexFormat->IntensityBits > 0)
624 *params = img->TexFormat->IntensityBits;
625 else /* intensity probably stored as rgb texture */
626 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
627 break;
628 case GL_TEXTURE_LUMINANCE_SIZE:
629 if (img->_BaseFormat != GL_LUMINANCE &&
630 img->_BaseFormat != GL_LUMINANCE_ALPHA)
631 *params = 0;
632 else if (img->TexFormat->LuminanceBits > 0)
633 *params = img->TexFormat->LuminanceBits;
634 else /* luminance probably stored as rgb texture */
635 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
636 break;
637 case GL_TEXTURE_INDEX_SIZE_EXT:
638 if (img->_BaseFormat == GL_COLOR_INDEX)
639 *params = img->TexFormat->IndexBits;
640 else
641 *params = 0;
642 break;
643 case GL_TEXTURE_DEPTH_SIZE_ARB:
644 if (ctx->Extensions.SGIX_depth_texture ||
645 ctx->Extensions.ARB_depth_texture)
646 *params = img->TexFormat->DepthBits;
647 else
648 _mesa_error(ctx, GL_INVALID_ENUM,
649 "glGetTexLevelParameter[if]v(pname)");
650 break;
651 case GL_TEXTURE_STENCIL_SIZE_EXT:
652 if (ctx->Extensions.EXT_packed_depth_stencil) {
653 *params = img->TexFormat->StencilBits;
654 }
655 else {
656 _mesa_error(ctx, GL_INVALID_ENUM,
657 "glGetTexLevelParameter[if]v(pname)");
658 }
659 break;
660
661 /* GL_ARB_texture_compression */
662 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
663 if (ctx->Extensions.ARB_texture_compression) {
664 if (img->IsCompressed && !isProxy) {
665 /* Don't use ctx->Driver.CompressedTextureSize() since that
666 * may returned a padded hardware size.
667 */
668 *params = _mesa_compressed_texture_size(ctx, img->Width,
669 img->Height, img->Depth,
670 img->TexFormat->MesaFormat);
671 }
672 else {
673 _mesa_error(ctx, GL_INVALID_OPERATION,
674 "glGetTexLevelParameter[if]v(pname)");
675 }
676 }
677 else {
678 _mesa_error(ctx, GL_INVALID_ENUM,
679 "glGetTexLevelParameter[if]v(pname)");
680 }
681 break;
682 case GL_TEXTURE_COMPRESSED:
683 if (ctx->Extensions.ARB_texture_compression) {
684 *params = (GLint) img->IsCompressed;
685 }
686 else {
687 _mesa_error(ctx, GL_INVALID_ENUM,
688 "glGetTexLevelParameter[if]v(pname)");
689 }
690 break;
691
692 /* GL_ARB_texture_float */
693 case GL_TEXTURE_RED_TYPE_ARB:
694 if (ctx->Extensions.ARB_texture_float) {
695 *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE;
696 }
697 else {
698 _mesa_error(ctx, GL_INVALID_ENUM,
699 "glGetTexLevelParameter[if]v(pname)");
700 }
701 break;
702 case GL_TEXTURE_GREEN_TYPE_ARB:
703 if (ctx->Extensions.ARB_texture_float) {
704 *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
705 }
706 else {
707 _mesa_error(ctx, GL_INVALID_ENUM,
708 "glGetTexLevelParameter[if]v(pname)");
709 }
710 break;
711 case GL_TEXTURE_BLUE_TYPE_ARB:
712 if (ctx->Extensions.ARB_texture_float) {
713 *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
714 }
715 else {
716 _mesa_error(ctx, GL_INVALID_ENUM,
717 "glGetTexLevelParameter[if]v(pname)");
718 }
719 break;
720 case GL_TEXTURE_ALPHA_TYPE_ARB:
721 if (ctx->Extensions.ARB_texture_float) {
722 *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
723 }
724 else {
725 _mesa_error(ctx, GL_INVALID_ENUM,
726 "glGetTexLevelParameter[if]v(pname)");
727 }
728 break;
729 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
730 if (ctx->Extensions.ARB_texture_float) {
731 *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
732 }
733 else {
734 _mesa_error(ctx, GL_INVALID_ENUM,
735 "glGetTexLevelParameter[if]v(pname)");
736 }
737 break;
738 case GL_TEXTURE_INTENSITY_TYPE_ARB:
739 if (ctx->Extensions.ARB_texture_float) {
740 *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
741 }
742 else {
743 _mesa_error(ctx, GL_INVALID_ENUM,
744 "glGetTexLevelParameter[if]v(pname)");
745 }
746 break;
747 case GL_TEXTURE_DEPTH_TYPE_ARB:
748 if (ctx->Extensions.ARB_texture_float) {
749 *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
750 }
751 else {
752 _mesa_error(ctx, GL_INVALID_ENUM,
753 "glGetTexLevelParameter[if]v(pname)");
754 }
755 break;
756
757 default:
758 _mesa_error(ctx, GL_INVALID_ENUM,
759 "glGetTexLevelParameter[if]v(pname)");
760 }
761
762 out:
763 _mesa_unlock_texture(ctx, texObj);
764 }
765
766
767
768 void GLAPIENTRY
769 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
770 {
771 struct gl_texture_unit *texUnit;
772 struct gl_texture_object *obj;
773 GLboolean error = GL_FALSE;
774 GET_CURRENT_CONTEXT(ctx);
775 ASSERT_OUTSIDE_BEGIN_END(ctx);
776
777 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
778 _mesa_error(ctx, GL_INVALID_OPERATION,
779 "glGetTexParameterfv(current unit)");
780 return;
781 }
782
783 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
784
785 obj = _mesa_select_tex_object(ctx, texUnit, target);
786 if (!obj) {
787 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
788 return;
789 }
790
791 _mesa_lock_texture(ctx, obj);
792 switch (pname) {
793 case GL_TEXTURE_MAG_FILTER:
794 *params = ENUM_TO_FLOAT(obj->MagFilter);
795 break;
796 case GL_TEXTURE_MIN_FILTER:
797 *params = ENUM_TO_FLOAT(obj->MinFilter);
798 break;
799 case GL_TEXTURE_WRAP_S:
800 *params = ENUM_TO_FLOAT(obj->WrapS);
801 break;
802 case GL_TEXTURE_WRAP_T:
803 *params = ENUM_TO_FLOAT(obj->WrapT);
804 break;
805 case GL_TEXTURE_WRAP_R:
806 *params = ENUM_TO_FLOAT(obj->WrapR);
807 break;
808 case GL_TEXTURE_BORDER_COLOR:
809 params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
810 params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
811 params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
812 params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
813 break;
814 case GL_TEXTURE_RESIDENT:
815 {
816 GLboolean resident;
817 if (ctx->Driver.IsTextureResident)
818 resident = ctx->Driver.IsTextureResident(ctx, obj);
819 else
820 resident = GL_TRUE;
821 *params = ENUM_TO_FLOAT(resident);
822 }
823 break;
824 case GL_TEXTURE_PRIORITY:
825 *params = obj->Priority;
826 break;
827 case GL_TEXTURE_MIN_LOD:
828 *params = obj->MinLod;
829 break;
830 case GL_TEXTURE_MAX_LOD:
831 *params = obj->MaxLod;
832 break;
833 case GL_TEXTURE_BASE_LEVEL:
834 *params = (GLfloat) obj->BaseLevel;
835 break;
836 case GL_TEXTURE_MAX_LEVEL:
837 *params = (GLfloat) obj->MaxLevel;
838 break;
839 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
840 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
841 *params = obj->MaxAnisotropy;
842 }
843 else
844 error = 1;
845 break;
846 case GL_TEXTURE_COMPARE_SGIX:
847 if (ctx->Extensions.SGIX_shadow) {
848 *params = (GLfloat) obj->CompareFlag;
849 }
850 else
851 error = 1;
852 break;
853 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
854 if (ctx->Extensions.SGIX_shadow) {
855 *params = (GLfloat) obj->CompareOperator;
856 }
857 else
858 error = 1;
859 break;
860 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
861 if (ctx->Extensions.SGIX_shadow_ambient) {
862 *params = obj->ShadowAmbient;
863 }
864 else
865 error = 1;
866 break;
867 case GL_GENERATE_MIPMAP_SGIS:
868 if (ctx->Extensions.SGIS_generate_mipmap) {
869 *params = (GLfloat) obj->GenerateMipmap;
870 }
871 else
872 error = 1;
873 break;
874 case GL_TEXTURE_COMPARE_MODE_ARB:
875 if (ctx->Extensions.ARB_shadow) {
876 *params = (GLfloat) obj->CompareMode;
877 }
878 else
879 error = 1;
880 break;
881 case GL_TEXTURE_COMPARE_FUNC_ARB:
882 if (ctx->Extensions.ARB_shadow) {
883 *params = (GLfloat) obj->CompareFunc;
884 }
885 else
886 error = 1;
887 break;
888 case GL_DEPTH_TEXTURE_MODE_ARB:
889 if (ctx->Extensions.ARB_depth_texture) {
890 *params = (GLfloat) obj->DepthMode;
891 }
892 else
893 error = 1;
894 break;
895 case GL_TEXTURE_LOD_BIAS:
896 if (ctx->Extensions.EXT_texture_lod_bias) {
897 *params = obj->LodBias;
898 }
899 else
900 error = 1;
901 break;
902 #ifdef FEATURE_OES_draw_texture
903 case GL_TEXTURE_CROP_RECT_OES:
904 params[0] = obj->CropRect[0];
905 params[0] = obj->CropRect[1];
906 params[0] = obj->CropRect[2];
907 params[0] = obj->CropRect[3];
908 break;
909 #endif
910 default:
911 error = 1;
912 break;
913 }
914 if (error)
915 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
916 pname);
917
918 _mesa_unlock_texture(ctx, obj);
919 }
920
921
922 void GLAPIENTRY
923 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
924 {
925 struct gl_texture_unit *texUnit;
926 struct gl_texture_object *obj;
927 GET_CURRENT_CONTEXT(ctx);
928 ASSERT_OUTSIDE_BEGIN_END(ctx);
929
930 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
931 _mesa_error(ctx, GL_INVALID_OPERATION,
932 "glGetTexParameteriv(current unit)");
933 return;
934 }
935
936 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
937
938 obj = _mesa_select_tex_object(ctx, texUnit, target);
939 if (!obj) {
940 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(target)");
941 return;
942 }
943
944 switch (pname) {
945 case GL_TEXTURE_MAG_FILTER:
946 *params = (GLint) obj->MagFilter;
947 return;
948 case GL_TEXTURE_MIN_FILTER:
949 *params = (GLint) obj->MinFilter;
950 return;
951 case GL_TEXTURE_WRAP_S:
952 *params = (GLint) obj->WrapS;
953 return;
954 case GL_TEXTURE_WRAP_T:
955 *params = (GLint) obj->WrapT;
956 return;
957 case GL_TEXTURE_WRAP_R:
958 *params = (GLint) obj->WrapR;
959 return;
960 case GL_TEXTURE_BORDER_COLOR:
961 {
962 GLfloat b[4];
963 b[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
964 b[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
965 b[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
966 b[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
967 params[0] = FLOAT_TO_INT(b[0]);
968 params[1] = FLOAT_TO_INT(b[1]);
969 params[2] = FLOAT_TO_INT(b[2]);
970 params[3] = FLOAT_TO_INT(b[3]);
971 }
972 return;
973 case GL_TEXTURE_RESIDENT:
974 {
975 GLboolean resident;
976 if (ctx->Driver.IsTextureResident)
977 resident = ctx->Driver.IsTextureResident(ctx, obj);
978 else
979 resident = GL_TRUE;
980 *params = (GLint) resident;
981 }
982 return;
983 case GL_TEXTURE_PRIORITY:
984 *params = FLOAT_TO_INT(obj->Priority);
985 return;
986 case GL_TEXTURE_MIN_LOD:
987 *params = (GLint) obj->MinLod;
988 return;
989 case GL_TEXTURE_MAX_LOD:
990 *params = (GLint) obj->MaxLod;
991 return;
992 case GL_TEXTURE_BASE_LEVEL:
993 *params = obj->BaseLevel;
994 return;
995 case GL_TEXTURE_MAX_LEVEL:
996 *params = obj->MaxLevel;
997 return;
998 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
999 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
1000 *params = (GLint) obj->MaxAnisotropy;
1001 return;
1002 }
1003 break;
1004 case GL_TEXTURE_COMPARE_SGIX:
1005 if (ctx->Extensions.SGIX_shadow) {
1006 *params = (GLint) obj->CompareFlag;
1007 return;
1008 }
1009 break;
1010 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
1011 if (ctx->Extensions.SGIX_shadow) {
1012 *params = (GLint) obj->CompareOperator;
1013 return;
1014 }
1015 break;
1016 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
1017 if (ctx->Extensions.SGIX_shadow_ambient) {
1018 *params = (GLint) FLOAT_TO_INT(obj->ShadowAmbient);
1019 return;
1020 }
1021 break;
1022 case GL_GENERATE_MIPMAP_SGIS:
1023 if (ctx->Extensions.SGIS_generate_mipmap) {
1024 *params = (GLint) obj->GenerateMipmap;
1025 return;
1026 }
1027 break;
1028 case GL_TEXTURE_COMPARE_MODE_ARB:
1029 if (ctx->Extensions.ARB_shadow) {
1030 *params = (GLint) obj->CompareMode;
1031 return;
1032 }
1033 break;
1034 case GL_TEXTURE_COMPARE_FUNC_ARB:
1035 if (ctx->Extensions.ARB_shadow) {
1036 *params = (GLint) obj->CompareFunc;
1037 return;
1038 }
1039 break;
1040 case GL_DEPTH_TEXTURE_MODE_ARB:
1041 if (ctx->Extensions.ARB_depth_texture) {
1042 *params = (GLint) obj->DepthMode;
1043 return;
1044 }
1045 break;
1046 case GL_TEXTURE_LOD_BIAS:
1047 if (ctx->Extensions.EXT_texture_lod_bias) {
1048 *params = (GLint) obj->LodBias;
1049 return;
1050 }
1051 break;
1052 #ifdef FEATURE_OES_draw_texture
1053 case GL_TEXTURE_CROP_RECT_OES:
1054 params[0] = obj->CropRect[0];
1055 params[0] = obj->CropRect[1];
1056 params[0] = obj->CropRect[2];
1057 params[0] = obj->CropRect[3];
1058 break;
1059 #endif
1060 default:
1061 ; /* silence warnings */
1062 }
1063 /* If we get here, pname was an unrecognized enum */
1064 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1065 }