7 * Mesa 3-D graphics library
10 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 * Specify the blending operation.
44 * \param sfactor source factor operator.
45 * \param dfactor destination factor operator.
47 * \sa glBlendFunc, glBlendFuncSeparateEXT
49 * Swizzles the inputs and calls \c glBlendFuncSeparateEXT. This is done
50 * using the \c CurrentDispatch table in the context, so this same function
51 * can be used while compiling display lists. Therefore, there is no need
52 * for the display list code to save and restore this function.
55 _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
57 GET_CURRENT_CONTEXT(ctx
);
59 (*ctx
->CurrentDispatch
->BlendFuncSeparateEXT
)( sfactor
, dfactor
,
65 * Process GL_EXT_blend_func_separate().
67 * \param sfactorRGB RGB source factor operator.
68 * \param dfactorRGB RGB destination factor operator.
69 * \param sfactorA alpha source factor operator.
70 * \param dfactorA alpha destination factor operator.
72 * Verifies the parameters and updates gl_colorbuffer_attrib.
73 * On a change, flush the vertices and notify the driver via
74 * dd_function_table::BlendFuncSeparate.
77 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
78 GLenum sfactorA
, GLenum dfactorA
)
80 GET_CURRENT_CONTEXT(ctx
);
81 ASSERT_OUTSIDE_BEGIN_END(ctx
);
83 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
84 _mesa_debug(ctx
, "glBlendFuncSeparate %s %s %s %s\n",
85 _mesa_lookup_enum_by_nr(sfactorRGB
),
86 _mesa_lookup_enum_by_nr(dfactorRGB
),
87 _mesa_lookup_enum_by_nr(sfactorA
),
88 _mesa_lookup_enum_by_nr(dfactorA
));
92 case GL_ONE_MINUS_SRC_COLOR
:
93 if (!ctx
->Extensions
.NV_blend_square
) {
94 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
101 case GL_ONE_MINUS_DST_COLOR
:
103 case GL_ONE_MINUS_SRC_ALPHA
:
105 case GL_ONE_MINUS_DST_ALPHA
:
106 case GL_SRC_ALPHA_SATURATE
:
107 case GL_CONSTANT_COLOR
:
108 case GL_ONE_MINUS_CONSTANT_COLOR
:
109 case GL_CONSTANT_ALPHA
:
110 case GL_ONE_MINUS_CONSTANT_ALPHA
:
113 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
117 switch (dfactorRGB
) {
119 case GL_ONE_MINUS_DST_COLOR
:
120 if (!ctx
->Extensions
.NV_blend_square
) {
121 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
128 case GL_ONE_MINUS_SRC_COLOR
:
130 case GL_ONE_MINUS_SRC_ALPHA
:
132 case GL_ONE_MINUS_DST_ALPHA
:
133 case GL_CONSTANT_COLOR
:
134 case GL_ONE_MINUS_CONSTANT_COLOR
:
135 case GL_CONSTANT_ALPHA
:
136 case GL_ONE_MINUS_CONSTANT_ALPHA
:
139 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
145 case GL_ONE_MINUS_SRC_COLOR
:
146 if (!ctx
->Extensions
.NV_blend_square
) {
147 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
154 case GL_ONE_MINUS_DST_COLOR
:
156 case GL_ONE_MINUS_SRC_ALPHA
:
158 case GL_ONE_MINUS_DST_ALPHA
:
159 case GL_SRC_ALPHA_SATURATE
:
160 case GL_CONSTANT_COLOR
:
161 case GL_ONE_MINUS_CONSTANT_COLOR
:
162 case GL_CONSTANT_ALPHA
:
163 case GL_ONE_MINUS_CONSTANT_ALPHA
:
166 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
172 case GL_ONE_MINUS_DST_COLOR
:
173 if (!ctx
->Extensions
.NV_blend_square
) {
174 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorA)");
181 case GL_ONE_MINUS_SRC_COLOR
:
183 case GL_ONE_MINUS_SRC_ALPHA
:
185 case GL_ONE_MINUS_DST_ALPHA
:
186 case GL_CONSTANT_COLOR
:
187 case GL_ONE_MINUS_CONSTANT_COLOR
:
188 case GL_CONSTANT_ALPHA
:
189 case GL_ONE_MINUS_CONSTANT_ALPHA
:
192 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorA)" );
196 if (ctx
->Color
.BlendSrcRGB
== sfactorRGB
&&
197 ctx
->Color
.BlendDstRGB
== dfactorRGB
&&
198 ctx
->Color
.BlendSrcA
== sfactorA
&&
199 ctx
->Color
.BlendDstA
== dfactorA
)
202 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
204 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
205 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
206 ctx
->Color
.BlendSrcA
= sfactorA
;
207 ctx
->Color
.BlendDstA
= dfactorA
;
209 if (ctx
->Driver
.BlendFuncSeparate
) {
210 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
211 sfactorA
, dfactorA
);
219 _mesa_validate_blend_equation( GLcontext
*ctx
,
220 GLenum mode
, GLboolean is_separate
)
227 if (!ctx
->Extensions
.EXT_blend_minmax
&&
228 !ctx
->Extensions
.ARB_imaging
) {
232 /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
235 if (!ctx
->Extensions
.EXT_blend_logic_op
|| is_separate
) {
239 case GL_FUNC_SUBTRACT
:
240 case GL_FUNC_REVERSE_SUBTRACT
:
241 if (!ctx
->Extensions
.EXT_blend_subtract
&&
242 !ctx
->Extensions
.ARB_imaging
) {
254 /* This is really an extension function! */
256 _mesa_BlendEquation( GLenum mode
)
258 GET_CURRENT_CONTEXT(ctx
);
259 ASSERT_OUTSIDE_BEGIN_END(ctx
);
261 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
262 _mesa_debug(ctx
, "glBlendEquation %s\n",
263 _mesa_lookup_enum_by_nr(mode
));
265 if ( ! _mesa_validate_blend_equation( ctx
, mode
, GL_FALSE
) ) {
266 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
270 if ( (ctx
->Color
.BlendEquationRGB
== mode
) &&
271 (ctx
->Color
.BlendEquationA
== mode
) )
274 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
275 ctx
->Color
.BlendEquationRGB
= mode
;
276 ctx
->Color
.BlendEquationA
= mode
;
278 /* This is needed to support 1.1's RGB logic ops AND
279 * 1.0's blending logicops.
281 ctx
->Color
._LogicOpEnabled
= (ctx
->Color
.ColorLogicOpEnabled
||
282 (ctx
->Color
.BlendEnabled
&&
283 mode
== GL_LOGIC_OP
));
285 if (ctx
->Driver
.BlendEquationSeparate
)
286 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, mode
, mode
);
290 _mesa_BlendEquationSeparateEXT( GLenum modeRGB
, GLenum modeA
)
292 GET_CURRENT_CONTEXT(ctx
);
293 ASSERT_OUTSIDE_BEGIN_END(ctx
);
295 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
296 _mesa_debug(ctx
, "glBlendEquationSeparateEXT %s %s\n",
297 _mesa_lookup_enum_by_nr(modeRGB
),
298 _mesa_lookup_enum_by_nr(modeA
));
300 if ( (modeRGB
!= modeA
) && !ctx
->Extensions
.EXT_blend_equation_separate
) {
301 _mesa_error(ctx
, GL_INVALID_OPERATION
,
302 "glBlendEquationSeparateEXT not supported by driver");
306 if ( ! _mesa_validate_blend_equation( ctx
, modeRGB
, GL_TRUE
) ) {
307 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeRGB)");
311 if ( ! _mesa_validate_blend_equation( ctx
, modeA
, GL_TRUE
) ) {
312 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeA)");
317 if ( (ctx
->Color
.BlendEquationRGB
== modeRGB
) &&
318 (ctx
->Color
.BlendEquationA
== modeA
) )
321 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
322 ctx
->Color
.BlendEquationRGB
= modeRGB
;
323 ctx
->Color
.BlendEquationA
= modeA
;
325 /* This is needed to support 1.1's RGB logic ops AND
326 * 1.0's blending logicops. This test is simplified over glBlendEquation
327 * because modeRGB cannot be GL_LOGIC_OP.
329 ctx
->Color
._LogicOpEnabled
= (ctx
->Color
.ColorLogicOpEnabled
);
331 if (ctx
->Driver
.BlendEquationSeparate
)
332 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, modeRGB
, modeA
);
338 * Set the blending color.
340 * \param red red color component.
341 * \param green green color component.
342 * \param blue blue color component.
343 * \param alpha alpha color component.
345 * \sa glBlendColor().
347 * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
348 * change, flushes the vertices and notifies the driver via
349 * dd_function_table::BlendColor callback.
352 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
355 GET_CURRENT_CONTEXT(ctx
);
356 ASSERT_OUTSIDE_BEGIN_END(ctx
);
358 tmp
[0] = CLAMP( red
, 0.0F
, 1.0F
);
359 tmp
[1] = CLAMP( green
, 0.0F
, 1.0F
);
360 tmp
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
361 tmp
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
363 if (TEST_EQ_4V(tmp
, ctx
->Color
.BlendColor
))
366 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
367 COPY_4FV( ctx
->Color
.BlendColor
, tmp
);
369 if (ctx
->Driver
.BlendColor
)
370 (*ctx
->Driver
.BlendColor
)(ctx
, tmp
);
375 * Specify the alpha test function.
377 * \param func alpha comparison function.
378 * \param ref reference value.
380 * Verifies the parameters and updates gl_colorbuffer_attrib.
381 * On a change, flushes the vertices and notifies the driver via
382 * dd_function_table::AlphaFunc callback.
385 _mesa_AlphaFunc( GLenum func
, GLclampf ref
)
387 GET_CURRENT_CONTEXT(ctx
);
388 ASSERT_OUTSIDE_BEGIN_END(ctx
);
399 ref
= CLAMP(ref
, 0.0F
, 1.0F
);
401 if (ctx
->Color
.AlphaFunc
== func
&& ctx
->Color
.AlphaRef
== ref
)
402 return; /* no change */
404 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
405 ctx
->Color
.AlphaFunc
= func
;
406 ctx
->Color
.AlphaRef
= ref
;
408 if (ctx
->Driver
.AlphaFunc
)
409 ctx
->Driver
.AlphaFunc(ctx
, func
, ref
);
413 _mesa_error( ctx
, GL_INVALID_ENUM
, "glAlphaFunc(func)" );
420 * Specify a logic pixel operation for color index rendering.
422 * \param opcode operation.
424 * Verifies that \p opcode is a valid enum and updates
425 gl_colorbuffer_attrib::LogicOp.
426 * On a change, flushes the vertices and notifies the driver via the
427 * dd_function_table::LogicOpcode callback.
430 _mesa_LogicOp( GLenum opcode
)
432 GET_CURRENT_CONTEXT(ctx
);
433 ASSERT_OUTSIDE_BEGIN_END(ctx
);
439 case GL_COPY_INVERTED
:
449 case GL_AND_INVERTED
:
454 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLogicOp" );
458 if (ctx
->Color
.LogicOp
== opcode
)
461 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
462 ctx
->Color
.LogicOp
= opcode
;
464 if (ctx
->Driver
.LogicOpcode
)
465 ctx
->Driver
.LogicOpcode( ctx
, opcode
);
470 _mesa_IndexMask( GLuint mask
)
472 GET_CURRENT_CONTEXT(ctx
);
473 ASSERT_OUTSIDE_BEGIN_END(ctx
);
475 if (ctx
->Color
.IndexMask
== mask
)
478 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
479 ctx
->Color
.IndexMask
= mask
;
481 if (ctx
->Driver
.IndexMask
)
482 ctx
->Driver
.IndexMask( ctx
, mask
);
488 * Enable or disable writing of frame buffer color components.
490 * \param red whether to mask writing of the red color component.
491 * \param green whether to mask writing of the green color component.
492 * \param blue whether to mask writing of the blue color component.
493 * \param alpha whether to mask writing of the alpha color component.
497 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
498 * change, flushes the vertices and notifies the driver via the
499 * dd_function_table::ColorMask callback.
502 _mesa_ColorMask( GLboolean red
, GLboolean green
,
503 GLboolean blue
, GLboolean alpha
)
505 GET_CURRENT_CONTEXT(ctx
);
507 ASSERT_OUTSIDE_BEGIN_END(ctx
);
509 if (MESA_VERBOSE
& VERBOSE_API
)
510 _mesa_debug(ctx
, "glColorMask %d %d %d %d\n", red
, green
, blue
, alpha
);
512 /* Shouldn't have any information about channel depth in core mesa
513 * -- should probably store these as the native booleans:
515 tmp
[RCOMP
] = red
? 0xff : 0x0;
516 tmp
[GCOMP
] = green
? 0xff : 0x0;
517 tmp
[BCOMP
] = blue
? 0xff : 0x0;
518 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
520 if (TEST_EQ_4UBV(tmp
, ctx
->Color
.ColorMask
))
523 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
524 COPY_4UBV(ctx
->Color
.ColorMask
, tmp
);
526 if (ctx
->Driver
.ColorMask
)
527 ctx
->Driver
.ColorMask( ctx
, red
, green
, blue
, alpha
);
530 /**********************************************************************/
531 /** \name Initialization */
535 * Initialization of the context color data.
537 * \param ctx GL context.
539 * Initializes the related fields in the context color attribute group,
540 * __GLcontextRec::Color.
542 void _mesa_init_color( GLcontext
* ctx
)
544 /* Color buffer group */
545 ctx
->Color
.IndexMask
= 0xffffffff;
546 ctx
->Color
.ColorMask
[0] = 0xff;
547 ctx
->Color
.ColorMask
[1] = 0xff;
548 ctx
->Color
.ColorMask
[2] = 0xff;
549 ctx
->Color
.ColorMask
[3] = 0xff;
550 ctx
->Color
.ClearIndex
= 0;
551 ASSIGN_4V( ctx
->Color
.ClearColor
, 0, 0, 0, 0 );
552 ctx
->Color
.DrawBuffer
= GL_FRONT
;
553 ctx
->Color
.AlphaEnabled
= GL_FALSE
;
554 ctx
->Color
.AlphaFunc
= GL_ALWAYS
;
555 ctx
->Color
.AlphaRef
= 0;
556 ctx
->Color
.BlendEnabled
= GL_FALSE
;
557 ctx
->Color
.BlendSrcRGB
= GL_ONE
;
558 ctx
->Color
.BlendDstRGB
= GL_ZERO
;
559 ctx
->Color
.BlendSrcA
= GL_ONE
;
560 ctx
->Color
.BlendDstA
= GL_ZERO
;
561 ctx
->Color
.BlendEquationRGB
= GL_FUNC_ADD
;
562 ctx
->Color
.BlendEquationA
= GL_FUNC_ADD
;
563 ASSIGN_4V( ctx
->Color
.BlendColor
, 0.0, 0.0, 0.0, 0.0 );
564 ctx
->Color
.IndexLogicOpEnabled
= GL_FALSE
;
565 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
566 ctx
->Color
._LogicOpEnabled
= GL_FALSE
;
567 ctx
->Color
.LogicOp
= GL_COPY
;
568 ctx
->Color
.DitherFlag
= GL_TRUE
;
570 if (ctx
->Visual
.doubleBufferMode
) {
571 ctx
->Color
.DrawBuffer
= GL_BACK
;
572 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
;
575 ctx
->Color
.DrawBuffer
= GL_FRONT
;
576 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;