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.
49 * Verifies the parameters and updates gl_colorbuffer_attrib. On a change,
50 * flushes the vertices and notifies the driver via
51 * dd_function_table::BlendFunc callback.
54 _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
57 GET_CURRENT_CONTEXT(ctx
);
58 ASSERT_OUTSIDE_BEGIN_END(ctx
);
60 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
61 _mesa_debug(ctx
, "glBlendFunc %s %s\n",
62 _mesa_lookup_enum_by_nr(sfactor
),
63 _mesa_lookup_enum_by_nr(dfactor
));
67 case GL_ONE_MINUS_SRC_COLOR
:
68 if (!ctx
->Extensions
.NV_blend_square
) {
69 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
76 case GL_ONE_MINUS_DST_COLOR
:
78 case GL_ONE_MINUS_SRC_ALPHA
:
80 case GL_ONE_MINUS_DST_ALPHA
:
81 case GL_SRC_ALPHA_SATURATE
:
82 case GL_CONSTANT_COLOR
:
83 case GL_ONE_MINUS_CONSTANT_COLOR
:
84 case GL_CONSTANT_ALPHA
:
85 case GL_ONE_MINUS_CONSTANT_ALPHA
:
88 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
94 case GL_ONE_MINUS_DST_COLOR
:
95 if (!ctx
->Extensions
.NV_blend_square
) {
96 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
103 case GL_ONE_MINUS_SRC_COLOR
:
105 case GL_ONE_MINUS_SRC_ALPHA
:
107 case GL_ONE_MINUS_DST_ALPHA
:
108 case GL_CONSTANT_COLOR
:
109 case GL_ONE_MINUS_CONSTANT_COLOR
:
110 case GL_CONSTANT_ALPHA
:
111 case GL_ONE_MINUS_CONSTANT_ALPHA
:
114 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
118 if (ctx
->Color
.BlendDstRGB
== dfactor
&&
119 ctx
->Color
.BlendSrcRGB
== sfactor
&&
120 ctx
->Color
.BlendDstA
== dfactor
&&
121 ctx
->Color
.BlendSrcA
== sfactor
)
124 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
125 ctx
->Color
.BlendDstRGB
= ctx
->Color
.BlendDstA
= dfactor
;
126 ctx
->Color
.BlendSrcRGB
= ctx
->Color
.BlendSrcA
= sfactor
;
128 if (ctx
->Driver
.BlendFunc
)
129 ctx
->Driver
.BlendFunc( ctx
, sfactor
, dfactor
);
136 * Process GL_EXT_blend_func_separate().
138 * \param sfactorRGB RGB source factor operator.
139 * \param dfactorRGB RGB destination factor operator.
140 * \param sfactorA alpha source factor operator.
141 * \param dfactorA alpha destination factor operator.
143 * Verifies the parameters and updates gl_colorbuffer_attrib.
144 * On a change, flush the vertices and notify the driver via
145 * dd_function_table::BlendFuncSeparate.
148 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
149 GLenum sfactorA
, GLenum dfactorA
)
151 GET_CURRENT_CONTEXT(ctx
);
152 ASSERT_OUTSIDE_BEGIN_END(ctx
);
154 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
155 _mesa_debug(ctx
, "glBlendFuncSeparate %s %s %s %s\n",
156 _mesa_lookup_enum_by_nr(sfactorRGB
),
157 _mesa_lookup_enum_by_nr(dfactorRGB
),
158 _mesa_lookup_enum_by_nr(sfactorA
),
159 _mesa_lookup_enum_by_nr(dfactorA
));
161 switch (sfactorRGB
) {
163 case GL_ONE_MINUS_SRC_COLOR
:
164 if (!ctx
->Extensions
.NV_blend_square
) {
165 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)");
172 case GL_ONE_MINUS_DST_COLOR
:
174 case GL_ONE_MINUS_SRC_ALPHA
:
176 case GL_ONE_MINUS_DST_ALPHA
:
177 case GL_SRC_ALPHA_SATURATE
:
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
, "glBlendFuncSeparate(sfactorRGB)");
188 switch (dfactorRGB
) {
190 case GL_ONE_MINUS_DST_COLOR
:
191 if (!ctx
->Extensions
.NV_blend_square
) {
192 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
199 case GL_ONE_MINUS_SRC_COLOR
:
201 case GL_ONE_MINUS_SRC_ALPHA
:
203 case GL_ONE_MINUS_DST_ALPHA
:
204 case GL_CONSTANT_COLOR
:
205 case GL_ONE_MINUS_CONSTANT_COLOR
:
206 case GL_CONSTANT_ALPHA
:
207 case GL_ONE_MINUS_CONSTANT_ALPHA
:
210 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
216 case GL_ONE_MINUS_SRC_COLOR
:
217 if (!ctx
->Extensions
.NV_blend_square
) {
218 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
225 case GL_ONE_MINUS_DST_COLOR
:
227 case GL_ONE_MINUS_SRC_ALPHA
:
229 case GL_ONE_MINUS_DST_ALPHA
:
230 case GL_SRC_ALPHA_SATURATE
:
231 case GL_CONSTANT_COLOR
:
232 case GL_ONE_MINUS_CONSTANT_COLOR
:
233 case GL_CONSTANT_ALPHA
:
234 case GL_ONE_MINUS_CONSTANT_ALPHA
:
237 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
243 case GL_ONE_MINUS_DST_COLOR
:
244 if (!ctx
->Extensions
.NV_blend_square
) {
245 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)");
252 case GL_ONE_MINUS_SRC_COLOR
:
254 case GL_ONE_MINUS_SRC_ALPHA
:
256 case GL_ONE_MINUS_DST_ALPHA
:
257 case GL_CONSTANT_COLOR
:
258 case GL_ONE_MINUS_CONSTANT_COLOR
:
259 case GL_CONSTANT_ALPHA
:
260 case GL_ONE_MINUS_CONSTANT_ALPHA
:
263 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)" );
267 if (ctx
->Color
.BlendSrcRGB
== sfactorRGB
&&
268 ctx
->Color
.BlendDstRGB
== dfactorRGB
&&
269 ctx
->Color
.BlendSrcA
== sfactorA
&&
270 ctx
->Color
.BlendDstA
== dfactorA
)
273 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
275 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
276 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
277 ctx
->Color
.BlendSrcA
= sfactorA
;
278 ctx
->Color
.BlendDstA
= dfactorA
;
280 if (ctx
->Driver
.BlendFuncSeparate
) {
281 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
282 sfactorA
, dfactorA
);
287 /* This is really an extension function! */
289 _mesa_BlendEquation( GLenum mode
)
291 GET_CURRENT_CONTEXT(ctx
);
292 ASSERT_OUTSIDE_BEGIN_END(ctx
);
294 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
295 _mesa_debug(ctx
, "glBlendEquation %s\n",
296 _mesa_lookup_enum_by_nr(mode
));
299 case GL_FUNC_ADD_EXT
:
303 if (!ctx
->Extensions
.EXT_blend_minmax
&&
304 !ctx
->Extensions
.ARB_imaging
) {
305 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
310 if (!ctx
->Extensions
.EXT_blend_logic_op
) {
311 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
315 case GL_FUNC_SUBTRACT_EXT
:
316 case GL_FUNC_REVERSE_SUBTRACT_EXT
:
317 if (!ctx
->Extensions
.EXT_blend_subtract
&&
318 !ctx
->Extensions
.ARB_imaging
) {
319 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
324 _mesa_error( ctx
, GL_INVALID_ENUM
, "glBlendEquation" );
328 if (ctx
->Color
.BlendEquation
== mode
)
331 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
332 ctx
->Color
.BlendEquation
= mode
;
334 /* This is needed to support 1.1's RGB logic ops AND
335 * 1.0's blending logicops.
337 ctx
->Color
.ColorLogicOpEnabled
= (mode
==GL_LOGIC_OP
&&
338 ctx
->Color
.BlendEnabled
);
340 if (ctx
->Driver
.BlendEquation
)
341 (*ctx
->Driver
.BlendEquation
)( ctx
, mode
);
348 * Set the blending color.
350 * \param red red color component.
351 * \param green green color component.
352 * \param blue blue color component.
353 * \param alpha alpha color component.
355 * \sa glBlendColor().
357 * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
358 * change, flushes the vertices and notifies the driver via
359 * dd_function_table::BlendColor callback.
362 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
365 GET_CURRENT_CONTEXT(ctx
);
366 ASSERT_OUTSIDE_BEGIN_END(ctx
);
368 tmp
[0] = CLAMP( red
, 0.0F
, 1.0F
);
369 tmp
[1] = CLAMP( green
, 0.0F
, 1.0F
);
370 tmp
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
371 tmp
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
373 if (TEST_EQ_4V(tmp
, ctx
->Color
.BlendColor
))
376 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
377 COPY_4FV( ctx
->Color
.BlendColor
, tmp
);
379 if (ctx
->Driver
.BlendColor
)
380 (*ctx
->Driver
.BlendColor
)(ctx
, tmp
);
385 * Specify the alpha test function.
387 * \param func alpha comparison function.
388 * \param ref reference value.
390 * Verifies the parameters and updates gl_colorbuffer_attrib.
391 * On a change, flushes the vertices and notifies the driver via
392 * dd_function_table::AlphaFunc callback.
395 _mesa_AlphaFunc( GLenum func
, GLclampf ref
)
397 GET_CURRENT_CONTEXT(ctx
);
398 ASSERT_OUTSIDE_BEGIN_END(ctx
);
409 ref
= CLAMP(ref
, 0.0F
, 1.0F
);
411 if (ctx
->Color
.AlphaFunc
== func
&& ctx
->Color
.AlphaRef
== ref
)
412 return; /* no change */
414 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
415 ctx
->Color
.AlphaFunc
= func
;
416 ctx
->Color
.AlphaRef
= ref
;
418 if (ctx
->Driver
.AlphaFunc
)
419 ctx
->Driver
.AlphaFunc(ctx
, func
, ref
);
423 _mesa_error( ctx
, GL_INVALID_ENUM
, "glAlphaFunc(func)" );
430 * Specify a logic pixel operation for color index rendering.
432 * \param opcode operation.
434 * Verifies that \p opcode is a valid enum and updates
435 gl_colorbuffer_attrib::LogicOp.
436 * On a change, flushes the vertices and notifies the driver via the
437 * dd_function_table::LogicOpcode callback.
440 _mesa_LogicOp( GLenum opcode
)
442 GET_CURRENT_CONTEXT(ctx
);
443 ASSERT_OUTSIDE_BEGIN_END(ctx
);
449 case GL_COPY_INVERTED
:
459 case GL_AND_INVERTED
:
464 _mesa_error( ctx
, GL_INVALID_ENUM
, "glLogicOp" );
468 if (ctx
->Color
.LogicOp
== opcode
)
471 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
472 ctx
->Color
.LogicOp
= opcode
;
474 if (ctx
->Driver
.LogicOpcode
)
475 ctx
->Driver
.LogicOpcode( ctx
, opcode
);
480 _mesa_IndexMask( GLuint mask
)
482 GET_CURRENT_CONTEXT(ctx
);
483 ASSERT_OUTSIDE_BEGIN_END(ctx
);
485 if (ctx
->Color
.IndexMask
== mask
)
488 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
489 ctx
->Color
.IndexMask
= mask
;
491 if (ctx
->Driver
.IndexMask
)
492 ctx
->Driver
.IndexMask( ctx
, mask
);
498 * Enable or disable writing of frame buffer color components.
500 * \param red whether to mask writing of the red color component.
501 * \param green whether to mask writing of the green color component.
502 * \param blue whether to mask writing of the blue color component.
503 * \param alpha whether to mask writing of the alpha color component.
507 * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
508 * change, flushes the vertices and notifies the driver via the
509 * dd_function_table::ColorMask callback.
512 _mesa_ColorMask( GLboolean red
, GLboolean green
,
513 GLboolean blue
, GLboolean alpha
)
515 GET_CURRENT_CONTEXT(ctx
);
517 ASSERT_OUTSIDE_BEGIN_END(ctx
);
519 if (MESA_VERBOSE
& VERBOSE_API
)
520 _mesa_debug(ctx
, "glColorMask %d %d %d %d\n", red
, green
, blue
, alpha
);
522 /* Shouldn't have any information about channel depth in core mesa
523 * -- should probably store these as the native booleans:
525 tmp
[RCOMP
] = red
? 0xff : 0x0;
526 tmp
[GCOMP
] = green
? 0xff : 0x0;
527 tmp
[BCOMP
] = blue
? 0xff : 0x0;
528 tmp
[ACOMP
] = alpha
? 0xff : 0x0;
530 if (TEST_EQ_4UBV(tmp
, ctx
->Color
.ColorMask
))
533 FLUSH_VERTICES(ctx
, _NEW_COLOR
);
534 COPY_4UBV(ctx
->Color
.ColorMask
, tmp
);
536 if (ctx
->Driver
.ColorMask
)
537 ctx
->Driver
.ColorMask( ctx
, red
, green
, blue
, alpha
);
540 /**********************************************************************/
541 /** \name Initialization */
545 * Initialization of the context color data.
547 * \param ctx GL context.
549 * Initializes the related fields in the context color attribute group,
550 * __GLcontextRec::Color.
552 void _mesa_init_color( GLcontext
* ctx
)
554 /* Color buffer group */
555 ctx
->Color
.IndexMask
= 0xffffffff;
556 ctx
->Color
.ColorMask
[0] = 0xff;
557 ctx
->Color
.ColorMask
[1] = 0xff;
558 ctx
->Color
.ColorMask
[2] = 0xff;
559 ctx
->Color
.ColorMask
[3] = 0xff;
560 ctx
->Color
.ClearIndex
= 0;
561 ASSIGN_4V( ctx
->Color
.ClearColor
, 0, 0, 0, 0 );
562 ctx
->Color
.DrawBuffer
= GL_FRONT
;
563 ctx
->Color
.AlphaEnabled
= GL_FALSE
;
564 ctx
->Color
.AlphaFunc
= GL_ALWAYS
;
565 ctx
->Color
.AlphaRef
= 0;
566 ctx
->Color
.BlendEnabled
= GL_FALSE
;
567 ctx
->Color
.BlendSrcRGB
= GL_ONE
;
568 ctx
->Color
.BlendDstRGB
= GL_ZERO
;
569 ctx
->Color
.BlendSrcA
= GL_ONE
;
570 ctx
->Color
.BlendDstA
= GL_ZERO
;
571 ctx
->Color
.BlendEquation
= GL_FUNC_ADD_EXT
;
572 ASSIGN_4V( ctx
->Color
.BlendColor
, 0.0, 0.0, 0.0, 0.0 );
573 ctx
->Color
.IndexLogicOpEnabled
= GL_FALSE
;
574 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
575 ctx
->Color
.LogicOp
= GL_COPY
;
576 ctx
->Color
.DitherFlag
= GL_TRUE
;
578 if (ctx
->Visual
.doubleBufferMode
) {
579 ctx
->Color
.DrawBuffer
= GL_BACK
;
580 ctx
->Color
._DrawDestMask
= BACK_LEFT_BIT
;
583 ctx
->Color
.DrawBuffer
= GL_FRONT
;
584 ctx
->Color
._DrawDestMask
= FRONT_LEFT_BIT
;