1 /* $Id: blend.c,v 1.8 1999/11/11 01:22:25 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.
44 void _mesa_BlendFunc( GLenum sfactor
, GLenum dfactor
)
46 GET_CURRENT_CONTEXT(ctx
);
47 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendFunc");
49 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
50 fprintf(stderr
, "glBlendFunc %s %s\n",
51 gl_lookup_enum_by_nr(sfactor
),
52 gl_lookup_enum_by_nr(dfactor
));
58 case GL_ONE_MINUS_DST_COLOR
:
60 case GL_ONE_MINUS_SRC_ALPHA
:
62 case GL_ONE_MINUS_DST_ALPHA
:
63 case GL_SRC_ALPHA_SATURATE
:
64 case GL_CONSTANT_COLOR
:
65 case GL_ONE_MINUS_CONSTANT_COLOR
:
66 case GL_CONSTANT_ALPHA
:
67 case GL_ONE_MINUS_CONSTANT_ALPHA
:
68 ctx
->Color
.BlendSrcRGB
= ctx
->Color
.BlendSrcA
= sfactor
;
71 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(sfactor)" );
79 case GL_ONE_MINUS_SRC_COLOR
:
81 case GL_ONE_MINUS_SRC_ALPHA
:
83 case GL_ONE_MINUS_DST_ALPHA
:
84 case GL_CONSTANT_COLOR
:
85 case GL_ONE_MINUS_CONSTANT_COLOR
:
86 case GL_CONSTANT_ALPHA
:
87 case GL_ONE_MINUS_CONSTANT_ALPHA
:
88 ctx
->Color
.BlendDstRGB
= ctx
->Color
.BlendDstA
= dfactor
;
91 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFunc(dfactor)" );
95 if (ctx
->Driver
.BlendFunc
) {
96 (*ctx
->Driver
.BlendFunc
)( ctx
, sfactor
, dfactor
);
99 ctx
->Color
.BlendFunc
= NULL
;
100 ctx
->NewState
|= NEW_RASTER_OPS
;
104 /* GL_INGR_blend_func_separate */
106 _mesa_BlendFuncSeparateINGR( GLenum sfactorRGB
, GLenum dfactorRGB
,
107 GLenum sfactorA
, GLenum dfactorA
)
109 GET_CURRENT_CONTEXT(ctx
);
110 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendFuncSeparate");
112 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
113 fprintf(stderr
, "glBlendFuncSeperate %s %s %s %s\n",
114 gl_lookup_enum_by_nr(sfactorRGB
),
115 gl_lookup_enum_by_nr(dfactorRGB
),
116 gl_lookup_enum_by_nr(sfactorA
),
117 gl_lookup_enum_by_nr(dfactorA
));
119 switch (sfactorRGB
) {
123 case GL_ONE_MINUS_DST_COLOR
:
125 case GL_ONE_MINUS_SRC_ALPHA
:
127 case GL_ONE_MINUS_DST_ALPHA
:
128 case GL_SRC_ALPHA_SATURATE
:
129 case GL_CONSTANT_COLOR
:
130 case GL_ONE_MINUS_CONSTANT_COLOR
:
131 case GL_CONSTANT_ALPHA
:
132 case GL_ONE_MINUS_CONSTANT_ALPHA
:
133 ctx
->Color
.BlendSrcRGB
= sfactorRGB
;
136 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorRGB)" );
140 switch (dfactorRGB
) {
144 case GL_ONE_MINUS_SRC_COLOR
:
146 case GL_ONE_MINUS_SRC_ALPHA
:
148 case GL_ONE_MINUS_DST_ALPHA
:
149 case GL_CONSTANT_COLOR
:
150 case GL_ONE_MINUS_CONSTANT_COLOR
:
151 case GL_CONSTANT_ALPHA
:
152 case GL_ONE_MINUS_CONSTANT_ALPHA
:
153 ctx
->Color
.BlendDstRGB
= dfactorRGB
;
156 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorRGB)" );
164 case GL_ONE_MINUS_DST_COLOR
:
166 case GL_ONE_MINUS_SRC_ALPHA
:
168 case GL_ONE_MINUS_DST_ALPHA
:
169 case GL_SRC_ALPHA_SATURATE
:
170 case GL_CONSTANT_COLOR
:
171 case GL_ONE_MINUS_CONSTANT_COLOR
:
172 case GL_CONSTANT_ALPHA
:
173 case GL_ONE_MINUS_CONSTANT_ALPHA
:
174 ctx
->Color
.BlendSrcA
= sfactorA
;
177 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(sfactorA)" );
185 case GL_ONE_MINUS_SRC_COLOR
:
187 case GL_ONE_MINUS_SRC_ALPHA
:
189 case GL_ONE_MINUS_DST_ALPHA
:
190 case GL_CONSTANT_COLOR
:
191 case GL_ONE_MINUS_CONSTANT_COLOR
:
192 case GL_CONSTANT_ALPHA
:
193 case GL_ONE_MINUS_CONSTANT_ALPHA
:
194 ctx
->Color
.BlendDstA
= dfactorA
;
197 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendFuncSeparate(dfactorA)" );
201 ctx
->Color
.BlendFunc
= NULL
;
202 ctx
->NewState
|= NEW_RASTER_OPS
;
204 if (ctx
->Driver
.BlendFuncSeparate
) {
205 (*ctx
->Driver
.BlendFuncSeparate
)( ctx
, sfactorRGB
, dfactorRGB
,
206 sfactorA
, dfactorA
);
212 /* This is really an extension function! */
214 _mesa_BlendEquationEXT( GLenum mode
)
216 GET_CURRENT_CONTEXT(ctx
);
217 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glBlendEquation");
219 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
220 fprintf(stderr
, "glBlendEquation %s\n",
221 gl_lookup_enum_by_nr(mode
));
228 case GL_FUNC_ADD_EXT
:
229 case GL_FUNC_SUBTRACT_EXT
:
230 case GL_FUNC_REVERSE_SUBTRACT_EXT
:
231 ctx
->Color
.BlendEquation
= mode
;
234 gl_error( ctx
, GL_INVALID_ENUM
, "glBlendEquation" );
238 /* This is needed to support 1.1's RGB logic ops AND
239 * 1.0's blending logicops.
241 if (mode
==GL_LOGIC_OP
&& ctx
->Color
.BlendEnabled
) {
242 ctx
->Color
.ColorLogicOpEnabled
= GL_TRUE
;
245 ctx
->Color
.ColorLogicOpEnabled
= GL_FALSE
;
248 ctx
->Color
.BlendFunc
= NULL
;
249 ctx
->NewState
|= NEW_RASTER_OPS
;
251 if (ctx
->Driver
.BlendEquation
)
252 ctx
->Driver
.BlendEquation( ctx
, mode
);
258 _mesa_BlendColorEXT( GLclampf red
, GLclampf green
, GLclampf blue
, GLclampf alpha
)
260 GET_CURRENT_CONTEXT(ctx
);
261 ctx
->Color
.BlendColor
[0] = CLAMP( red
, 0.0F
, 1.0F
);
262 ctx
->Color
.BlendColor
[1] = CLAMP( green
, 0.0F
, 1.0F
);
263 ctx
->Color
.BlendColor
[2] = CLAMP( blue
, 0.0F
, 1.0F
);
264 ctx
->Color
.BlendColor
[3] = CLAMP( alpha
, 0.0F
, 1.0F
);
270 * Common transparency blending mode.
272 static void blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
273 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
276 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
277 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
278 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
283 GLint t
= rgba
[i
][ACOMP
]; /* t in [0,255] */
285 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
286 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
287 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
288 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
295 GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) >> 8;
296 GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) >> 8;
297 GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) >> 8;
298 GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) >> 8;
303 rgba
[i
][RCOMP
] = (GLubyte
) r
;
304 rgba
[i
][GCOMP
] = (GLubyte
) g
;
305 rgba
[i
][BCOMP
] = (GLubyte
) b
;
306 rgba
[i
][ACOMP
] = (GLubyte
) a
;
317 static void blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
318 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
321 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
322 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
323 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
328 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
329 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
330 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
331 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
332 rgba
[i
][RCOMP
] = (GLubyte
) MIN2( r
, 255 );
333 rgba
[i
][GCOMP
] = (GLubyte
) MIN2( g
, 255 );
334 rgba
[i
][BCOMP
] = (GLubyte
) MIN2( b
, 255 );
335 rgba
[i
][ACOMP
] = (GLubyte
) MIN2( a
, 255 );
343 * Blend min function (for GL_EXT_blend_minmax)
345 static void blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
346 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
349 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
354 rgba
[i
][RCOMP
] = (GLubyte
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
355 rgba
[i
][GCOMP
] = (GLubyte
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
356 rgba
[i
][BCOMP
] = (GLubyte
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
357 rgba
[i
][ACOMP
] = (GLubyte
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
365 * Blend max function (for GL_EXT_blend_minmax)
367 static void blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
368 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
371 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
376 rgba
[i
][RCOMP
] = (GLubyte
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
377 rgba
[i
][GCOMP
] = (GLubyte
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
378 rgba
[i
][BCOMP
] = (GLubyte
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
379 rgba
[i
][ACOMP
] = (GLubyte
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
387 * Modulate: result = src * dest
389 static void blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
390 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
397 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
]) >> 8;
398 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
]) >> 8;
399 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
]) >> 8;
400 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
]) >> 8;
401 rgba
[i
][RCOMP
] = (GLubyte
) r
;
402 rgba
[i
][GCOMP
] = (GLubyte
) g
;
403 rgba
[i
][BCOMP
] = (GLubyte
) b
;
404 rgba
[i
][ACOMP
] = (GLubyte
) a
;
412 * General case blend pixels.
413 * Input: n - number of pixels
414 * mask - the usual write mask
415 * In/Out: rgba - the incoming and modified pixels
416 * Input: dest - the pixels from the dest color buffer
418 static void blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
419 GLubyte rgba
[][4], CONST GLubyte dest
[][4] )
421 GLfloat rscale
= 1.0F
/ 255.0F
;
422 GLfloat gscale
= 1.0F
/ 255.0F
;
423 GLfloat bscale
= 1.0F
/ 255.0F
;
424 GLfloat ascale
= 1.0F
/ 255.0F
;
429 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
430 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
431 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
432 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
441 /* Frame buffer color */
447 /* Source RGB factor */
448 switch (ctx
->Color
.BlendSrcRGB
) {
456 sR
= (GLfloat
) Rd
* rscale
;
457 sG
= (GLfloat
) Gd
* gscale
;
458 sB
= (GLfloat
) Bd
* bscale
;
460 case GL_ONE_MINUS_DST_COLOR
:
461 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
462 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
463 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
466 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
468 case GL_ONE_MINUS_SRC_ALPHA
:
469 sR
= sG
= sB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
472 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
474 case GL_ONE_MINUS_DST_ALPHA
:
475 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
477 case GL_SRC_ALPHA_SATURATE
:
478 if (As
< 1.0F
- (GLfloat
) Ad
* ascale
) {
479 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
482 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
485 case GL_CONSTANT_COLOR
:
486 sR
= ctx
->Color
.BlendColor
[0];
487 sG
= ctx
->Color
.BlendColor
[1];
488 sB
= ctx
->Color
.BlendColor
[2];
490 case GL_ONE_MINUS_CONSTANT_COLOR
:
491 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
492 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
493 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
495 case GL_CONSTANT_ALPHA
:
496 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
498 case GL_ONE_MINUS_CONSTANT_ALPHA
:
499 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
502 /* this should never happen */
503 gl_problem(ctx
, "Bad blend source RGB factor in do_blend");
507 /* Source Alpha factor */
508 switch (ctx
->Color
.BlendSrcA
) {
516 sA
= (GLfloat
) Ad
* ascale
;
518 case GL_ONE_MINUS_DST_COLOR
:
519 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
522 sA
= (GLfloat
) As
* ascale
;
524 case GL_ONE_MINUS_SRC_ALPHA
:
525 sA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
528 sA
=(GLfloat
) Ad
* ascale
;
530 case GL_ONE_MINUS_DST_ALPHA
:
531 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
533 case GL_SRC_ALPHA_SATURATE
:
536 case GL_CONSTANT_COLOR
:
537 sA
= ctx
->Color
.BlendColor
[3];
539 case GL_ONE_MINUS_CONSTANT_COLOR
:
540 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
542 case GL_CONSTANT_ALPHA
:
543 sA
= ctx
->Color
.BlendColor
[3];
545 case GL_ONE_MINUS_CONSTANT_ALPHA
:
546 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
549 /* this should never happen */
551 gl_problem(ctx
, "Bad blend source A factor in do_blend");
554 /* Dest RGB factor */
555 switch (ctx
->Color
.BlendDstRGB
) {
563 dR
= (GLfloat
) Rs
* rscale
;
564 dG
= (GLfloat
) Gs
* gscale
;
565 dB
= (GLfloat
) Bs
* bscale
;
567 case GL_ONE_MINUS_SRC_COLOR
:
568 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
569 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
570 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
573 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
575 case GL_ONE_MINUS_SRC_ALPHA
:
576 dR
= dG
= dB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
579 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
581 case GL_ONE_MINUS_DST_ALPHA
:
582 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
584 case GL_CONSTANT_COLOR
:
585 dR
= ctx
->Color
.BlendColor
[0];
586 dG
= ctx
->Color
.BlendColor
[1];
587 dB
= ctx
->Color
.BlendColor
[2];
589 case GL_ONE_MINUS_CONSTANT_COLOR
:
590 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
591 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
592 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
594 case GL_CONSTANT_ALPHA
:
595 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
597 case GL_ONE_MINUS_CONSTANT_ALPHA
:
598 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3] * ascale
;
601 /* this should never happen */
603 gl_problem(ctx
, "Bad blend dest RGB factor in do_blend");
606 /* Dest Alpha factor */
607 switch (ctx
->Color
.BlendDstA
) {
615 dA
= (GLfloat
) As
* ascale
;
617 case GL_ONE_MINUS_SRC_COLOR
:
618 dA
= 1.0F
- (GLfloat
) As
* ascale
;
621 dA
= (GLfloat
) As
* ascale
;
623 case GL_ONE_MINUS_SRC_ALPHA
:
624 dA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
627 dA
= (GLfloat
) Ad
* ascale
;
629 case GL_ONE_MINUS_DST_ALPHA
:
630 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
632 case GL_CONSTANT_COLOR
:
633 dA
= ctx
->Color
.BlendColor
[3];
635 case GL_ONE_MINUS_CONSTANT_COLOR
:
636 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
638 case GL_CONSTANT_ALPHA
:
639 dA
= ctx
->Color
.BlendColor
[3];
641 case GL_ONE_MINUS_CONSTANT_ALPHA
:
642 dA
= 1.0F
- ctx
->Color
.BlendColor
[3] * ascale
;
645 /* this should never happen */
647 gl_problem(ctx
, "Bad blend dest A factor in do_blend");
651 /* Due to round-off problems we have to clamp against zero. */
652 /* Optimization: we don't have to do this for all src & dst factors */
653 if (dA
< 0.0F
) dA
= 0.0F
;
654 if (dR
< 0.0F
) dR
= 0.0F
;
655 if (dG
< 0.0F
) dG
= 0.0F
;
656 if (dB
< 0.0F
) dB
= 0.0F
;
657 if (sA
< 0.0F
) sA
= 0.0F
;
658 if (sR
< 0.0F
) sR
= 0.0F
;
659 if (sG
< 0.0F
) sG
= 0.0F
;
660 if (sB
< 0.0F
) sB
= 0.0F
;
671 /* compute blended color */
672 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
673 r
= Rs
* sR
+ Rd
* dR
;
674 g
= Gs
* sG
+ Gd
* dG
;
675 b
= Bs
* sB
+ Bd
* dB
;
676 a
= As
* sA
+ Ad
* dA
;
678 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
679 r
= Rs
* sR
- Rd
* dR
;
680 g
= Gs
* sG
- Gd
* dG
;
681 b
= Bs
* sB
- Bd
* dB
;
682 a
= As
* sA
- Ad
* dA
;
684 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
685 r
= Rd
* dR
- Rs
* sR
;
686 g
= Gd
* dG
- Gs
* sG
;
687 b
= Bd
* dB
- Bs
* sB
;
688 a
= Ad
* dA
- As
* sA
;
691 /* should never get here */
692 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
693 gl_problem(ctx
, "unexpected BlendEquation in blend_general()");
697 rgba
[i
][RCOMP
] = (GLubyte
) (GLint
) CLAMP( r
, 0.0F
, 255.0F
);
698 rgba
[i
][GCOMP
] = (GLubyte
) (GLint
) CLAMP( g
, 0.0F
, 255.0F
);
699 rgba
[i
][BCOMP
] = (GLubyte
) (GLint
) CLAMP( b
, 0.0F
, 255.0F
);
700 rgba
[i
][ACOMP
] = (GLubyte
) (GLint
) CLAMP( a
, 0.0F
, 255.0F
);
707 #if defined(USE_MMX_ASM)
709 #include "X86/common_x86asm.h"
714 * Analyze current blending parameters to pick fastest blending function.
715 * Result: the ctx->Color.BlendFunc pointer is updated.
717 static void set_blend_function( GLcontext
*ctx
)
719 const GLenum eq
= ctx
->Color
.BlendEquation
;
720 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
721 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
722 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
723 const GLenum dstA
= ctx
->Color
.BlendDstA
;
725 #if defined(USE_MMX_ASM)
726 /* Hmm. A table here would have 12^4 == way too many entries.
727 * Provide a hook for MMX instead.
729 if (gl_x86_cpu_features
& GL_CPU_MMX
) {
730 gl_mmx_set_blend_function (ctx
);
733 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
734 ctx
->Color
.BlendFunc
= blend_general
;
736 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
737 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
) {
738 ctx
->Color
.BlendFunc
= blend_transparency
;
740 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
741 ctx
->Color
.BlendFunc
= blend_add
;
743 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
744 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
746 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
747 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
748 ctx
->Color
.BlendFunc
= blend_modulate
;
750 else if (eq
==GL_MIN_EXT
) {
751 ctx
->Color
.BlendFunc
= blend_min
;
753 else if (eq
==GL_MAX_EXT
) {
754 ctx
->Color
.BlendFunc
= blend_max
;
757 ctx
->Color
.BlendFunc
= blend_general
;
764 * Apply the blending operator to a span of pixels.
765 * Input: n - number of pixels in span
766 * x, y - location of leftmost pixel in span in window coords.
767 * mask - boolean mask indicating which pixels to blend.
768 * In/Out: rgba - pixel values
770 void gl_blend_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
771 GLubyte rgba
[][4], const GLubyte mask
[] )
773 GLubyte dest
[MAX_WIDTH
][4];
775 /* Check if device driver can do the work */
776 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&& !ctx
->Color
.SWLogicOpEnabled
) {
780 /* Read span of current frame buffer pixels */
781 gl_read_rgba_span( ctx
, n
, x
, y
, dest
);
783 if (!ctx
->Color
.BlendFunc
)
784 set_blend_function(ctx
);
786 (*ctx
->Color
.BlendFunc
)( ctx
, n
, mask
, rgba
, (const GLubyte (*)[4])dest
);
794 * Apply the blending operator to an array of pixels.
795 * Input: n - number of pixels in span
796 * x, y - array of pixel locations
797 * mask - boolean mask indicating which pixels to blend.
798 * In/Out: rgba - pixel values
800 void gl_blend_pixels( GLcontext
*ctx
,
801 GLuint n
, const GLint x
[], const GLint y
[],
802 GLubyte rgba
[][4], const GLubyte mask
[] )
804 GLubyte dest
[PB_SIZE
][4];
806 /* Check if device driver can do the work */
807 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&& !ctx
->Color
.SWLogicOpEnabled
) {
811 /* Read pixels from current color buffer */
812 (*ctx
->Driver
.ReadRGBAPixels
)( ctx
, n
, x
, y
, dest
, mask
);
813 if (ctx
->RasterMask
& ALPHABUF_BIT
) {
814 gl_read_alpha_pixels( ctx
, n
, x
, y
, dest
, mask
);
817 if (!ctx
->Color
.BlendFunc
)
818 set_blend_function(ctx
);
820 (*ctx
->Color
.BlendFunc
)( ctx
, n
, mask
, rgba
, (const GLubyte (*)[4])dest
);