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
&&
219 !ctx
->Extensions
.ARB_imaging
) {
223 /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
226 if (!ctx
->Extensions
.EXT_blend_logic_op
|| is_separate
) {
230 case GL_FUNC_SUBTRACT
:
231 case GL_FUNC_REVERSE_SUBTRACT
:
232 if (!ctx
->Extensions
.EXT_blend_subtract
&&
233 !ctx
->Extensions
.ARB_imaging
) {
245 /* This is really an extension function! */
247 _mesa_BlendEquation( GLenum mode
)
249 GET_CURRENT_CONTEXT(ctx
);
250 ASSERT_OUTSIDE_BEGIN_END(ctx
);
252 if (MESA_VERBOSE
& VERBOSE_API
)
253 _mesa_debug(ctx
, "glBlendEquation %s\n",
254 _mesa_lookup_enum_by_nr(mode
));
256 if ( ! _mesa_validate_blend_equation( ctx
, mode
, GL_FALSE
) ) {
257 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
261 if ( (ctx
->Color
.BlendEquationRGB
== mode
) &&
262 (ctx
->Color
.BlendEquationA
== mode
) )
265 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
266 ctx
->Color
.BlendEquationRGB
= mode
;
267 ctx
->Color
.BlendEquationA
= mode
;
269 if (ctx
->Driver
.BlendEquationSeparate
)
270 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, mode
, mode
);
275 _mesa_BlendEquationSeparateEXT( GLenum modeRGB
, GLenum modeA
)
277 GET_CURRENT_CONTEXT(ctx
);
278 ASSERT_OUTSIDE_BEGIN_END(ctx
);
280 if (MESA_VERBOSE
& VERBOSE_API
)
281 _mesa_debug(ctx
, "glBlendEquationSeparateEXT %s %s\n",
282 _mesa_lookup_enum_by_nr(modeRGB
),
283 _mesa_lookup_enum_by_nr(modeA
));
285 if ( (modeRGB
!= modeA
) && !ctx
->Extensions
.EXT_blend_equation_separate
) {
286 _mesa_error(ctx
, GL_INVALID_OPERATION
,
287 "glBlendEquationSeparateEXT not supported by driver");
291 if ( ! _mesa_validate_blend_equation( ctx
, modeRGB
, GL_TRUE
) ) {
292 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeRGB)");
296 if ( ! _mesa_validate_blend_equation( ctx
, modeA
, GL_TRUE
) ) {
297 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquationSeparateEXT(modeA)");
302 if ( (ctx
->Color
.BlendEquationRGB
== modeRGB
) &&
303 (ctx
->Color
.BlendEquationA
== modeA
) )
306 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
307 ctx
->Color
.BlendEquationRGB
= modeRGB
;
308 ctx
->Color
.BlendEquationA
= modeA
;
310 if (ctx
->Driver
.BlendEquationSeparate
)
311 (*ctx
->Driver
.BlendEquationSeparate
)( ctx
, modeRGB
, modeA
);
317 * Set the blending color.
319 * \param red red color component.
320 * \param green green color component.
321 * \param blue blue color component.
322 * \param alpha alpha color component.
324 * \sa glBlendColor().
326 * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
327 * change, flushes the vertices and notifies the driver via
328 * dd_function_table::BlendColor callback.
331 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
334 GET_CURRENT_CONTEXT(ctx
);
335 ASSERT_OUTSIDE_BEGIN_END(ctx
);
337 tmp
[0] = CLAMP( red
, 0.0F
, 1.0F
);
338 tmp
[1] = CLAMP( green
, 0.0F
, 1.0F
);
339 tmp
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
340 tmp
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
342 if (TEST_EQ_4V(tmp
, ctx
->Color
.BlendColor
))
345 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
346 COPY_4FV( ctx
->Color
.BlendColor
, tmp
);
348 if (ctx
->Driver
.BlendColor
)
349 (*ctx
->Driver
.BlendColor
)(ctx
, tmp
);
354 * Specify the alpha test function.
356 * \param func alpha comparison function.
357 * \param ref reference value.
359 * Verifies the parameters and updates gl_colorbuffer_attrib.
360 * On a change, flushes the vertices and notifies the driver via
361 * dd_function_table::AlphaFunc callback.
364 _mesa_AlphaFunc( GLenum func
, GLclampf ref
)
366 GET_CURRENT_CONTEXT(ctx
);
367 ASSERT_OUTSIDE_BEGIN_END(ctx
);
378 ref
= CLAMP(ref
, 0.0F
, 1.0F
);
380 if (ctx
->Color
.AlphaFunc
== func
&& ctx
->Color
.AlphaRef
== ref
)
381 return; /* no change */
383 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
384 ctx
->Color
.AlphaFunc
= func
;
385 ctx
->Color
.AlphaRef
= ref
;
387 if (ctx
->Driver
.AlphaFunc
)
388 ctx
->Driver
.AlphaFunc(ctx
, func
, ref
);
392 _mesa_error( ctx
, GL_INVALID_ENUM
, "glAlphaFunc(func)" );
399 * Specify a logic pixel operation for color index rendering.
401 * \param opcode operation.
403 * Verifies that \p opcode is a valid enum and updates
404 gl_colorbuffer_attrib::LogicOp.
405 * On a change, flushes the vertices and notifies the driver via the
406 * dd_function_table::LogicOpcode callback.
409 _mesa_LogicOp( GLenum opcode
)
411 GET_CURRENT_CONTEXT(ctx
);
412 ASSERT_OUTSIDE_BEGIN_END(ctx
);
418 case GL_COPY_INVERTED
:
428 case GL_AND_INVERTED
:
433 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLogicOp" );
437 if (ctx
->Color
.LogicOp
== opcode
)
440 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
441 ctx
->Color
.LogicOp
= opcode
;
443 if (ctx
->Driver
.LogicOpcode
)
444 ctx
->Driver
.LogicOpcode( ctx
, opcode
);
449 _mesa_IndexMask( GLuint mask
)
451 GET_CURRENT_CONTEXT(ctx
);
452 ASSERT_OUTSIDE_BEGIN_END(ctx
);
454 if (ctx
->Color
.IndexMask
== mask
)
457 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
458 ctx
->Color
.IndexMask
= mask
;
460 if (ctx
->Driver
.IndexMask
)
461 ctx
->Driver
.IndexMask( ctx
, mask
);
467 * Enable or disable writing of frame buffer color components.
469 * \param red whether to mask writing of the red color component.
470 * \param green whether to mask writing of the green color component.
471 * \param blue whether to mask writing of the blue color component.
472 * \param alpha whether to mask writing of the alpha color component.
476 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
477 * change, flushes the vertices and notifies the driver via the
478 * dd_function_table::ColorMask callback.
481 _mesa_ColorMask( GLboolean red
, GLboolean green
,
482 GLboolean blue
, GLboolean alpha
)
484 GET_CURRENT_CONTEXT(ctx
);
488 ASSERT_OUTSIDE_BEGIN_END(ctx
);
490 if (MESA_VERBOSE
& VERBOSE_API
)
491 _mesa_debug(ctx
, "glColorMask %d %d %d %d\n", red
, green
, blue
, alpha
);
493 /* Shouldn't have any information about channel depth in core mesa
494 * -- should probably store these as the native booleans:
496 tmp
[RCOMP
] = red
? 0xff : 0x0;
497 tmp
[GCOMP
] = green
? 0xff : 0x0;
498 tmp
[BCOMP
] = blue
? 0xff : 0x0;
499 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
502 for (i
= 0; i
< ctx
->Const
.MaxDrawBuffers
; i
++) {
503 if (!TEST_EQ_4V(tmp
, ctx
->Color
.ColorMask
[i
])) {
505 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
508 COPY_4UBV(ctx
->Color
.ColorMask
[i
], tmp
);
512 if (ctx
->Driver
.ColorMask
)
513 ctx
->Driver
.ColorMask( ctx
, red
, green
, blue
, alpha
);
518 * For GL_EXT_draw_buffers2 and GL3
521 _mesa_ColorMaskIndexed( GLuint buf
, GLboolean red
, GLboolean green
,
522 GLboolean blue
, GLboolean alpha
)
525 GET_CURRENT_CONTEXT(ctx
);
526 ASSERT_OUTSIDE_BEGIN_END(ctx
);
528 if (MESA_VERBOSE
& VERBOSE_API
)
529 _mesa_debug(ctx
, "glColorMaskIndexed %u %d %d %d %d\n",
530 buf
, red
, green
, blue
, alpha
);
532 if (buf
>= ctx
->Const
.MaxDrawBuffers
) {
533 _mesa_error(ctx
, GL_INVALID_VALUE
, "glColorMaskIndexed(buf=%u)", buf
);
537 /* Shouldn't have any information about channel depth in core mesa
538 * -- should probably store these as the native booleans:
540 tmp
[RCOMP
] = red
? 0xff : 0x0;
541 tmp
[GCOMP
] = green
? 0xff : 0x0;
542 tmp
[BCOMP
] = blue
? 0xff : 0x0;
543 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
545 if (TEST_EQ_4V(tmp
, ctx
->Color
.ColorMask
[buf
]))
548 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
549 COPY_4UBV(ctx
->Color
.ColorMask
[buf
], tmp
);
551 if (ctx
->Driver
.ColorMaskIndexed
)
552 ctx
->Driver
.ColorMaskIndexed(ctx
, buf
, red
, green
, blue
, alpha
);
556 extern void GLAPIENTRY
557 _mesa_ClampColorARB(GLenum target
, GLenum clamp
)
559 GET_CURRENT_CONTEXT(ctx
);
561 ASSERT_OUTSIDE_BEGIN_END(ctx
);
563 if (clamp
!= GL_TRUE
&& clamp
!= GL_FALSE
&& clamp
!= GL_FIXED_ONLY_ARB
) {
564 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClampColorARB(clamp)");
569 case GL_CLAMP_VERTEX_COLOR_ARB
:
570 ctx
->Light
.ClampVertexColor
= clamp
;
572 case GL_CLAMP_FRAGMENT_COLOR_ARB
:
573 ctx
->Color
.ClampFragmentColor
= clamp
;
575 case GL_CLAMP_READ_COLOR_ARB
:
576 ctx
->Color
.ClampReadColor
= clamp
;
579 _mesa_error(ctx
, GL_INVALID_ENUM
, "glClampColorARB(target)");
587 /**********************************************************************/
588 /** \name Initialization */
592 * Initialization of the context's Color attribute group.
594 * \param ctx GL context.
596 * Initializes the related fields in the context color attribute group,
597 * __GLcontextRec::Color.
599 void _mesa_init_color( GLcontext
* ctx
)
601 /* Color buffer group */
602 ctx
->Color
.IndexMask
= ~0u;
603 memset(ctx
->Color
.ColorMask
, 0xff, sizeof(ctx
->Color
.ColorMask
));
604 ctx
->Color
.ClearIndex
= 0;
605 ASSIGN_4V( ctx
->Color
.ClearColor
, 0, 0, 0, 0 );
606 ctx
->Color
.AlphaEnabled
= GL_FALSE
;
607 ctx
->Color
.AlphaFunc
= GL_ALWAYS
;
608 ctx
->Color
.AlphaRef
= 0;
609 ctx
->Color
.BlendEnabled
= 0x0;
610 ctx
->Color
.BlendSrcRGB
= GL_ONE
;
611 ctx
->Color
.BlendDstRGB
= GL_ZERO
;
612 ctx
->Color
.BlendSrcA
= GL_ONE
;
613 ctx
->Color
.BlendDstA
= GL_ZERO
;
614 ctx
->Color
.BlendEquationRGB
= GL_FUNC_ADD
;
615 ctx
->Color
.BlendEquationA
= GL_FUNC_ADD
;
616 ASSIGN_4V( ctx
->Color
.BlendColor
, 0.0, 0.0, 0.0, 0.0 );
617 ctx
->Color
.IndexLogicOpEnabled
= GL_FALSE
;
618 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
619 ctx
->Color
._LogicOpEnabled
= GL_FALSE
;
620 ctx
->Color
.LogicOp
= GL_COPY
;
621 ctx
->Color
.DitherFlag
= GL_TRUE
;
623 if (ctx
->Visual
.doubleBufferMode
) {
624 ctx
->Color
.DrawBuffer
[0] = GL_BACK
;
627 ctx
->Color
.DrawBuffer
[0] = GL_FRONT
;
630 ctx
->Color
.ClampFragmentColor
= GL_FIXED_ONLY_ARB
;
631 ctx
->Color
.ClampReadColor
= GL_FIXED_ONLY_ARB
;