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