Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / mesa / main / texenv.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 texenv.c
27 *
28 * glTexEnv-related functions
29 */
30
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/enums.h"
35 #include "main/macros.h"
36 #include "main/texenv.h"
37 #include "math/m_xform.h"
38
39
40
41 void GLAPIENTRY
42 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
43 {
44 GLuint maxUnit;
45 GET_CURRENT_CONTEXT(ctx);
46 struct gl_texture_unit *texUnit;
47 ASSERT_OUTSIDE_BEGIN_END(ctx);
48
49 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
50 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
51 if (ctx->Texture.CurrentUnit >= maxUnit) {
52 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
53 return;
54 }
55
56 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
57
58 #define TE_ERROR(errCode, msg, value) \
59 _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
60
61 if (target == GL_TEXTURE_ENV) {
62 switch (pname) {
63 case GL_TEXTURE_ENV_MODE:
64 {
65 GLenum mode = (GLenum) (GLint) *param;
66 if (mode == GL_REPLACE_EXT)
67 mode = GL_REPLACE;
68 if (texUnit->EnvMode == mode)
69 return;
70 if (mode == GL_MODULATE ||
71 mode == GL_BLEND ||
72 mode == GL_DECAL ||
73 mode == GL_REPLACE ||
74 (mode == GL_ADD && ctx->Extensions.EXT_texture_env_add) ||
75 (mode == GL_COMBINE &&
76 (ctx->Extensions.EXT_texture_env_combine ||
77 ctx->Extensions.ARB_texture_env_combine))) {
78 /* legal */
79 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
80 texUnit->EnvMode = mode;
81 }
82 else {
83 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
84 return;
85 }
86 }
87 break;
88 case GL_TEXTURE_ENV_COLOR:
89 {
90 GLfloat tmp[4];
91 tmp[0] = CLAMP( param[0], 0.0F, 1.0F );
92 tmp[1] = CLAMP( param[1], 0.0F, 1.0F );
93 tmp[2] = CLAMP( param[2], 0.0F, 1.0F );
94 tmp[3] = CLAMP( param[3], 0.0F, 1.0F );
95 if (TEST_EQ_4V(tmp, texUnit->EnvColor))
96 return;
97 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
98 COPY_4FV(texUnit->EnvColor, tmp);
99 }
100 break;
101 case GL_COMBINE_RGB:
102 if (ctx->Extensions.EXT_texture_env_combine ||
103 ctx->Extensions.ARB_texture_env_combine) {
104 const GLenum mode = (GLenum) (GLint) *param;
105 if (texUnit->Combine.ModeRGB == mode)
106 return;
107 switch (mode) {
108 case GL_REPLACE:
109 case GL_MODULATE:
110 case GL_ADD:
111 case GL_ADD_SIGNED:
112 case GL_INTERPOLATE:
113 /* OK */
114 break;
115 case GL_SUBTRACT:
116 if (!ctx->Extensions.ARB_texture_env_combine) {
117 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
118 return;
119 }
120 break;
121 case GL_DOT3_RGB_EXT:
122 case GL_DOT3_RGBA_EXT:
123 if (!ctx->Extensions.EXT_texture_env_dot3) {
124 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
125 return;
126 }
127 break;
128 case GL_DOT3_RGB:
129 case GL_DOT3_RGBA:
130 if (!ctx->Extensions.ARB_texture_env_dot3) {
131 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
132 return;
133 }
134 break;
135 case GL_MODULATE_ADD_ATI:
136 case GL_MODULATE_SIGNED_ADD_ATI:
137 case GL_MODULATE_SUBTRACT_ATI:
138 if (!ctx->Extensions.ATI_texture_env_combine3) {
139 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
140 return;
141 }
142 break;
143 default:
144 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
145 return;
146 }
147 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
148 texUnit->Combine.ModeRGB = mode;
149 }
150 else {
151 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
152 return;
153 }
154 break;
155 case GL_COMBINE_ALPHA:
156 if (ctx->Extensions.EXT_texture_env_combine ||
157 ctx->Extensions.ARB_texture_env_combine) {
158 const GLenum mode = (GLenum) (GLint) *param;
159 if (texUnit->Combine.ModeA == mode)
160 return;
161 switch (mode) {
162 case GL_REPLACE:
163 case GL_MODULATE:
164 case GL_ADD:
165 case GL_ADD_SIGNED:
166 case GL_INTERPOLATE:
167 /* OK */
168 break;
169 case GL_SUBTRACT:
170 if (!ctx->Extensions.ARB_texture_env_combine) {
171 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
172 return;
173 }
174 break;
175 case GL_MODULATE_ADD_ATI:
176 case GL_MODULATE_SIGNED_ADD_ATI:
177 case GL_MODULATE_SUBTRACT_ATI:
178 if (!ctx->Extensions.ATI_texture_env_combine3) {
179 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
180 return;
181 }
182 break;
183 default:
184 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
185 return;
186 }
187 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
188 texUnit->Combine.ModeA = mode;
189 }
190 else {
191 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
192 return;
193 }
194 break;
195 case GL_SOURCE0_RGB:
196 case GL_SOURCE1_RGB:
197 case GL_SOURCE2_RGB:
198 if (ctx->Extensions.EXT_texture_env_combine ||
199 ctx->Extensions.ARB_texture_env_combine) {
200 const GLenum source = (GLenum) (GLint) *param;
201 const GLuint s = pname - GL_SOURCE0_RGB;
202 if (texUnit->Combine.SourceRGB[s] == source)
203 return;
204 if (source == GL_TEXTURE ||
205 source == GL_CONSTANT ||
206 source == GL_PRIMARY_COLOR ||
207 source == GL_PREVIOUS ||
208 (ctx->Extensions.ARB_texture_env_crossbar &&
209 source >= GL_TEXTURE0 &&
210 source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) ||
211 (ctx->Extensions.ATI_texture_env_combine3 &&
212 (source == GL_ZERO || source == GL_ONE))) {
213 /* legal */
214 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
215 texUnit->Combine.SourceRGB[s] = source;
216 }
217 else {
218 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
219 return;
220 }
221 }
222 else {
223 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
224 return;
225 }
226 break;
227 case GL_SOURCE0_ALPHA:
228 case GL_SOURCE1_ALPHA:
229 case GL_SOURCE2_ALPHA:
230 if (ctx->Extensions.EXT_texture_env_combine ||
231 ctx->Extensions.ARB_texture_env_combine) {
232 const GLenum source = (GLenum) (GLint) *param;
233 const GLuint s = pname - GL_SOURCE0_ALPHA;
234 if (texUnit->Combine.SourceA[s] == source)
235 return;
236 if (source == GL_TEXTURE ||
237 source == GL_CONSTANT ||
238 source == GL_PRIMARY_COLOR ||
239 source == GL_PREVIOUS ||
240 (ctx->Extensions.ARB_texture_env_crossbar &&
241 source >= GL_TEXTURE0 &&
242 source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) ||
243 (ctx->Extensions.ATI_texture_env_combine3 &&
244 (source == GL_ZERO || source == GL_ONE))) {
245 /* legal */
246 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
247 texUnit->Combine.SourceA[s] = source;
248 }
249 else {
250 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source);
251 return;
252 }
253 }
254 else {
255 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
256 return;
257 }
258 break;
259 case GL_OPERAND0_RGB:
260 case GL_OPERAND1_RGB:
261 if (ctx->Extensions.EXT_texture_env_combine ||
262 ctx->Extensions.ARB_texture_env_combine) {
263 const GLenum operand = (GLenum) (GLint) *param;
264 const GLuint s = pname - GL_OPERAND0_RGB;
265 if (texUnit->Combine.OperandRGB[s] == operand)
266 return;
267 switch (operand) {
268 case GL_SRC_COLOR:
269 case GL_ONE_MINUS_SRC_COLOR:
270 case GL_SRC_ALPHA:
271 case GL_ONE_MINUS_SRC_ALPHA:
272 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
273 texUnit->Combine.OperandRGB[s] = operand;
274 break;
275 default:
276 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
277 return;
278 }
279 }
280 else {
281 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
282 return;
283 }
284 break;
285 case GL_OPERAND0_ALPHA:
286 case GL_OPERAND1_ALPHA:
287 if (ctx->Extensions.EXT_texture_env_combine ||
288 ctx->Extensions.ARB_texture_env_combine) {
289 const GLenum operand = (GLenum) (GLint) *param;
290 if (texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] == operand)
291 return;
292 switch (operand) {
293 case GL_SRC_ALPHA:
294 case GL_ONE_MINUS_SRC_ALPHA:
295 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
296 texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] = operand;
297 break;
298 default:
299 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
300 return;
301 }
302 }
303 else {
304 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
305 return;
306 }
307 break;
308 case GL_OPERAND2_RGB:
309 if (ctx->Extensions.ARB_texture_env_combine) {
310 const GLenum operand = (GLenum) (GLint) *param;
311 if (texUnit->Combine.OperandRGB[2] == operand)
312 return;
313 switch (operand) {
314 case GL_SRC_COLOR: /* ARB combine only */
315 case GL_ONE_MINUS_SRC_COLOR: /* ARB combine only */
316 case GL_SRC_ALPHA:
317 case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
318 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
319 texUnit->Combine.OperandRGB[2] = operand;
320 break;
321 default:
322 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
323 return;
324 }
325 }
326 else if (ctx->Extensions.EXT_texture_env_combine) {
327 const GLenum operand = (GLenum) (GLint) *param;
328 if (texUnit->Combine.OperandRGB[2] == operand)
329 return;
330 /* operand must be GL_SRC_ALPHA which is the initial value - thus
331 don't need to actually compare the operand to the possible value */
332 else {
333 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
334 return;
335 }
336 }
337 else {
338 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
339 return;
340 }
341 break;
342 case GL_OPERAND2_ALPHA:
343 if (ctx->Extensions.ARB_texture_env_combine) {
344 const GLenum operand = (GLenum) (GLint) *param;
345 if (texUnit->Combine.OperandA[2] == operand)
346 return;
347 switch (operand) {
348 case GL_SRC_ALPHA:
349 case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */
350 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
351 texUnit->Combine.OperandA[2] = operand;
352 break;
353 default:
354 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
355 return;
356 }
357 }
358 else if (ctx->Extensions.EXT_texture_env_combine) {
359 const GLenum operand = (GLenum) (GLint) *param;
360 if (texUnit->Combine.OperandA[2] == operand)
361 return;
362 /* operand must be GL_SRC_ALPHA which is the initial value - thus
363 don't need to actually compare the operand to the possible value */
364 else {
365 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand);
366 return;
367 }
368 }
369 else {
370 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
371 return;
372 }
373 break;
374 case GL_RGB_SCALE:
375 if (ctx->Extensions.EXT_texture_env_combine ||
376 ctx->Extensions.ARB_texture_env_combine) {
377 GLuint newshift;
378 if (*param == 1.0) {
379 newshift = 0;
380 }
381 else if (*param == 2.0) {
382 newshift = 1;
383 }
384 else if (*param == 4.0) {
385 newshift = 2;
386 }
387 else {
388 _mesa_error( ctx, GL_INVALID_VALUE,
389 "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
390 return;
391 }
392 if (texUnit->Combine.ScaleShiftRGB == newshift)
393 return;
394 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
395 texUnit->Combine.ScaleShiftRGB = newshift;
396 }
397 else {
398 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
399 return;
400 }
401 break;
402 case GL_ALPHA_SCALE:
403 if (ctx->Extensions.EXT_texture_env_combine ||
404 ctx->Extensions.ARB_texture_env_combine) {
405 GLuint newshift;
406 if (*param == 1.0) {
407 newshift = 0;
408 }
409 else if (*param == 2.0) {
410 newshift = 1;
411 }
412 else if (*param == 4.0) {
413 newshift = 2;
414 }
415 else {
416 _mesa_error( ctx, GL_INVALID_VALUE,
417 "glTexEnv(GL_ALPHA_SCALE not 1, 2 or 4)" );
418 return;
419 }
420 if (texUnit->Combine.ScaleShiftA == newshift)
421 return;
422 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
423 texUnit->Combine.ScaleShiftA = newshift;
424 }
425 else {
426 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
427 return;
428 }
429 break;
430 default:
431 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
432 return;
433 }
434 }
435 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
436 /* GL_EXT_texture_lod_bias */
437 if (!ctx->Extensions.EXT_texture_lod_bias) {
438 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
439 return;
440 }
441 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
442 if (texUnit->LodBias == param[0])
443 return;
444 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
445 texUnit->LodBias = param[0];
446 }
447 else {
448 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
449 return;
450 }
451 }
452 else if (target == GL_POINT_SPRITE_NV) {
453 /* GL_ARB_point_sprite / GL_NV_point_sprite */
454 if (!ctx->Extensions.NV_point_sprite
455 && !ctx->Extensions.ARB_point_sprite) {
456 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
457 return;
458 }
459 if (pname == GL_COORD_REPLACE_NV) {
460 const GLenum value = (GLenum) param[0];
461 if (value == GL_TRUE || value == GL_FALSE) {
462 /* It's kind of weird to set point state via glTexEnv,
463 * but that's what the spec calls for.
464 */
465 const GLboolean state = (GLboolean) value;
466 if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state)
467 return;
468 FLUSH_VERTICES(ctx, _NEW_POINT);
469 ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state;
470 }
471 else {
472 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value);
473 return;
474 }
475 }
476 else {
477 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
478 return;
479 }
480 }
481 else {
482 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target );
483 return;
484 }
485
486 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
487 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
488 _mesa_lookup_enum_by_nr(target),
489 _mesa_lookup_enum_by_nr(pname),
490 *param,
491 _mesa_lookup_enum_by_nr((GLenum) (GLint) *param));
492
493 /* Tell device driver about the new texture environment */
494 if (ctx->Driver.TexEnv) {
495 (*ctx->Driver.TexEnv)( ctx, target, pname, param );
496 }
497 }
498
499
500 void GLAPIENTRY
501 _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
502 {
503 _mesa_TexEnvfv( target, pname, &param );
504 }
505
506
507
508 void GLAPIENTRY
509 _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
510 {
511 GLfloat p[4];
512 p[0] = (GLfloat) param;
513 p[1] = p[2] = p[3] = 0.0;
514 _mesa_TexEnvfv( target, pname, p );
515 }
516
517
518 void GLAPIENTRY
519 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
520 {
521 GLfloat p[4];
522 if (pname == GL_TEXTURE_ENV_COLOR) {
523 p[0] = INT_TO_FLOAT( param[0] );
524 p[1] = INT_TO_FLOAT( param[1] );
525 p[2] = INT_TO_FLOAT( param[2] );
526 p[3] = INT_TO_FLOAT( param[3] );
527 }
528 else {
529 p[0] = (GLfloat) param[0];
530 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */
531 }
532 _mesa_TexEnvfv( target, pname, p );
533 }
534
535
536 void GLAPIENTRY
537 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
538 {
539 GLuint maxUnit;
540 const struct gl_texture_unit *texUnit;
541 GET_CURRENT_CONTEXT(ctx);
542 ASSERT_OUTSIDE_BEGIN_END(ctx);
543
544 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
545 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
546 if (ctx->Texture.CurrentUnit >= maxUnit) {
547 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
548 return;
549 }
550
551 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
552
553 if (target == GL_TEXTURE_ENV) {
554 switch (pname) {
555 case GL_TEXTURE_ENV_MODE:
556 *params = ENUM_TO_FLOAT(texUnit->EnvMode);
557 break;
558 case GL_TEXTURE_ENV_COLOR:
559 COPY_4FV( params, texUnit->EnvColor );
560 break;
561 case GL_COMBINE_RGB:
562 if (ctx->Extensions.EXT_texture_env_combine ||
563 ctx->Extensions.ARB_texture_env_combine) {
564 *params = (GLfloat) texUnit->Combine.ModeRGB;
565 }
566 else {
567 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
568 }
569 break;
570 case GL_COMBINE_ALPHA:
571 if (ctx->Extensions.EXT_texture_env_combine ||
572 ctx->Extensions.ARB_texture_env_combine) {
573 *params = (GLfloat) texUnit->Combine.ModeA;
574 }
575 else {
576 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
577 }
578 break;
579 case GL_SOURCE0_RGB:
580 case GL_SOURCE1_RGB:
581 case GL_SOURCE2_RGB:
582 if (ctx->Extensions.EXT_texture_env_combine ||
583 ctx->Extensions.ARB_texture_env_combine) {
584 const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
585 *params = (GLfloat) texUnit->Combine.SourceRGB[rgb_idx];
586 }
587 else {
588 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
589 }
590 break;
591 case GL_SOURCE0_ALPHA:
592 case GL_SOURCE1_ALPHA:
593 case GL_SOURCE2_ALPHA:
594 if (ctx->Extensions.EXT_texture_env_combine ||
595 ctx->Extensions.ARB_texture_env_combine) {
596 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
597 *params = (GLfloat) texUnit->Combine.SourceA[alpha_idx];
598 }
599 else {
600 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
601 }
602 break;
603 case GL_OPERAND0_RGB:
604 case GL_OPERAND1_RGB:
605 case GL_OPERAND2_RGB:
606 if (ctx->Extensions.EXT_texture_env_combine ||
607 ctx->Extensions.ARB_texture_env_combine) {
608 const unsigned op_rgb = pname - GL_OPERAND0_RGB;
609 *params = (GLfloat) texUnit->Combine.OperandRGB[op_rgb];
610 }
611 else {
612 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
613 }
614 break;
615 case GL_OPERAND0_ALPHA:
616 case GL_OPERAND1_ALPHA:
617 case GL_OPERAND2_ALPHA:
618 if (ctx->Extensions.EXT_texture_env_combine ||
619 ctx->Extensions.ARB_texture_env_combine) {
620 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
621 *params = (GLfloat) texUnit->Combine.OperandA[op_alpha];
622 }
623 else {
624 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
625 }
626 break;
627 case GL_RGB_SCALE:
628 if (ctx->Extensions.EXT_texture_env_combine ||
629 ctx->Extensions.ARB_texture_env_combine) {
630 if (texUnit->Combine.ScaleShiftRGB == 0)
631 *params = 1.0;
632 else if (texUnit->Combine.ScaleShiftRGB == 1)
633 *params = 2.0;
634 else
635 *params = 4.0;
636 }
637 else {
638 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
639 return;
640 }
641 break;
642 case GL_ALPHA_SCALE:
643 if (ctx->Extensions.EXT_texture_env_combine ||
644 ctx->Extensions.ARB_texture_env_combine) {
645 if (texUnit->Combine.ScaleShiftA == 0)
646 *params = 1.0;
647 else if (texUnit->Combine.ScaleShiftA == 1)
648 *params = 2.0;
649 else
650 *params = 4.0;
651 }
652 else {
653 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
654 return;
655 }
656 break;
657 default:
658 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname=0x%x)", pname);
659 }
660 }
661 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
662 /* GL_EXT_texture_lod_bias */
663 if (!ctx->Extensions.EXT_texture_lod_bias) {
664 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
665 return;
666 }
667 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
668 *params = texUnit->LodBias;
669 }
670 else {
671 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
672 return;
673 }
674 }
675 else if (target == GL_POINT_SPRITE_NV) {
676 /* GL_ARB_point_sprite / GL_NV_point_sprite */
677 if (!ctx->Extensions.NV_point_sprite
678 && !ctx->Extensions.ARB_point_sprite) {
679 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
680 return;
681 }
682 if (pname == GL_COORD_REPLACE_NV) {
683 *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
684 }
685 else {
686 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
687 return;
688 }
689 }
690 else {
691 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
692 return;
693 }
694 }
695
696
697 void GLAPIENTRY
698 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
699 {
700 GLuint maxUnit;
701 const struct gl_texture_unit *texUnit;
702 GET_CURRENT_CONTEXT(ctx);
703 ASSERT_OUTSIDE_BEGIN_END(ctx);
704
705 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
706 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
707 if (ctx->Texture.CurrentUnit >= maxUnit) {
708 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
709 return;
710 }
711
712 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
713
714 if (target == GL_TEXTURE_ENV) {
715 switch (pname) {
716 case GL_TEXTURE_ENV_MODE:
717 *params = (GLint) texUnit->EnvMode;
718 break;
719 case GL_TEXTURE_ENV_COLOR:
720 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
721 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
722 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
723 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
724 break;
725 case GL_COMBINE_RGB:
726 if (ctx->Extensions.EXT_texture_env_combine ||
727 ctx->Extensions.ARB_texture_env_combine) {
728 *params = (GLint) texUnit->Combine.ModeRGB;
729 }
730 else {
731 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
732 }
733 break;
734 case GL_COMBINE_ALPHA:
735 if (ctx->Extensions.EXT_texture_env_combine ||
736 ctx->Extensions.ARB_texture_env_combine) {
737 *params = (GLint) texUnit->Combine.ModeA;
738 }
739 else {
740 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
741 }
742 break;
743 case GL_SOURCE0_RGB:
744 case GL_SOURCE1_RGB:
745 case GL_SOURCE2_RGB:
746 if (ctx->Extensions.EXT_texture_env_combine ||
747 ctx->Extensions.ARB_texture_env_combine) {
748 const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
749 *params = (GLint) texUnit->Combine.SourceRGB[rgb_idx];
750 }
751 else {
752 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
753 }
754 break;
755 case GL_SOURCE0_ALPHA:
756 case GL_SOURCE1_ALPHA:
757 case GL_SOURCE2_ALPHA:
758 if (ctx->Extensions.EXT_texture_env_combine ||
759 ctx->Extensions.ARB_texture_env_combine) {
760 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
761 *params = (GLint) texUnit->Combine.SourceA[alpha_idx];
762 }
763 else {
764 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
765 }
766 break;
767 case GL_OPERAND0_RGB:
768 case GL_OPERAND1_RGB:
769 case GL_OPERAND2_RGB:
770 if (ctx->Extensions.EXT_texture_env_combine ||
771 ctx->Extensions.ARB_texture_env_combine) {
772 const unsigned op_rgb = pname - GL_OPERAND0_RGB;
773 *params = (GLint) texUnit->Combine.OperandRGB[op_rgb];
774 }
775 else {
776 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
777 }
778 break;
779 case GL_OPERAND0_ALPHA:
780 case GL_OPERAND1_ALPHA:
781 case GL_OPERAND2_ALPHA:
782 if (ctx->Extensions.EXT_texture_env_combine ||
783 ctx->Extensions.ARB_texture_env_combine) {
784 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
785 *params = (GLint) texUnit->Combine.OperandA[op_alpha];
786 }
787 else {
788 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
789 }
790 break;
791 case GL_RGB_SCALE:
792 if (ctx->Extensions.EXT_texture_env_combine ||
793 ctx->Extensions.ARB_texture_env_combine) {
794 if (texUnit->Combine.ScaleShiftRGB == 0)
795 *params = 1;
796 else if (texUnit->Combine.ScaleShiftRGB == 1)
797 *params = 2;
798 else
799 *params = 4;
800 }
801 else {
802 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
803 return;
804 }
805 break;
806 case GL_ALPHA_SCALE:
807 if (ctx->Extensions.EXT_texture_env_combine ||
808 ctx->Extensions.ARB_texture_env_combine) {
809 if (texUnit->Combine.ScaleShiftA == 0)
810 *params = 1;
811 else if (texUnit->Combine.ScaleShiftA == 1)
812 *params = 2;
813 else
814 *params = 4;
815 }
816 else {
817 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)");
818 return;
819 }
820 break;
821 default:
822 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname=0x%x)",
823 pname);
824 }
825 }
826 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
827 /* GL_EXT_texture_lod_bias */
828 if (!ctx->Extensions.EXT_texture_lod_bias) {
829 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
830 return;
831 }
832 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
833 *params = (GLint) texUnit->LodBias;
834 }
835 else {
836 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
837 return;
838 }
839 }
840 else if (target == GL_POINT_SPRITE_NV) {
841 /* GL_ARB_point_sprite / GL_NV_point_sprite */
842 if (!ctx->Extensions.NV_point_sprite
843 && !ctx->Extensions.ARB_point_sprite) {
844 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
845 return;
846 }
847 if (pname == GL_COORD_REPLACE_NV) {
848 *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
849 }
850 else {
851 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
852 return;
853 }
854 }
855 else {
856 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
857 return;
858 }
859 }
860
861