1 /* $Id: blend.c,v 1.13 2000/02/24 22:04:03 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 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
));
59 case GL_ONE_MINUS_DST_COLOR
:
61 case GL_ONE_MINUS_SRC_ALPHA
:
63 case GL_ONE_MINUS_DST_ALPHA
:
64 case GL_SRC_ALPHA_SATURATE
:
65 case GL_CONSTANT_COLOR
:
66 case GL_ONE_MINUS_CONSTANT_COLOR
:
67 case GL_CONSTANT_ALPHA
:
68 case GL_ONE_MINUS_CONSTANT_ALPHA
:
69 ctx
->Color
.BlendSrcRGB
= ctx
->Color
.BlendSrcA
= sfactor
;
72 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
80 case GL_ONE_MINUS_SRC_COLOR
:
82 case GL_ONE_MINUS_SRC_ALPHA
:
84 case GL_ONE_MINUS_DST_ALPHA
:
85 case GL_CONSTANT_COLOR
:
86 case GL_ONE_MINUS_CONSTANT_COLOR
:
87 case GL_CONSTANT_ALPHA
:
88 case GL_ONE_MINUS_CONSTANT_ALPHA
:
89 ctx
->Color
.BlendDstRGB
= ctx
->Color
.BlendDstA
= dfactor
;
92 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
96 if (ctx
->Driver
.BlendFunc
) {
97 (*ctx
->Driver
.BlendFunc
)( ctx
, sfactor
, dfactor
);
100 ctx
->Color
.BlendFunc
= NULL
;
101 ctx
->NewState
|= NEW_RASTER_OPS
;
105 /* GL_EXT_blend_func_separate */
107 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB
, GLenum dfactorRGB
,
108 GLenum sfactorA
, GLenum dfactorA
)
110 GET_CURRENT_CONTEXT(ctx
);
111 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendFuncSeparate");
113 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
114 fprintf(stderr
, "glBlendFuncSeperate %s %s %s %s\n",
115 gl_lookup_enum_by_nr(sfactorRGB
),
116 gl_lookup_enum_by_nr(dfactorRGB
),
117 gl_lookup_enum_by_nr(sfactorA
),
118 gl_lookup_enum_by_nr(dfactorA
));
120 switch (sfactorRGB
) {
124 case GL_ONE_MINUS_DST_COLOR
:
126 case GL_ONE_MINUS_SRC_ALPHA
:
128 case GL_ONE_MINUS_DST_ALPHA
:
129 case GL_SRC_ALPHA_SATURATE
:
130 case GL_CONSTANT_COLOR
:
131 case GL_ONE_MINUS_CONSTANT_COLOR
:
132 case GL_CONSTANT_ALPHA
:
133 case GL_ONE_MINUS_CONSTANT_ALPHA
:
134 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
137 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)" );
141 switch (dfactorRGB
) {
145 case GL_ONE_MINUS_SRC_COLOR
:
147 case GL_ONE_MINUS_SRC_ALPHA
:
149 case GL_ONE_MINUS_DST_ALPHA
:
150 case GL_CONSTANT_COLOR
:
151 case GL_ONE_MINUS_CONSTANT_COLOR
:
152 case GL_CONSTANT_ALPHA
:
153 case GL_ONE_MINUS_CONSTANT_ALPHA
:
154 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
157 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)" );
165 case GL_ONE_MINUS_DST_COLOR
:
167 case GL_ONE_MINUS_SRC_ALPHA
:
169 case GL_ONE_MINUS_DST_ALPHA
:
170 case GL_SRC_ALPHA_SATURATE
:
171 case GL_CONSTANT_COLOR
:
172 case GL_ONE_MINUS_CONSTANT_COLOR
:
173 case GL_CONSTANT_ALPHA
:
174 case GL_ONE_MINUS_CONSTANT_ALPHA
:
175 ctx
->Color
.BlendSrcA
= sfactorA
;
178 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)" );
186 case GL_ONE_MINUS_SRC_COLOR
:
188 case GL_ONE_MINUS_SRC_ALPHA
:
190 case GL_ONE_MINUS_DST_ALPHA
:
191 case GL_CONSTANT_COLOR
:
192 case GL_ONE_MINUS_CONSTANT_COLOR
:
193 case GL_CONSTANT_ALPHA
:
194 case GL_ONE_MINUS_CONSTANT_ALPHA
:
195 ctx
->Color
.BlendDstA
= dfactorA
;
198 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)" );
202 ctx
->Color
.BlendFunc
= NULL
;
203 ctx
->NewState
|= NEW_RASTER_OPS
;
205 if (ctx
->Driver
.BlendFuncSeparate
) {
206 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
207 sfactorA
, dfactorA
);
213 /* This is really an extension function! */
215 _mesa_BlendEquation( GLenum mode
)
217 GET_CURRENT_CONTEXT(ctx
);
218 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendEquation");
220 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
221 fprintf(stderr
, "glBlendEquation %s\n",
222 gl_lookup_enum_by_nr(mode
));
229 case GL_FUNC_ADD_EXT
:
230 case GL_FUNC_SUBTRACT_EXT
:
231 case GL_FUNC_REVERSE_SUBTRACT_EXT
:
232 ctx
->Color
.BlendEquation
= mode
;
235 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendEquation" );
239 /* This is needed to support 1.1's RGB logic ops AND
240 * 1.0's blending logicops.
242 if (mode
==GL_LOGIC_OP
&& ctx
->Color
.BlendEnabled
) {
243 ctx
->Color
.ColorLogicOpEnabled
= GL_TRUE
;
246 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
249 ctx
->Color
.BlendFunc
= NULL
;
250 ctx
->NewState
|= NEW_RASTER_OPS
;
252 if (ctx
->Driver
.BlendEquation
)
253 ctx
->Driver
.BlendEquation( ctx
, mode
);
259 _mesa_BlendColor( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
261 GET_CURRENT_CONTEXT(ctx
);
262 ctx
->Color
.BlendColor
[0] = CLAMP( red
, 0.0F
, 1.0F
);
263 ctx
->Color
.BlendColor
[1] = CLAMP( green
, 0.0F
, 1.0F
);
264 ctx
->Color
.BlendColor
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
265 ctx
->Color
.BlendColor
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
269 #define _BLENDAPI _ASMAPI
275 * Common transparency blending mode.
277 static void _BLENDAPI
278 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
279 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
282 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
283 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
284 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
289 const GLint t
= rgba
[i
][ACOMP
]; /* t in [0,255] */
292 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
293 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
294 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
295 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
297 else if (t
== CHAN_MAX
) {
298 /* 100% alpha, no-op */
301 const GLint s
= CHAN_MAX
- t
;
302 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) >> 8;
303 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) >> 8;
304 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) >> 8;
305 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) >> 8;
306 ASSERT(r
<= CHAN_MAX
);
307 ASSERT(g
<= CHAN_MAX
);
308 ASSERT(b
<= CHAN_MAX
);
309 ASSERT(a
<= CHAN_MAX
);
310 rgba
[i
][RCOMP
] = (GLubyte
) r
;
311 rgba
[i
][GCOMP
] = (GLubyte
) g
;
312 rgba
[i
][BCOMP
] = (GLubyte
) b
;
313 rgba
[i
][ACOMP
] = (GLubyte
) a
;
324 static void _BLENDAPI
325 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
326 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
329 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
330 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
331 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
336 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
337 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
338 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
339 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
340 rgba
[i
][RCOMP
] = (GLubyte
) MIN2( r
, CHAN_MAX
);
341 rgba
[i
][GCOMP
] = (GLubyte
) MIN2( g
, CHAN_MAX
);
342 rgba
[i
][BCOMP
] = (GLubyte
) MIN2( b
, CHAN_MAX
);
343 rgba
[i
][ACOMP
] = (GLubyte
) MIN2( a
, CHAN_MAX
);
351 * Blend min function (for GL_EXT_blend_minmax)
353 static void _BLENDAPI
354 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
355 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
358 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
363 rgba
[i
][RCOMP
] = (GLubyte
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
364 rgba
[i
][GCOMP
] = (GLubyte
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
365 rgba
[i
][BCOMP
] = (GLubyte
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
366 rgba
[i
][ACOMP
] = (GLubyte
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
374 * Blend max function (for GL_EXT_blend_minmax)
376 static void _BLENDAPI
377 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
378 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
381 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
386 rgba
[i
][RCOMP
] = (GLubyte
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
387 rgba
[i
][GCOMP
] = (GLubyte
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
388 rgba
[i
][BCOMP
] = (GLubyte
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
389 rgba
[i
][ACOMP
] = (GLubyte
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
397 * Modulate: result = src * dest
399 static void _BLENDAPI
400 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
401 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
408 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
]) >> 8;
409 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
]) >> 8;
410 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
]) >> 8;
411 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
]) >> 8;
412 rgba
[i
][RCOMP
] = (GLubyte
) r
;
413 rgba
[i
][GCOMP
] = (GLubyte
) g
;
414 rgba
[i
][BCOMP
] = (GLubyte
) b
;
415 rgba
[i
][ACOMP
] = (GLubyte
) a
;
423 * General case blend pixels.
424 * Input: n - number of pixels
425 * mask - the usual write mask
426 * In/Out: rgba - the incoming and modified pixels
427 * Input: dest - the pixels from the dest color buffer
429 static void _BLENDAPI
430 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
431 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
433 GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
434 GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
435 GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
436 GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
441 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
442 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
443 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
444 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
453 /* Frame buffer color */
459 /* Source RGB factor */
460 switch (ctx
->Color
.BlendSrcRGB
) {
468 sR
= (GLfloat
) Rd
* rscale
;
469 sG
= (GLfloat
) Gd
* gscale
;
470 sB
= (GLfloat
) Bd
* bscale
;
472 case GL_ONE_MINUS_DST_COLOR
:
473 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
474 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
475 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
478 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
480 case GL_ONE_MINUS_SRC_ALPHA
:
481 sR
= sG
= sB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
484 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
486 case GL_ONE_MINUS_DST_ALPHA
:
487 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
489 case GL_SRC_ALPHA_SATURATE
:
490 if (As
< CHAN_MAX
- Ad
) {
491 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
494 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
497 case GL_CONSTANT_COLOR
:
498 sR
= ctx
->Color
.BlendColor
[0];
499 sG
= ctx
->Color
.BlendColor
[1];
500 sB
= ctx
->Color
.BlendColor
[2];
502 case GL_ONE_MINUS_CONSTANT_COLOR
:
503 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
504 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
505 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
507 case GL_CONSTANT_ALPHA
:
508 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
510 case GL_ONE_MINUS_CONSTANT_ALPHA
:
511 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
514 /* this should never happen */
515 gl_problem(ctx
, "Bad blend source RGB factor in do_blend");
519 /* Source Alpha factor */
520 switch (ctx
->Color
.BlendSrcA
) {
528 sA
= (GLfloat
) Ad
* ascale
;
530 case GL_ONE_MINUS_DST_COLOR
:
531 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
534 sA
= (GLfloat
) As
* ascale
;
536 case GL_ONE_MINUS_SRC_ALPHA
:
537 sA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
540 sA
=(GLfloat
) Ad
* ascale
;
542 case GL_ONE_MINUS_DST_ALPHA
:
543 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
545 case GL_SRC_ALPHA_SATURATE
:
548 case GL_CONSTANT_COLOR
:
549 sA
= ctx
->Color
.BlendColor
[3];
551 case GL_ONE_MINUS_CONSTANT_COLOR
:
552 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
554 case GL_CONSTANT_ALPHA
:
555 sA
= ctx
->Color
.BlendColor
[3];
557 case GL_ONE_MINUS_CONSTANT_ALPHA
:
558 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
561 /* this should never happen */
563 gl_problem(ctx
, "Bad blend source A factor in do_blend");
566 /* Dest RGB factor */
567 switch (ctx
->Color
.BlendDstRGB
) {
575 dR
= (GLfloat
) Rs
* rscale
;
576 dG
= (GLfloat
) Gs
* gscale
;
577 dB
= (GLfloat
) Bs
* bscale
;
579 case GL_ONE_MINUS_SRC_COLOR
:
580 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
581 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
582 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
585 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
587 case GL_ONE_MINUS_SRC_ALPHA
:
588 dR
= dG
= dB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
591 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
593 case GL_ONE_MINUS_DST_ALPHA
:
594 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
596 case GL_CONSTANT_COLOR
:
597 dR
= ctx
->Color
.BlendColor
[0];
598 dG
= ctx
->Color
.BlendColor
[1];
599 dB
= ctx
->Color
.BlendColor
[2];
601 case GL_ONE_MINUS_CONSTANT_COLOR
:
602 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
603 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
604 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
606 case GL_CONSTANT_ALPHA
:
607 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
609 case GL_ONE_MINUS_CONSTANT_ALPHA
:
610 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3] * ascale
;
613 /* this should never happen */
615 gl_problem(ctx
, "Bad blend dest RGB factor in do_blend");
618 /* Dest Alpha factor */
619 switch (ctx
->Color
.BlendDstA
) {
627 dA
= (GLfloat
) As
* ascale
;
629 case GL_ONE_MINUS_SRC_COLOR
:
630 dA
= 1.0F
- (GLfloat
) As
* ascale
;
633 dA
= (GLfloat
) As
* ascale
;
635 case GL_ONE_MINUS_SRC_ALPHA
:
636 dA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
639 dA
= (GLfloat
) Ad
* ascale
;
641 case GL_ONE_MINUS_DST_ALPHA
:
642 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
644 case GL_CONSTANT_COLOR
:
645 dA
= ctx
->Color
.BlendColor
[3];
647 case GL_ONE_MINUS_CONSTANT_COLOR
:
648 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
650 case GL_CONSTANT_ALPHA
:
651 dA
= ctx
->Color
.BlendColor
[3];
653 case GL_ONE_MINUS_CONSTANT_ALPHA
:
654 dA
= 1.0F
- ctx
->Color
.BlendColor
[3] * ascale
;
657 /* this should never happen */
659 gl_problem(ctx
, "Bad blend dest A factor in do_blend");
663 /* Due to round-off problems we have to clamp against zero. */
664 /* Optimization: we don't have to do this for all src & dst factors */
665 if (dA
< 0.0F
) dA
= 0.0F
;
666 if (dR
< 0.0F
) dR
= 0.0F
;
667 if (dG
< 0.0F
) dG
= 0.0F
;
668 if (dB
< 0.0F
) dB
= 0.0F
;
669 if (sA
< 0.0F
) sA
= 0.0F
;
670 if (sR
< 0.0F
) sR
= 0.0F
;
671 if (sG
< 0.0F
) sG
= 0.0F
;
672 if (sB
< 0.0F
) sB
= 0.0F
;
683 /* compute blended color */
684 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
685 r
= Rs
* sR
+ Rd
* dR
;
686 g
= Gs
* sG
+ Gd
* dG
;
687 b
= Bs
* sB
+ Bd
* dB
;
688 a
= As
* sA
+ Ad
* dA
;
690 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
691 r
= Rs
* sR
- Rd
* dR
;
692 g
= Gs
* sG
- Gd
* dG
;
693 b
= Bs
* sB
- Bd
* dB
;
694 a
= As
* sA
- Ad
* dA
;
696 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
697 r
= Rd
* dR
- Rs
* sR
;
698 g
= Gd
* dG
- Gs
* sG
;
699 b
= Bd
* dB
- Bs
* sB
;
700 a
= Ad
* dA
- As
* sA
;
703 /* should never get here */
704 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
705 gl_problem(ctx
, "unexpected BlendEquation in blend_general()");
709 rgba
[i
][RCOMP
] = (GLubyte
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
710 rgba
[i
][GCOMP
] = (GLubyte
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
711 rgba
[i
][BCOMP
] = (GLubyte
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
712 rgba
[i
][ACOMP
] = (GLubyte
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
719 #if defined(USE_MMX_ASM)
721 #include "X86/common_x86asm.h"
726 * Analyze current blending parameters to pick fastest blending function.
727 * Result: the ctx->Color.BlendFunc pointer is updated.
729 static void set_blend_function( GLcontext
*ctx
)
731 const GLenum eq
= ctx
->Color
.BlendEquation
;
732 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
733 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
734 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
735 const GLenum dstA
= ctx
->Color
.BlendDstA
;
737 #if defined(USE_MMX_ASM)
738 /* Hmm. A table here would have 12^4 == way too many entries.
739 * Provide a hook for MMX instead.
741 if (gl_x86_cpu_features
& GL_CPU_MMX
) {
742 gl_mmx_set_blend_function (ctx
);
746 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
747 ctx
->Color
.BlendFunc
= blend_general
;
749 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
750 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
) {
751 ctx
->Color
.BlendFunc
= blend_transparency
;
753 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
754 ctx
->Color
.BlendFunc
= blend_add
;
756 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
757 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
759 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
760 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
761 ctx
->Color
.BlendFunc
= blend_modulate
;
763 else if (eq
==GL_MIN_EXT
) {
764 ctx
->Color
.BlendFunc
= blend_min
;
766 else if (eq
==GL_MAX_EXT
) {
767 ctx
->Color
.BlendFunc
= blend_max
;
770 ctx
->Color
.BlendFunc
= blend_general
;
777 * Apply the blending operator to a span of pixels.
778 * Input: n - number of pixels in span
779 * x, y - location of leftmost pixel in span in window coords.
780 * mask - boolean mask indicating which pixels to blend.
781 * In/Out: rgba - pixel values
784 _mesa_blend_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
785 GLubyte rgba
[][4], const GLubyte mask
[] )
787 GLubyte dest
[MAX_WIDTH
][4];
789 /* Check if device driver can do the work */
790 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&& !ctx
->Color
.SWLogicOpEnabled
) {
794 /* Read span of current frame buffer pixels */
795 gl_read_rgba_span( ctx
, ctx
->DrawBuffer
, n
, x
, y
, dest
);
797 if (!ctx
->Color
.BlendFunc
)
798 set_blend_function(ctx
);
800 (*ctx
->Color
.BlendFunc
)( ctx
, n
, mask
, rgba
, (const GLubyte (*)[4])dest
);
808 * Apply the blending operator to an array of pixels.
809 * Input: n - number of pixels in span
810 * x, y - array of pixel locations
811 * mask - boolean mask indicating which pixels to blend.
812 * In/Out: rgba - pixel values
815 _mesa_blend_pixels( GLcontext
*ctx
,
816 GLuint n
, const GLint x
[], const GLint y
[],
817 GLubyte rgba
[][4], const GLubyte mask
[] )
819 GLubyte dest
[PB_SIZE
][4];
821 /* Check if device driver can do the work */
822 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&& !ctx
->Color
.SWLogicOpEnabled
) {
826 /* Read pixels from current color buffer */
827 (*ctx
->Driver
.ReadRGBAPixels
)( ctx
, n
, x
, y
, dest
, mask
);
828 if (ctx
->RasterMask
& ALPHABUF_BIT
) {
829 gl_read_alpha_pixels( ctx
, n
, x
, y
, dest
, mask
);
832 if (!ctx
->Color
.BlendFunc
)
833 set_blend_function(ctx
);
835 (*ctx
->Color
.BlendFunc
)( ctx
, n
, mask
, rgba
, (const GLubyte (*)[4])dest
);