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