1 /* $Id: blend.c,v 1.23 2000/10/30 16:32:43 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45 _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
47 GET_CURRENT_CONTEXT(ctx
);
48 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendFunc");
50 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
51 fprintf(stderr
, "glBlendFunc %s %s\n",
52 gl_lookup_enum_by_nr(sfactor
),
53 gl_lookup_enum_by_nr(dfactor
));
57 case GL_ONE_MINUS_SRC_COLOR
:
58 if (!ctx
->Extensions
.NV_blend_square
) {
59 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
66 case GL_ONE_MINUS_DST_COLOR
:
68 case GL_ONE_MINUS_SRC_ALPHA
:
70 case GL_ONE_MINUS_DST_ALPHA
:
71 case GL_SRC_ALPHA_SATURATE
:
72 case GL_CONSTANT_COLOR
:
73 case GL_ONE_MINUS_CONSTANT_COLOR
:
74 case GL_CONSTANT_ALPHA
:
75 case GL_ONE_MINUS_CONSTANT_ALPHA
:
76 ctx
->Color
.BlendSrcRGB
= ctx
->Color
.BlendSrcA
= sfactor
;
79 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
85 case GL_ONE_MINUS_DST_COLOR
:
86 if (!ctx
->Extensions
.NV_blend_square
) {
87 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
94 case GL_ONE_MINUS_SRC_COLOR
:
96 case GL_ONE_MINUS_SRC_ALPHA
:
98 case GL_ONE_MINUS_DST_ALPHA
:
99 case GL_CONSTANT_COLOR
:
100 case GL_ONE_MINUS_CONSTANT_COLOR
:
101 case GL_CONSTANT_ALPHA
:
102 case GL_ONE_MINUS_CONSTANT_ALPHA
:
103 ctx
->Color
.BlendDstRGB
= ctx
->Color
.BlendDstA
= dfactor
;
106 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
110 if (ctx
->Driver
.BlendFunc
) {
111 (*ctx
->Driver
.BlendFunc
)( ctx
, sfactor
, dfactor
);
114 ctx
->Color
.BlendFunc
= NULL
;
115 ctx
->NewState
|= _NEW_COLOR
;
119 /* GL_EXT_blend_func_separate */
121 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
122 GLenum sfactorA
, GLenum dfactorA
)
124 GET_CURRENT_CONTEXT(ctx
);
125 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendFuncSeparate");
127 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
128 fprintf(stderr
, "glBlendFuncSeperate %s %s %s %s\n",
129 gl_lookup_enum_by_nr(sfactorRGB
),
130 gl_lookup_enum_by_nr(dfactorRGB
),
131 gl_lookup_enum_by_nr(sfactorA
),
132 gl_lookup_enum_by_nr(dfactorA
));
134 switch (sfactorRGB
) {
136 case GL_ONE_MINUS_SRC_COLOR
:
137 if (!ctx
->Extensions
.NV_blend_square
) {
138 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)");
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
:
155 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
158 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)");
162 switch (dfactorRGB
) {
164 case GL_ONE_MINUS_DST_COLOR
:
165 if (!ctx
->Extensions
.NV_blend_square
) {
166 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
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
:
182 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
185 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)");
191 case GL_ONE_MINUS_SRC_COLOR
:
192 if (!ctx
->Extensions
.NV_blend_square
) {
193 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
200 case GL_ONE_MINUS_DST_COLOR
:
202 case GL_ONE_MINUS_SRC_ALPHA
:
204 case GL_ONE_MINUS_DST_ALPHA
:
205 case GL_SRC_ALPHA_SATURATE
:
206 case GL_CONSTANT_COLOR
:
207 case GL_ONE_MINUS_CONSTANT_COLOR
:
208 case GL_CONSTANT_ALPHA
:
209 case GL_ONE_MINUS_CONSTANT_ALPHA
:
210 ctx
->Color
.BlendSrcA
= sfactorA
;
213 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)");
219 case GL_ONE_MINUS_DST_COLOR
:
220 if (!ctx
->Extensions
.NV_blend_square
) {
221 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)");
228 case GL_ONE_MINUS_SRC_COLOR
:
230 case GL_ONE_MINUS_SRC_ALPHA
:
232 case GL_ONE_MINUS_DST_ALPHA
:
233 case GL_CONSTANT_COLOR
:
234 case GL_ONE_MINUS_CONSTANT_COLOR
:
235 case GL_CONSTANT_ALPHA
:
236 case GL_ONE_MINUS_CONSTANT_ALPHA
:
237 ctx
->Color
.BlendDstA
= dfactorA
;
240 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)" );
244 ctx
->Color
.BlendFunc
= NULL
;
245 ctx
->NewState
|= _NEW_COLOR
;
247 if (ctx
->Driver
.BlendFuncSeparate
) {
248 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
249 sfactorA
, dfactorA
);
255 /* This is really an extension function! */
257 _mesa_BlendEquation( GLenum mode
)
259 GET_CURRENT_CONTEXT(ctx
);
260 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendEquation");
262 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
263 fprintf(stderr
, "glBlendEquation %s\n",
264 gl_lookup_enum_by_nr(mode
));
269 case GL_FUNC_ADD_EXT
:
270 if (ctx
->Extensions
.EXT_blend_minmax
) {
271 ctx
->Color
.BlendEquation
= mode
;
274 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
278 ctx
->Color
.BlendEquation
= mode
;
280 case GL_FUNC_SUBTRACT_EXT
:
281 case GL_FUNC_REVERSE_SUBTRACT_EXT
:
282 if (ctx
->Extensions
.EXT_blend_subtract
) {
283 ctx
->Color
.BlendEquation
= mode
;
286 gl_error(ctx
, GL_INVALID_ENUM
, "glBlendEquation");
291 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendEquation" );
295 /* This is needed to support 1.1's RGB logic ops AND
296 * 1.0's blending logicops.
298 if (mode
==GL_LOGIC_OP
&& ctx
->Color
.BlendEnabled
) {
299 ctx
->Color
.ColorLogicOpEnabled
= GL_TRUE
;
302 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
305 ctx
->Color
.BlendFunc
= NULL
;
306 ctx
->NewState
|= _NEW_COLOR
;
308 if (ctx
->Driver
.BlendEquation
)
309 ctx
->Driver
.BlendEquation( ctx
, mode
);
315 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
317 GET_CURRENT_CONTEXT(ctx
);
318 ctx
->Color
.BlendColor
[0] = CLAMP( red
, 0.0F
, 1.0F
);
319 ctx
->Color
.BlendColor
[1] = CLAMP( green
, 0.0F
, 1.0F
);
320 ctx
->Color
.BlendColor
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
321 ctx
->Color
.BlendColor
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
322 ctx
->NewState
|= _NEW_COLOR
;
326 #define _BLENDAPI _ASMAPI
332 * Common transparency blending mode.
334 static void _BLENDAPI
335 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
336 GLchan rgba
[][4], CONST GLchan dest
[][4] )
339 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
340 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
341 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
346 const GLint t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
349 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
350 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
351 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
352 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
354 else if (t
== CHAN_MAX
) {
355 /* 100% alpha, no-op */
359 /* This is pretty close, but Glean complains */
360 const GLint s
= CHAN_MAX
- t
;
361 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
362 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
363 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
364 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
366 /* This is slower but satisfies Glean */
367 const GLint s
= CHAN_MAX
- t
;
368 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
369 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
370 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
371 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
374 /* This satisfies Glean and should be reasonably fast */
375 /* Contributed by Nathan Hand */
376 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
377 const GLint s
= CHAN_MAX
- t
;
378 const GLint r
= DIV255(rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
);
379 const GLint g
= DIV255(rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
);
380 const GLint b
= DIV255(rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
);
381 const GLint a
= DIV255(rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
);
384 const GLint s
= CHAN_MAX
- t
;
385 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / CHAN_MAX
;
386 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / CHAN_MAX
;
387 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / CHAN_MAX
;
388 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / CHAN_MAX
;
391 ASSERT(r
<= CHAN_MAX
);
392 ASSERT(g
<= CHAN_MAX
);
393 ASSERT(b
<= CHAN_MAX
);
394 ASSERT(a
<= CHAN_MAX
);
395 rgba
[i
][RCOMP
] = (GLchan
) r
;
396 rgba
[i
][GCOMP
] = (GLchan
) g
;
397 rgba
[i
][BCOMP
] = (GLchan
) b
;
398 rgba
[i
][ACOMP
] = (GLchan
) a
;
409 static void _BLENDAPI
410 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
411 GLchan rgba
[][4], CONST GLchan dest
[][4] )
414 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
415 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
416 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
421 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
422 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
423 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
424 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
425 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
426 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
427 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
428 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
436 * Blend min function (for GL_EXT_blend_minmax)
438 static void _BLENDAPI
439 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
440 GLchan rgba
[][4], CONST GLchan dest
[][4] )
443 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
448 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
449 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
450 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
451 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
459 * Blend max function (for GL_EXT_blend_minmax)
461 static void _BLENDAPI
462 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
463 GLchan rgba
[][4], CONST GLchan dest
[][4] )
466 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
471 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
472 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
473 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
474 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
482 * Modulate: result = src * dest
484 static void _BLENDAPI
485 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
486 GLchan rgba
[][4], CONST GLchan dest
[][4] )
493 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
]) >> 8;
494 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
]) >> 8;
495 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
]) >> 8;
496 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
]) >> 8;
497 rgba
[i
][RCOMP
] = (GLchan
) r
;
498 rgba
[i
][GCOMP
] = (GLchan
) g
;
499 rgba
[i
][BCOMP
] = (GLchan
) b
;
500 rgba
[i
][ACOMP
] = (GLchan
) a
;
508 * General case blend pixels.
509 * Input: n - number of pixels
510 * mask - the usual write mask
511 * In/Out: rgba - the incoming and modified pixels
512 * Input: dest - the pixels from the dest color buffer
514 static void _BLENDAPI
515 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
516 GLchan rgba
[][4], CONST GLchan dest
[][4] )
518 GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
519 GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
520 GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
521 GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
526 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
527 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
528 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
529 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
538 /* Frame buffer color */
544 /* Source RGB factor */
545 switch (ctx
->Color
.BlendSrcRGB
) {
553 sR
= (GLfloat
) Rd
* rscale
;
554 sG
= (GLfloat
) Gd
* gscale
;
555 sB
= (GLfloat
) Bd
* bscale
;
557 case GL_ONE_MINUS_DST_COLOR
:
558 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
559 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
560 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
563 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
565 case GL_ONE_MINUS_SRC_ALPHA
:
566 sR
= sG
= sB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
569 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
571 case GL_ONE_MINUS_DST_ALPHA
:
572 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
574 case GL_SRC_ALPHA_SATURATE
:
575 if (As
< CHAN_MAX
- Ad
) {
576 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
579 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
582 case GL_CONSTANT_COLOR
:
583 sR
= ctx
->Color
.BlendColor
[0];
584 sG
= ctx
->Color
.BlendColor
[1];
585 sB
= ctx
->Color
.BlendColor
[2];
587 case GL_ONE_MINUS_CONSTANT_COLOR
:
588 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
589 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
590 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
592 case GL_CONSTANT_ALPHA
:
593 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
595 case GL_ONE_MINUS_CONSTANT_ALPHA
:
596 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
598 case GL_SRC_COLOR
: /* GL_NV_blend_square */
599 sR
= (GLfloat
) Rs
* rscale
;
600 sG
= (GLfloat
) Gs
* gscale
;
601 sB
= (GLfloat
) Bs
* bscale
;
603 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
604 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
605 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
606 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
609 /* this should never happen */
610 gl_problem(ctx
, "Bad blend source RGB factor in do_blend");
614 /* Source Alpha factor */
615 switch (ctx
->Color
.BlendSrcA
) {
623 sA
= (GLfloat
) Ad
* ascale
;
625 case GL_ONE_MINUS_DST_COLOR
:
626 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
629 sA
= (GLfloat
) As
* ascale
;
631 case GL_ONE_MINUS_SRC_ALPHA
:
632 sA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
635 sA
=(GLfloat
) Ad
* ascale
;
637 case GL_ONE_MINUS_DST_ALPHA
:
638 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
640 case GL_SRC_ALPHA_SATURATE
:
643 case GL_CONSTANT_COLOR
:
644 sA
= ctx
->Color
.BlendColor
[3];
646 case GL_ONE_MINUS_CONSTANT_COLOR
:
647 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
649 case GL_CONSTANT_ALPHA
:
650 sA
= ctx
->Color
.BlendColor
[3];
652 case GL_ONE_MINUS_CONSTANT_ALPHA
:
653 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
655 case GL_SRC_COLOR
: /* GL_NV_blend_square */
656 sA
= (GLfloat
) As
* ascale
;
658 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
659 sA
= 1.0F
- (GLfloat
) As
* ascale
;
662 /* this should never happen */
664 gl_problem(ctx
, "Bad blend source A factor in do_blend");
667 /* Dest RGB factor */
668 switch (ctx
->Color
.BlendDstRGB
) {
676 dR
= (GLfloat
) Rs
* rscale
;
677 dG
= (GLfloat
) Gs
* gscale
;
678 dB
= (GLfloat
) Bs
* bscale
;
680 case GL_ONE_MINUS_SRC_COLOR
:
681 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
682 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
683 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
686 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
688 case GL_ONE_MINUS_SRC_ALPHA
:
689 dR
= dG
= dB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
692 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
694 case GL_ONE_MINUS_DST_ALPHA
:
695 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
697 case GL_CONSTANT_COLOR
:
698 dR
= ctx
->Color
.BlendColor
[0];
699 dG
= ctx
->Color
.BlendColor
[1];
700 dB
= ctx
->Color
.BlendColor
[2];
702 case GL_ONE_MINUS_CONSTANT_COLOR
:
703 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
704 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
705 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
707 case GL_CONSTANT_ALPHA
:
708 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
710 case GL_ONE_MINUS_CONSTANT_ALPHA
:
711 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
713 case GL_DST_COLOR
: /* GL_NV_blend_square */
714 dR
= (GLfloat
) Rd
* rscale
;
715 dG
= (GLfloat
) Gd
* gscale
;
716 dB
= (GLfloat
) Bd
* bscale
;
718 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
719 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
720 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
721 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
724 /* this should never happen */
726 gl_problem(ctx
, "Bad blend dest RGB factor in do_blend");
729 /* Dest Alpha factor */
730 switch (ctx
->Color
.BlendDstA
) {
738 dA
= (GLfloat
) As
* ascale
;
740 case GL_ONE_MINUS_SRC_COLOR
:
741 dA
= 1.0F
- (GLfloat
) As
* ascale
;
744 dA
= (GLfloat
) As
* ascale
;
746 case GL_ONE_MINUS_SRC_ALPHA
:
747 dA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
750 dA
= (GLfloat
) Ad
* ascale
;
752 case GL_ONE_MINUS_DST_ALPHA
:
753 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
755 case GL_CONSTANT_COLOR
:
756 dA
= ctx
->Color
.BlendColor
[3];
758 case GL_ONE_MINUS_CONSTANT_COLOR
:
759 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
761 case GL_CONSTANT_ALPHA
:
762 dA
= ctx
->Color
.BlendColor
[3];
764 case GL_ONE_MINUS_CONSTANT_ALPHA
:
765 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
767 case GL_DST_COLOR
: /* GL_NV_blend_square */
768 dA
= (GLfloat
) Ad
* ascale
;
770 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
771 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
774 /* this should never happen */
776 gl_problem(ctx
, "Bad blend dest A factor in do_blend");
780 /* Due to round-off problems we have to clamp against zero. */
781 /* Optimization: we don't have to do this for all src & dst factors */
782 if (dA
< 0.0F
) dA
= 0.0F
;
783 if (dR
< 0.0F
) dR
= 0.0F
;
784 if (dG
< 0.0F
) dG
= 0.0F
;
785 if (dB
< 0.0F
) dB
= 0.0F
;
786 if (sA
< 0.0F
) sA
= 0.0F
;
787 if (sR
< 0.0F
) sR
= 0.0F
;
788 if (sG
< 0.0F
) sG
= 0.0F
;
789 if (sB
< 0.0F
) sB
= 0.0F
;
800 /* compute blended color */
801 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
802 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
803 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
804 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
805 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
807 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
808 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
809 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
810 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
811 a
= As
* sA
- Ad
* dA
+ 0.5F
;
813 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
814 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
815 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
816 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
817 a
= Ad
* dA
- As
* sA
+ 0.5F
;
820 /* should never get here */
821 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
822 gl_problem(ctx
, "unexpected BlendEquation in blend_general()");
826 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
827 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
828 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
829 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
836 #if defined(USE_MMX_ASM)
838 #include "X86/common_x86_asm.h"
843 * Analyze current blending parameters to pick fastest blending function.
844 * Result: the ctx->Color.BlendFunc pointer is updated.
846 static void set_blend_function( GLcontext
*ctx
)
848 const GLenum eq
= ctx
->Color
.BlendEquation
;
849 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
850 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
851 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
852 const GLenum dstA
= ctx
->Color
.BlendDstA
;
854 #if defined(USE_MMX_ASM)
855 /* Hmm. A table here would have 12^4 == way too many entries.
856 * Provide a hook for MMX instead.
859 gl_mmx_set_blend_function( ctx
);
863 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
864 ctx
->Color
.BlendFunc
= blend_general
;
866 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
867 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
) {
868 ctx
->Color
.BlendFunc
= blend_transparency
;
870 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
871 ctx
->Color
.BlendFunc
= blend_add
;
873 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
874 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
876 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
877 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
878 ctx
->Color
.BlendFunc
= blend_modulate
;
880 else if (eq
==GL_MIN_EXT
) {
881 ctx
->Color
.BlendFunc
= blend_min
;
883 else if (eq
==GL_MAX_EXT
) {
884 ctx
->Color
.BlendFunc
= blend_max
;
887 ctx
->Color
.BlendFunc
= blend_general
;
894 * Apply the blending operator to a span of pixels.
895 * Input: n - number of pixels in span
896 * x, y - location of leftmost pixel in span in window coords.
897 * mask - boolean mask indicating which pixels to blend.
898 * In/Out: rgba - pixel values
901 _mesa_blend_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
902 GLchan rgba
[][4], const GLubyte mask
[] )
904 GLchan dest
[MAX_WIDTH
][4];
906 /* Check if device driver can do the work */
907 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&&
908 !ctx
->Color
.ColorLogicOpEnabled
) {
912 /* Read span of current frame buffer pixels */
913 gl_read_rgba_span( ctx
, ctx
->DrawBuffer
, n
, x
, y
, dest
);
915 if (!ctx
->Color
.BlendFunc
)
916 set_blend_function(ctx
);
918 (*ctx
->Color
.BlendFunc
)( ctx
, n
, mask
, rgba
, (const GLchan (*)[4])dest
);
924 * Apply the blending operator to an array of pixels.
925 * Input: n - number of pixels in span
926 * x, y - array of pixel locations
927 * mask - boolean mask indicating which pixels to blend.
928 * In/Out: rgba - pixel values
931 _mesa_blend_pixels( GLcontext
*ctx
,
932 GLuint n
, const GLint x
[], const GLint y
[],
933 GLchan rgba
[][4], const GLubyte mask
[] )
935 GLchan dest
[PB_SIZE
][4];
937 /* Check if device driver can do the work */
938 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&&
939 !ctx
->Color
.ColorLogicOpEnabled
) {
943 /* Read pixels from current color buffer */
944 (*ctx
->Driver
.ReadRGBAPixels
)( ctx
, n
, x
, y
, dest
, mask
);
945 if (ctx
->RasterMask
& ALPHABUF_BIT
) {
946 _mesa_read_alpha_pixels( ctx
, n
, x
, y
, dest
, mask
);
949 if (!ctx
->Color
.BlendFunc
)
950 set_blend_function(ctx
);
952 (*ctx
->Color
.BlendFunc
)( ctx
, n
, mask
, rgba
, (const GLchan (*)[4])dest
);