1 /* $Id: s_blend.c,v 1.16 2002/04/02 23:36:51 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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"
39 #if defined(USE_MMX_ASM)
41 #include "X86/common_x86_asm.h"
42 #define _BLENDAPI _ASMAPI
49 * Special case for glBlendFunc(GL_ZERO, GL_ONE)
52 blend_noop( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
53 GLchan rgba
[][4], CONST GLchan dest
[][4] )
56 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
57 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ZERO
);
58 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
61 for (i
= 0; i
< n
; i
++) {
63 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
64 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
65 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
66 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
73 * Special case for glBlendFunc(GL_ONE, GL_ZERO)
76 blend_replace( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
77 GLchan rgba
[][4], CONST GLchan dest
[][4] )
79 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
80 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
81 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ZERO
);
91 * Common transparency blending mode.
94 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
95 GLchan rgba
[][4], CONST GLchan dest
[][4] )
98 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
99 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
100 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
105 const GLint t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
108 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
109 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
110 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
111 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
113 else if (t
== CHAN_MAX
) {
114 /* 100% alpha, no-op */
118 /* This is pretty close, but Glean complains */
119 const GLint s
= CHAN_MAX
- t
;
120 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
121 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
122 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
123 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
125 /* This is slower but satisfies Glean */
126 const GLint s
= CHAN_MAX
- t
;
127 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
128 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
129 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
130 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
133 /* This satisfies Glean and should be reasonably fast */
134 /* Contributed by Nathan Hand */
136 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
139 #define DIV255(X) (temp = (X), ((temp << 8) + temp + 256) >> 16)
141 const GLint r
= DIV255((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * t
) + dest
[i
][RCOMP
];
142 const GLint g
= DIV255((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * t
) + dest
[i
][GCOMP
];
143 const GLint b
= DIV255((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * t
) + dest
[i
][BCOMP
];
144 const GLint a
= DIV255((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * t
) + dest
[i
][ACOMP
];
146 #elif CHAN_BITS == 16
147 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
148 const GLint r
= (GLint
) ((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
]);
149 const GLint g
= (GLint
) ((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
]);
150 const GLint b
= (GLint
) ((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
]);
151 const GLint a
= (GLint
) ((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * tt
+ dest
[i
][ACOMP
]);
152 #else /* CHAN_BITS == 32 */
153 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
154 const GLfloat r
= (rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
];
155 const GLfloat g
= (rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
];
156 const GLfloat b
= (rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
];
157 const GLfloat a
= (rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * tt
+ dest
[i
][ACOMP
];
160 ASSERT(r
<= CHAN_MAX
);
161 ASSERT(g
<= CHAN_MAX
);
162 ASSERT(b
<= CHAN_MAX
);
163 ASSERT(a
<= CHAN_MAX
);
164 rgba
[i
][RCOMP
] = (GLchan
) r
;
165 rgba
[i
][GCOMP
] = (GLchan
) g
;
166 rgba
[i
][BCOMP
] = (GLchan
) b
;
167 rgba
[i
][ACOMP
] = (GLchan
) a
;
178 static void _BLENDAPI
179 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
180 GLchan rgba
[][4], CONST GLchan dest
[][4] )
183 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
184 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
185 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
190 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
191 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
192 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
193 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
194 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
195 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
196 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
197 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
205 * Blend min function (for GL_EXT_blend_minmax)
207 static void _BLENDAPI
208 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
209 GLchan rgba
[][4], CONST GLchan dest
[][4] )
212 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
217 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
218 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
219 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
220 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
228 * Blend max function (for GL_EXT_blend_minmax)
230 static void _BLENDAPI
231 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
232 GLchan rgba
[][4], CONST GLchan dest
[][4] )
235 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
240 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
241 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
242 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
243 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
251 * Modulate: result = src * dest
253 static void _BLENDAPI
254 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
255 GLchan rgba
[][4], CONST GLchan dest
[][4] )
262 #if CHAN_TYPE == GL_FLOAT
263 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * dest
[i
][RCOMP
];
264 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * dest
[i
][GCOMP
];
265 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * dest
[i
][BCOMP
];
266 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * dest
[i
][ACOMP
];
268 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
]) >> 8;
269 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
]) >> 8;
270 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
]) >> 8;
271 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
]) >> 8;
272 rgba
[i
][RCOMP
] = (GLchan
) r
;
273 rgba
[i
][GCOMP
] = (GLchan
) g
;
274 rgba
[i
][BCOMP
] = (GLchan
) b
;
275 rgba
[i
][ACOMP
] = (GLchan
) a
;
284 * General case blend pixels.
285 * Input: n - number of pixels
286 * mask - the usual write mask
287 * In/Out: rgba - the incoming and modified pixels
288 * Input: dest - the pixels from the dest color buffer
290 static void _BLENDAPI
291 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
292 GLchan rgba
[][4], CONST GLchan dest
[][4] )
294 GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
295 GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
296 GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
297 GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
302 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
303 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
304 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
305 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
314 /* Frame buffer color */
320 /* Source RGB factor */
321 switch (ctx
->Color
.BlendSrcRGB
) {
329 sR
= (GLfloat
) Rd
* rscale
;
330 sG
= (GLfloat
) Gd
* gscale
;
331 sB
= (GLfloat
) Bd
* bscale
;
333 case GL_ONE_MINUS_DST_COLOR
:
334 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
335 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
336 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
339 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
341 case GL_ONE_MINUS_SRC_ALPHA
:
342 sR
= sG
= sB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
345 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
347 case GL_ONE_MINUS_DST_ALPHA
:
348 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
350 case GL_SRC_ALPHA_SATURATE
:
351 if (As
< CHAN_MAX
- Ad
) {
352 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
355 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
358 case GL_CONSTANT_COLOR
:
359 sR
= ctx
->Color
.BlendColor
[0];
360 sG
= ctx
->Color
.BlendColor
[1];
361 sB
= ctx
->Color
.BlendColor
[2];
363 case GL_ONE_MINUS_CONSTANT_COLOR
:
364 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
365 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
366 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
368 case GL_CONSTANT_ALPHA
:
369 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
371 case GL_ONE_MINUS_CONSTANT_ALPHA
:
372 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
374 case GL_SRC_COLOR
: /* GL_NV_blend_square */
375 sR
= (GLfloat
) Rs
* rscale
;
376 sG
= (GLfloat
) Gs
* gscale
;
377 sB
= (GLfloat
) Bs
* bscale
;
379 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
380 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
381 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
382 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
385 /* this should never happen */
386 _mesa_problem(ctx
, "Bad blend source RGB factor in do_blend");
390 /* Source Alpha factor */
391 switch (ctx
->Color
.BlendSrcA
) {
399 sA
= (GLfloat
) Ad
* ascale
;
401 case GL_ONE_MINUS_DST_COLOR
:
402 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
405 sA
= (GLfloat
) As
* ascale
;
407 case GL_ONE_MINUS_SRC_ALPHA
:
408 sA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
411 sA
=(GLfloat
) Ad
* ascale
;
413 case GL_ONE_MINUS_DST_ALPHA
:
414 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
416 case GL_SRC_ALPHA_SATURATE
:
419 case GL_CONSTANT_COLOR
:
420 sA
= ctx
->Color
.BlendColor
[3];
422 case GL_ONE_MINUS_CONSTANT_COLOR
:
423 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
425 case GL_CONSTANT_ALPHA
:
426 sA
= ctx
->Color
.BlendColor
[3];
428 case GL_ONE_MINUS_CONSTANT_ALPHA
:
429 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
431 case GL_SRC_COLOR
: /* GL_NV_blend_square */
432 sA
= (GLfloat
) As
* ascale
;
434 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
435 sA
= 1.0F
- (GLfloat
) As
* ascale
;
438 /* this should never happen */
440 _mesa_problem(ctx
, "Bad blend source A factor in do_blend");
443 /* Dest RGB factor */
444 switch (ctx
->Color
.BlendDstRGB
) {
452 dR
= (GLfloat
) Rs
* rscale
;
453 dG
= (GLfloat
) Gs
* gscale
;
454 dB
= (GLfloat
) Bs
* bscale
;
456 case GL_ONE_MINUS_SRC_COLOR
:
457 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
458 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
459 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
462 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
464 case GL_ONE_MINUS_SRC_ALPHA
:
465 dR
= dG
= dB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
468 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
470 case GL_ONE_MINUS_DST_ALPHA
:
471 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
473 case GL_CONSTANT_COLOR
:
474 dR
= ctx
->Color
.BlendColor
[0];
475 dG
= ctx
->Color
.BlendColor
[1];
476 dB
= ctx
->Color
.BlendColor
[2];
478 case GL_ONE_MINUS_CONSTANT_COLOR
:
479 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
480 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
481 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
483 case GL_CONSTANT_ALPHA
:
484 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
486 case GL_ONE_MINUS_CONSTANT_ALPHA
:
487 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
489 case GL_DST_COLOR
: /* GL_NV_blend_square */
490 dR
= (GLfloat
) Rd
* rscale
;
491 dG
= (GLfloat
) Gd
* gscale
;
492 dB
= (GLfloat
) Bd
* bscale
;
494 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
495 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
496 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
497 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
500 /* this should never happen */
502 _mesa_problem(ctx
, "Bad blend dest RGB factor in do_blend");
505 /* Dest Alpha factor */
506 switch (ctx
->Color
.BlendDstA
) {
514 dA
= (GLfloat
) As
* ascale
;
516 case GL_ONE_MINUS_SRC_COLOR
:
517 dA
= 1.0F
- (GLfloat
) As
* ascale
;
520 dA
= (GLfloat
) As
* ascale
;
522 case GL_ONE_MINUS_SRC_ALPHA
:
523 dA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
526 dA
= (GLfloat
) Ad
* ascale
;
528 case GL_ONE_MINUS_DST_ALPHA
:
529 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
531 case GL_CONSTANT_COLOR
:
532 dA
= ctx
->Color
.BlendColor
[3];
534 case GL_ONE_MINUS_CONSTANT_COLOR
:
535 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
537 case GL_CONSTANT_ALPHA
:
538 dA
= ctx
->Color
.BlendColor
[3];
540 case GL_ONE_MINUS_CONSTANT_ALPHA
:
541 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
543 case GL_DST_COLOR
: /* GL_NV_blend_square */
544 dA
= (GLfloat
) Ad
* ascale
;
546 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
547 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
550 /* this should never happen */
552 _mesa_problem(ctx
, "Bad blend dest A factor in do_blend");
556 /* Due to round-off problems we have to clamp against zero. */
557 /* Optimization: we don't have to do this for all src & dst factors */
558 if (dA
< 0.0F
) dA
= 0.0F
;
559 if (dR
< 0.0F
) dR
= 0.0F
;
560 if (dG
< 0.0F
) dG
= 0.0F
;
561 if (dB
< 0.0F
) dB
= 0.0F
;
562 if (sA
< 0.0F
) sA
= 0.0F
;
563 if (sR
< 0.0F
) sR
= 0.0F
;
564 if (sG
< 0.0F
) sG
= 0.0F
;
565 if (sB
< 0.0F
) sB
= 0.0F
;
576 /* compute blended color */
577 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
578 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
579 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
580 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
581 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
583 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
584 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
585 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
586 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
587 a
= As
* sA
- Ad
* dA
+ 0.5F
;
589 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
590 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
591 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
592 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
593 a
= Ad
* dA
- As
* sA
+ 0.5F
;
596 /* should never get here */
597 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
598 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
602 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
603 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
604 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
605 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
615 * Analyze current blending parameters to pick fastest blending function.
616 * Result: the ctx->Color.BlendFunc pointer is updated.
618 void _swrast_choose_blend_func( GLcontext
*ctx
)
620 const GLenum eq
= ctx
->Color
.BlendEquation
;
621 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
622 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
623 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
624 const GLenum dstA
= ctx
->Color
.BlendDstA
;
626 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
627 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
629 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
630 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
)
632 /* XXX It looks like the MMX blend code is broken. Disable for now. */
633 #if 0 && defined(USE_MMX_ASM)
635 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_transparency
;
639 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_transparency
;
641 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
642 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_add
;
644 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
645 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
647 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
648 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
649 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_modulate
;
651 else if (eq
==GL_MIN_EXT
) {
652 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_min
;
654 else if (eq
==GL_MAX_EXT
) {
655 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_max
;
657 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ZERO
&& dstRGB
== GL_ONE
) {
658 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_noop
;
660 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ONE
&& dstRGB
== GL_ZERO
) {
661 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_replace
;
664 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
671 * Apply the blending operator to a span of pixels.
672 * We can handle horizontal runs of pixels (spans) or arrays of x/y
676 _mesa_blend_span( GLcontext
*ctx
, const struct sw_span
*span
,
679 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
680 GLchan framebuffer
[MAX_WIDTH
][4];
682 ASSERT(span
->end
<= MAX_WIDTH
);
683 ASSERT(span
->arrayMask
& SPAN_RGBA
);
684 ASSERT(!ctx
->Color
.ColorLogicOpEnabled
);
686 /* Read span of current frame buffer pixels */
687 if (span
->arrayMask
& SPAN_XY
) {
688 /* array of x/y pixel coords */
689 (*swrast
->Driver
.ReadRGBAPixels
)( ctx
, span
->end
,
690 span
->xArray
, span
->yArray
,
691 framebuffer
, span
->mask
);
692 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
693 _mesa_read_alpha_pixels( ctx
, span
->end
, span
->xArray
, span
->yArray
,
694 framebuffer
, span
->mask
);
698 /* horizontal run of pixels */
699 _mesa_read_rgba_span( ctx
, ctx
->DrawBuffer
, span
->end
,
700 span
->x
, span
->y
, framebuffer
);
703 SWRAST_CONTEXT(ctx
)->BlendFunc( ctx
, span
->end
, span
->mask
, rgba
,
704 (const GLchan (*)[4]) framebuffer
);