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