1 /* $Id: s_blend.c,v 1.10 2001/12/13 16:14:26 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 * Special case for glBlendFunc(GL_ZERO, GL_ONE)
53 blend_noop( 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_ZERO
);
59 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
62 for (i
= 0; i
< n
; i
++) {
64 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
65 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
66 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
67 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
74 * Special case for glBlendFunc(GL_ONE, GL_ZERO)
77 blend_replace( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
78 GLchan rgba
[][4], CONST GLchan dest
[][4] )
80 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
81 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
82 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ZERO
);
92 * Common transparency blending mode.
95 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
96 GLchan rgba
[][4], CONST GLchan dest
[][4] )
99 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
100 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
101 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
106 const GLint t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
109 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
110 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
111 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
112 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
114 else if (t
== CHAN_MAX
) {
115 /* 100% alpha, no-op */
119 /* This is pretty close, but Glean complains */
120 const GLint s
= CHAN_MAX
- t
;
121 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
122 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
123 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
124 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
126 /* This is slower but satisfies Glean */
127 const GLint s
= CHAN_MAX
- t
;
128 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
129 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
130 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
131 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
134 /* This satisfies Glean and should be reasonably fast */
135 /* Contributed by Nathan Hand */
136 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
137 const GLint s
= CHAN_MAX
- t
;
138 const GLint r
= DIV255(rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
);
139 const GLint g
= DIV255(rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
);
140 const GLint b
= DIV255(rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
);
141 const GLint a
= DIV255(rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
);
143 #elif CHAN_BITS == 16
144 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
145 const GLfloat s
= 1.0 - tt
;
146 const GLint r
= (GLint
) (rgba
[i
][RCOMP
] * tt
+ dest
[i
][RCOMP
] * s
);
147 const GLint g
= (GLint
) (rgba
[i
][GCOMP
] * tt
+ dest
[i
][GCOMP
] * s
);
148 const GLint b
= (GLint
) (rgba
[i
][BCOMP
] * tt
+ dest
[i
][BCOMP
] * s
);
149 const GLint a
= (GLint
) (rgba
[i
][ACOMP
] * tt
+ dest
[i
][ACOMP
] * s
);
150 #else /* CHAN_BITS == 32 */
151 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
152 const GLfloat s
= 1.0 - tt
;
153 const GLfloat r
= rgba
[i
][RCOMP
] * tt
+ dest
[i
][RCOMP
] * s
;
154 const GLfloat g
= rgba
[i
][GCOMP
] * tt
+ dest
[i
][GCOMP
] * s
;
155 const GLfloat b
= rgba
[i
][BCOMP
] * tt
+ dest
[i
][BCOMP
] * s
;
156 const GLfloat a
= rgba
[i
][ACOMP
] * tt
+ dest
[i
][ACOMP
] * s
;
159 ASSERT(r
<= CHAN_MAX
);
160 ASSERT(g
<= CHAN_MAX
);
161 ASSERT(b
<= CHAN_MAX
);
162 ASSERT(a
<= CHAN_MAX
);
163 rgba
[i
][RCOMP
] = (GLchan
) r
;
164 rgba
[i
][GCOMP
] = (GLchan
) g
;
165 rgba
[i
][BCOMP
] = (GLchan
) b
;
166 rgba
[i
][ACOMP
] = (GLchan
) a
;
177 static void _BLENDAPI
178 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
179 GLchan rgba
[][4], CONST GLchan dest
[][4] )
182 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
183 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
184 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
189 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
190 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
191 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
192 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
193 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
194 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
195 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
196 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
204 * Blend min function (for GL_EXT_blend_minmax)
206 static void _BLENDAPI
207 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
208 GLchan rgba
[][4], CONST GLchan dest
[][4] )
211 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
216 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
217 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
218 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
219 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
227 * Blend max function (for GL_EXT_blend_minmax)
229 static void _BLENDAPI
230 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
231 GLchan rgba
[][4], CONST GLchan dest
[][4] )
234 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
239 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
240 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
241 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
242 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
250 * Modulate: result = src * dest
252 static void _BLENDAPI
253 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
254 GLchan rgba
[][4], CONST GLchan dest
[][4] )
261 #if CHAN_TYPE == GL_FLOAT
262 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * dest
[i
][RCOMP
];
263 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * dest
[i
][GCOMP
];
264 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * dest
[i
][BCOMP
];
265 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * dest
[i
][ACOMP
];
267 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
]) >> 8;
268 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
]) >> 8;
269 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
]) >> 8;
270 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
]) >> 8;
271 rgba
[i
][RCOMP
] = (GLchan
) r
;
272 rgba
[i
][GCOMP
] = (GLchan
) g
;
273 rgba
[i
][BCOMP
] = (GLchan
) b
;
274 rgba
[i
][ACOMP
] = (GLchan
) a
;
283 * General case blend pixels.
284 * Input: n - number of pixels
285 * mask - the usual write mask
286 * In/Out: rgba - the incoming and modified pixels
287 * Input: dest - the pixels from the dest color buffer
289 static void _BLENDAPI
290 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
291 GLchan rgba
[][4], CONST GLchan dest
[][4] )
293 GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
294 GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
295 GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
296 GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
301 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
302 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
303 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
304 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
313 /* Frame buffer color */
319 /* Source RGB factor */
320 switch (ctx
->Color
.BlendSrcRGB
) {
328 sR
= (GLfloat
) Rd
* rscale
;
329 sG
= (GLfloat
) Gd
* gscale
;
330 sB
= (GLfloat
) Bd
* bscale
;
332 case GL_ONE_MINUS_DST_COLOR
:
333 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
334 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
335 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
338 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
340 case GL_ONE_MINUS_SRC_ALPHA
:
341 sR
= sG
= sB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
344 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
346 case GL_ONE_MINUS_DST_ALPHA
:
347 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
349 case GL_SRC_ALPHA_SATURATE
:
350 if (As
< CHAN_MAX
- Ad
) {
351 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
354 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
357 case GL_CONSTANT_COLOR
:
358 sR
= ctx
->Color
.BlendColor
[0];
359 sG
= ctx
->Color
.BlendColor
[1];
360 sB
= ctx
->Color
.BlendColor
[2];
362 case GL_ONE_MINUS_CONSTANT_COLOR
:
363 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
364 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
365 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
367 case GL_CONSTANT_ALPHA
:
368 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
370 case GL_ONE_MINUS_CONSTANT_ALPHA
:
371 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
373 case GL_SRC_COLOR
: /* GL_NV_blend_square */
374 sR
= (GLfloat
) Rs
* rscale
;
375 sG
= (GLfloat
) Gs
* gscale
;
376 sB
= (GLfloat
) Bs
* bscale
;
378 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
379 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
380 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
381 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
384 /* this should never happen */
385 _mesa_problem(ctx
, "Bad blend source RGB factor in do_blend");
389 /* Source Alpha factor */
390 switch (ctx
->Color
.BlendSrcA
) {
398 sA
= (GLfloat
) Ad
* ascale
;
400 case GL_ONE_MINUS_DST_COLOR
:
401 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
404 sA
= (GLfloat
) As
* ascale
;
406 case GL_ONE_MINUS_SRC_ALPHA
:
407 sA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
410 sA
=(GLfloat
) Ad
* ascale
;
412 case GL_ONE_MINUS_DST_ALPHA
:
413 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
415 case GL_SRC_ALPHA_SATURATE
:
418 case GL_CONSTANT_COLOR
:
419 sA
= ctx
->Color
.BlendColor
[3];
421 case GL_ONE_MINUS_CONSTANT_COLOR
:
422 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
424 case GL_CONSTANT_ALPHA
:
425 sA
= ctx
->Color
.BlendColor
[3];
427 case GL_ONE_MINUS_CONSTANT_ALPHA
:
428 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
430 case GL_SRC_COLOR
: /* GL_NV_blend_square */
431 sA
= (GLfloat
) As
* ascale
;
433 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
434 sA
= 1.0F
- (GLfloat
) As
* ascale
;
437 /* this should never happen */
439 _mesa_problem(ctx
, "Bad blend source A factor in do_blend");
442 /* Dest RGB factor */
443 switch (ctx
->Color
.BlendDstRGB
) {
451 dR
= (GLfloat
) Rs
* rscale
;
452 dG
= (GLfloat
) Gs
* gscale
;
453 dB
= (GLfloat
) Bs
* bscale
;
455 case GL_ONE_MINUS_SRC_COLOR
:
456 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
457 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
458 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
461 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
463 case GL_ONE_MINUS_SRC_ALPHA
:
464 dR
= dG
= dB
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
467 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
469 case GL_ONE_MINUS_DST_ALPHA
:
470 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
472 case GL_CONSTANT_COLOR
:
473 dR
= ctx
->Color
.BlendColor
[0];
474 dG
= ctx
->Color
.BlendColor
[1];
475 dB
= ctx
->Color
.BlendColor
[2];
477 case GL_ONE_MINUS_CONSTANT_COLOR
:
478 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
479 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
480 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
482 case GL_CONSTANT_ALPHA
:
483 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
485 case GL_ONE_MINUS_CONSTANT_ALPHA
:
486 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
488 case GL_DST_COLOR
: /* GL_NV_blend_square */
489 dR
= (GLfloat
) Rd
* rscale
;
490 dG
= (GLfloat
) Gd
* gscale
;
491 dB
= (GLfloat
) Bd
* bscale
;
493 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
494 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
495 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
496 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
499 /* this should never happen */
501 _mesa_problem(ctx
, "Bad blend dest RGB factor in do_blend");
504 /* Dest Alpha factor */
505 switch (ctx
->Color
.BlendDstA
) {
513 dA
= (GLfloat
) As
* ascale
;
515 case GL_ONE_MINUS_SRC_COLOR
:
516 dA
= 1.0F
- (GLfloat
) As
* ascale
;
519 dA
= (GLfloat
) As
* ascale
;
521 case GL_ONE_MINUS_SRC_ALPHA
:
522 dA
= (GLfloat
) 1.0F
- (GLfloat
) As
* ascale
;
525 dA
= (GLfloat
) Ad
* ascale
;
527 case GL_ONE_MINUS_DST_ALPHA
:
528 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
530 case GL_CONSTANT_COLOR
:
531 dA
= ctx
->Color
.BlendColor
[3];
533 case GL_ONE_MINUS_CONSTANT_COLOR
:
534 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
536 case GL_CONSTANT_ALPHA
:
537 dA
= ctx
->Color
.BlendColor
[3];
539 case GL_ONE_MINUS_CONSTANT_ALPHA
:
540 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
542 case GL_DST_COLOR
: /* GL_NV_blend_square */
543 dA
= (GLfloat
) Ad
* ascale
;
545 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
546 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
549 /* this should never happen */
551 _mesa_problem(ctx
, "Bad blend dest A factor in do_blend");
555 /* Due to round-off problems we have to clamp against zero. */
556 /* Optimization: we don't have to do this for all src & dst factors */
557 if (dA
< 0.0F
) dA
= 0.0F
;
558 if (dR
< 0.0F
) dR
= 0.0F
;
559 if (dG
< 0.0F
) dG
= 0.0F
;
560 if (dB
< 0.0F
) dB
= 0.0F
;
561 if (sA
< 0.0F
) sA
= 0.0F
;
562 if (sR
< 0.0F
) sR
= 0.0F
;
563 if (sG
< 0.0F
) sG
= 0.0F
;
564 if (sB
< 0.0F
) sB
= 0.0F
;
575 /* compute blended color */
576 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
577 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
578 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
579 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
580 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
582 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
583 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
584 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
585 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
586 a
= As
* sA
- Ad
* dA
+ 0.5F
;
588 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
589 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
590 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
591 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
592 a
= Ad
* dA
- As
* sA
+ 0.5F
;
595 /* should never get here */
596 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
597 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
601 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
602 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
603 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
604 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
614 * Analyze current blending parameters to pick fastest blending function.
615 * Result: the ctx->Color.BlendFunc pointer is updated.
617 void _swrast_choose_blend_func( GLcontext
*ctx
)
619 const GLenum eq
= ctx
->Color
.BlendEquation
;
620 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
621 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
622 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
623 const GLenum dstA
= ctx
->Color
.BlendDstA
;
625 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
626 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
628 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
629 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
)
631 /* XXX It looks like the MMX blend code is broken. Disable for now. */
632 #if 0 && defined(USE_MMX_ASM)
634 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_transparency
;
638 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_transparency
;
640 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
641 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_add
;
643 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
644 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
646 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
647 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
648 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_modulate
;
650 else if (eq
==GL_MIN_EXT
) {
651 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_min
;
653 else if (eq
==GL_MAX_EXT
) {
654 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_max
;
656 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ZERO
&& dstRGB
== GL_ONE
) {
657 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_noop
;
659 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ONE
&& dstRGB
== GL_ZERO
) {
660 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_replace
;
663 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
670 * Apply the blending operator to a span of pixels.
671 * Input: n - number of pixels in span
672 * x, y - location of leftmost pixel in span in window coords.
673 * mask - boolean mask indicating which pixels to blend.
674 * In/Out: rgba - pixel values
677 _mesa_blend_span( GLcontext
*ctx
, GLuint n
, GLint x
, GLint y
,
678 GLchan rgba
[][4], const GLubyte mask
[] )
680 GLchan dest
[MAX_WIDTH
][4];
682 /* Check if device driver can do the work */
683 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&&
684 !ctx
->Color
.ColorLogicOpEnabled
) {
688 /* Read span of current frame buffer pixels */
689 _mesa_read_rgba_span( ctx
, ctx
->DrawBuffer
, n
, x
, y
, dest
);
691 SWRAST_CONTEXT(ctx
)->BlendFunc( ctx
, n
, mask
, rgba
,
692 (const GLchan (*)[4]) dest
);
698 * Apply the blending operator to an array of pixels.
699 * Input: n - number of pixels in span
700 * x, y - array of pixel locations
701 * mask - boolean mask indicating which pixels to blend.
702 * In/Out: rgba - pixel values
705 _mesa_blend_pixels( GLcontext
*ctx
,
706 GLuint n
, const GLint x
[], const GLint y
[],
707 GLchan rgba
[][4], const GLubyte mask
[] )
709 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
710 GLchan dest
[PB_SIZE
][4];
712 /* Check if device driver can do the work */
713 if (ctx
->Color
.BlendEquation
==GL_LOGIC_OP
&&
714 !ctx
->Color
.ColorLogicOpEnabled
) {
718 /* Read pixels from current color buffer */
719 (*swrast
->Driver
.ReadRGBAPixels
)( ctx
, n
, x
, y
, dest
, mask
);
720 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
721 _mesa_read_alpha_pixels( ctx
, n
, x
, y
, dest
, mask
);
724 swrast
->BlendFunc( ctx
, n
, mask
, rgba
, (const GLchan (*)[4])dest
);