1 /* $Id: blend.c,v 1.38 2002/10/24 23:57:19 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.
38 _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
41 GET_CURRENT_CONTEXT(ctx
);
42 ASSERT_OUTSIDE_BEGIN_END(ctx
);
44 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
45 _mesa_debug(ctx
, "glBlendFunc %s %s\n",
46 _mesa_lookup_enum_by_nr(sfactor
),
47 _mesa_lookup_enum_by_nr(dfactor
));
51 case GL_ONE_MINUS_SRC_COLOR
:
52 if (!ctx
->Extensions
.NV_blend_square
) {
53 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
60 case GL_ONE_MINUS_DST_COLOR
:
62 case GL_ONE_MINUS_SRC_ALPHA
:
64 case GL_ONE_MINUS_DST_ALPHA
:
65 case GL_SRC_ALPHA_SATURATE
:
66 case GL_CONSTANT_COLOR
:
67 case GL_ONE_MINUS_CONSTANT_COLOR
:
68 case GL_CONSTANT_ALPHA
:
69 case GL_ONE_MINUS_CONSTANT_ALPHA
:
72 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
78 case GL_ONE_MINUS_DST_COLOR
:
79 if (!ctx
->Extensions
.NV_blend_square
) {
80 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
87 case GL_ONE_MINUS_SRC_COLOR
:
89 case GL_ONE_MINUS_SRC_ALPHA
:
91 case GL_ONE_MINUS_DST_ALPHA
:
92 case GL_CONSTANT_COLOR
:
93 case GL_ONE_MINUS_CONSTANT_COLOR
:
94 case GL_CONSTANT_ALPHA
:
95 case GL_ONE_MINUS_CONSTANT_ALPHA
:
98 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
102 if (ctx
->Color
.BlendDstRGB
== dfactor
&&
103 ctx
->Color
.BlendSrcRGB
== sfactor
&&
104 ctx
->Color
.BlendDstA
== dfactor
&&
105 ctx
->Color
.BlendSrcA
== sfactor
)
108 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
109 ctx
->Color
.BlendDstRGB
= ctx
->Color
.BlendDstA
= dfactor
;
110 ctx
->Color
.BlendSrcRGB
= ctx
->Color
.BlendSrcA
= sfactor
;
112 if (ctx
->Driver
.BlendFunc
)
113 ctx
->Driver
.BlendFunc( ctx
, sfactor
, dfactor
);
117 /* GL_EXT_blend_func_separate */
119 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
120 GLenum sfactorA
, GLenum dfactorA
)
122 GET_CURRENT_CONTEXT(ctx
);
123 ASSERT_OUTSIDE_BEGIN_END(ctx
);
125 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
126 _mesa_debug(ctx
, "glBlendFuncSeparate %s %s %s %s\n",
127 _mesa_lookup_enum_by_nr(sfactorRGB
),
128 _mesa_lookup_enum_by_nr(dfactorRGB
),
129 _mesa_lookup_enum_by_nr(sfactorA
),
130 _mesa_lookup_enum_by_nr(dfactorA
));
132 switch (sfactorRGB
) {
134 case GL_ONE_MINUS_SRC_COLOR
:
135 if (!ctx
->Extensions
.NV_blend_square
) {
136 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)");
143 case GL_ONE_MINUS_DST_COLOR
:
145 case GL_ONE_MINUS_SRC_ALPHA
:
147 case GL_ONE_MINUS_DST_ALPHA
:
148 case GL_SRC_ALPHA_SATURATE
:
149 case GL_CONSTANT_COLOR
:
150 case GL_ONE_MINUS_CONSTANT_COLOR
:
151 case GL_CONSTANT_ALPHA
:
152 case GL_ONE_MINUS_CONSTANT_ALPHA
:
155 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)");
159 switch (dfactorRGB
) {
161 case GL_ONE_MINUS_DST_COLOR
:
162 if (!ctx
->Extensions
.NV_blend_square
) {
163 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
170 case GL_ONE_MINUS_SRC_COLOR
:
172 case GL_ONE_MINUS_SRC_ALPHA
:
174 case GL_ONE_MINUS_DST_ALPHA
:
175 case GL_CONSTANT_COLOR
:
176 case GL_ONE_MINUS_CONSTANT_COLOR
:
177 case GL_CONSTANT_ALPHA
:
178 case GL_ONE_MINUS_CONSTANT_ALPHA
:
181 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
187 case GL_ONE_MINUS_SRC_COLOR
:
188 if (!ctx
->Extensions
.NV_blend_square
) {
189 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
196 case GL_ONE_MINUS_DST_COLOR
:
198 case GL_ONE_MINUS_SRC_ALPHA
:
200 case GL_ONE_MINUS_DST_ALPHA
:
201 case GL_SRC_ALPHA_SATURATE
:
202 case GL_CONSTANT_COLOR
:
203 case GL_ONE_MINUS_CONSTANT_COLOR
:
204 case GL_CONSTANT_ALPHA
:
205 case GL_ONE_MINUS_CONSTANT_ALPHA
:
208 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
214 case GL_ONE_MINUS_DST_COLOR
:
215 if (!ctx
->Extensions
.NV_blend_square
) {
216 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)");
223 case GL_ONE_MINUS_SRC_COLOR
:
225 case GL_ONE_MINUS_SRC_ALPHA
:
227 case GL_ONE_MINUS_DST_ALPHA
:
228 case GL_CONSTANT_COLOR
:
229 case GL_ONE_MINUS_CONSTANT_COLOR
:
230 case GL_CONSTANT_ALPHA
:
231 case GL_ONE_MINUS_CONSTANT_ALPHA
:
234 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)" );
238 if (ctx
->Color
.BlendSrcRGB
== sfactorRGB
&&
239 ctx
->Color
.BlendDstRGB
== dfactorRGB
&&
240 ctx
->Color
.BlendSrcA
== sfactorA
&&
241 ctx
->Color
.BlendDstA
== dfactorA
)
244 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
246 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
247 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
248 ctx
->Color
.BlendSrcA
= sfactorA
;
249 ctx
->Color
.BlendDstA
= dfactorA
;
251 if (ctx
->Driver
.BlendFuncSeparate
) {
252 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
253 sfactorA
, dfactorA
);
259 /* This is really an extension function! */
261 _mesa_BlendEquation( GLenum mode
)
263 GET_CURRENT_CONTEXT(ctx
);
264 ASSERT_OUTSIDE_BEGIN_END(ctx
);
266 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
267 _mesa_debug(ctx
, "glBlendEquation %s\n",
268 _mesa_lookup_enum_by_nr(mode
));
271 case GL_FUNC_ADD_EXT
:
275 if (!ctx
->Extensions
.EXT_blend_minmax
&&
276 !ctx
->Extensions
.ARB_imaging
) {
277 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
282 if (!ctx
->Extensions
.EXT_blend_logic_op
) {
283 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
287 case GL_FUNC_SUBTRACT_EXT
:
288 case GL_FUNC_REVERSE_SUBTRACT_EXT
:
289 if (!ctx
->Extensions
.EXT_blend_subtract
&&
290 !ctx
->Extensions
.ARB_imaging
) {
291 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
296 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendEquation" );
300 if (ctx
->Color
.BlendEquation
== mode
)
303 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
304 ctx
->Color
.BlendEquation
= mode
;
306 /* This is needed to support 1.1's RGB logic ops AND
307 * 1.0's blending logicops.
309 ctx
->Color
.ColorLogicOpEnabled
= (mode
==GL_LOGIC_OP
&&
310 ctx
->Color
.BlendEnabled
);
312 if (ctx
->Driver
.BlendEquation
)
313 (*ctx
->Driver
.BlendEquation
)( ctx
, mode
);
319 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
322 GET_CURRENT_CONTEXT(ctx
);
323 ASSERT_OUTSIDE_BEGIN_END(ctx
);
325 tmp
[0] = CLAMP( red
, 0.0F
, 1.0F
);
326 tmp
[1] = CLAMP( green
, 0.0F
, 1.0F
);
327 tmp
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
328 tmp
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
330 if (TEST_EQ_4V(tmp
, ctx
->Color
.BlendColor
))
333 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
334 COPY_4FV( ctx
->Color
.BlendColor
, tmp
);
336 if (ctx
->Driver
.BlendColor
)
337 (*ctx
->Driver
.BlendColor
)(ctx
, tmp
);
342 _mesa_AlphaFunc( GLenum func
, GLclampf ref
)
344 GET_CURRENT_CONTEXT(ctx
);
345 ASSERT_OUTSIDE_BEGIN_END(ctx
);
356 ref
= CLAMP(ref
, 0.0F
, 1.0F
);
358 if (ctx
->Color
.AlphaFunc
== func
&& ctx
->Color
.AlphaRef
== ref
)
359 return; /* no change */
361 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
362 ctx
->Color
.AlphaFunc
= func
;
363 ctx
->Color
.AlphaRef
= ref
;
365 if (ctx
->Driver
.AlphaFunc
)
366 ctx
->Driver
.AlphaFunc(ctx
, func
, ref
);
370 _mesa_error( ctx
, GL_INVALID_ENUM
, "glAlphaFunc(func)" );
377 _mesa_LogicOp( GLenum opcode
)
379 GET_CURRENT_CONTEXT(ctx
);
380 ASSERT_OUTSIDE_BEGIN_END(ctx
);
386 case GL_COPY_INVERTED
:
396 case GL_AND_INVERTED
:
401 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLogicOp" );
405 if (ctx
->Color
.LogicOp
== opcode
)
408 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
409 ctx
->Color
.LogicOp
= opcode
;
411 if (ctx
->Driver
.LogicOpcode
)
412 ctx
->Driver
.LogicOpcode( ctx
, opcode
);
417 _mesa_IndexMask( GLuint mask
)
419 GET_CURRENT_CONTEXT(ctx
);
420 ASSERT_OUTSIDE_BEGIN_END(ctx
);
422 if (ctx
->Color
.IndexMask
== mask
)
425 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
426 ctx
->Color
.IndexMask
= mask
;
428 if (ctx
->Driver
.IndexMask
)
429 ctx
->Driver
.IndexMask( ctx
, mask
);
434 _mesa_ColorMask( GLboolean red
, GLboolean green
,
435 GLboolean blue
, GLboolean alpha
)
437 GET_CURRENT_CONTEXT(ctx
);
439 ASSERT_OUTSIDE_BEGIN_END(ctx
);
441 if (MESA_VERBOSE
& VERBOSE_API
)
442 _mesa_debug(ctx
, "glColorMask %d %d %d %d\n", red
, green
, blue
, alpha
);
444 /* Shouldn't have any information about channel depth in core mesa
445 * -- should probably store these as the native booleans:
447 tmp
[RCOMP
] = red
? 0xff : 0x0;
448 tmp
[GCOMP
] = green
? 0xff : 0x0;
449 tmp
[BCOMP
] = blue
? 0xff : 0x0;
450 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
452 if (TEST_EQ_4UBV(tmp
, ctx
->Color
.ColorMask
))
455 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
456 COPY_4UBV(ctx
->Color
.ColorMask
, tmp
);
458 if (ctx
->Driver
.ColorMask
)
459 ctx
->Driver
.ColorMask( ctx
, red
, green
, blue
, alpha
);