mesa: for ARB_fbo, lift restriction that all FBO attachments are same size and color...
[mesa.git] / src / mesa / main / texparam.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file texparam.c
27 *
28 * glTexParameter-related functions
29 */
30
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/enums.h"
35 #include "main/colormac.h"
36 #include "main/macros.h"
37 #include "main/texcompress.h"
38 #include "main/texparam.h"
39 #include "main/teximage.h"
40
41
42 /**
43 * Check if a coordinate wrap mode is supported for the texture target.
44 * \return GL_TRUE if legal, GL_FALSE otherwise
45 */
46 static GLboolean
47 validate_texture_wrap_mode(GLcontext * ctx, GLenum target, GLenum wrap)
48 {
49 const struct gl_extensions * const e = & ctx->Extensions;
50
51 if (wrap == GL_CLAMP || wrap == GL_CLAMP_TO_EDGE ||
52 (wrap == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
53 /* any texture target */
54 return GL_TRUE;
55 }
56 else if (target != GL_TEXTURE_RECTANGLE_NV &&
57 (wrap == GL_REPEAT ||
58 (wrap == GL_MIRRORED_REPEAT &&
59 e->ARB_texture_mirrored_repeat) ||
60 (wrap == GL_MIRROR_CLAMP_EXT &&
61 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
62 (wrap == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
63 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
64 (wrap == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
65 (e->EXT_texture_mirror_clamp)))) {
66 /* non-rectangle texture */
67 return GL_TRUE;
68 }
69
70 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
71 return GL_FALSE;
72 }
73
74
75 void GLAPIENTRY
76 _mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
77 {
78 _mesa_TexParameterfv(target, pname, &param);
79 }
80
81
82 void GLAPIENTRY
83 _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
84 {
85 const GLenum eparam = (GLenum) (GLint) params[0];
86 struct gl_texture_unit *texUnit;
87 struct gl_texture_object *texObj;
88 GET_CURRENT_CONTEXT(ctx);
89 ASSERT_OUTSIDE_BEGIN_END(ctx);
90
91 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
92 _mesa_debug(ctx, "glTexParameter %s %s %.1f(%s)...\n",
93 _mesa_lookup_enum_by_nr(target),
94 _mesa_lookup_enum_by_nr(pname),
95 *params,
96 _mesa_lookup_enum_by_nr(eparam));
97
98 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
99 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameterfv(current unit)");
100 return;
101 }
102
103 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
104
105 switch (target) {
106 case GL_TEXTURE_1D:
107 texObj = texUnit->Current1D;
108 break;
109 case GL_TEXTURE_2D:
110 texObj = texUnit->Current2D;
111 break;
112 case GL_TEXTURE_3D:
113 texObj = texUnit->Current3D;
114 break;
115 case GL_TEXTURE_CUBE_MAP:
116 if (!ctx->Extensions.ARB_texture_cube_map) {
117 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
118 return;
119 }
120 texObj = texUnit->CurrentCubeMap;
121 break;
122 case GL_TEXTURE_RECTANGLE_NV:
123 if (!ctx->Extensions.NV_texture_rectangle) {
124 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
125 return;
126 }
127 texObj = texUnit->CurrentRect;
128 break;
129 case GL_TEXTURE_1D_ARRAY_EXT:
130 if (!ctx->Extensions.MESA_texture_array) {
131 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
132 return;
133 }
134 texObj = texUnit->Current1DArray;
135 break;
136 case GL_TEXTURE_2D_ARRAY_EXT:
137 if (!ctx->Extensions.MESA_texture_array) {
138 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
139 return;
140 }
141 texObj = texUnit->Current2DArray;
142 break;
143 default:
144 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
145 return;
146 }
147
148 switch (pname) {
149 case GL_TEXTURE_MIN_FILTER:
150 /* A small optimization */
151 if (texObj->MinFilter == eparam)
152 return;
153 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
154 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
155 texObj->MinFilter = eparam;
156 }
157 else if ((eparam==GL_NEAREST_MIPMAP_NEAREST ||
158 eparam==GL_LINEAR_MIPMAP_NEAREST ||
159 eparam==GL_NEAREST_MIPMAP_LINEAR ||
160 eparam==GL_LINEAR_MIPMAP_LINEAR) &&
161 texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
162 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
163 texObj->MinFilter = eparam;
164 }
165 else {
166 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
167 return;
168 }
169 break;
170 case GL_TEXTURE_MAG_FILTER:
171 /* A small optimization */
172 if (texObj->MagFilter == eparam)
173 return;
174
175 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
176 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
177 texObj->MagFilter = eparam;
178 }
179 else {
180 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
181 return;
182 }
183 break;
184 case GL_TEXTURE_WRAP_S:
185 if (texObj->WrapS == eparam)
186 return;
187 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
188 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
189 texObj->WrapS = eparam;
190 }
191 else {
192 return;
193 }
194 break;
195 case GL_TEXTURE_WRAP_T:
196 if (texObj->WrapT == eparam)
197 return;
198 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
199 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
200 texObj->WrapT = eparam;
201 }
202 else {
203 return;
204 }
205 break;
206 case GL_TEXTURE_WRAP_R:
207 if (texObj->WrapR == eparam)
208 return;
209 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
210 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
211 texObj->WrapR = eparam;
212 }
213 else {
214 return;
215 }
216 break;
217 case GL_TEXTURE_BORDER_COLOR:
218 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
219 texObj->BorderColor[RCOMP] = params[0];
220 texObj->BorderColor[GCOMP] = params[1];
221 texObj->BorderColor[BCOMP] = params[2];
222 texObj->BorderColor[ACOMP] = params[3];
223 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[RCOMP], params[0]);
224 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[GCOMP], params[1]);
225 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[BCOMP], params[2]);
226 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[ACOMP], params[3]);
227 break;
228 case GL_TEXTURE_MIN_LOD:
229 if (texObj->MinLod == params[0])
230 return;
231 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
232 texObj->MinLod = params[0];
233 break;
234 case GL_TEXTURE_MAX_LOD:
235 if (texObj->MaxLod == params[0])
236 return;
237 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
238 texObj->MaxLod = params[0];
239 break;
240 case GL_TEXTURE_BASE_LEVEL:
241 if (params[0] < 0.0) {
242 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
243 return;
244 }
245 if (target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0.0) {
246 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
247 return;
248 }
249 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
250 texObj->BaseLevel = (GLint) params[0];
251 break;
252 case GL_TEXTURE_MAX_LEVEL:
253 if (params[0] < 0.0) {
254 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
255 return;
256 }
257 if (target == GL_TEXTURE_RECTANGLE_ARB) {
258 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(param)");
259 return;
260 }
261 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
262 texObj->MaxLevel = (GLint) params[0];
263 break;
264 case GL_TEXTURE_PRIORITY:
265 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
266 texObj->Priority = CLAMP( params[0], 0.0F, 1.0F );
267 break;
268 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
269 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
270 if (params[0] < 1.0) {
271 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
272 return;
273 }
274 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
275 /* clamp to max, that's what NVIDIA does */
276 texObj->MaxAnisotropy = MIN2(params[0],
277 ctx->Const.MaxTextureMaxAnisotropy);
278 }
279 else {
280 _mesa_error(ctx, GL_INVALID_ENUM,
281 "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
282 return;
283 }
284 break;
285 case GL_TEXTURE_COMPARE_SGIX:
286 if (ctx->Extensions.SGIX_shadow) {
287 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
288 texObj->CompareFlag = params[0] ? GL_TRUE : GL_FALSE;
289 }
290 else {
291 _mesa_error(ctx, GL_INVALID_ENUM,
292 "glTexParameter(pname=GL_TEXTURE_COMPARE_SGIX)");
293 return;
294 }
295 break;
296 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
297 if (ctx->Extensions.SGIX_shadow) {
298 GLenum op = (GLenum) params[0];
299 if (op == GL_TEXTURE_LEQUAL_R_SGIX ||
300 op == GL_TEXTURE_GEQUAL_R_SGIX) {
301 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
302 texObj->CompareOperator = op;
303 }
304 else {
305 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)");
306 }
307 }
308 else {
309 _mesa_error(ctx, GL_INVALID_ENUM,
310 "glTexParameter(pname=GL_TEXTURE_COMPARE_OPERATOR_SGIX)");
311 return;
312 }
313 break;
314 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
315 if (ctx->Extensions.SGIX_shadow_ambient) {
316 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
317 texObj->ShadowAmbient = CLAMP(params[0], 0.0F, 1.0F);
318 }
319 else {
320 _mesa_error(ctx, GL_INVALID_ENUM,
321 "glTexParameter(pname=GL_SHADOW_AMBIENT_SGIX)");
322 return;
323 }
324 break;
325 case GL_GENERATE_MIPMAP_SGIS:
326 if (ctx->Extensions.SGIS_generate_mipmap) {
327 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
328 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
329 }
330 else {
331 _mesa_error(ctx, GL_INVALID_ENUM,
332 "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
333 return;
334 }
335 break;
336 case GL_TEXTURE_COMPARE_MODE_ARB:
337 if (ctx->Extensions.ARB_shadow) {
338 const GLenum mode = (GLenum) params[0];
339 if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) {
340 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
341 texObj->CompareMode = mode;
342 }
343 else {
344 _mesa_error(ctx, GL_INVALID_ENUM,
345 "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB: 0x%x)", mode);
346 return;
347 }
348 }
349 else {
350 _mesa_error(ctx, GL_INVALID_ENUM,
351 "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)");
352 return;
353 }
354 break;
355 case GL_TEXTURE_COMPARE_FUNC_ARB:
356 if (ctx->Extensions.ARB_shadow) {
357 const GLenum func = (GLenum) params[0];
358 if (func == GL_LEQUAL || func == GL_GEQUAL) {
359 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
360 texObj->CompareFunc = func;
361 }
362 else if (ctx->Extensions.EXT_shadow_funcs &&
363 (func == GL_EQUAL ||
364 func == GL_NOTEQUAL ||
365 func == GL_LESS ||
366 func == GL_GREATER ||
367 func == GL_ALWAYS ||
368 func == GL_NEVER)) {
369 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
370 texObj->CompareFunc = func;
371 }
372 else {
373 _mesa_error(ctx, GL_INVALID_ENUM,
374 "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)");
375 return;
376 }
377 }
378 else {
379 _mesa_error(ctx, GL_INVALID_ENUM,
380 "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)");
381 return;
382 }
383 break;
384 case GL_DEPTH_TEXTURE_MODE_ARB:
385 if (ctx->Extensions.ARB_depth_texture) {
386 const GLenum result = (GLenum) params[0];
387 if (result == GL_LUMINANCE || result == GL_INTENSITY
388 || result == GL_ALPHA) {
389 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
390 texObj->DepthMode = result;
391 }
392 else {
393 _mesa_error(ctx, GL_INVALID_ENUM,
394 "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)");
395 return;
396 }
397 }
398 else {
399 _mesa_error(ctx, GL_INVALID_ENUM,
400 "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)");
401 return;
402 }
403 break;
404 case GL_TEXTURE_LOD_BIAS:
405 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias*/
406 if (ctx->Extensions.EXT_texture_lod_bias) {
407 if (texObj->LodBias != params[0]) {
408 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
409 texObj->LodBias = params[0];
410 }
411 }
412 break;
413 #ifdef FEATURE_OES_draw_texture
414 case GL_TEXTURE_CROP_RECT_OES:
415 texObj->CropRect[0] = (GLint) params[0];
416 texObj->CropRect[1] = (GLint) params[1];
417 texObj->CropRect[2] = (GLint) params[2];
418 texObj->CropRect[3] = (GLint) params[3];
419 break;
420 #endif
421
422 default:
423 _mesa_error(ctx, GL_INVALID_ENUM,
424 "glTexParameter(pname=0x%x)", pname);
425 return;
426 }
427
428 texObj->_Complete = GL_FALSE;
429
430 if (ctx->Driver.TexParameter) {
431 (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params );
432 }
433 }
434
435
436 void GLAPIENTRY
437 _mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
438 {
439 GLfloat fparam[4];
440 if (pname == GL_TEXTURE_PRIORITY)
441 fparam[0] = INT_TO_FLOAT(param);
442 else
443 fparam[0] = (GLfloat) param;
444 fparam[1] = fparam[2] = fparam[3] = 0.0;
445 _mesa_TexParameterfv(target, pname, fparam);
446 }
447
448
449 void GLAPIENTRY
450 _mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
451 {
452 GLfloat fparam[4];
453 if (pname == GL_TEXTURE_BORDER_COLOR) {
454 fparam[0] = INT_TO_FLOAT(params[0]);
455 fparam[1] = INT_TO_FLOAT(params[1]);
456 fparam[2] = INT_TO_FLOAT(params[2]);
457 fparam[3] = INT_TO_FLOAT(params[3]);
458 }
459 else if (pname == GL_TEXTURE_CROP_RECT_OES) {
460 fparam[0] = (GLfloat) params[0];
461 fparam[1] = (GLfloat) params[1];
462 fparam[2] = (GLfloat) params[2];
463 fparam[3] = (GLfloat) params[3];
464 }
465 else {
466 if (pname == GL_TEXTURE_PRIORITY)
467 fparam[0] = INT_TO_FLOAT(params[0]);
468 else
469 fparam[0] = (GLfloat) params[0];
470 fparam[1] = fparam[2] = fparam[3] = 0.0F;
471 }
472 _mesa_TexParameterfv(target, pname, fparam);
473 }
474
475
476 void GLAPIENTRY
477 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
478 GLenum pname, GLfloat *params )
479 {
480 GLint iparam;
481 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
482 *params = (GLfloat) iparam;
483 }
484
485
486 static GLuint
487 tex_image_dimensions(GLcontext *ctx, GLenum target)
488 {
489 switch (target) {
490 case GL_TEXTURE_1D:
491 case GL_PROXY_TEXTURE_1D:
492 return 1;
493 case GL_TEXTURE_2D:
494 case GL_PROXY_TEXTURE_2D:
495 return 2;
496 case GL_TEXTURE_3D:
497 case GL_PROXY_TEXTURE_3D:
498 return 3;
499 case GL_TEXTURE_CUBE_MAP:
500 case GL_PROXY_TEXTURE_CUBE_MAP:
501 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
502 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
503 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
504 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
505 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
506 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
507 return ctx->Extensions.ARB_texture_cube_map ? 2 : 0;
508 case GL_TEXTURE_RECTANGLE_NV:
509 case GL_PROXY_TEXTURE_RECTANGLE_NV:
510 return ctx->Extensions.NV_texture_rectangle ? 2 : 0;
511 case GL_TEXTURE_1D_ARRAY_EXT:
512 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
513 return ctx->Extensions.MESA_texture_array ? 2 : 0;
514 case GL_TEXTURE_2D_ARRAY_EXT:
515 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
516 return ctx->Extensions.MESA_texture_array ? 3 : 0;
517 default:
518 _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()");
519 return 0;
520 }
521 }
522
523
524 void GLAPIENTRY
525 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
526 GLenum pname, GLint *params )
527 {
528 const struct gl_texture_unit *texUnit;
529 struct gl_texture_object *texObj;
530 const struct gl_texture_image *img = NULL;
531 GLuint dimensions;
532 GLboolean isProxy;
533 GLint maxLevels;
534 GET_CURRENT_CONTEXT(ctx);
535 ASSERT_OUTSIDE_BEGIN_END(ctx);
536
537 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
538 _mesa_error(ctx, GL_INVALID_OPERATION,
539 "glGetTexLevelParameteriv(current unit)");
540 return;
541 }
542
543 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
544
545 /* this will catch bad target values */
546 dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */
547 if (dimensions == 0) {
548 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
549 return;
550 }
551
552 maxLevels = _mesa_max_texture_levels(ctx, target);
553 if (maxLevels == 0) {
554 /* should not happen since <target> was just checked above */
555 _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter");
556 return;
557 }
558
559 if (level < 0 || level >= maxLevels) {
560 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
561 return;
562 }
563
564 texObj = _mesa_select_tex_object(ctx, texUnit, target);
565 _mesa_lock_texture(ctx, texObj);
566
567 img = _mesa_select_tex_image(ctx, texObj, target, level);
568 if (!img || !img->TexFormat) {
569 /* undefined texture image */
570 if (pname == GL_TEXTURE_COMPONENTS)
571 *params = 1;
572 else
573 *params = 0;
574 goto out;
575 }
576
577 isProxy = _mesa_is_proxy_texture(target);
578
579 switch (pname) {
580 case GL_TEXTURE_WIDTH:
581 *params = img->Width;
582 break;
583 case GL_TEXTURE_HEIGHT:
584 *params = img->Height;
585 break;
586 case GL_TEXTURE_DEPTH:
587 *params = img->Depth;
588 break;
589 case GL_TEXTURE_INTERNAL_FORMAT:
590 *params = img->InternalFormat;
591 break;
592 case GL_TEXTURE_BORDER:
593 *params = img->Border;
594 break;
595 case GL_TEXTURE_RED_SIZE:
596 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
597 *params = img->TexFormat->RedBits;
598 else
599 *params = 0;
600 break;
601 case GL_TEXTURE_GREEN_SIZE:
602 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
603 *params = img->TexFormat->GreenBits;
604 else
605 *params = 0;
606 break;
607 case GL_TEXTURE_BLUE_SIZE:
608 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
609 *params = img->TexFormat->BlueBits;
610 else
611 *params = 0;
612 break;
613 case GL_TEXTURE_ALPHA_SIZE:
614 if (img->_BaseFormat == GL_ALPHA ||
615 img->_BaseFormat == GL_LUMINANCE_ALPHA ||
616 img->_BaseFormat == GL_RGBA)
617 *params = img->TexFormat->AlphaBits;
618 else
619 *params = 0;
620 break;
621 case GL_TEXTURE_INTENSITY_SIZE:
622 if (img->_BaseFormat != GL_INTENSITY)
623 *params = 0;
624 else if (img->TexFormat->IntensityBits > 0)
625 *params = img->TexFormat->IntensityBits;
626 else /* intensity probably stored as rgb texture */
627 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
628 break;
629 case GL_TEXTURE_LUMINANCE_SIZE:
630 if (img->_BaseFormat != GL_LUMINANCE &&
631 img->_BaseFormat != GL_LUMINANCE_ALPHA)
632 *params = 0;
633 else if (img->TexFormat->LuminanceBits > 0)
634 *params = img->TexFormat->LuminanceBits;
635 else /* luminance probably stored as rgb texture */
636 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
637 break;
638 case GL_TEXTURE_INDEX_SIZE_EXT:
639 if (img->_BaseFormat == GL_COLOR_INDEX)
640 *params = img->TexFormat->IndexBits;
641 else
642 *params = 0;
643 break;
644 case GL_TEXTURE_DEPTH_SIZE_ARB:
645 if (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[1] = obj->CropRect[1];
906 params[2] = obj->CropRect[2];
907 params[3] = 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[1] = obj->CropRect[1];
1056 params[2] = obj->CropRect[2];
1057 params[3] = 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 }