1 /* $Id: blend.c,v 1.37 2002/10/04 19:10:07 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
45 GET_CURRENT_CONTEXT(ctx
);
46 ASSERT_OUTSIDE_BEGIN_END(ctx
);
48 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
49 _mesa_debug(ctx
, "glBlendFunc %s %s\n",
50 _mesa_lookup_enum_by_nr(sfactor
),
51 _mesa_lookup_enum_by_nr(dfactor
));
55 case GL_ONE_MINUS_SRC_COLOR
:
56 if (!ctx
->Extensions
.NV_blend_square
) {
57 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
64 case GL_ONE_MINUS_DST_COLOR
:
66 case GL_ONE_MINUS_SRC_ALPHA
:
68 case GL_ONE_MINUS_DST_ALPHA
:
69 case GL_SRC_ALPHA_SATURATE
:
70 case GL_CONSTANT_COLOR
:
71 case GL_ONE_MINUS_CONSTANT_COLOR
:
72 case GL_CONSTANT_ALPHA
:
73 case GL_ONE_MINUS_CONSTANT_ALPHA
:
76 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
82 case GL_ONE_MINUS_DST_COLOR
:
83 if (!ctx
->Extensions
.NV_blend_square
) {
84 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
91 case GL_ONE_MINUS_SRC_COLOR
:
93 case GL_ONE_MINUS_SRC_ALPHA
:
95 case GL_ONE_MINUS_DST_ALPHA
:
96 case GL_CONSTANT_COLOR
:
97 case GL_ONE_MINUS_CONSTANT_COLOR
:
98 case GL_CONSTANT_ALPHA
:
99 case GL_ONE_MINUS_CONSTANT_ALPHA
:
102 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
106 if (ctx
->Color
.BlendDstRGB
== dfactor
&&
107 ctx
->Color
.BlendSrcRGB
== sfactor
&&
108 ctx
->Color
.BlendDstA
== dfactor
&&
109 ctx
->Color
.BlendSrcA
== sfactor
)
112 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
113 ctx
->Color
.BlendDstRGB
= ctx
->Color
.BlendDstA
= dfactor
;
114 ctx
->Color
.BlendSrcRGB
= ctx
->Color
.BlendSrcA
= sfactor
;
116 if (ctx
->Driver
.BlendFunc
)
117 ctx
->Driver
.BlendFunc( ctx
, sfactor
, dfactor
);
121 /* GL_EXT_blend_func_separate */
123 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
124 GLenum sfactorA
, GLenum dfactorA
)
126 GET_CURRENT_CONTEXT(ctx
);
127 ASSERT_OUTSIDE_BEGIN_END(ctx
);
129 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
130 _mesa_debug(ctx
, "glBlendFuncSeparate %s %s %s %s\n",
131 _mesa_lookup_enum_by_nr(sfactorRGB
),
132 _mesa_lookup_enum_by_nr(dfactorRGB
),
133 _mesa_lookup_enum_by_nr(sfactorA
),
134 _mesa_lookup_enum_by_nr(dfactorA
));
136 switch (sfactorRGB
) {
138 case GL_ONE_MINUS_SRC_COLOR
:
139 if (!ctx
->Extensions
.NV_blend_square
) {
140 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)");
147 case GL_ONE_MINUS_DST_COLOR
:
149 case GL_ONE_MINUS_SRC_ALPHA
:
151 case GL_ONE_MINUS_DST_ALPHA
:
152 case GL_SRC_ALPHA_SATURATE
:
153 case GL_CONSTANT_COLOR
:
154 case GL_ONE_MINUS_CONSTANT_COLOR
:
155 case GL_CONSTANT_ALPHA
:
156 case GL_ONE_MINUS_CONSTANT_ALPHA
:
159 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)");
163 switch (dfactorRGB
) {
165 case GL_ONE_MINUS_DST_COLOR
:
166 if (!ctx
->Extensions
.NV_blend_square
) {
167 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
174 case GL_ONE_MINUS_SRC_COLOR
:
176 case GL_ONE_MINUS_SRC_ALPHA
:
178 case GL_ONE_MINUS_DST_ALPHA
:
179 case GL_CONSTANT_COLOR
:
180 case GL_ONE_MINUS_CONSTANT_COLOR
:
181 case GL_CONSTANT_ALPHA
:
182 case GL_ONE_MINUS_CONSTANT_ALPHA
:
185 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
191 case GL_ONE_MINUS_SRC_COLOR
:
192 if (!ctx
->Extensions
.NV_blend_square
) {
193 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
200 case GL_ONE_MINUS_DST_COLOR
:
202 case GL_ONE_MINUS_SRC_ALPHA
:
204 case GL_ONE_MINUS_DST_ALPHA
:
205 case GL_SRC_ALPHA_SATURATE
:
206 case GL_CONSTANT_COLOR
:
207 case GL_ONE_MINUS_CONSTANT_COLOR
:
208 case GL_CONSTANT_ALPHA
:
209 case GL_ONE_MINUS_CONSTANT_ALPHA
:
212 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
218 case GL_ONE_MINUS_DST_COLOR
:
219 if (!ctx
->Extensions
.NV_blend_square
) {
220 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)");
227 case GL_ONE_MINUS_SRC_COLOR
:
229 case GL_ONE_MINUS_SRC_ALPHA
:
231 case GL_ONE_MINUS_DST_ALPHA
:
232 case GL_CONSTANT_COLOR
:
233 case GL_ONE_MINUS_CONSTANT_COLOR
:
234 case GL_CONSTANT_ALPHA
:
235 case GL_ONE_MINUS_CONSTANT_ALPHA
:
238 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)" );
242 if (ctx
->Color
.BlendSrcRGB
== sfactorRGB
&&
243 ctx
->Color
.BlendDstRGB
== dfactorRGB
&&
244 ctx
->Color
.BlendSrcA
== sfactorA
&&
245 ctx
->Color
.BlendDstA
== dfactorA
)
248 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
250 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
251 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
252 ctx
->Color
.BlendSrcA
= sfactorA
;
253 ctx
->Color
.BlendDstA
= dfactorA
;
255 if (ctx
->Driver
.BlendFuncSeparate
) {
256 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
257 sfactorA
, dfactorA
);
263 /* This is really an extension function! */
265 _mesa_BlendEquation( GLenum mode
)
267 GET_CURRENT_CONTEXT(ctx
);
268 ASSERT_OUTSIDE_BEGIN_END(ctx
);
270 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
271 _mesa_debug(ctx
, "glBlendEquation %s\n",
272 _mesa_lookup_enum_by_nr(mode
));
275 case GL_FUNC_ADD_EXT
:
279 if (!ctx
->Extensions
.EXT_blend_minmax
&&
280 !ctx
->Extensions
.ARB_imaging
) {
281 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
286 if (!ctx
->Extensions
.EXT_blend_logic_op
) {
287 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
291 case GL_FUNC_SUBTRACT_EXT
:
292 case GL_FUNC_REVERSE_SUBTRACT_EXT
:
293 if (!ctx
->Extensions
.EXT_blend_subtract
&&
294 !ctx
->Extensions
.ARB_imaging
) {
295 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
300 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendEquation" );
304 if (ctx
->Color
.BlendEquation
== mode
)
307 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
308 ctx
->Color
.BlendEquation
= mode
;
310 /* This is needed to support 1.1's RGB logic ops AND
311 * 1.0's blending logicops.
313 ctx
->Color
.ColorLogicOpEnabled
= (mode
==GL_LOGIC_OP
&&
314 ctx
->Color
.BlendEnabled
);
316 if (ctx
->Driver
.BlendEquation
)
317 (*ctx
->Driver
.BlendEquation
)( ctx
, mode
);
323 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
326 GET_CURRENT_CONTEXT(ctx
);
327 ASSERT_OUTSIDE_BEGIN_END(ctx
);
329 tmp
[0] = CLAMP( red
, 0.0F
, 1.0F
);
330 tmp
[1] = CLAMP( green
, 0.0F
, 1.0F
);
331 tmp
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
332 tmp
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
334 if (TEST_EQ_4V(tmp
, ctx
->Color
.BlendColor
))
337 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
338 COPY_4FV( ctx
->Color
.BlendColor
, tmp
);
340 if (ctx
->Driver
.BlendColor
)
341 (*ctx
->Driver
.BlendColor
)(ctx
, tmp
);
346 _mesa_AlphaFunc( GLenum func
, GLclampf ref
)
348 GET_CURRENT_CONTEXT(ctx
);
349 ASSERT_OUTSIDE_BEGIN_END(ctx
);
360 ref
= CLAMP(ref
, 0.0F
, 1.0F
);
362 if (ctx
->Color
.AlphaFunc
== func
&& ctx
->Color
.AlphaRef
== ref
)
363 return; /* no change */
365 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
366 ctx
->Color
.AlphaFunc
= func
;
367 ctx
->Color
.AlphaRef
= ref
;
369 if (ctx
->Driver
.AlphaFunc
)
370 ctx
->Driver
.AlphaFunc(ctx
, func
, ref
);
374 _mesa_error( ctx
, GL_INVALID_ENUM
, "glAlphaFunc(func)" );
381 _mesa_LogicOp( GLenum opcode
)
383 GET_CURRENT_CONTEXT(ctx
);
384 ASSERT_OUTSIDE_BEGIN_END(ctx
);
390 case GL_COPY_INVERTED
:
400 case GL_AND_INVERTED
:
405 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLogicOp" );
409 if (ctx
->Color
.LogicOp
== opcode
)
412 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
413 ctx
->Color
.LogicOp
= opcode
;
415 if (ctx
->Driver
.LogicOpcode
)
416 ctx
->Driver
.LogicOpcode( ctx
, opcode
);
421 _mesa_IndexMask( GLuint mask
)
423 GET_CURRENT_CONTEXT(ctx
);
424 ASSERT_OUTSIDE_BEGIN_END(ctx
);
426 if (ctx
->Color
.IndexMask
== mask
)
429 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
430 ctx
->Color
.IndexMask
= mask
;
432 if (ctx
->Driver
.IndexMask
)
433 ctx
->Driver
.IndexMask( ctx
, mask
);
438 _mesa_ColorMask( GLboolean red
, GLboolean green
,
439 GLboolean blue
, GLboolean alpha
)
441 GET_CURRENT_CONTEXT(ctx
);
443 ASSERT_OUTSIDE_BEGIN_END(ctx
);
445 if (MESA_VERBOSE
& VERBOSE_API
)
446 _mesa_debug(ctx
, "glColorMask %d %d %d %d\n", red
, green
, blue
, alpha
);
448 /* Shouldn't have any information about channel depth in core mesa
449 * -- should probably store these as the native booleans:
451 tmp
[RCOMP
] = red
? 0xff : 0x0;
452 tmp
[GCOMP
] = green
? 0xff : 0x0;
453 tmp
[BCOMP
] = blue
? 0xff : 0x0;
454 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
456 if (TEST_EQ_4UBV(tmp
, ctx
->Color
.ColorMask
))
459 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
460 COPY_4UBV(ctx
->Color
.ColorMask
, tmp
);
462 if (ctx
->Driver
.ColorMask
)
463 ctx
->Driver
.ColorMask( ctx
, red
, green
, blue
, alpha
);