7 * Mesa 3-D graphics library
10 * Copyright (C) 1999-2006 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.
38 #include "glapi/glapitable.h"
42 * Specify the blending operation.
44 * \param sfactor source factor operator.
45 * \param dfactor destination factor operator.
47 * \sa glBlendFunc, glBlendFuncSeparateEXT
50 _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
52 _mesa_BlendFuncSeparateEXT(sfactor
, dfactor
, sfactor
, dfactor
);
57 * Process GL_EXT_blend_func_separate().
59 * \param sfactorRGB RGB source factor operator.
60 * \param dfactorRGB RGB destination factor operator.
61 * \param sfactorA alpha source factor operator.
62 * \param dfactorA alpha destination factor operator.
64 * Verifies the parameters and updates gl_colorbuffer_attrib.
65 * On a change, flush the vertices and notify the driver via
66 * dd_function_table::BlendFuncSeparate.
69 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
70 GLenum sfactorA
, GLenum dfactorA
)
72 GET_CURRENT_CONTEXT(ctx
);
73 ASSERT_OUTSIDE_BEGIN_END(ctx
);
75 if (MESA_VERBOSE
& VERBOSE_API
)
76 _mesa_debug(ctx
, "glBlendFuncSeparate %s %s %s %s\n",
77 _mesa_lookup_enum_by_nr(sfactorRGB
),
78 _mesa_lookup_enum_by_nr(dfactorRGB
),
79 _mesa_lookup_enum_by_nr(sfactorA
),
80 _mesa_lookup_enum_by_nr(dfactorA
));
84 case GL_ONE_MINUS_SRC_COLOR
:
85 if (!ctx
->Extensions
.NV_blend_square
) {
86 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
93 case GL_ONE_MINUS_DST_COLOR
:
95 case GL_ONE_MINUS_SRC_ALPHA
:
97 case GL_ONE_MINUS_DST_ALPHA
:
98 case GL_SRC_ALPHA_SATURATE
:
99 case GL_CONSTANT_COLOR
:
100 case GL_ONE_MINUS_CONSTANT_COLOR
:
101 case GL_CONSTANT_ALPHA
:
102 case GL_ONE_MINUS_CONSTANT_ALPHA
:
105 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
109 switch (dfactorRGB
) {
111 case GL_ONE_MINUS_DST_COLOR
:
112 if (!ctx
->Extensions
.NV_blend_square
) {
113 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
120 case GL_ONE_MINUS_SRC_COLOR
:
122 case GL_ONE_MINUS_SRC_ALPHA
:
124 case GL_ONE_MINUS_DST_ALPHA
:
125 case GL_CONSTANT_COLOR
:
126 case GL_ONE_MINUS_CONSTANT_COLOR
:
127 case GL_CONSTANT_ALPHA
:
128 case GL_ONE_MINUS_CONSTANT_ALPHA
:
131 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
137 case GL_ONE_MINUS_SRC_COLOR
:
138 if (!ctx
->Extensions
.NV_blend_square
) {
139 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
146 case GL_ONE_MINUS_DST_COLOR
:
148 case GL_ONE_MINUS_SRC_ALPHA
:
150 case GL_ONE_MINUS_DST_ALPHA
:
151 case GL_SRC_ALPHA_SATURATE
:
152 case GL_CONSTANT_COLOR
:
153 case GL_ONE_MINUS_CONSTANT_COLOR
:
154 case GL_CONSTANT_ALPHA
:
155 case GL_ONE_MINUS_CONSTANT_ALPHA
:
158 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
164 case GL_ONE_MINUS_DST_COLOR
:
165 if (!ctx
->Extensions
.NV_blend_square
) {
166 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorA)");
173 case GL_ONE_MINUS_SRC_COLOR
:
175 case GL_ONE_MINUS_SRC_ALPHA
:
177 case GL_ONE_MINUS_DST_ALPHA
:
178 case GL_CONSTANT_COLOR
:
179 case GL_ONE_MINUS_CONSTANT_COLOR
:
180 case GL_CONSTANT_ALPHA
:
181 case GL_ONE_MINUS_CONSTANT_ALPHA
:
184 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorA)" );
188 if (ctx
->Color
.BlendSrcRGB
== sfactorRGB
&&
189 ctx
->Color
.BlendDstRGB
== dfactorRGB
&&
190 ctx
->Color
.BlendSrcA
== sfactorA
&&
191 ctx
->Color
.BlendDstA
== dfactorA
)
194 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
196 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
197 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
198 ctx
->Color
.BlendSrcA
= sfactorA
;
199 ctx
->Color
.BlendDstA
= dfactorA
;
201 if (ctx
->Driver
.BlendFuncSeparate
) {
202 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
203 sfactorA
, dfactorA
);
211 _mesa_validate_blend_equation( GLcontext
*ctx
,
212 GLenum mode
, GLboolean is_separate
)
219 if (!ctx
->Extensions
.EXT_blend_minmax
&&
220 !ctx
->Extensions
.ARB_imaging
) {
224 /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
227 if (!ctx
->Extensions
.EXT_blend_logic_op
|| is_separate
) {
231 case GL_FUNC_SUBTRACT
:
232 case GL_FUNC_REVERSE_SUBTRACT
:
233 if (!ctx
->Extensions
.EXT_blend_subtract
&&
234 !ctx
->Extensions
.ARB_imaging
) {
246 /* This is really an extension function! */
248 _mesa_BlendEquation( GLenum mode
)
250 GET_CURRENT_CONTEXT(ctx
);
251 ASSERT_OUTSIDE_BEGIN_END(ctx
);
253 if (MESA_VERBOSE
& VERBOSE_API
)
254 _mesa_debug(ctx
, "glBlendEquation %s\n",
255 _mesa_lookup_enum_by_nr(mode
));
257 if ( ! _mesa_validate_blend_equation( ctx
, mode
, GL_FALSE
) ) {
258 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
262 if ( (ctx
->Color
.BlendEquationRGB
== mode
) &&
263 (ctx
->Color
.BlendEquationA
== mode
) )
266 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
267 ctx
->Color
.BlendEquationRGB
= mode
;
268 ctx
->Color
.BlendEquationA
= mode
;
270 if (ctx
->Driver
.BlendEquationSeparate
)
271 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, mode
, mode
);
276 _mesa_BlendEquationSeparateEXT( GLenum modeRGB
, GLenum modeA
)
278 GET_CURRENT_CONTEXT(ctx
);
279 ASSERT_OUTSIDE_BEGIN_END(ctx
);
281 if (MESA_VERBOSE
& VERBOSE_API
)
282 _mesa_debug(ctx
, "glBlendEquationSeparateEXT %s %s\n",
283 _mesa_lookup_enum_by_nr(modeRGB
),
284 _mesa_lookup_enum_by_nr(modeA
));
286 if ( (modeRGB
!= modeA
) && !ctx
->Extensions
.EXT_blend_equation_separate
) {
287 _mesa_error(ctx
, GL_INVALID_OPERATION
,
288 "glBlendEquationSeparateEXT not supported by driver");
292 if ( ! _mesa_validate_blend_equation( ctx
, modeRGB
, GL_TRUE
) ) {
293 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeRGB)");
297 if ( ! _mesa_validate_blend_equation( ctx
, modeA
, GL_TRUE
) ) {
298 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeA)");
303 if ( (ctx
->Color
.BlendEquationRGB
== modeRGB
) &&
304 (ctx
->Color
.BlendEquationA
== modeA
) )
307 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
308 ctx
->Color
.BlendEquationRGB
= modeRGB
;
309 ctx
->Color
.BlendEquationA
= modeA
;
311 if (ctx
->Driver
.BlendEquationSeparate
)
312 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, modeRGB
, modeA
);
318 * Set the blending color.
320 * \param red red color component.
321 * \param green green color component.
322 * \param blue blue color component.
323 * \param alpha alpha color component.
325 * \sa glBlendColor().
327 * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
328 * change, flushes the vertices and notifies the driver via
329 * dd_function_table::BlendColor callback.
332 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
335 GET_CURRENT_CONTEXT(ctx
);
336 ASSERT_OUTSIDE_BEGIN_END(ctx
);
338 tmp
[0] = CLAMP( red
, 0.0F
, 1.0F
);
339 tmp
[1] = CLAMP( green
, 0.0F
, 1.0F
);
340 tmp
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
341 tmp
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
343 if (TEST_EQ_4V(tmp
, ctx
->Color
.BlendColor
))
346 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
347 COPY_4FV( ctx
->Color
.BlendColor
, tmp
);
349 if (ctx
->Driver
.BlendColor
)
350 (*ctx
->Driver
.BlendColor
)(ctx
, tmp
);
355 * Specify the alpha test function.
357 * \param func alpha comparison function.
358 * \param ref reference value.
360 * Verifies the parameters and updates gl_colorbuffer_attrib.
361 * On a change, flushes the vertices and notifies the driver via
362 * dd_function_table::AlphaFunc callback.
365 _mesa_AlphaFunc( GLenum func
, GLclampf ref
)
367 GET_CURRENT_CONTEXT(ctx
);
368 ASSERT_OUTSIDE_BEGIN_END(ctx
);
379 ref
= CLAMP(ref
, 0.0F
, 1.0F
);
381 if (ctx
->Color
.AlphaFunc
== func
&& ctx
->Color
.AlphaRef
== ref
)
382 return; /* no change */
384 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
385 ctx
->Color
.AlphaFunc
= func
;
386 ctx
->Color
.AlphaRef
= ref
;
388 if (ctx
->Driver
.AlphaFunc
)
389 ctx
->Driver
.AlphaFunc(ctx
, func
, ref
);
393 _mesa_error( ctx
, GL_INVALID_ENUM
, "glAlphaFunc(func)" );
400 * Specify a logic pixel operation for color index rendering.
402 * \param opcode operation.
404 * Verifies that \p opcode is a valid enum and updates
405 gl_colorbuffer_attrib::LogicOp.
406 * On a change, flushes the vertices and notifies the driver via the
407 * dd_function_table::LogicOpcode callback.
410 _mesa_LogicOp( GLenum opcode
)
412 GET_CURRENT_CONTEXT(ctx
);
413 ASSERT_OUTSIDE_BEGIN_END(ctx
);
419 case GL_COPY_INVERTED
:
429 case GL_AND_INVERTED
:
434 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLogicOp" );
438 if (ctx
->Color
.LogicOp
== opcode
)
441 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
442 ctx
->Color
.LogicOp
= opcode
;
444 if (ctx
->Driver
.LogicOpcode
)
445 ctx
->Driver
.LogicOpcode( ctx
, opcode
);
450 _mesa_IndexMask( GLuint mask
)
452 GET_CURRENT_CONTEXT(ctx
);
453 ASSERT_OUTSIDE_BEGIN_END(ctx
);
455 if (ctx
->Color
.IndexMask
== mask
)
458 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
459 ctx
->Color
.IndexMask
= mask
;
461 if (ctx
->Driver
.IndexMask
)
462 ctx
->Driver
.IndexMask( ctx
, mask
);
468 * Enable or disable writing of frame buffer color components.
470 * \param red whether to mask writing of the red color component.
471 * \param green whether to mask writing of the green color component.
472 * \param blue whether to mask writing of the blue color component.
473 * \param alpha whether to mask writing of the alpha color component.
477 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
478 * change, flushes the vertices and notifies the driver via the
479 * dd_function_table::ColorMask callback.
482 _mesa_ColorMask( GLboolean red
, GLboolean green
,
483 GLboolean blue
, GLboolean alpha
)
485 GET_CURRENT_CONTEXT(ctx
);
489 ASSERT_OUTSIDE_BEGIN_END(ctx
);
491 if (MESA_VERBOSE
& VERBOSE_API
)
492 _mesa_debug(ctx
, "glColorMask %d %d %d %d\n", red
, green
, blue
, alpha
);
494 /* Shouldn't have any information about channel depth in core mesa
495 * -- should probably store these as the native booleans:
497 tmp
[RCOMP
] = red
? 0xff : 0x0;
498 tmp
[GCOMP
] = green
? 0xff : 0x0;
499 tmp
[BCOMP
] = blue
? 0xff : 0x0;
500 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
503 for (i
= 0; i
< ctx
->Const
.MaxDrawBuffers
; i
++) {
504 if (!TEST_EQ_4V(tmp
, ctx
->Color
.ColorMask
[i
])) {
506 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
509 COPY_4UBV(ctx
->Color
.ColorMask
[i
], tmp
);
513 if (ctx
->Driver
.ColorMask
)
514 ctx
->Driver
.ColorMask( ctx
, red
, green
, blue
, alpha
);
519 * For GL_EXT_draw_buffers2 and GL3
522 _mesa_ColorMaskIndexed( GLuint buf
, GLboolean red
, GLboolean green
,
523 GLboolean blue
, GLboolean alpha
)
526 GET_CURRENT_CONTEXT(ctx
);
527 ASSERT_OUTSIDE_BEGIN_END(ctx
);
529 if (MESA_VERBOSE
& VERBOSE_API
)
530 _mesa_debug(ctx
, "glColorMaskIndexed %u %d %d %d %d\n",
531 buf
, red
, green
, blue
, alpha
);
533 if (buf
>= ctx
->Const
.MaxDrawBuffers
) {
534 _mesa_error(ctx
, GL_INVALID_VALUE
, "glColorMaskIndexed(buf=%u)", buf
);
538 /* Shouldn't have any information about channel depth in core mesa
539 * -- should probably store these as the native booleans:
541 tmp
[RCOMP
] = red
? 0xff : 0x0;
542 tmp
[GCOMP
] = green
? 0xff : 0x0;
543 tmp
[BCOMP
] = blue
? 0xff : 0x0;
544 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
546 if (TEST_EQ_4V(tmp
, ctx
->Color
.ColorMask
[buf
]))
549 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
550 COPY_4UBV(ctx
->Color
.ColorMask
[buf
], tmp
);
552 if (ctx
->Driver
.ColorMaskIndexed
)
553 ctx
->Driver
.ColorMaskIndexed(ctx
, buf
, red
, green
, blue
, alpha
);
557 extern void GLAPIENTRY
558 _mesa_ClampColorARB(GLenum target
, GLenum clamp
)
560 GET_CURRENT_CONTEXT(ctx
);
562 ASSERT_OUTSIDE_BEGIN_END(ctx
);
564 if (clamp
!= GL_TRUE
&& clamp
!= GL_FALSE
&& clamp
!= GL_FIXED_ONLY_ARB
) {
565 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClampColorARB(clamp)");
570 case GL_CLAMP_VERTEX_COLOR_ARB
:
571 ctx
->Light
.ClampVertexColor
= clamp
;
573 case GL_CLAMP_FRAGMENT_COLOR_ARB
:
574 ctx
->Color
.ClampFragmentColor
= clamp
;
576 case GL_CLAMP_READ_COLOR_ARB
:
577 ctx
->Color
.ClampReadColor
= clamp
;
580 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClampColorARB(target)");
588 /**********************************************************************/
589 /** \name Initialization */
593 * Initialization of the context's Color attribute group.
595 * \param ctx GL context.
597 * Initializes the related fields in the context color attribute group,
598 * __GLcontextRec::Color.
600 void _mesa_init_color( GLcontext
* ctx
)
602 /* Color buffer group */
603 ctx
->Color
.IndexMask
= ~0u;
604 memset(ctx
->Color
.ColorMask
, 0xff, sizeof(ctx
->Color
.ColorMask
));
605 ctx
->Color
.ClearIndex
= 0;
606 ASSIGN_4V( ctx
->Color
.ClearColor
, 0, 0, 0, 0 );
607 ctx
->Color
.AlphaEnabled
= GL_FALSE
;
608 ctx
->Color
.AlphaFunc
= GL_ALWAYS
;
609 ctx
->Color
.AlphaRef
= 0;
610 ctx
->Color
.BlendEnabled
= 0x0;
611 ctx
->Color
.BlendSrcRGB
= GL_ONE
;
612 ctx
->Color
.BlendDstRGB
= GL_ZERO
;
613 ctx
->Color
.BlendSrcA
= GL_ONE
;
614 ctx
->Color
.BlendDstA
= GL_ZERO
;
615 ctx
->Color
.BlendEquationRGB
= GL_FUNC_ADD
;
616 ctx
->Color
.BlendEquationA
= GL_FUNC_ADD
;
617 ASSIGN_4V( ctx
->Color
.BlendColor
, 0.0, 0.0, 0.0, 0.0 );
618 ctx
->Color
.IndexLogicOpEnabled
= GL_FALSE
;
619 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
620 ctx
->Color
._LogicOpEnabled
= GL_FALSE
;
621 ctx
->Color
.LogicOp
= GL_COPY
;
622 ctx
->Color
.DitherFlag
= GL_TRUE
;
624 if (ctx
->Visual
.doubleBufferMode
) {
625 ctx
->Color
.DrawBuffer
[0] = GL_BACK
;
628 ctx
->Color
.DrawBuffer
[0] = GL_FRONT
;
631 ctx
->Color
.ClampFragmentColor
= GL_FIXED_ONLY_ARB
;
632 ctx
->Color
.ClampReadColor
= GL_FIXED_ONLY_ARB
;