2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
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.
29 * glTexEnv-related functions
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"
41 #define TE_ERROR(errCode, msg, value) \
42 _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
45 /** Set texture env mode */
47 set_env_mode(GLcontext
*ctx
,
48 struct gl_texture_unit
*texUnit
,
53 if (texUnit
->EnvMode
== mode
)
64 mode
= GL_REPLACE
; /* GL_REPLACE_EXT != GL_REPLACE */
68 legal
= ctx
->Extensions
.EXT_texture_env_add
;
71 legal
= (ctx
->Extensions
.EXT_texture_env_combine
||
72 ctx
->Extensions
.ARB_texture_env_combine
);
75 legal
= ctx
->Extensions
.NV_texture_env_combine4
;
82 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
83 texUnit
->EnvMode
= mode
;
86 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(param=%s)", mode
);
92 set_env_color(GLcontext
*ctx
,
93 struct gl_texture_unit
*texUnit
,
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
))
103 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
104 COPY_4FV(texUnit
->EnvColor
, tmp
);
108 /** Set an RGB or A combiner mode/function */
110 set_combiner_mode(GLcontext
*ctx
,
111 struct gl_texture_unit
*texUnit
,
112 GLenum pname
, GLenum mode
)
116 if (!ctx
->Extensions
.EXT_texture_env_combine
&&
117 !ctx
->Extensions
.ARB_texture_env_combine
) {
118 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexEnv(pname)");
131 legal
= ctx
->Extensions
.ARB_texture_env_combine
;
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
);
140 legal
= (ctx
->Extensions
.ARB_texture_env_dot3
&&
141 pname
== GL_COMBINE_RGB
);
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
;
153 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(param=%s)", mode
);
159 if (texUnit
->Combine
.ModeRGB
== mode
)
161 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
162 texUnit
->Combine
.ModeRGB
= mode
;
165 case GL_COMBINE_ALPHA
:
166 if (texUnit
->Combine
.ModeA
== mode
)
168 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
169 texUnit
->Combine
.ModeA
= mode
;
172 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(pname=%s)", pname
);
178 /** Set an RGB or A combiner source term */
180 set_combiner_source(GLcontext
*ctx
,
181 struct gl_texture_unit
*texUnit
,
182 GLenum pname
, GLenum param
)
185 GLboolean alpha
, legal
;
187 if (!ctx
->Extensions
.EXT_texture_env_combine
&&
188 !ctx
->Extensions
.ARB_texture_env_combine
) {
189 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexEnv(pname)");
194 * Translate pname to (src, alpha).
209 case GL_SOURCE0_ALPHA
:
213 case GL_SOURCE1_ALPHA
:
217 case GL_SOURCE2_ALPHA
:
222 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(pname=%s)", pname
);
227 * Error-check param (the source term)
232 case GL_PRIMARY_COLOR
:
244 legal
= (ctx
->Extensions
.ARB_texture_env_crossbar
&&
245 param
- GL_TEXTURE0
< ctx
->Const
.MaxTextureUnits
);
249 legal
= ctx
->Extensions
.ATI_texture_env_combine3
;
256 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(param=%s)", param
);
260 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
264 texUnit
->Combine
.SourceA
[src
] = param
;
266 texUnit
->Combine
.SourceRGB
[src
] = param
;
270 /** Set an RGB or A combiner operand term */
272 set_combiner_operand(GLcontext
*ctx
,
273 struct gl_texture_unit
*texUnit
,
274 GLenum pname
, GLenum param
)
277 GLboolean alpha
, legal
;
279 if (!ctx
->Extensions
.EXT_texture_env_combine
&&
280 !ctx
->Extensions
.ARB_texture_env_combine
) {
281 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexEnv(pname)");
286 case GL_OPERAND0_RGB
:
290 case GL_OPERAND1_RGB
:
294 case GL_OPERAND2_RGB
:
295 if (ctx
->Extensions
.ARB_texture_env_combine
) {
300 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(pname=%s)", pname
);
304 case GL_OPERAND0_ALPHA
:
308 case GL_OPERAND1_ALPHA
:
312 case GL_OPERAND2_ALPHA
:
313 if (ctx
->Extensions
.ARB_texture_env_combine
) {
318 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(pname=%s)", pname
);
323 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(pname=%s)", pname
);
328 * Error-check param (the source operand)
332 case GL_ONE_MINUS_SRC_COLOR
:
336 case GL_ONE_MINUS_SRC_ALPHA
:
344 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(param=%s)", param
);
348 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
351 texUnit
->Combine
.OperandA
[op
] = param
;
353 texUnit
->Combine
.OperandRGB
[op
] = param
;
358 set_combiner_scale(GLcontext
*ctx
,
359 struct gl_texture_unit
*texUnit
,
360 GLenum pname
, GLfloat scale
)
364 if (!ctx
->Extensions
.EXT_texture_env_combine
&&
365 !ctx
->Extensions
.ARB_texture_env_combine
) {
366 _mesa_error(ctx
, GL_INVALID_ENUM
, "glTexEnv(pname)");
373 else if (scale
== 2.0F
) {
376 else if (scale
== 4.0F
) {
380 _mesa_error( ctx
, GL_INVALID_VALUE
,
381 "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
387 if (texUnit
->Combine
.ScaleShiftRGB
== shift
)
389 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
390 texUnit
->Combine
.ScaleShiftRGB
= shift
;
393 if (texUnit
->Combine
.ScaleShiftA
== shift
)
395 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
396 texUnit
->Combine
.ScaleShiftA
= shift
;
399 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(pname=%s)", pname
);
407 _mesa_TexEnvfv( GLenum target
, GLenum pname
, const GLfloat
*param
)
410 GET_CURRENT_CONTEXT(ctx
);
411 struct gl_texture_unit
*texUnit
;
412 ASSERT_OUTSIDE_BEGIN_END(ctx
);
414 maxUnit
= (target
== GL_POINT_SPRITE_NV
&& pname
== GL_COORD_REPLACE_NV
)
415 ? ctx
->Const
.MaxTextureCoordUnits
: ctx
->Const
.MaxTextureImageUnits
;
416 if (ctx
->Texture
.CurrentUnit
>= maxUnit
) {
417 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glTexEnvfv(current unit)");
421 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
423 if (target
== GL_TEXTURE_ENV
) {
425 case GL_TEXTURE_ENV_MODE
:
426 set_env_mode(ctx
, texUnit
, (GLenum
) (GLint
) param
[0]);
428 case GL_TEXTURE_ENV_COLOR
:
429 set_env_color(ctx
, texUnit
, param
);
432 case GL_COMBINE_ALPHA
:
433 set_combiner_mode(ctx
, texUnit
, pname
, (GLenum
) (GLint
) param
[0]);
438 case GL_SOURCE0_ALPHA
:
439 case GL_SOURCE1_ALPHA
:
440 case GL_SOURCE2_ALPHA
:
441 set_combiner_source(ctx
, texUnit
, pname
, (GLenum
) (GLint
) param
[0]);
443 case GL_OPERAND0_RGB
:
444 case GL_OPERAND1_RGB
:
445 case GL_OPERAND2_RGB
:
446 case GL_OPERAND0_ALPHA
:
447 case GL_OPERAND1_ALPHA
:
448 case GL_OPERAND2_ALPHA
:
449 set_combiner_operand(ctx
, texUnit
, pname
, (GLenum
) (GLint
) param
[0]);
453 set_combiner_scale(ctx
, texUnit
, pname
, param
[0]);
456 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexEnv(pname)" );
460 else if (target
== GL_TEXTURE_FILTER_CONTROL_EXT
) {
461 /* GL_EXT_texture_lod_bias */
462 if (!ctx
->Extensions
.EXT_texture_lod_bias
) {
463 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexEnv(target=0x%x)", target
);
466 if (pname
== GL_TEXTURE_LOD_BIAS_EXT
) {
467 if (texUnit
->LodBias
== param
[0])
469 FLUSH_VERTICES(ctx
, _NEW_TEXTURE
);
470 texUnit
->LodBias
= param
[0];
473 TE_ERROR(GL_INVALID_ENUM
, "glTexEnv(pname=%s)", pname
);
477 else if (target
== GL_POINT_SPRITE_NV
) {
478 /* GL_ARB_point_sprite / GL_NV_point_sprite */
479 if (!ctx
->Extensions
.NV_point_sprite
480 && !ctx
->Extensions
.ARB_point_sprite
) {
481 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexEnv(target=0x%x)", target
);
484 if (pname
== GL_COORD_REPLACE_NV
) {
485 const GLenum value
= (GLenum
) param
[0];
486 if (value
== GL_TRUE
|| value
== GL_FALSE
) {
487 /* It's kind of weird to set point state via glTexEnv,
488 * but that's what the spec calls for.
490 const GLboolean state
= (GLboolean
) value
;
491 if (ctx
->Point
.CoordReplace
[ctx
->Texture
.CurrentUnit
] == state
)
493 FLUSH_VERTICES(ctx
, _NEW_POINT
);
494 ctx
->Point
.CoordReplace
[ctx
->Texture
.CurrentUnit
] = state
;
497 _mesa_error( ctx
, GL_INVALID_VALUE
, "glTexEnv(param=0x%x)", value
);
502 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexEnv(pname=0x%x)", pname
);
507 _mesa_error( ctx
, GL_INVALID_ENUM
, "glTexEnv(target=0x%x)",target
);
511 if (MESA_VERBOSE
&(VERBOSE_API
|VERBOSE_TEXTURE
))
512 _mesa_debug(ctx
, "glTexEnv %s %s %.1f(%s) ...\n",
513 _mesa_lookup_enum_by_nr(target
),
514 _mesa_lookup_enum_by_nr(pname
),
516 _mesa_lookup_enum_by_nr((GLenum
) (GLint
) *param
));
518 /* Tell device driver about the new texture environment */
519 if (ctx
->Driver
.TexEnv
) {
520 (*ctx
->Driver
.TexEnv
)( ctx
, target
, pname
, param
);
526 _mesa_TexEnvf( GLenum target
, GLenum pname
, GLfloat param
)
528 _mesa_TexEnvfv( target
, pname
, ¶m
);
534 _mesa_TexEnvi( GLenum target
, GLenum pname
, GLint param
)
537 p
[0] = (GLfloat
) param
;
538 p
[1] = p
[2] = p
[3] = 0.0;
539 _mesa_TexEnvfv( target
, pname
, p
);
544 _mesa_TexEnviv( GLenum target
, GLenum pname
, const GLint
*param
)
547 if (pname
== GL_TEXTURE_ENV_COLOR
) {
548 p
[0] = INT_TO_FLOAT( param
[0] );
549 p
[1] = INT_TO_FLOAT( param
[1] );
550 p
[2] = INT_TO_FLOAT( param
[2] );
551 p
[3] = INT_TO_FLOAT( param
[3] );
554 p
[0] = (GLfloat
) param
[0];
555 p
[1] = p
[2] = p
[3] = 0; /* init to zero, just to be safe */
557 _mesa_TexEnvfv( target
, pname
, p
);
563 * Helper for glGetTexEnvi/f()
564 * \return value of queried pname or -1 if error.
567 get_texenvi(GLcontext
*ctx
, const struct gl_texture_unit
*texUnit
,
571 case GL_TEXTURE_ENV_MODE
:
572 return texUnit
->EnvMode
;
575 if (ctx
->Extensions
.EXT_texture_env_combine
||
576 ctx
->Extensions
.ARB_texture_env_combine
) {
577 return texUnit
->Combine
.ModeRGB
;
580 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
583 case GL_COMBINE_ALPHA
:
584 if (ctx
->Extensions
.EXT_texture_env_combine
||
585 ctx
->Extensions
.ARB_texture_env_combine
) {
586 return texUnit
->Combine
.ModeA
;
589 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
595 if (ctx
->Extensions
.EXT_texture_env_combine
||
596 ctx
->Extensions
.ARB_texture_env_combine
) {
597 const unsigned rgb_idx
= pname
- GL_SOURCE0_RGB
;
598 return texUnit
->Combine
.SourceRGB
[rgb_idx
];
601 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
604 case GL_SOURCE0_ALPHA
:
605 case GL_SOURCE1_ALPHA
:
606 case GL_SOURCE2_ALPHA
:
607 if (ctx
->Extensions
.EXT_texture_env_combine
||
608 ctx
->Extensions
.ARB_texture_env_combine
) {
609 const unsigned alpha_idx
= pname
- GL_SOURCE0_ALPHA
;
610 return texUnit
->Combine
.SourceA
[alpha_idx
];
613 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
616 case GL_OPERAND0_RGB
:
617 case GL_OPERAND1_RGB
:
618 case GL_OPERAND2_RGB
:
619 if (ctx
->Extensions
.EXT_texture_env_combine
||
620 ctx
->Extensions
.ARB_texture_env_combine
) {
621 const unsigned op_rgb
= pname
- GL_OPERAND0_RGB
;
622 return texUnit
->Combine
.OperandRGB
[op_rgb
];
625 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
628 case GL_OPERAND0_ALPHA
:
629 case GL_OPERAND1_ALPHA
:
630 case GL_OPERAND2_ALPHA
:
631 if (ctx
->Extensions
.EXT_texture_env_combine
||
632 ctx
->Extensions
.ARB_texture_env_combine
) {
633 const unsigned op_alpha
= pname
- GL_OPERAND0_ALPHA
;
634 return texUnit
->Combine
.OperandA
[op_alpha
];
637 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
641 if (ctx
->Extensions
.EXT_texture_env_combine
||
642 ctx
->Extensions
.ARB_texture_env_combine
) {
643 return 1 << texUnit
->Combine
.ScaleShiftRGB
;
646 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
650 if (ctx
->Extensions
.EXT_texture_env_combine
||
651 ctx
->Extensions
.ARB_texture_env_combine
) {
652 return 1 << texUnit
->Combine
.ScaleShiftA
;
655 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)");
662 return -1; /* error */
668 _mesa_GetTexEnvfv( GLenum target
, GLenum pname
, GLfloat
*params
)
671 const struct gl_texture_unit
*texUnit
;
672 GET_CURRENT_CONTEXT(ctx
);
673 ASSERT_OUTSIDE_BEGIN_END(ctx
);
675 maxUnit
= (target
== GL_POINT_SPRITE_NV
&& pname
== GL_COORD_REPLACE_NV
)
676 ? ctx
->Const
.MaxTextureCoordUnits
: ctx
->Const
.MaxTextureImageUnits
;
677 if (ctx
->Texture
.CurrentUnit
>= maxUnit
) {
678 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexEnvfv(current unit)");
682 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
684 if (target
== GL_TEXTURE_ENV
) {
685 if (pname
== GL_TEXTURE_ENV_COLOR
) {
686 COPY_4FV( params
, texUnit
->EnvColor
);
689 GLint val
= get_texenvi(ctx
, texUnit
, pname
);
691 *params
= (GLfloat
) val
;
695 else if (target
== GL_TEXTURE_FILTER_CONTROL_EXT
) {
696 /* GL_EXT_texture_lod_bias */
697 if (!ctx
->Extensions
.EXT_texture_lod_bias
) {
698 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(target)" );
701 if (pname
== GL_TEXTURE_LOD_BIAS_EXT
) {
702 *params
= texUnit
->LodBias
;
705 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)" );
709 else if (target
== GL_POINT_SPRITE_NV
) {
710 /* GL_ARB_point_sprite / GL_NV_point_sprite */
711 if (!ctx
->Extensions
.NV_point_sprite
712 && !ctx
->Extensions
.ARB_point_sprite
) {
713 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(target)" );
716 if (pname
== GL_COORD_REPLACE_NV
) {
717 *params
= (GLfloat
) ctx
->Point
.CoordReplace
[ctx
->Texture
.CurrentUnit
];
720 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(pname)" );
725 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnvfv(target)" );
732 _mesa_GetTexEnviv( GLenum target
, GLenum pname
, GLint
*params
)
735 const struct gl_texture_unit
*texUnit
;
736 GET_CURRENT_CONTEXT(ctx
);
737 ASSERT_OUTSIDE_BEGIN_END(ctx
);
739 maxUnit
= (target
== GL_POINT_SPRITE_NV
&& pname
== GL_COORD_REPLACE_NV
)
740 ? ctx
->Const
.MaxTextureCoordUnits
: ctx
->Const
.MaxTextureImageUnits
;
741 if (ctx
->Texture
.CurrentUnit
>= maxUnit
) {
742 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexEnviv(current unit)");
746 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
748 if (target
== GL_TEXTURE_ENV
) {
749 if (pname
== GL_TEXTURE_ENV_COLOR
) {
750 params
[0] = FLOAT_TO_INT( texUnit
->EnvColor
[0] );
751 params
[1] = FLOAT_TO_INT( texUnit
->EnvColor
[1] );
752 params
[2] = FLOAT_TO_INT( texUnit
->EnvColor
[2] );
753 params
[3] = FLOAT_TO_INT( texUnit
->EnvColor
[3] );
756 GLint val
= get_texenvi(ctx
, texUnit
, pname
);
762 else if (target
== GL_TEXTURE_FILTER_CONTROL_EXT
) {
763 /* GL_EXT_texture_lod_bias */
764 if (!ctx
->Extensions
.EXT_texture_lod_bias
) {
765 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnviv(target)" );
768 if (pname
== GL_TEXTURE_LOD_BIAS_EXT
) {
769 *params
= (GLint
) texUnit
->LodBias
;
772 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnviv(pname)" );
776 else if (target
== GL_POINT_SPRITE_NV
) {
777 /* GL_ARB_point_sprite / GL_NV_point_sprite */
778 if (!ctx
->Extensions
.NV_point_sprite
779 && !ctx
->Extensions
.ARB_point_sprite
) {
780 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnviv(target)" );
783 if (pname
== GL_COORD_REPLACE_NV
) {
784 *params
= (GLint
) ctx
->Point
.CoordReplace
[ctx
->Texture
.CurrentUnit
];
787 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnviv(pname)" );
792 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexEnviv(target)" );