1 /* $Id: s_blend.c,v 1.8 2001/07/13 20:07:37 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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.
33 #include "s_alphabuf.h"
35 #include "s_context.h"
40 #if defined(USE_MMX_ASM)
42 #include "X86/common_x86_asm.h"
43 #define _BLENDAPI _ASMAPI
50 * Common transparency blending mode.
53 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
54 GLchan rgba
[][4], CONST GLchan dest
[][4] )
57 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
58 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
59 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
64 const GLint t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
67 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
68 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
69 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
70 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
72 else if (t
== CHAN_MAX
) {
73 /* 100% alpha, no-op */
77 /* This is pretty close, but Glean complains */
78 const GLint s
= CHAN_MAX
- t
;
79 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
80 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
81 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
82 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
84 /* This is slower but satisfies Glean */
85 const GLint s
= CHAN_MAX
- t
;
86 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
87 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
88 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
89 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
92 /* This satisfies Glean and should be reasonably fast */
93 /* Contributed by Nathan Hand */
94 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
95 const GLint s
= CHAN_MAX
- t
;
96 const GLint r
= DIV255(rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
);
97 const GLint g
= DIV255(rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
);
98 const GLint b
= DIV255(rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
);
99 const GLint a
= DIV255(rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
);
101 #elif CHAN_BITS == 16
102 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
103 const GLfloat s
= 1.0 - tt
;
104 const GLint r
= (GLint
) (rgba
[i
][RCOMP
] * tt
+ dest
[i
][RCOMP
] * s
);
105 const GLint g
= (GLint
) (rgba
[i
][GCOMP
] * tt
+ dest
[i
][GCOMP
] * s
);
106 const GLint b
= (GLint
) (rgba
[i
][BCOMP
] * tt
+ dest
[i
][BCOMP
] * s
);
107 const GLint a
= (GLint
) (rgba
[i
][ACOMP
] * tt
+ dest
[i
][ACOMP
] * s
);
108 #else /* CHAN_BITS == 32 */
109 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
110 const GLfloat s
= 1.0 - tt
;
111 const GLfloat r
= rgba
[i
][RCOMP
] * tt
+ dest
[i
][RCOMP
] * s
;
112 const GLfloat g
= rgba
[i
][GCOMP
] * tt
+ dest
[i
][GCOMP
] * s
;
113 const GLfloat b
= rgba
[i
][BCOMP
] * tt
+ dest
[i
][BCOMP
] * s
;
114 const GLfloat a
= rgba
[i
][ACOMP
] * tt
+ dest
[i
][ACOMP
] * s
;
117 ASSERT(r
<= CHAN_MAX
);
118 ASSERT(g
<= CHAN_MAX
);
119 ASSERT(b
<= CHAN_MAX
);
120 ASSERT(a
<= CHAN_MAX
);
121 rgba
[i
][RCOMP
] = (GLchan
) r
;
122 rgba
[i
][GCOMP
] = (GLchan
) g
;
123 rgba
[i
][BCOMP
] = (GLchan
) b
;
124 rgba
[i
][ACOMP
] = (GLchan
) a
;
135 static void _BLENDAPI
136 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
137 GLchan rgba
[][4], CONST GLchan dest
[][4] )
140 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
141 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
142 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
147 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
148 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
149 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
150 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
151 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
152 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
153 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
154 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
162 * Blend min function (for GL_EXT_blend_minmax)
164 static void _BLENDAPI
165 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
166 GLchan rgba
[][4], CONST GLchan dest
[][4] )
169 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
174 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
175 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
176 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
177 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
185 * Blend max function (for GL_EXT_blend_minmax)
187 static void _BLENDAPI
188 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
189 GLchan rgba
[][4], CONST GLchan dest
[][4] )
192 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
197 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
198 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
199 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
200 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
208 * Modulate: result = src * dest
210 static void _BLENDAPI
211 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
212 GLchan rgba
[][4], CONST GLchan dest
[][4] )
219 #if CHAN_TYPE == GL_FLOAT
220 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * dest
[i
][RCOMP
];
221 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * dest
[i
][GCOMP
];
222 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * dest
[i
][BCOMP
];
223 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * dest
[i
][ACOMP
];
225 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
]) >> 8;
226 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
]) >> 8;
227 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
]) >> 8;
228 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
]) >> 8;
229 rgba
[i
][RCOMP
] = (GLchan
) r
;
230 rgba
[i
][GCOMP
] = (GLchan
) g
;
231 rgba
[i
][BCOMP
] = (GLchan
) b
;
232 rgba
[i
][ACOMP
] = (GLchan
) a
;
241 * General case blend pixels.
242 * Input: n - number of pixels
243 * mask - the usual write mask
244 * In/Out: rgba - the incoming and modified pixels
245 * Input: dest - the pixels from the dest color buffer
247 static void _BLENDAPI
248 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
249 GLchan rgba
[][4], CONST GLchan dest
[][4] )
251 GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
252 GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
253 GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
254 GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
259 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
260 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
261 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
262 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
271 /* Frame buffer color */
277 /* Source RGB factor */
278 switch (ctx
->Color
.BlendSrcRGB
) {
286 sR
= (GLfloat
) Rd
* rscale
;
287 sG
= (GLfloat
) Gd
* gscale
;
288 sB
= (GLfloat
) Bd
* bscale
;
290 case GL_ONE_MINUS_DST_COLOR
:
291 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
292 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
293 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
296 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
298 case GL_ONE_MINUS_SRC_ALPHA
:
299 sR
= sG
= sB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
302 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
304 case GL_ONE_MINUS_DST_ALPHA
:
305 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
307 case GL_SRC_ALPHA_SATURATE
:
308 if (As
< CHAN_MAX
- Ad
) {
309 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
312 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
315 case GL_CONSTANT_COLOR
:
316 sR
= ctx
->Color
.BlendColor
[0];
317 sG
= ctx
->Color
.BlendColor
[1];
318 sB
= ctx
->Color
.BlendColor
[2];
320 case GL_ONE_MINUS_CONSTANT_COLOR
:
321 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
322 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
323 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
325 case GL_CONSTANT_ALPHA
:
326 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
328 case GL_ONE_MINUS_CONSTANT_ALPHA
:
329 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
331 case GL_SRC_COLOR
: /* GL_NV_blend_square */
332 sR
= (GLfloat
) Rs
* rscale
;
333 sG
= (GLfloat
) Gs
* gscale
;
334 sB
= (GLfloat
) Bs
* bscale
;
336 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
337 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
338 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
339 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
342 /* this should never happen */
343 _mesa_problem(ctx
, "Bad blend source RGB factor in do_blend");
347 /* Source Alpha factor */
348 switch (ctx
->Color
.BlendSrcA
) {
356 sA
= (GLfloat
) Ad
* ascale
;
358 case GL_ONE_MINUS_DST_COLOR
:
359 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
362 sA
= (GLfloat
) As
* ascale
;
364 case GL_ONE_MINUS_SRC_ALPHA
:
365 sA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
368 sA
=(GLfloat
) Ad
* ascale
;
370 case GL_ONE_MINUS_DST_ALPHA
:
371 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
373 case GL_SRC_ALPHA_SATURATE
:
376 case GL_CONSTANT_COLOR
:
377 sA
= ctx
->Color
.BlendColor
[3];
379 case GL_ONE_MINUS_CONSTANT_COLOR
:
380 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
382 case GL_CONSTANT_ALPHA
:
383 sA
= ctx
->Color
.BlendColor
[3];
385 case GL_ONE_MINUS_CONSTANT_ALPHA
:
386 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
388 case GL_SRC_COLOR
: /* GL_NV_blend_square */
389 sA
= (GLfloat
) As
* ascale
;
391 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
392 sA
= 1.0F
- (GLfloat
) As
* ascale
;
395 /* this should never happen */
397 _mesa_problem(ctx
, "Bad blend source A factor in do_blend");
400 /* Dest RGB factor */
401 switch (ctx
->Color
.BlendDstRGB
) {
409 dR
= (GLfloat
) Rs
* rscale
;
410 dG
= (GLfloat
) Gs
* gscale
;
411 dB
= (GLfloat
) Bs
* bscale
;
413 case GL_ONE_MINUS_SRC_COLOR
:
414 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
415 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
416 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
419 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
421 case GL_ONE_MINUS_SRC_ALPHA
:
422 dR
= dG
= dB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
425 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
427 case GL_ONE_MINUS_DST_ALPHA
:
428 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
430 case GL_CONSTANT_COLOR
:
431 dR
= ctx
->Color
.BlendColor
[0];
432 dG
= ctx
->Color
.BlendColor
[1];
433 dB
= ctx
->Color
.BlendColor
[2];
435 case GL_ONE_MINUS_CONSTANT_COLOR
:
436 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
437 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
438 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
440 case GL_CONSTANT_ALPHA
:
441 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
443 case GL_ONE_MINUS_CONSTANT_ALPHA
:
444 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
446 case GL_DST_COLOR
: /* GL_NV_blend_square */
447 dR
= (GLfloat
) Rd
* rscale
;
448 dG
= (GLfloat
) Gd
* gscale
;
449 dB
= (GLfloat
) Bd
* bscale
;
451 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
452 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
453 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
454 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
457 /* this should never happen */
459 _mesa_problem(ctx
, "Bad blend dest RGB factor in do_blend");
462 /* Dest Alpha factor */
463 switch (ctx
->Color
.BlendDstA
) {
471 dA
= (GLfloat
) As
* ascale
;
473 case GL_ONE_MINUS_SRC_COLOR
:
474 dA
= 1.0F
- (GLfloat
) As
* ascale
;
477 dA
= (GLfloat
) As
* ascale
;
479 case GL_ONE_MINUS_SRC_ALPHA
:
480 dA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
483 dA
= (GLfloat
) Ad
* ascale
;
485 case GL_ONE_MINUS_DST_ALPHA
:
486 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
488 case GL_CONSTANT_COLOR
:
489 dA
= ctx
->Color
.BlendColor
[3];
491 case GL_ONE_MINUS_CONSTANT_COLOR
:
492 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
494 case GL_CONSTANT_ALPHA
:
495 dA
= ctx
->Color
.BlendColor
[3];
497 case GL_ONE_MINUS_CONSTANT_ALPHA
:
498 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
500 case GL_DST_COLOR
: /* GL_NV_blend_square */
501 dA
= (GLfloat
) Ad
* ascale
;
503 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
504 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
507 /* this should never happen */
509 _mesa_problem(ctx
, "Bad blend dest A factor in do_blend");
513 /* Due to round-off problems we have to clamp against zero. */
514 /* Optimization: we don't have to do this for all src & dst factors */
515 if (dA
< 0.0F
) dA
= 0.0F
;
516 if (dR
< 0.0F
) dR
= 0.0F
;
517 if (dG
< 0.0F
) dG
= 0.0F
;
518 if (dB
< 0.0F
) dB
= 0.0F
;
519 if (sA
< 0.0F
) sA
= 0.0F
;
520 if (sR
< 0.0F
) sR
= 0.0F
;
521 if (sG
< 0.0F
) sG
= 0.0F
;
522 if (sB
< 0.0F
) sB
= 0.0F
;
533 /* compute blended color */
534 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
535 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
536 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
537 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
538 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
540 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
541 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
542 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
543 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
544 a
= As
* sA
- Ad
* dA
+ 0.5F
;
546 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
547 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
548 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
549 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
550 a
= Ad
* dA
- As
* sA
+ 0.5F
;
553 /* should never get here */
554 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
555 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
559 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
560 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
561 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
562 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
572 * Analyze current blending parameters to pick fastest blending function.
573 * Result: the ctx->Color.BlendFunc pointer is updated.
575 void _swrast_choose_blend_func( GLcontext
*ctx
)
577 const GLenum eq
= ctx
->Color
.BlendEquation
;
578 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
579 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
580 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
581 const GLenum dstA
= ctx
->Color
.BlendDstA
;
583 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
584 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
586 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
587 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
)
589 #if defined(USE_MMX_ASM)
591 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_transparency
;
595 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_transparency
;
597 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
598 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_add
;
600 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
601 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
603 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
604 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
605 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_modulate
;
607 else if (eq
==GL_MIN_EXT
) {
608 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_min
;
610 else if (eq
==GL_MAX_EXT
) {
611 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_max
;
614 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
621 * Apply the blending operator to a span of pixels.
622 * Input: n - number of pixels in span
623 * x, y - location of leftmost pixel in span in window coords.
624 * mask - boolean mask indicating which pixels to blend.
625 * In/Out: rgba - pixel values
628 _mesa_blend_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
629 GLchan rgba
[][4], const GLubyte mask
[] )
631 GLchan dest
[MAX_WIDTH
][4];
633 /* Check if device driver can do the work */
634 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&&
635 !ctx
->Color
.ColorLogicOpEnabled
) {
639 /* Read span of current frame buffer pixels */
640 _mesa_read_rgba_span( ctx
, ctx
->DrawBuffer
, n
, x
, y
, dest
);
642 SWRAST_CONTEXT(ctx
)->BlendFunc( ctx
, n
, mask
, rgba
,
643 (const GLchan (*)[4]) dest
);
649 * Apply the blending operator to an array of pixels.
650 * Input: n - number of pixels in span
651 * x, y - array of pixel locations
652 * mask - boolean mask indicating which pixels to blend.
653 * In/Out: rgba - pixel values
656 _mesa_blend_pixels( GLcontext
*ctx
,
657 GLuint n
, const GLint x
[], const GLint y
[],
658 GLchan rgba
[][4], const GLubyte mask
[] )
660 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
661 GLchan dest
[PB_SIZE
][4];
663 /* Check if device driver can do the work */
664 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&&
665 !ctx
->Color
.ColorLogicOpEnabled
) {
669 /* Read pixels from current color buffer */
670 (*swrast
->Driver
.ReadRGBAPixels
)( ctx
, n
, x
, y
, dest
, mask
);
671 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
672 _mesa_read_alpha_pixels( ctx
, n
, x
, y
, dest
, mask
);
675 swrast
->BlendFunc( ctx
, n
, mask
, rgba
, (const GLchan (*)[4])dest
);