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.
41 * Specify the blending operation.
43 * \param sfactor source factor operator.
44 * \param dfactor destination factor operator.
46 * \sa glBlendFunc, glBlendFuncSeparateEXT
49 _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
51 _mesa_BlendFuncSeparateEXT(sfactor
, dfactor
, sfactor
, dfactor
);
56 * Process GL_EXT_blend_func_separate().
58 * \param sfactorRGB RGB source factor operator.
59 * \param dfactorRGB RGB destination factor operator.
60 * \param sfactorA alpha source factor operator.
61 * \param dfactorA alpha destination factor operator.
63 * Verifies the parameters and updates gl_colorbuffer_attrib.
64 * On a change, flush the vertices and notify the driver via
65 * dd_function_table::BlendFuncSeparate.
68 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
69 GLenum sfactorA
, GLenum dfactorA
)
71 GET_CURRENT_CONTEXT(ctx
);
72 ASSERT_OUTSIDE_BEGIN_END(ctx
);
74 if (MESA_VERBOSE
& VERBOSE_API
)
75 _mesa_debug(ctx
, "glBlendFuncSeparate %s %s %s %s\n",
76 _mesa_lookup_enum_by_nr(sfactorRGB
),
77 _mesa_lookup_enum_by_nr(dfactorRGB
),
78 _mesa_lookup_enum_by_nr(sfactorA
),
79 _mesa_lookup_enum_by_nr(dfactorA
));
83 case GL_ONE_MINUS_SRC_COLOR
:
84 if (!ctx
->Extensions
.NV_blend_square
) {
85 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
92 case GL_ONE_MINUS_DST_COLOR
:
94 case GL_ONE_MINUS_SRC_ALPHA
:
96 case GL_ONE_MINUS_DST_ALPHA
:
97 case GL_SRC_ALPHA_SATURATE
:
98 case GL_CONSTANT_COLOR
:
99 case GL_ONE_MINUS_CONSTANT_COLOR
:
100 case GL_CONSTANT_ALPHA
:
101 case GL_ONE_MINUS_CONSTANT_ALPHA
:
104 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
108 switch (dfactorRGB
) {
110 case GL_ONE_MINUS_DST_COLOR
:
111 if (!ctx
->Extensions
.NV_blend_square
) {
112 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
119 case GL_ONE_MINUS_SRC_COLOR
:
121 case GL_ONE_MINUS_SRC_ALPHA
:
123 case GL_ONE_MINUS_DST_ALPHA
:
124 case GL_CONSTANT_COLOR
:
125 case GL_ONE_MINUS_CONSTANT_COLOR
:
126 case GL_CONSTANT_ALPHA
:
127 case GL_ONE_MINUS_CONSTANT_ALPHA
:
130 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
136 case GL_ONE_MINUS_SRC_COLOR
:
137 if (!ctx
->Extensions
.NV_blend_square
) {
138 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
145 case GL_ONE_MINUS_DST_COLOR
:
147 case GL_ONE_MINUS_SRC_ALPHA
:
149 case GL_ONE_MINUS_DST_ALPHA
:
150 case GL_SRC_ALPHA_SATURATE
:
151 case GL_CONSTANT_COLOR
:
152 case GL_ONE_MINUS_CONSTANT_COLOR
:
153 case GL_CONSTANT_ALPHA
:
154 case GL_ONE_MINUS_CONSTANT_ALPHA
:
157 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
163 case GL_ONE_MINUS_DST_COLOR
:
164 if (!ctx
->Extensions
.NV_blend_square
) {
165 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorA)");
172 case GL_ONE_MINUS_SRC_COLOR
:
174 case GL_ONE_MINUS_SRC_ALPHA
:
176 case GL_ONE_MINUS_DST_ALPHA
:
177 case GL_CONSTANT_COLOR
:
178 case GL_ONE_MINUS_CONSTANT_COLOR
:
179 case GL_CONSTANT_ALPHA
:
180 case GL_ONE_MINUS_CONSTANT_ALPHA
:
183 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc or glBlendFuncSeparate (dfactorA)" );
187 if (ctx
->Color
.BlendSrcRGB
== sfactorRGB
&&
188 ctx
->Color
.BlendDstRGB
== dfactorRGB
&&
189 ctx
->Color
.BlendSrcA
== sfactorA
&&
190 ctx
->Color
.BlendDstA
== dfactorA
)
193 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
195 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
196 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
197 ctx
->Color
.BlendSrcA
= sfactorA
;
198 ctx
->Color
.BlendDstA
= dfactorA
;
200 if (ctx
->Driver
.BlendFuncSeparate
) {
201 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
202 sfactorA
, dfactorA
);
210 _mesa_validate_blend_equation( GLcontext
*ctx
,
211 GLenum mode
, GLboolean is_separate
)
218 if (!ctx
->Extensions
.EXT_blend_minmax
) {
222 /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
225 if (!ctx
->Extensions
.EXT_blend_logic_op
|| is_separate
) {
229 case GL_FUNC_SUBTRACT
:
230 case GL_FUNC_REVERSE_SUBTRACT
:
231 if (!ctx
->Extensions
.EXT_blend_subtract
) {
243 /* This is really an extension function! */
245 _mesa_BlendEquation( GLenum mode
)
247 GET_CURRENT_CONTEXT(ctx
);
248 ASSERT_OUTSIDE_BEGIN_END(ctx
);
250 if (MESA_VERBOSE
& VERBOSE_API
)
251 _mesa_debug(ctx
, "glBlendEquation %s\n",
252 _mesa_lookup_enum_by_nr(mode
));
254 if ( ! _mesa_validate_blend_equation( ctx
, mode
, GL_FALSE
) ) {
255 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
259 if ( (ctx
->Color
.BlendEquationRGB
== mode
) &&
260 (ctx
->Color
.BlendEquationA
== mode
) )
263 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
264 ctx
->Color
.BlendEquationRGB
= mode
;
265 ctx
->Color
.BlendEquationA
= mode
;
267 if (ctx
->Driver
.BlendEquationSeparate
)
268 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, mode
, mode
);
273 _mesa_BlendEquationSeparateEXT( GLenum modeRGB
, GLenum modeA
)
275 GET_CURRENT_CONTEXT(ctx
);
276 ASSERT_OUTSIDE_BEGIN_END(ctx
);
278 if (MESA_VERBOSE
& VERBOSE_API
)
279 _mesa_debug(ctx
, "glBlendEquationSeparateEXT %s %s\n",
280 _mesa_lookup_enum_by_nr(modeRGB
),
281 _mesa_lookup_enum_by_nr(modeA
));
283 if ( (modeRGB
!= modeA
) && !ctx
->Extensions
.EXT_blend_equation_separate
) {
284 _mesa_error(ctx
, GL_INVALID_OPERATION
,
285 "glBlendEquationSeparateEXT not supported by driver");
289 if ( ! _mesa_validate_blend_equation( ctx
, modeRGB
, GL_TRUE
) ) {
290 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeRGB)");
294 if ( ! _mesa_validate_blend_equation( ctx
, modeA
, GL_TRUE
) ) {
295 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeA)");
300 if ( (ctx
->Color
.BlendEquationRGB
== modeRGB
) &&
301 (ctx
->Color
.BlendEquationA
== modeA
) )
304 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
305 ctx
->Color
.BlendEquationRGB
= modeRGB
;
306 ctx
->Color
.BlendEquationA
= modeA
;
308 if (ctx
->Driver
.BlendEquationSeparate
)
309 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, modeRGB
, modeA
);
315 * Set the blending color.
317 * \param red red color component.
318 * \param green green color component.
319 * \param blue blue color component.
320 * \param alpha alpha color component.
322 * \sa glBlendColor().
324 * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
325 * change, flushes the vertices and notifies the driver via
326 * dd_function_table::BlendColor callback.
329 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
332 GET_CURRENT_CONTEXT(ctx
);
333 ASSERT_OUTSIDE_BEGIN_END(ctx
);
335 tmp
[0] = CLAMP( red
, 0.0F
, 1.0F
);
336 tmp
[1] = CLAMP( green
, 0.0F
, 1.0F
);
337 tmp
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
338 tmp
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
340 if (TEST_EQ_4V(tmp
, ctx
->Color
.BlendColor
))
343 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
344 COPY_4FV( ctx
->Color
.BlendColor
, tmp
);
346 if (ctx
->Driver
.BlendColor
)
347 (*ctx
->Driver
.BlendColor
)(ctx
, tmp
);
352 * Specify the alpha test function.
354 * \param func alpha comparison function.
355 * \param ref reference value.
357 * Verifies the parameters and updates gl_colorbuffer_attrib.
358 * On a change, flushes the vertices and notifies the driver via
359 * dd_function_table::AlphaFunc callback.
362 _mesa_AlphaFunc( GLenum func
, GLclampf ref
)
364 GET_CURRENT_CONTEXT(ctx
);
365 ASSERT_OUTSIDE_BEGIN_END(ctx
);
376 ref
= CLAMP(ref
, 0.0F
, 1.0F
);
378 if (ctx
->Color
.AlphaFunc
== func
&& ctx
->Color
.AlphaRef
== ref
)
379 return; /* no change */
381 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
382 ctx
->Color
.AlphaFunc
= func
;
383 ctx
->Color
.AlphaRef
= ref
;
385 if (ctx
->Driver
.AlphaFunc
)
386 ctx
->Driver
.AlphaFunc(ctx
, func
, ref
);
390 _mesa_error( ctx
, GL_INVALID_ENUM
, "glAlphaFunc(func)" );
397 * Specify a logic pixel operation for color index rendering.
399 * \param opcode operation.
401 * Verifies that \p opcode is a valid enum and updates
402 gl_colorbuffer_attrib::LogicOp.
403 * On a change, flushes the vertices and notifies the driver via the
404 * dd_function_table::LogicOpcode callback.
407 _mesa_LogicOp( GLenum opcode
)
409 GET_CURRENT_CONTEXT(ctx
);
410 ASSERT_OUTSIDE_BEGIN_END(ctx
);
416 case GL_COPY_INVERTED
:
426 case GL_AND_INVERTED
:
431 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLogicOp" );
435 if (ctx
->Color
.LogicOp
== opcode
)
438 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
439 ctx
->Color
.LogicOp
= opcode
;
441 if (ctx
->Driver
.LogicOpcode
)
442 ctx
->Driver
.LogicOpcode( ctx
, opcode
);
447 _mesa_IndexMask( GLuint mask
)
449 GET_CURRENT_CONTEXT(ctx
);
450 ASSERT_OUTSIDE_BEGIN_END(ctx
);
452 if (ctx
->Color
.IndexMask
== mask
)
455 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
456 ctx
->Color
.IndexMask
= mask
;
462 * Enable or disable writing of frame buffer color components.
464 * \param red whether to mask writing of the red color component.
465 * \param green whether to mask writing of the green color component.
466 * \param blue whether to mask writing of the blue color component.
467 * \param alpha whether to mask writing of the alpha color component.
471 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
472 * change, flushes the vertices and notifies the driver via the
473 * dd_function_table::ColorMask callback.
476 _mesa_ColorMask( GLboolean red
, GLboolean green
,
477 GLboolean blue
, GLboolean alpha
)
479 GET_CURRENT_CONTEXT(ctx
);
483 ASSERT_OUTSIDE_BEGIN_END(ctx
);
485 if (MESA_VERBOSE
& VERBOSE_API
)
486 _mesa_debug(ctx
, "glColorMask %d %d %d %d\n", red
, green
, blue
, alpha
);
488 /* Shouldn't have any information about channel depth in core mesa
489 * -- should probably store these as the native booleans:
491 tmp
[RCOMP
] = red
? 0xff : 0x0;
492 tmp
[GCOMP
] = green
? 0xff : 0x0;
493 tmp
[BCOMP
] = blue
? 0xff : 0x0;
494 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
497 for (i
= 0; i
< ctx
->Const
.MaxDrawBuffers
; i
++) {
498 if (!TEST_EQ_4V(tmp
, ctx
->Color
.ColorMask
[i
])) {
500 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
503 COPY_4UBV(ctx
->Color
.ColorMask
[i
], tmp
);
507 if (ctx
->Driver
.ColorMask
)
508 ctx
->Driver
.ColorMask( ctx
, red
, green
, blue
, alpha
);
513 * For GL_EXT_draw_buffers2 and GL3
516 _mesa_ColorMaskIndexed( GLuint buf
, GLboolean red
, GLboolean green
,
517 GLboolean blue
, GLboolean alpha
)
520 GET_CURRENT_CONTEXT(ctx
);
521 ASSERT_OUTSIDE_BEGIN_END(ctx
);
523 if (MESA_VERBOSE
& VERBOSE_API
)
524 _mesa_debug(ctx
, "glColorMaskIndexed %u %d %d %d %d\n",
525 buf
, red
, green
, blue
, alpha
);
527 if (buf
>= ctx
->Const
.MaxDrawBuffers
) {
528 _mesa_error(ctx
, GL_INVALID_VALUE
, "glColorMaskIndexed(buf=%u)", buf
);
532 /* Shouldn't have any information about channel depth in core mesa
533 * -- should probably store these as the native booleans:
535 tmp
[RCOMP
] = red
? 0xff : 0x0;
536 tmp
[GCOMP
] = green
? 0xff : 0x0;
537 tmp
[BCOMP
] = blue
? 0xff : 0x0;
538 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
540 if (TEST_EQ_4V(tmp
, ctx
->Color
.ColorMask
[buf
]))
543 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
544 COPY_4UBV(ctx
->Color
.ColorMask
[buf
], tmp
);
546 if (ctx
->Driver
.ColorMaskIndexed
)
547 ctx
->Driver
.ColorMaskIndexed(ctx
, buf
, red
, green
, blue
, alpha
);
551 extern void GLAPIENTRY
552 _mesa_ClampColorARB(GLenum target
, GLenum clamp
)
554 GET_CURRENT_CONTEXT(ctx
);
556 ASSERT_OUTSIDE_BEGIN_END(ctx
);
558 if (clamp
!= GL_TRUE
&& clamp
!= GL_FALSE
&& clamp
!= GL_FIXED_ONLY_ARB
) {
559 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClampColorARB(clamp)");
564 case GL_CLAMP_VERTEX_COLOR_ARB
:
565 ctx
->Light
.ClampVertexColor
= clamp
;
567 case GL_CLAMP_FRAGMENT_COLOR_ARB
:
568 ctx
->Color
.ClampFragmentColor
= clamp
;
570 case GL_CLAMP_READ_COLOR_ARB
:
571 ctx
->Color
.ClampReadColor
= clamp
;
574 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClampColorARB(target)");
582 /**********************************************************************/
583 /** \name Initialization */
587 * Initialization of the context's Color attribute group.
589 * \param ctx GL context.
591 * Initializes the related fields in the context color attribute group,
592 * __GLcontextRec::Color.
594 void _mesa_init_color( GLcontext
* ctx
)
596 /* Color buffer group */
597 ctx
->Color
.IndexMask
= ~0u;
598 memset(ctx
->Color
.ColorMask
, 0xff, sizeof(ctx
->Color
.ColorMask
));
599 ctx
->Color
.ClearIndex
= 0;
600 ASSIGN_4V( ctx
->Color
.ClearColor
, 0, 0, 0, 0 );
601 ctx
->Color
.AlphaEnabled
= GL_FALSE
;
602 ctx
->Color
.AlphaFunc
= GL_ALWAYS
;
603 ctx
->Color
.AlphaRef
= 0;
604 ctx
->Color
.BlendEnabled
= 0x0;
605 ctx
->Color
.BlendSrcRGB
= GL_ONE
;
606 ctx
->Color
.BlendDstRGB
= GL_ZERO
;
607 ctx
->Color
.BlendSrcA
= GL_ONE
;
608 ctx
->Color
.BlendDstA
= GL_ZERO
;
609 ctx
->Color
.BlendEquationRGB
= GL_FUNC_ADD
;
610 ctx
->Color
.BlendEquationA
= GL_FUNC_ADD
;
611 ASSIGN_4V( ctx
->Color
.BlendColor
, 0.0, 0.0, 0.0, 0.0 );
612 ctx
->Color
.IndexLogicOpEnabled
= GL_FALSE
;
613 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
614 ctx
->Color
._LogicOpEnabled
= GL_FALSE
;
615 ctx
->Color
.LogicOp
= GL_COPY
;
616 ctx
->Color
.DitherFlag
= GL_TRUE
;
618 if (ctx
->Visual
.doubleBufferMode
) {
619 ctx
->Color
.DrawBuffer
[0] = GL_BACK
;
622 ctx
->Color
.DrawBuffer
[0] = GL_FRONT
;
625 ctx
->Color
.ClampFragmentColor
= GL_FIXED_ONLY_ARB
;
626 ctx
->Color
.ClampReadColor
= GL_FIXED_ONLY_ARB
;